Update from https://crrev.com/320343 This required some manual patching to ui/event and ui/gfx. Sky tests were suppressed. https://github.com/domokit/mojo/issues/64 BUG=401761 R=jamesr@chromium.org Review URL: https://codereview.chromium.org/1001833005
diff --git a/DEPS b/DEPS index bc8e552..0958e5b 100644 --- a/DEPS +++ b/DEPS
@@ -21,15 +21,15 @@ 'chromium_git': 'https://chromium.googlesource.com', 'dart_svn': 'https://dart.googlecode.com', 'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac', - 'skia_revision': 'a9baa652bb329b5a286e1638938f63433701efca', + 'skia_revision': 'd1783aefcc0da86c5ff1d124c54704252d817621', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and V8 without interference from each other. - 'v8_revision': 'a1d36b4b6b1a3bb35d3bc5b64fbd5de9f55fed26', + 'v8_revision': '8f7dfb46871191fa9c96f9030d88be6757d46eab', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '019304886ad8b985d67202edec431407bb1b5c53', + 'angle_revision': '524e3bde19d0df76cc9d1c5926345f5d0ec4d3f8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -45,7 +45,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '09bdb2a2c3d40646ac4b20f5e73421307a80185f', + 'boringssl_revision': 'bf0df92964565f819881e78ff3bfb5343e95e130', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lss # and whatever else without interference from each other.
diff --git a/base/BUILD.gn b/base/BUILD.gn index 402b19a..69f366e 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -9,6 +9,41 @@ import("//build/config/android/rules.gni") } +source_set("base_paths") { + sources = [ + "base_paths.cc", + "base_paths.h", + "base_paths_android.cc", + "base_paths_android.h", + "base_paths_mac.h", + "base_paths_mac.mm", + "base_paths_posix.cc", + "base_paths_posix.h", + "base_paths_win.cc", + "base_paths_win.h", + ] + + if (is_android || is_mac) { + sources -= [ "base_paths_posix.cc" ] + } + + if (is_nacl) { + sources -= [ + "base_paths.cc", + "base_paths_posix.cc", + ] + } + + defines = [ "BASE_IMPLEMENTATION" ] + + deps = [ + "//base/memory", + "//base/process", + ] + + visibility = [ ":base" ] +} + component("base") { sources = [ "allocator/allocator_extension.cc", @@ -92,16 +127,6 @@ "base64.cc", "base64.h", "base_export.h", - "base_paths.cc", - "base_paths.h", - "base_paths_android.cc", - "base_paths_android.h", - "base_paths_mac.h", - "base_paths_mac.mm", - "base_paths_posix.cc", - "base_paths_posix.h", - "base_paths_win.cc", - "base_paths_win.h", "base_switches.h", "basictypes.h", "big_endian.cc", @@ -135,43 +160,6 @@ "cpu.h", "critical_closure.h", "critical_closure_internal_ios.mm", - "debug/alias.cc", - "debug/alias.h", - "debug/asan_invalid_access.cc", - "debug/asan_invalid_access.h", - "debug/crash_logging.cc", - "debug/crash_logging.h", - "debug/debugger.cc", - "debug/debugger.h", - "debug/debugger_posix.cc", - "debug/debugger_win.cc", - "debug/dump_without_crashing.cc", - "debug/dump_without_crashing.h", - "debug/gdi_debug_util_win.cc", - "debug/gdi_debug_util_win.h", - "third_party/dmg_fp/dmg_fp.h", - "third_party/dmg_fp/dtoa_wrapper.cc", - "third_party/dmg_fp/g_fmt.cc", - "third_party/icu/icu_utf.cc", - "third_party/icu/icu_utf.h", - "third_party/superfasthash/superfasthash.c", - - # This file depends on files from the "allocator" target, - # but this target does not depend on "allocator" (see - # allocator.gyp for details). - "debug/leak_annotations.h", - "debug/leak_tracker.h", - "debug/proc_maps_linux.cc", - "debug/proc_maps_linux.h", - "debug/profiler.cc", - "debug/profiler.h", - "debug/stack_trace.cc", - "debug/stack_trace.h", - "debug/stack_trace_android.cc", - "debug/stack_trace_posix.cc", - "debug/stack_trace_win.cc", - "debug/task_annotator.cc", - "debug/task_annotator.h", "deferred_sequenced_task_runner.cc", "deferred_sequenced_task_runner.h", "environment.cc", @@ -243,20 +231,6 @@ "ios/scoped_critical_action.mm", "ios/weak_nsobject.h", "ios/weak_nsobject.mm", - "json/json_file_value_serializer.cc", - "json/json_file_value_serializer.h", - "json/json_parser.cc", - "json/json_parser.h", - "json/json_reader.cc", - "json/json_reader.h", - "json/json_string_value_serializer.cc", - "json/json_string_value_serializer.h", - "json/json_value_converter.cc", - "json/json_value_converter.h", - "json/json_writer.cc", - "json/json_writer.h", - "json/string_escape.cc", - "json/string_escape.h", "lazy_instance.cc", "lazy_instance.h", "linux_util.cc", @@ -316,46 +290,6 @@ "macros.h", "md5.cc", "md5.h", - "memory/aligned_memory.cc", - "memory/aligned_memory.h", - "memory/discardable_memory.cc", - "memory/discardable_memory.h", - "memory/discardable_memory_android.cc", - "memory/discardable_memory_emulated.cc", - "memory/discardable_memory_emulated.h", - "memory/discardable_memory_linux.cc", - "memory/discardable_memory_mac.cc", - "memory/discardable_memory_manager.cc", - "memory/discardable_memory_manager.h", - "memory/discardable_memory_shmem.cc", - "memory/discardable_memory_shmem.h", - "memory/discardable_memory_shmem_allocator.cc", - "memory/discardable_memory_shmem_allocator.h", - "memory/discardable_memory_win.cc", - "memory/discardable_shared_memory.cc", - "memory/discardable_shared_memory.h", - "memory/linked_ptr.h", - "memory/manual_constructor.h", - "memory/memory_pressure_listener.cc", - "memory/memory_pressure_listener.h", - "memory/raw_scoped_refptr_mismatch_checker.h", - "memory/ref_counted.cc", - "memory/ref_counted.h", - "memory/ref_counted_delete_on_message_loop.h", - "memory/ref_counted_memory.cc", - "memory/ref_counted_memory.h", - "memory/scoped_policy.h", - "memory/scoped_ptr.h", - "memory/scoped_vector.h", - "memory/shared_memory.h", - "memory/shared_memory_android.cc", - "memory/shared_memory_nacl.cc", - "memory/shared_memory_posix.cc", - "memory/shared_memory_win.cc", - "memory/singleton.cc", - "memory/singleton.h", - "memory/weak_ptr.cc", - "memory/weak_ptr.h", "message_loop/incoming_task_queue.cc", "message_loop/incoming_task_queue.h", "message_loop/message_loop.cc", @@ -380,33 +314,6 @@ "message_loop/message_pump_mac.mm", "message_loop/message_pump_win.cc", "message_loop/message_pump_win.h", - "metrics/bucket_ranges.cc", - "metrics/bucket_ranges.h", - "metrics/field_trial.cc", - "metrics/field_trial.h", - "metrics/histogram.cc", - "metrics/histogram.h", - "metrics/histogram_base.cc", - "metrics/histogram_base.h", - "metrics/histogram_delta_serialization.", - "metrics/histogram_delta_serialization.cc", - "metrics/histogram_flattener.h", - "metrics/histogram_macros.h", - "metrics/histogram_samples.cc", - "metrics/histogram_samples.h", - "metrics/histogram_snapshot_manager.cc", - "metrics/histogram_snapshot_manager.h", - "metrics/sample_map.cc", - "metrics/sample_map.h", - "metrics/sample_vector.cc", - "metrics/sample_vector.h", - "metrics/sparse_histogram.cc", - "metrics/sparse_histogram.h", - "metrics/statistics_recorder.cc", - "metrics/statistics_recorder.h", - "metrics/user_metrics.cc", - "metrics/user_metrics.h", - "metrics/user_metrics_action.h", "move.h", "native_library.h", "native_library_mac.mm", @@ -453,54 +360,6 @@ "power_monitor/power_monitor_source.cc", "power_monitor/power_monitor_source.h", "power_monitor/power_observer.h", - "process/internal_linux.cc", - "process/internal_linux.h", - "process/kill.cc", - "process/kill.h", - "process/kill_mac.cc", - "process/kill_posix.cc", - "process/kill_win.cc", - "process/launch.cc", - "process/launch.h", - "process/launch_ios.cc", - "process/launch_mac.cc", - "process/launch_posix.cc", - "process/launch_win.cc", - "process/memory.cc", - "process/memory.h", - "process/memory_linux.cc", - "process/memory_mac.mm", - "process/memory_win.cc", - "process/process.h", - "process/process_handle_freebsd.cc", - "process/process_handle_linux.cc", - "process/process_handle_mac.cc", - "process/process_handle_openbsd.cc", - "process/process_handle_posix.cc", - "process/process_handle_win.cc", - "process/process_info.h", - "process/process_info_linux.cc", - "process/process_info_mac.cc", - "process/process_info_win.cc", - "process/process_iterator.cc", - "process/process_iterator.h", - "process/process_iterator_freebsd.cc", - "process/process_iterator_linux.cc", - "process/process_iterator_mac.cc", - "process/process_iterator_openbsd.cc", - "process/process_iterator_win.cc", - "process/process_linux.cc", - "process/process_metrics.cc", - "process/process_metrics.h", - "process/process_metrics_freebsd.cc", - "process/process_metrics_ios.cc", - "process/process_metrics_linux.cc", - "process/process_metrics_mac.cc", - "process/process_metrics_openbsd.cc", - "process/process_metrics_posix.cc", - "process/process_metrics_win.cc", - "process/process_posix.cc", - "process/process_win.cc", "profiler/alternate_timer.cc", "profiler/alternate_timer.h", "profiler/scoped_profile.cc", @@ -608,6 +467,12 @@ "task_runner.h", "task_runner_util.h", "template_util.h", + "third_party/dmg_fp/dmg_fp.h", + "third_party/dmg_fp/dtoa_wrapper.cc", + "third_party/dmg_fp/g_fmt.cc", + "third_party/icu/icu_utf.cc", + "third_party/icu/icu_utf.h", + "third_party/superfasthash/superfasthash.c", "thread_task_runner_handle.cc", "thread_task_runner_handle.h", "threading/non_thread_safe.h", @@ -673,34 +538,6 @@ "timer/mock_timer.h", "timer/timer.cc", "timer/timer.h", - "trace_event/memory_dump_manager.cc", - "trace_event/memory_dump_manager.h", - "trace_event/memory_dump_provider.h", - "trace_event/process_memory_dump.cc", - "trace_event/process_memory_dump.h", - "trace_event/process_memory_maps.cc", - "trace_event/process_memory_maps.h", - "trace_event/process_memory_maps_dump_provider.cc", - "trace_event/process_memory_maps_dump_provider.h", - "trace_event/process_memory_totals.cc", - "trace_event/process_memory_totals.h", - "trace_event/process_memory_totals_dump_provider.cc", - "trace_event/process_memory_totals_dump_provider.h", - "trace_event/trace_event.h", - "trace_event/trace_event_android.cc", - "trace_event/trace_event_argument.cc", - "trace_event/trace_event_argument.h", - "trace_event/trace_event_impl.cc", - "trace_event/trace_event_impl.h", - "trace_event/trace_event_impl_constants.cc", - "trace_event/trace_event_memory.cc", - "trace_event/trace_event_memory.h", - "trace_event/trace_event_synthetic_delay.cc", - "trace_event/trace_event_synthetic_delay.h", - "trace_event/trace_event_system_stats_monitor.cc", - "trace_event/trace_event_system_stats_monitor.h", - "trace_event/trace_event_win.cc", - "trace_event/trace_event_win.h", "tracked_objects.cc", "tracked_objects.h", "tracking_info.cc", @@ -765,6 +602,63 @@ "win/wrapped_window_proc.h", ] + sources -= [ + "sys_info_freebsd.cc", + "sys_info_openbsd.cc", + ] + + defines = [ "BASE_IMPLEMENTATION" ] + + deps = [ + ":base_static", + "//base/allocator:allocator_extension_thunks", + "//base/third_party/dynamic_annotations", + "//base/third_party/nspr", + "//third_party/modp_b64", + ] + + public_deps = [ + ":base_paths", + "//base/debug", + "//base/json", + "//base/memory", + "//base/metrics", + "//base/process", + "//base/trace_event", + ] + + # Allow more direct string conversions on platforms with native utf8 + # strings + if (is_mac || is_ios || is_chromeos) { + defines += [ "SYSTEM_NATIVE_UTF8" ] + } + + if (is_android) { + sources -= [ "power_monitor/power_monitor_device_source_posix.cc" ] + + # Android uses some Linux sources, put those back. + set_sources_assignment_filter([]) + sources += [ + "files/file_path_watcher_linux.cc", + "posix/unix_domain_socket_linux.cc", + "sys_info_linux.cc", + ] + set_sources_assignment_filter(sources_assignment_filter) + + deps += [ + ":base_jni_headers", + "//third_party/ashmem", + "//third_party/android_tools:cpu_features", + ] + + # logging.cc uses the Android logging library. + libs = [ "log" ] + } + + if (is_chromeos) { + sources -= [ "power_monitor/power_monitor_device_source_posix.cc" ] + } + if (is_nacl) { # We reset sources_assignment_filter in order to explicitly include # the linux file (which would otherwise be filtered out). @@ -780,110 +674,27 @@ "allocator/type_profiler_control.cc", "allocator/type_profiler_control.h", "async_socket_io_handler_posix.cc", - "base_paths.cc", "cpu.cc", + "files/file_enumerator_posix.cc", "files/file_proxy.cc", "files/file_util.cc", - "files/file_util_proxy.cc", - "files/scoped_temp_dir.cc", - "path_service.cc", - "scoped_native_library.cc", - ] - } - - sources -= [ - "process/process_handle_freebsd.cc", - "process/process_handle_openbsd.cc", - "process/process_iterator_freebsd.cc", - "process/process_iterator_openbsd.cc", - "process/process_metrics_freebsd.cc", - "process/process_metrics_openbsd.cc", - "sys_info_freebsd.cc", - "sys_info_openbsd.cc", - ] - - defines = [ "BASE_IMPLEMENTATION" ] - - deps = [ - ":base_static", - "//base/allocator:allocator_extension_thunks", - "//base/third_party/dynamic_annotations", - "//base/third_party/nspr", - "//third_party/modp_b64", - ] - - # Allow more direct string conversions on platforms with native utf8 - # strings - if (is_mac || is_ios || is_chromeos) { - defines += [ "SYSTEM_NATIVE_UTF8" ] - } - - if (is_android) { - sources += [ - "memory/discardable_memory_ashmem.cc", - "memory/discardable_memory_ashmem.h", - "memory/discardable_memory_ashmem_allocator.cc", - "memory/discardable_memory_ashmem_allocator.h", - ] - sources -= [ - "base_paths_posix.cc", - "power_monitor/power_monitor_device_source_posix.cc", - ] - - # Android uses some Linux sources, put those back. - set_sources_assignment_filter([]) - sources += [ - "debug/proc_maps_linux.cc", - "files/file_path_watcher_linux.cc", - "posix/unix_domain_socket_linux.cc", - "process/internal_linux.cc", - "process/memory_linux.cc", - "process/process_handle_linux.cc", - "process/process_iterator_linux.cc", - "process/process_metrics_linux.cc", - "sys_info_linux.cc", - ] - set_sources_assignment_filter(sources_assignment_filter) - - deps += [ - ":base_jni_headers", - "//third_party/ashmem", - "//third_party/android_tools:cpu_features", - ] - - # logging.cc uses the Android logging library. - libs = [ "log" ] - - sources -= [ "debug/stack_trace_posix.cc" ] - } - - if (is_chromeos) { - sources -= [ "power_monitor/power_monitor_device_source_posix.cc" ] - } - - if (is_nacl) { - # These things would otherwise be built on a Posix build but aren't - # supported on NaCl. - sources -= [ - "debug/stack_trace_posix.cc", - "files/file_enumerator_posix.cc", "files/file_util_posix.cc", - "memory/shared_memory_posix.cc", + "files/file_util_proxy.cc", + "files/important_file_writer.cc", + "files/important_file_writer.h", + "files/scoped_temp_dir.cc", "message_loop/message_pump_libevent.cc", - "metrics/field_trial.cc", "native_library_posix.cc", - "process/kill_posix.cc", - "process/launch_posix.cc", - "process/process_metrics_posix.cc", - "process/process_posix.cc", + "path_service.cc", "rand_util_posix.cc", + "scoped_native_library.cc", "sync_socket_posix.cc", + "sys_info.cc", "sys_info_posix.cc", ] } else { # Remove NaCl stuff. sources -= [ - "memory/shared_memory_nacl.cc", "os_compat_nacl.cc", "os_compat_nacl.h", "rand_util_nacl.cc", @@ -922,12 +733,7 @@ # Mac. if (is_mac) { - sources += [ - "memory/discardable_memory_mach.cc", - "memory/discardable_memory_mach.h", - ] sources -= [ - "base_paths_posix.cc", "native_library_posix.cc", "strings/sys_string_conversions_posix.cc", ] @@ -990,6 +796,8 @@ configs -= [ "//build/config/compiler:optimize" ] configs += [ "//build/config/compiler:optimize_max" ] } + + allow_circular_includes_from = public_deps } # This is the subset of files from base that should not be used with a dynamic @@ -1065,11 +873,66 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] } +if (is_linux && !is_chromeos) { + # TODO(GYP): Figure out which of these work and are needed on other platforms. + test("base_perftests") { + sources = [ + "message_loop/message_pump_perftest.cc", + + # "test/run_all_unittests.cc", + "threading/thread_perftest.cc", + ] + deps = [ + ":base", + "//base/test:test_support", + "//base/test:test_support_perf", + "//testing/perf", + "//testing/gtest", + ] + + if (is_android) { + deps += [ "//testing/android:native_test_native_code" ] + } + } + + test("base_i18n_perftests") { + sources = [ + "i18n/streaming_utf8_validator_perftest.cc", + ] + deps = [ + ":base", + ":i18n", + "//base/test:test_support", + "//base/test:test_support_perf", + "//testing/gtest", + ] + } + + if (!is_ios) { + executable("build_utf8_validator_tables") { + sources = [ + "i18n/build_utf8_validator_tables.cc", + ] + deps = [ + ":base", + "//third_party/icu:icuuc", + ] + } + + executable("check_example") { + sources = [ + "check_example.cc", + ] + deps = [ + ":base", + ] + } + } +} + source_set("prefs") { sources = [ "prefs/base_prefs_export.h", - "prefs/base_prefs_switches.cc", - "prefs/base_prefs_switches.h", "prefs/default_pref_store.cc", "prefs/default_pref_store.h", "prefs/json_pref_store.cc", @@ -1272,7 +1135,6 @@ "mac/scoped_sending_event_unittest.mm", "md5_unittest.cc", "memory/aligned_memory_unittest.cc", - "memory/discardable_memory_manager_unittest.cc", "memory/discardable_memory_unittest.cc", "memory/discardable_shared_memory_unittest.cc", "memory/linked_ptr_unittest.cc", @@ -1421,6 +1283,8 @@ "win/wrapped_window_proc_unittest.cc", ] + defines = [] + deps = [ ":base", ":i18n", @@ -1437,6 +1301,12 @@ "//third_party/icu", ] + # Allow more direct string conversions on platforms with native utf8 + # strings + if (is_mac || is_ios || is_chromeos) { + defines += [ "SYSTEM_NATIVE_UTF8" ] + } + if (is_android) { apk_deps = [ ":base_java", @@ -1471,7 +1341,7 @@ if (is_linux) { sources -= [ "file_version_info_unittest.cc" ] sources += [ "nix/xdg_util_unittest.cc" ] - defines = [ "USE_SYMBOLIZE" ] + defines += [ "USE_SYMBOLIZE" ] if (use_glib) { configs += [ "//build/config/linux:glib" ] } @@ -1501,8 +1371,8 @@ # GYP: //base.gyp:base_jni_headers generate_jni("base_jni_headers") { sources = [ - "android/java/src/org/chromium/base/ApplicationStatus.java", "android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java", + "android/java/src/org/chromium/base/ApplicationStatus.java", "android/java/src/org/chromium/base/BuildInfo.java", "android/java/src/org/chromium/base/CommandLine.java", "android/java/src/org/chromium/base/ContentUriUtils.java",
diff --git a/base/OWNERS b/base/OWNERS index 03c20e7..5d3e38b 100644 --- a/base/OWNERS +++ b/base/OWNERS
@@ -24,26 +24,6 @@ per-file *.isolate=csharp@chromium.org per-file *.isolate=maruel@chromium.org -per-file bind.h=ajwong@chromium.org -per-file bind_helpers.cc=ajwong@chromium.org -per-file bind_helpers.h=ajwong@chromium.org -per-file bind_helpers_unittest.cc=ajwong@chromium.org -per-file bind.h.pump=ajwong@chromium.org -per-file bind_internal.h=ajwong@chromium.org -per-file bind_internal.h.pump=ajwong@chromium.org -per-file bind_internal_win.h=ajwong@chromium.org -per-file bind_internal_win.h.pump=ajwong@chromium.org -per-file bind_unittest.cc=ajwong@chromium.org -per-file bind_unittest.nc=ajwong@chromium.org -per-file callback_forward.h=ajwong@chromium.org -per-file callback.h=ajwong@chromium.org -per-file callback_helpers.h=ajwong@chromium.org -per-file callback.h.pump=ajwong@chromium.org -per-file callback_internal.cc=ajwong@chromium.org -per-file callback_internal.h=ajwong@chromium.org -per-file callback_unittest.cc=ajwong@chromium.org -per-file callback_unittest.h=ajwong@chromium.org -per-file callback_unittest.nc=ajwong@chromium.org per-file security_unittest.cc=jln@chromium.org # For Android-specific changes:
diff --git a/base/allocator/allocator_extension.h b/base/allocator/allocator_extension.h index de3119f..e65822b 100644 --- a/base/allocator/allocator_extension.h +++ b/base/allocator/allocator_extension.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H -#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H +#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H_ +#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H_ #include <stddef.h> // for size_t @@ -56,4 +56,4 @@ } // namespace allocator } // namespace base -#endif +#endif // BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H_
diff --git a/base/allocator/allocator_extension_thunks.h b/base/allocator/allocator_extension_thunks.h index 1e97a84..4e5027b 100644 --- a/base/allocator/allocator_extension_thunks.h +++ b/base/allocator/allocator_extension_thunks.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H -#define BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H +#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_THUNKS_H_ +#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_THUNKS_H_ #include <stddef.h> // for size_t @@ -33,4 +33,4 @@ } // namespace allocator } // namespace base -#endif +#endif // BASE_ALLOCATOR_ALLOCATOR_EXTENSION_THUNKS_H_
diff --git a/base/android/base_jni_onload.cc b/base/android/base_jni_onload.cc index c3a65d4..7ab4982 100644 --- a/base/android/base_jni_onload.cc +++ b/base/android/base_jni_onload.cc
@@ -19,6 +19,7 @@ } bool Init() { + InitAtExitManager(); JNIEnv* env = base::android::AttachCurrentThread(); base::android::InitReplacementClassLoader(env, base::android::GetClassLoader(env));
diff --git a/base/android/important_file_writer_android.h b/base/android/important_file_writer_android.h index 20956ba..88e4441 100644 --- a/base/android/important_file_writer_android.h +++ b/base/android/important_file_writer_android.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef NATIVE_FRAMEWORK_CHROME_IMPORTANT_FILE_WRITE_ANDROID_H_ -#define NATIVE_FRAMEWORK_CHROME_IMPORTANT_FILE_WRITE_ANDROID_H_ +#ifndef BASE_ANDROID_IMPORTANT_FILE_WRITER_ANDROID_H_ +#define BASE_ANDROID_IMPORTANT_FILE_WRITER_ANDROID_H_ #include <jni.h> @@ -15,4 +15,4 @@ } // namespace android } // namespace base -#endif // NATIVE_FRAMEWORK_CHROME_IMPORTANT_FILE_WRITE_ANDROID_H_ +#endif // BASE_ANDROID_IMPORTANT_FILE_WRITER_ANDROID_H_
diff --git a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java index ad5cdd8..d4b0d98 100644 --- a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java +++ b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
@@ -9,6 +9,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.TimeAnimator; import android.animation.TimeAnimator.TimeListener; +import android.annotation.TargetApi; +import android.os.Build; import android.util.Log; /** @@ -80,6 +82,9 @@ /** * Record Android animation frame rate and return the result. */ + // Note: TimeAnimator was added to the Android public API in level 16, but has actually been + // available since level 14. So, it's safe to use TimeAnimator here, even on ICS. + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private static class Recorder implements TimeListener { // TODO(kkimlabs): If we can use in the future, migrate to Choreographer for minimal // workload.
diff --git a/base/android/java/src/org/chromium/base/JavaHandlerThread.java b/base/android/java/src/org/chromium/base/JavaHandlerThread.java index 9643a63..3153a9b 100644 --- a/base/android/java/src/org/chromium/base/JavaHandlerThread.java +++ b/base/android/java/src/org/chromium/base/JavaHandlerThread.java
@@ -4,6 +4,8 @@ package org.chromium.base; +import android.annotation.TargetApi; +import android.os.Build; import android.os.Handler; import android.os.HandlerThread; @@ -35,15 +37,18 @@ }); } + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) @CalledByNative private void stop(final long nativeThread, final long nativeEvent) { + final boolean quitSafely = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; new Handler(mThread.getLooper()).post(new Runnable() { @Override public void run() { nativeStopThread(nativeThread, nativeEvent); + if (!quitSafely) mThread.quit(); } }); - mThread.quitSafely(); + if (quitSafely) mThread.quitSafely(); } private native void nativeInitializeThread(long nativeJavaHandlerThread, long nativeEvent);
diff --git a/base/android/java/src/org/chromium/base/SysUtils.java b/base/android/java/src/org/chromium/base/SysUtils.java index 1455a61..9dad516 100644 --- a/base/android/java/src/org/chromium/base/SysUtils.java +++ b/base/android/java/src/org/chromium/base/SysUtils.java
@@ -4,6 +4,7 @@ package org.chromium.base; +import android.annotation.TargetApi; import android.app.ActivityManager; import android.content.Context; import android.os.Build; @@ -19,10 +20,6 @@ * Exposes system related information about the current device. */ public class SysUtils { - // Any device that runs this or an older version of the system cannot be considered 'low-end' - private static final int ANDROID_LOW_MEMORY_ANDROID_SDK_THRESHOLD = - Build.VERSION_CODES.JELLY_BEAN_MR2; - // A device reporting strictly more total memory in megabytes cannot be considered 'low-end'. private static final int ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB = 512; @@ -107,6 +104,7 @@ return sLowEndDevice.booleanValue(); } + @TargetApi(Build.VERSION_CODES.KITKAT) private static boolean detectLowEndDevice() { assert CommandLine.isInitialized(); if (CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_LOW_END_DEVICE_MODE)) { @@ -115,7 +113,8 @@ if (CommandLine.getInstance().hasSwitch(BaseSwitches.DISABLE_LOW_END_DEVICE_MODE)) { return false; } - if (Build.VERSION.SDK_INT <= ANDROID_LOW_MEMORY_ANDROID_SDK_THRESHOLD) { + // Any pre-KitKat device cannot be considered 'low-end'. + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return false; }
diff --git a/base/android/java_handler_thread.h b/base/android/java_handler_thread.h index 7cd274d..c9a2c02 100644 --- a/base/android/java_handler_thread.h +++ b/base/android/java_handler_thread.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_THREADING_JAVA_THREAD_H_ -#define BASE_THREADING_JAVA_THREAD_H_ +#ifndef BASE_ANDROID_JAVA_HANDLER_THREAD_H_ +#define BASE_ANDROID_JAVA_HANDLER_THREAD_H_ #include <jni.h> @@ -46,4 +46,4 @@ } // namespace android } // namespace base -#endif // BASE_THREADING_JAVA_THREAD_H_ +#endif // BASE_ANDROID_JAVA_HANDLER_THREAD_H_
diff --git a/base/android/jni_generator/jni_generator.gyp b/base/android/jni_generator/jni_generator.gyp index 2ea36b0..4a17f3e 100644 --- a/base/android/jni_generator/jni_generator.gyp +++ b/base/android/jni_generator/jni_generator.gyp
@@ -7,6 +7,9 @@ { 'target_name': 'jni_generator_py_tests', 'type': 'none', + 'variables': { + 'stamp': '<(INTERMEDIATE_DIR)/jni_generator_py_tests.stamp', + }, 'actions': [ { 'action_name': 'run_jni_generator_py_tests', @@ -17,10 +20,11 @@ 'golden_sample_for_tests_jni.h', ], 'outputs': [ - '', + '<(stamp)', ], 'action': [ 'python', 'jni_generator_tests.py', + '--stamp=<(stamp)', ], }, ],
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index e29bc0c..6014847 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py
@@ -13,6 +13,7 @@ import difflib import inspect +import optparse import os import sys import unittest @@ -1148,5 +1149,27 @@ self.assertGoldenTextEquals(jni_from_java.GetContent()) +def TouchStamp(stamp_path): + dir_name = os.path.dirname(stamp_path) + if not os.path.isdir(dir_name): + os.makedirs() + + with open(stamp_path, 'a'): + os.utime(stamp_path, None) + + +def main(argv): + parser = optparse.OptionParser() + parser.add_option('--stamp', help='Path to touch on success.') + options, _ = parser.parse_args(argv[1:]) + + test_result = unittest.main(argv=argv[0:1], exit=False) + + if test_result.result.wasSuccessful() and options.stamp: + TouchStamp(options.stamp) + + return not test_result.result.wasSuccessful() + + if __name__ == '__main__': - unittest.main() + sys.exit(main(sys.argv))
diff --git a/base/android/jni_generator/sample_for_tests.h b/base/android/jni_generator/sample_for_tests.h index 4d76408..c98cf97 100644 --- a/base/android/jni_generator/sample_for_tests.h +++ b/base/android/jni_generator/sample_for_tests.h
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_ +#define BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_ + #include <jni.h> #include <map> #include <string> @@ -48,3 +51,5 @@ } // namespace android } // namespace base + +#endif // BASE_ANDROID_JNI_GENERATOR_SAMPLE_FOR_TESTS_H_
diff --git a/base/android/jni_string.cc b/base/android/jni_string.cc index d25fed8..57c2805 100644 --- a/base/android/jni_string.cc +++ b/base/android/jni_string.cc
@@ -18,7 +18,7 @@ return result; } -} +} // namespace namespace base { namespace android {
diff --git a/base/android/library_loader/library_load_from_apk_status_codes.h b/base/android/library_loader/library_load_from_apk_status_codes.h index f99eebc..9591d3f 100644 --- a/base/android/library_loader/library_load_from_apk_status_codes.h +++ b/base/android/library_loader/library_load_from_apk_status_codes.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_ANDROID_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_ -#define BASE_ANDROID_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_ +#ifndef BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_ +#define BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_ namespace base { namespace android { @@ -43,4 +43,4 @@ } // namespace android } // namespace base -#endif // BASE_ANDROID_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_ +#endif // BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
diff --git a/base/android/library_loader/library_loader_hooks.cc b/base/android/library_loader/library_loader_hooks.cc index 97aec8c..555420a 100644 --- a/base/android/library_loader/library_loader_hooks.cc +++ b/base/android/library_loader/library_loader_hooks.cc
@@ -123,9 +123,6 @@ } bool RegisterLibraryLoaderEntryHook(JNIEnv* env) { - // We need the AtExitManager to be created at the very beginning. - g_at_exit_manager = new base::AtExitManager(); - return RegisterNativesImpl(env); } @@ -142,5 +139,9 @@ Java_LibraryLoader_getLibraryProcessType(env)); } +void InitAtExitManager() { + g_at_exit_manager = new base::AtExitManager(); +} + } // namespace android } // namespace base
diff --git a/base/android/library_loader/library_loader_hooks.h b/base/android/library_loader/library_loader_hooks.h index 7e8d527..ca3c5a2 100644 --- a/base/android/library_loader/library_loader_hooks.h +++ b/base/android/library_loader/library_loader_hooks.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_ANDROID_LIBRARY_LOADER_HOOKS_H_ -#define BASE_ANDROID_LIBRARY_LOADER_HOOKS_H_ +#ifndef BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_ +#define BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_ #include <jni.h> @@ -64,7 +64,11 @@ // Return the process type the shared library is loaded in. BASE_EXPORT LibraryProcessType GetLibraryProcessType(JNIEnv* env); +// Initialize AtExitManager, this must be done at the begining of loading +// shared library. +void InitAtExitManager(); + } // namespace android } // namespace base -#endif // BASE_ANDROID_LIBRARY_LOADER_HOOKS_H_ +#endif // BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_
diff --git a/base/android/trace_event_binding.h b/base/android/trace_event_binding.h index ed06266..1c1a60b 100644 --- a/base/android/trace_event_binding.h +++ b/base/android/trace_event_binding.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_ANDROID_TRACE_EVENT_H_ -#define BASE_ANDROID_TRACE_EVENT_H_ +#ifndef BASE_ANDROID_TRACE_EVENT_BINDING_H_ +#define BASE_ANDROID_TRACE_EVENT_BINDING_H_ #include <jni.h> @@ -15,4 +15,4 @@ } // namespace android } // namespace base -#endif // CONTENT_COMMON_ANDROID_TRACE_EVENT_H_ +#endif // BASE_ANDROID_TRACE_EVENT_BINDING_H_
diff --git a/base/atomicops_internals_arm64_gcc.h b/base/atomicops_internals_arm64_gcc.h index bb6a346..ddcfec9 100644 --- a/base/atomicops_internals_arm64_gcc.h +++ b/base/atomicops_internals_arm64_gcc.h
@@ -301,7 +301,7 @@ return *ptr; } -} // namespace base::subtle +} // namespace subtle } // namespace base #endif // BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_
diff --git a/base/atomicops_internals_arm_gcc.h b/base/atomicops_internals_arm_gcc.h index e654afa..44c91c8 100644 --- a/base/atomicops_internals_arm_gcc.h +++ b/base/atomicops_internals_arm_gcc.h
@@ -288,7 +288,7 @@ return *ptr; } -} // namespace base::subtle +} // namespace subtle } // namespace base #endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
diff --git a/base/atomicops_internals_atomicword_compat.h b/base/atomicops_internals_atomicword_compat.h index e02d11d..342a6e4 100644 --- a/base/atomicops_internals_atomicword_compat.h +++ b/base/atomicops_internals_atomicword_compat.h
@@ -92,8 +92,8 @@ reinterpret_cast<volatile const Atomic32*>(ptr)); } -} // namespace base::subtle -} // namespace base +} // namespace subtle +} // namespace base #endif // !defined(ARCH_CPU_64_BITS)
diff --git a/base/atomicops_internals_gcc.h b/base/atomicops_internals_gcc.h index ed1b2d7..35c95fe 100644 --- a/base/atomicops_internals_gcc.h +++ b/base/atomicops_internals_gcc.h
@@ -99,7 +99,7 @@ return *ptr; } -} // namespace base::subtle +} // namespace subtle } // namespace base #endif // BASE_ATOMICOPS_INTERNALS_GCC_H_
diff --git a/base/atomicops_internals_mac.h b/base/atomicops_internals_mac.h index ccbb896..98864a7 100644 --- a/base/atomicops_internals_mac.h +++ b/base/atomicops_internals_mac.h
@@ -191,7 +191,7 @@ #endif // defined(__LP64__) -} // namespace base::subtle -} // namespace base +} // namespace subtle +} // namespace base #endif // BASE_ATOMICOPS_INTERNALS_MAC_H_
diff --git a/base/atomicops_internals_mips_gcc.h b/base/atomicops_internals_mips_gcc.h index e206e03..b4551b8 100644 --- a/base/atomicops_internals_mips_gcc.h +++ b/base/atomicops_internals_mips_gcc.h
@@ -274,7 +274,7 @@ } #endif -} // namespace base::subtle -} // namespace base +} // namespace subtle +} // namespace base #endif // BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
diff --git a/base/atomicops_internals_portable.h b/base/atomicops_internals_portable.h index b25099f..d285610 100644 --- a/base/atomicops_internals_portable.h +++ b/base/atomicops_internals_portable.h
@@ -221,7 +221,7 @@ } #endif // defined(ARCH_CPU_64_BITS) -} -} // namespace base::subtle +} // namespace subtle +} // namespace base #endif // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
diff --git a/base/atomicops_internals_x86_gcc.h b/base/atomicops_internals_x86_gcc.h index 69eacdb..f0d2242 100644 --- a/base/atomicops_internals_x86_gcc.h +++ b/base/atomicops_internals_x86_gcc.h
@@ -220,8 +220,8 @@ #endif // defined(__x86_64__) -} // namespace base::subtle -} // namespace base +} // namespace subtle +} // namespace base #undef ATOMICOPS_COMPILER_BARRIER
diff --git a/base/atomicops_internals_x86_msvc.h b/base/atomicops_internals_x86_msvc.h index 26f1813..71ddca2 100644 --- a/base/atomicops_internals_x86_msvc.h +++ b/base/atomicops_internals_x86_msvc.h
@@ -189,7 +189,7 @@ #endif // defined(_WIN64) -} // namespace base::subtle +} // namespace subtle } // namespace base #endif // BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
diff --git a/base/auto_reset.h b/base/auto_reset.h index 32f138e..a5bcfaa 100644 --- a/base/auto_reset.h +++ b/base/auto_reset.h
@@ -36,6 +36,6 @@ DISALLOW_COPY_AND_ASSIGN(AutoReset); }; -} +} // namespace base #endif // BASE_AUTO_RESET_H_
diff --git a/base/barrier_closure.cc b/base/barrier_closure.cc index 5abe2bf..1b77429 100644 --- a/base/barrier_closure.cc +++ b/base/barrier_closure.cc
@@ -39,7 +39,7 @@ base::Closure BarrierClosure(int num_callbacks_left, const base::Closure& done_closure) { - DCHECK(num_callbacks_left >= 0); + DCHECK_GE(num_callbacks_left, 0); if (num_callbacks_left == 0) done_closure.Run();
diff --git a/base/base.gyp b/base/base.gyp index 3888ad9..5f640d8 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -338,8 +338,6 @@ ], 'sources': [ 'prefs/base_prefs_export.h', - 'prefs/base_prefs_switches.cc', - 'prefs/base_prefs_switches.h', 'prefs/default_pref_store.cc', 'prefs/default_pref_store.h', 'prefs/json_pref_store.cc', @@ -543,7 +541,6 @@ 'mac/scoped_sending_event_unittest.mm', 'md5_unittest.cc', 'memory/aligned_memory_unittest.cc', - 'memory/discardable_memory_manager_unittest.cc', 'memory/discardable_memory_unittest.cc', 'memory/discardable_shared_memory_unittest.cc', 'memory/linked_ptr_unittest.cc', @@ -835,19 +832,20 @@ ['include', '^sys_string_conversions_mac_unittest\\.mm$'], ], }], - ['OS == "android" and _toolset == "target"', { - 'sources': [ - 'memory/discardable_memory_ashmem_allocator_unittest.cc', - ], - }], ['OS == "android"', { 'sources/': [ ['include', '^debug/proc_maps_linux_unittest\\.cc$'], ], }], + # Enable more direct string conversions on platforms with native utf8 + # strings + ['OS=="mac" or OS=="ios" or <(chromeos)==1 or <(chromecast)==1', { + 'defines': ['SYSTEM_NATIVE_UTF8'], + }], ], # target_conditions }, { + # GN: //base:base_perftests 'target_name': 'base_perftests', 'type': '<(gtest_target_type)', 'dependencies': [ @@ -870,6 +868,7 @@ ], }, { + # GN: //base:base_i18n_perftests 'target_name': 'base_i18n_perftests', 'type': '<(gtest_target_type)', 'dependencies': [ @@ -1077,6 +1076,7 @@ ['OS!="ios"', { 'targets': [ { + # GN: //base:check_example 'target_name': 'check_example', 'type': 'executable', 'sources': [
diff --git a/base/base.gypi b/base/base.gypi index 0f8fff2..ebc7e3e 100644 --- a/base/base.gypi +++ b/base/base.gypi
@@ -319,12 +319,8 @@ 'memory/discardable_memory.cc', 'memory/discardable_memory.h', 'memory/discardable_memory_android.cc', - 'memory/discardable_memory_emulated.cc', - 'memory/discardable_memory_emulated.h', 'memory/discardable_memory_linux.cc', 'memory/discardable_memory_mac.cc', - 'memory/discardable_memory_manager.cc', - 'memory/discardable_memory_manager.h', 'memory/discardable_memory_shmem.cc', 'memory/discardable_memory_shmem.h', 'memory/discardable_memory_shmem_allocator.cc', @@ -829,14 +825,6 @@ ['include', '^threading/platform_thread_linux\\.cc$'], ], }], - ['OS == "android" and _toolset == "target" and >(nacl_untrusted_build)==0', { - 'sources': [ - 'memory/discardable_memory_ashmem.cc', - 'memory/discardable_memory_ashmem.h', - 'memory/discardable_memory_ashmem_allocator.cc', - 'memory/discardable_memory_ashmem_allocator.h', - ], - }], ['OS == "android" and >(nacl_untrusted_build)==0', { 'sources!': [ 'base_paths_posix.cc', @@ -979,10 +967,6 @@ ], }], ['(OS == "mac" or OS == "ios") and >(nacl_untrusted_build)==0', { - 'sources': [ - 'memory/discardable_memory_mach.cc', - 'memory/discardable_memory_mach.h', - ], 'sources/': [ ['exclude', '^files/file_path_watcher_stub\\.cc$'], ['exclude', '^base_paths_posix\\.cc$'],
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate index 5126fb3..e329152 100644 --- a/base/base_unittests.isolate +++ b/base/base_unittests.isolate
@@ -3,14 +3,20 @@ # found in the LICENSE file. { 'conditions': [ - ['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', { + ['use_x11==0', { 'variables': { - 'files': [ - 'test/data/', + 'command': [ + '../testing/test_env.py', + '<(PRODUCT_DIR)/base_unittests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--msan=<(msan)', + '--tsan=<(tsan)', ], }, }], - ['OS=="linux"', { + ['use_x11==1', { 'variables': { 'command': [ '../testing/xvfb.py', @@ -24,13 +30,14 @@ ], 'files': [ '../testing/xvfb.py', + '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', ], }, }], - ['OS=="linux" and use_ozone==0', { + ['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { 'files': [ - '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', + 'test/data/', ], }, }], @@ -43,19 +50,6 @@ 'read_only': 1, }, }], - ['OS=="mac" or OS=="win"', { - 'variables': { - 'command': [ - '../testing/test_env.py', - '<(PRODUCT_DIR)/base_unittests<(EXECUTABLE_SUFFIX)', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--msan=<(msan)', - '--tsan=<(tsan)', - ], - }, - }], ['OS=="mac" and asan==1 and fastbuild==0', { 'variables': { 'files': [
diff --git a/base/build_time.h b/base/build_time.h index c7df479..4f0abc3 100644 --- a/base/build_time.h +++ b/base/build_time.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_BUILD_TIME_ -#define BASE_BUILD_TIME_ +#ifndef BASE_BUILD_TIME_H_ +#define BASE_BUILD_TIME_H_ #include "base/base_export.h" #include "base/time/time.h" @@ -25,4 +25,4 @@ } // namespace base -#endif // BASE_BUILD_TIME_ +#endif // BASE_BUILD_TIME_H_
diff --git a/base/callback_forward.h b/base/callback_forward.h index 7983248..262c306 100644 --- a/base/callback_forward.h +++ b/base/callback_forward.h
@@ -14,4 +14,4 @@ } // namespace base -#endif // BASE_CALLBACK_FORWARD_H +#endif // BASE_CALLBACK_FORWARD_H_
diff --git a/base/command_line.cc b/base/command_line.cc index 6125667..d28a4b4 100644 --- a/base/command_line.cc +++ b/base/command_line.cc
@@ -187,7 +187,7 @@ // static void CommandLine::set_slash_is_not_a_switch() { // The last switch prefix should be slash, so adjust the size to skip it. - DCHECK(wcscmp(kSwitchPrefixes[arraysize(kSwitchPrefixes) - 1], L"/") == 0); + DCHECK_EQ(wcscmp(kSwitchPrefixes[arraysize(kSwitchPrefixes) - 1], L"/"), 0); switch_prefix_count = arraysize(kSwitchPrefixes) - 1; } #endif
diff --git a/base/containers/hash_tables.h b/base/containers/hash_tables.h index 6bf029e..d13c469 100644 --- a/base/containers/hash_tables.h +++ b/base/containers/hash_tables.h
@@ -320,7 +320,7 @@ } }; -} +} // namespace BASE_HASH_NAMESPACE #undef DEFINE_PAIR_HASH_FUNCTION_START #undef DEFINE_PAIR_HASH_FUNCTION_END
diff --git a/base/containers/mru_cache.h b/base/containers/mru_cache.h index 15ea2fc..ed1ad25 100644 --- a/base/containers/mru_cache.h +++ b/base/containers/mru_cache.h
@@ -213,8 +213,7 @@ template<class PayloadType> class MRUCacheNullDeletor { public: - void operator()(PayloadType& payload) { - } + void operator()(const PayloadType& payload) {} }; // A container that does not do anything to free its data. Use this when storing @@ -244,9 +243,7 @@ template<class PayloadType> class MRUCachePointerDeletor { public: - void operator()(PayloadType& payload) { - delete payload; - } + void operator()(const PayloadType& payload) { delete payload; } }; // A cache that owns the payload type, which must be a non-const pointer type.
diff --git a/base/containers/stack_container.h b/base/containers/stack_container.h index 87fa036..54090d3 100644 --- a/base/containers/stack_container.h +++ b/base/containers/stack_container.h
@@ -176,6 +176,7 @@ Allocator allocator_; ContainerType container_; + private: DISALLOW_COPY_AND_ASSIGN(StackContainer); };
diff --git a/base/debug/BUILD.gn b/base/debug/BUILD.gn new file mode 100644 index 0000000..37a0ab2 --- /dev/null +++ b/base/debug/BUILD.gn
@@ -0,0 +1,75 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("debug") { + sources = [ + "alias.cc", + "alias.h", + "asan_invalid_access.cc", + "asan_invalid_access.h", + "crash_logging.cc", + "crash_logging.h", + "debugger.cc", + "debugger.h", + "debugger_posix.cc", + "debugger_win.cc", + "dump_without_crashing.cc", + "dump_without_crashing.h", + "gdi_debug_util_win.cc", + "gdi_debug_util_win.h", + + # This file depends on files from the "allocator" target, + # but this target does not depend on "allocator" (see + # allocator.gyp for details). + "leak_annotations.h", + "leak_tracker.h", + "proc_maps_linux.cc", + "proc_maps_linux.h", + "profiler.cc", + "profiler.h", + "stack_trace.cc", + "stack_trace.h", + "stack_trace_android.cc", + "stack_trace_posix.cc", + "stack_trace_win.cc", + "task_annotator.cc", + "task_annotator.h", + ] + + if (is_android) { + # Android uses some Linux sources, put those back. + set_sources_assignment_filter([]) + sources += [ "proc_maps_linux.cc" ] + set_sources_assignment_filter(sources_assignment_filter) + + sources -= [ "stack_trace_posix.cc" ] + } + + if (is_nacl) { + sources -= [ + "crash_logging.cc", + "crash_logging.h", + "stack_trace.cc", + "stack_trace_posix.cc", + ] + } + + defines = [ "BASE_IMPLEMENTATION" ] + + deps = [ + "//base/memory", + "//base/process", + ] + + if (is_linux) { + deps += [ "//base/third_party/symbolize" ] + } + + allow_circular_includes_from = [ + "//base/memory", + "//base/process", + ] + + visibility = [ "//base/*" ] +}
diff --git a/base/debug/debugger.h b/base/debug/debugger.h index d62ea3f..8680e28 100644 --- a/base/debug/debugger.h +++ b/base/debug/debugger.h
@@ -6,8 +6,8 @@ // debuggers. You should use this to test if you're running under a debugger, // and if you would like to yield (breakpoint) into the debugger. -#ifndef BASE_DEBUG_DEBUGGER_H -#define BASE_DEBUG_DEBUGGER_H +#ifndef BASE_DEBUG_DEBUGGER_H_ +#define BASE_DEBUG_DEBUGGER_H_ #include "base/base_export.h" @@ -41,4 +41,4 @@ } // namespace debug } // namespace base -#endif // BASE_DEBUG_DEBUGGER_H +#endif // BASE_DEBUG_DEBUGGER_H_
diff --git a/base/debug/leak_annotations.h b/base/debug/leak_annotations.h index 27fe663..ef37959 100644 --- a/base/debug/leak_annotations.h +++ b/base/debug/leak_annotations.h
@@ -21,15 +21,7 @@ #if defined(LEAK_SANITIZER) && !defined(OS_NACL) -// Public LSan API from <sanitizer/lsan_interface.h>. -extern "C" { -void __lsan_disable(); -void __lsan_enable(); -void __lsan_ignore_object(const void *p); - -// Invoke leak detection immediately. If leaks are found, the process will exit. -void __lsan_do_leak_check(); -} // extern "C" +#include <sanitizer/lsan_interface.h> class ScopedLeakSanitizerDisabler { public: @@ -46,7 +38,6 @@ #else -// If neither HeapChecker nor LSan are used, the annotations should be no-ops. #define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0) #define ANNOTATE_LEAKING_OBJECT_PTR(X) ((void)0)
diff --git a/base/debug/profiler.h b/base/debug/profiler.h index e1dda89..c50555e 100644 --- a/base/debug/profiler.h +++ b/base/debug/profiler.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_DEBUG_PROFILER_H -#define BASE_DEBUG_PROFILER_H +#ifndef BASE_DEBUG_PROFILER_H_ +#define BASE_DEBUG_PROFILER_H_ #include <string> @@ -87,4 +87,4 @@ } // namespace debug } // namespace base -#endif // BASE_DEBUG_DEBUGGER_H +#endif // BASE_DEBUG_PROFILER_H__
diff --git a/base/deferred_sequenced_task_runner.h b/base/deferred_sequenced_task_runner.h index bc8db7a..110d988 100644 --- a/base/deferred_sequenced_task_runner.h +++ b/base/deferred_sequenced_task_runner.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_ -#define BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_ +#ifndef BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_ +#define BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_ #include <vector> @@ -75,4 +75,4 @@ } // namespace base -#endif // BASE_DEFERRED_SEQUENCED_TASKRUNNER_H_ +#endif // BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_
diff --git a/base/event_types.h b/base/event_types.h index af586e4..9905800 100644 --- a/base/event_types.h +++ b/base/event_types.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_EVENT_TYPES_H -#define BASE_EVENT_TYPES_H +#ifndef BASE_EVENT_TYPES_H_ +#define BASE_EVENT_TYPES_H_ #include "build/build_config.h" @@ -34,4 +34,4 @@ } // namespace base -#endif // BASE_EVENT_TYPES_H +#endif // BASE_EVENT_TYPES_H_
diff --git a/base/files/file_path_watcher_browsertest.cc b/base/files/file_path_watcher_browsertest.cc index 9081626..bc7e630 100644 --- a/base/files/file_path_watcher_browsertest.cc +++ b/base/files/file_path_watcher_browsertest.cc
@@ -192,6 +192,7 @@ ScopedTempDir temp_dir_; scoped_refptr<NotificationCollector> collector_; + private: DISALLOW_COPY_AND_ASSIGN(FilePathWatcherTest); };
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc index af932ce..b107b0f 100644 --- a/base/files/file_util_unittest.cc +++ b/base/files/file_util_unittest.cc
@@ -197,9 +197,9 @@ // interface to query whether a given file is present. class FindResultCollector { public: - explicit FindResultCollector(FileEnumerator& enumerator) { + explicit FindResultCollector(FileEnumerator* enumerator) { FilePath cur_file; - while (!(cur_file = enumerator.Next()).value().empty()) { + while (!(cur_file = enumerator->Next()).value().empty()) { FilePath::StringType path = cur_file.value(); // The file should not be returned twice. EXPECT_TRUE(files_.end() == files_.find(path)) @@ -824,7 +824,7 @@ // Make sure the file in the directory can't be enumerated. FileEnumerator f1(subdir_path, true, FileEnumerator::FILES); EXPECT_TRUE(PathExists(subdir_path)); - FindResultCollector c1(f1); + FindResultCollector c1(&f1); EXPECT_EQ(0, c1.size()); EXPECT_FALSE(GetPosixFilePermissions(file_name, &mode)); @@ -835,7 +835,7 @@ // Make sure the file in the directory can be enumerated. FileEnumerator f2(subdir_path, true, FileEnumerator::FILES); - FindResultCollector c2(f2); + FindResultCollector c2(&f2); EXPECT_TRUE(c2.HasFile(file_name)); EXPECT_EQ(1, c2.size()); @@ -1871,7 +1871,7 @@ // Only enumerate files. FileEnumerator f1(temp_dir_.path(), true, FileEnumerator::FILES); - FindResultCollector c1(f1); + FindResultCollector c1(&f1); EXPECT_TRUE(c1.HasFile(file1)); EXPECT_TRUE(c1.HasFile(file2_abs)); EXPECT_TRUE(c1.HasFile(dir2file)); @@ -1880,7 +1880,7 @@ // Only enumerate directories. FileEnumerator f2(temp_dir_.path(), true, FileEnumerator::DIRECTORIES); - FindResultCollector c2(f2); + FindResultCollector c2(&f2); EXPECT_TRUE(c2.HasFile(dir1)); EXPECT_TRUE(c2.HasFile(dir2)); EXPECT_TRUE(c2.HasFile(dir2inner)); @@ -1889,7 +1889,7 @@ // Only enumerate directories non-recursively. FileEnumerator f2_non_recursive( temp_dir_.path(), false, FileEnumerator::DIRECTORIES); - FindResultCollector c2_non_recursive(f2_non_recursive); + FindResultCollector c2_non_recursive(&f2_non_recursive); EXPECT_TRUE(c2_non_recursive.HasFile(dir1)); EXPECT_TRUE(c2_non_recursive.HasFile(dir2)); EXPECT_EQ(2, c2_non_recursive.size()); @@ -1898,7 +1898,7 @@ FileEnumerator f2_dotdot(temp_dir_.path(), false, FileEnumerator::DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT); - FindResultCollector c2_dotdot(f2_dotdot); + FindResultCollector c2_dotdot(&f2_dotdot); EXPECT_TRUE(c2_dotdot.HasFile(dir1)); EXPECT_TRUE(c2_dotdot.HasFile(dir2)); EXPECT_TRUE(c2_dotdot.HasFile(temp_dir_.path().Append(FPL("..")))); @@ -1906,7 +1906,7 @@ // Enumerate files and directories. FileEnumerator f3(temp_dir_.path(), true, FILES_AND_DIRECTORIES); - FindResultCollector c3(f3); + FindResultCollector c3(&f3); EXPECT_TRUE(c3.HasFile(dir1)); EXPECT_TRUE(c3.HasFile(dir2)); EXPECT_TRUE(c3.HasFile(file1)); @@ -1918,7 +1918,7 @@ // Non-recursive operation. FileEnumerator f4(temp_dir_.path(), false, FILES_AND_DIRECTORIES); - FindResultCollector c4(f4); + FindResultCollector c4(&f4); EXPECT_TRUE(c4.HasFile(dir2)); EXPECT_TRUE(c4.HasFile(dir2)); EXPECT_TRUE(c4.HasFile(file1)); @@ -1927,7 +1927,7 @@ // Enumerate with a pattern. FileEnumerator f5(temp_dir_.path(), true, FILES_AND_DIRECTORIES, FPL("dir*")); - FindResultCollector c5(f5); + FindResultCollector c5(&f5); EXPECT_TRUE(c5.HasFile(dir1)); EXPECT_TRUE(c5.HasFile(dir2)); EXPECT_TRUE(c5.HasFile(dir2file)); @@ -1946,7 +1946,7 @@ // the file system so skip this test for XP. // Enumerate the reparse point. FileEnumerator f6(dir1, true, FILES_AND_DIRECTORIES); - FindResultCollector c6(f6); + FindResultCollector c6(&f6); FilePath inner2 = dir1.Append(FPL("inner")); EXPECT_TRUE(c6.HasFile(inner2)); EXPECT_TRUE(c6.HasFile(inner2.Append(FPL("innerfile.txt")))); @@ -1956,7 +1956,7 @@ // No changes for non recursive operation. FileEnumerator f7(temp_dir_.path(), false, FILES_AND_DIRECTORIES); - FindResultCollector c7(f7); + FindResultCollector c7(&f7); EXPECT_TRUE(c7.HasFile(dir2)); EXPECT_TRUE(c7.HasFile(dir2)); EXPECT_TRUE(c7.HasFile(file1)); @@ -1965,7 +1965,7 @@ // Should not enumerate inside dir1 when using recursion. FileEnumerator f8(temp_dir_.path(), true, FILES_AND_DIRECTORIES); - FindResultCollector c8(f8); + FindResultCollector c8(&f8); EXPECT_TRUE(c8.HasFile(dir1)); EXPECT_TRUE(c8.HasFile(dir2)); EXPECT_TRUE(c8.HasFile(file1));
diff --git a/base/guid_posix.cc b/base/guid_posix.cc index 9681b08..f0fedc2 100644 --- a/base/guid_posix.cc +++ b/base/guid_posix.cc
@@ -39,4 +39,4 @@ bytes[1] & 0x0000ffffffffffffULL); } -} // namespace guid +} // namespace base
diff --git a/base/guid_win.cc b/base/guid_win.cc index cdb860a..da3453d 100644 --- a/base/guid_win.cc +++ b/base/guid_win.cc
@@ -35,4 +35,4 @@ return WideToUTF8(guid_string.substr(1, guid_string.length() - 2)); } -} // namespace guid +} // namespace base
diff --git a/base/i18n/string_compare.h b/base/i18n/string_compare.h index f0f3e29..158c93b 100644 --- a/base/i18n/string_compare.h +++ b/base/i18n/string_compare.h
@@ -25,4 +25,4 @@ } // namespace i18n } // namespace base -#endif // BASE_I18N_STRING_COMPARATOR_H_ +#endif // BASE_I18N_STRING_COMPARE_H_
diff --git a/base/i18n/timezone.h b/base/i18n/timezone.h index b7275f7..f7fda94 100644 --- a/base/i18n/timezone.h +++ b/base/i18n/timezone.h
@@ -18,4 +18,4 @@ } // namespace base -#endif // BASE_TIME_TIMEZONE_H_ +#endif // BASE_I18N_TIMEZONE_H_
diff --git a/base/json/BUILD.gn b/base/json/BUILD.gn new file mode 100644 index 0000000..0310ea9 --- /dev/null +++ b/base/json/BUILD.gn
@@ -0,0 +1,37 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("json") { + sources = [ + "json_file_value_serializer.cc", + "json_file_value_serializer.h", + "json_parser.cc", + "json_parser.h", + "json_reader.cc", + "json_reader.h", + "json_string_value_serializer.cc", + "json_string_value_serializer.h", + "json_value_converter.cc", + "json_value_converter.h", + "json_writer.cc", + "json_writer.h", + "string_escape.cc", + "string_escape.h", + ] + + if (is_nacl) { + sources -= [ + "json_file_value_serializer.cc", + "json_file_value_serializer.h", + ] + } + + defines = [ "BASE_IMPLEMENTATION" ] + + deps = [ + "//base/memory", + ] + + visibility = [ "//base/*" ] +}
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc index 225ee67..b8aebe0 100644 --- a/base/json/json_value_serializer_unittest.cc +++ b/base/json/json_value_serializer_unittest.cc
@@ -61,7 +61,7 @@ const char kLinuxLineEnds[] = "\n"; // Verifies the generated JSON against the expected output. -void CheckJSONIsStillTheSame(Value& value) { +void CheckJSONIsStillTheSame(const Value& value) { // Serialize back the output. std::string serialized_json; JSONStringValueSerializer str_serializer(&serialized_json);
diff --git a/base/mac/authorization_util.mm b/base/mac/authorization_util.mm index 003c26d..1dfd5a0 100644 --- a/base/mac/authorization_util.mm +++ b/base/mac/authorization_util.mm
@@ -28,10 +28,9 @@ AuthorizationFlags extraFlags) { // Create an empty AuthorizationRef. ScopedAuthorizationRef authorization; - OSStatus status = AuthorizationCreate(NULL, - kAuthorizationEmptyEnvironment, + OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, - &authorization); + authorization.get_pointer()); if (status != errAuthorizationSuccess) { OSSTATUS_LOG(ERROR, status) << "AuthorizationCreate"; return NULL;
diff --git a/base/mac/cocoa_protocols.h b/base/mac/cocoa_protocols.h index ab34a19..a28795c 100644 --- a/base/mac/cocoa_protocols.h +++ b/base/mac/cocoa_protocols.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_COCOA_PROTOCOLS_MAC_H_ -#define BASE_COCOA_PROTOCOLS_MAC_H_ +#ifndef BASE_MAC_COCOA_PROTOCOLS_H_ +#define BASE_MAC_COCOA_PROTOCOLS_H_ #import <Cocoa/Cocoa.h> @@ -28,4 +28,4 @@ #undef DEFINE_EMPTY_PROTOCOL -#endif // BASE_COCOA_PROTOCOLS_MAC_H_ +#endif // BASE_MAC_COCOA_PROTOCOLS_H_
diff --git a/base/mac/libdispatch_task_runner.h b/base/mac/libdispatch_task_runner.h index f5fd866..b479bc7 100644 --- a/base/mac/libdispatch_task_runner.h +++ b/base/mac/libdispatch_task_runner.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_MAC_LIBDISPATCH_SEQUENCED_TASK_RUNNER_H_ -#define BASE_MAC_LIBDISPATCH_SEQUENCED_TASK_RUNNER_H_ +#ifndef BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_ +#define BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_ #include <dispatch/dispatch.h> @@ -77,4 +77,4 @@ } // namespace mac } // namespace base -#endif // BASE_MAC_LIBDISPATCH_SEQUENCED_TASK_RUNNER_H_ +#endif // BASE_MAC_LIBDISPATCH_TASK_RUNNER_H_
diff --git a/base/mac/scoped_authorizationref.h b/base/mac/scoped_authorizationref.h index 6413f2e..1811488 100644 --- a/base/mac/scoped_authorizationref.h +++ b/base/mac/scoped_authorizationref.h
@@ -49,9 +49,7 @@ return authorization_; } - AuthorizationRef* operator&() { - return &authorization_; - } + AuthorizationRef* get_pointer() { return &authorization_; } AuthorizationRef get() const { return authorization_;
diff --git a/base/mac/scoped_mach_vm.cc b/base/mac/scoped_mach_vm.cc index 1c28d9c..d52c77f 100644 --- a/base/mac/scoped_mach_vm.cc +++ b/base/mac/scoped_mach_vm.cc
@@ -8,8 +8,8 @@ namespace mac { void ScopedMachVM::reset(vm_address_t address, vm_size_t size) { - DCHECK(address % PAGE_SIZE == 0); - DCHECK(size % PAGE_SIZE == 0); + DCHECK_EQ(address % PAGE_SIZE, 0u); + DCHECK_EQ(size % PAGE_SIZE, 0u); if (size_) { if (address_ < address) {
diff --git a/base/mac/scoped_mach_vm.h b/base/mac/scoped_mach_vm.h index b130a79..ffc00d5 100644 --- a/base/mac/scoped_mach_vm.h +++ b/base/mac/scoped_mach_vm.h
@@ -48,10 +48,9 @@ class BASE_EXPORT ScopedMachVM { public: explicit ScopedMachVM(vm_address_t address = 0, vm_size_t size = 0) - : address_(address), - size_(size) { - DCHECK(address % PAGE_SIZE == 0); - DCHECK(size % PAGE_SIZE == 0); + : address_(address), size_(size) { + DCHECK_EQ(address % PAGE_SIZE, 0u); + DCHECK_EQ(size % PAGE_SIZE, 0u); } ~ScopedMachVM() {
diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn new file mode 100644 index 0000000..5d016ff --- /dev/null +++ b/base/memory/BUILD.gn
@@ -0,0 +1,64 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("memory") { + sources = [ + "aligned_memory.cc", + "aligned_memory.h", + "discardable_memory.cc", + "discardable_memory.h", + "discardable_memory_android.cc", + "discardable_memory_linux.cc", + "discardable_memory_mac.cc", + "discardable_memory_shmem.cc", + "discardable_memory_shmem.h", + "discardable_memory_shmem_allocator.cc", + "discardable_memory_shmem_allocator.h", + "discardable_memory_win.cc", + "discardable_shared_memory.cc", + "discardable_shared_memory.h", + "linked_ptr.h", + "manual_constructor.h", + "memory_pressure_listener.cc", + "memory_pressure_listener.h", + "raw_scoped_refptr_mismatch_checker.h", + "ref_counted.cc", + "ref_counted.h", + "ref_counted_delete_on_message_loop.h", + "ref_counted_memory.cc", + "ref_counted_memory.h", + "scoped_policy.h", + "scoped_ptr.h", + "scoped_vector.h", + "shared_memory.h", + "shared_memory_android.cc", + "shared_memory_nacl.cc", + "shared_memory_posix.cc", + "shared_memory_win.cc", + "singleton.cc", + "singleton.h", + "weak_ptr.cc", + "weak_ptr.h", + ] + + if (is_nacl) { + sources -= [ + "discardable_memory.cc", + "discardable_memory.h", + "discardable_memory_shmem.cc", + "discardable_memory_shmem.h", + "discardable_memory_shmem_allocator.cc", + "discardable_memory_shmem_allocator.h", + "discardable_shared_memory.cc", + "discardable_shared_memory.h", + "shared_memory_posix.cc", + ] + } else { + sources -= [ "shared_memory_nacl.cc" ] + } + + defines = [ "BASE_IMPLEMENTATION" ] + + visibility = [ "//base/*" ] +}
diff --git a/base/memory/discardable_memory.cc b/base/memory/discardable_memory.cc index 3d82f91..7d19f9a 100644 --- a/base/memory/discardable_memory.cc +++ b/base/memory/discardable_memory.cc
@@ -14,9 +14,6 @@ DiscardableMemoryType type; const char* name; } kTypeNamePairs[] = { - { DISCARDABLE_MEMORY_TYPE_ASHMEM, "ashmem" }, - { DISCARDABLE_MEMORY_TYPE_MACH, "mach" }, - { DISCARDABLE_MEMORY_TYPE_EMULATED, "emulated" }, { DISCARDABLE_MEMORY_TYPE_SHMEM, "shmem" } };
diff --git a/base/memory/discardable_memory.h b/base/memory/discardable_memory.h index c49a99f..4e5a9af 100644 --- a/base/memory/discardable_memory.h +++ b/base/memory/discardable_memory.h
@@ -17,18 +17,9 @@ enum DiscardableMemoryType { DISCARDABLE_MEMORY_TYPE_NONE, - DISCARDABLE_MEMORY_TYPE_ASHMEM, - DISCARDABLE_MEMORY_TYPE_MACH, - DISCARDABLE_MEMORY_TYPE_EMULATED, DISCARDABLE_MEMORY_TYPE_SHMEM }; -enum DiscardableMemoryLockStatus { - DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, - DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, - DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS -}; - // Platform abstraction for discardable memory. DiscardableMemory is used to // cache large objects without worrying about blowing out memory, both on mobile // devices where there is no swap, and desktop devices where unused free memory @@ -89,23 +80,10 @@ // Create a DiscardableMemory instance with preferred type and |size|. static scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size); - // Discardable memory implementations might allow an elevated usage level - // while in frequent use. Call this to have the usage reduced to the base - // level. Returns true if there's no need to call this again until - // memory instances have been used. This indicates that all discardable - // memory implementations have reduced usage to the base level or below. - // Note: calling this too often or while discardable memory is in frequent - // use can hurt performance, whereas calling it too infrequently can result - // in memory bloat. - static bool ReduceMemoryUsage(); - // Locks the memory so that it will not be purged by the system. Returns - // DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS on success. If the return value is - // DISCARDABLE_MEMORY_LOCK_STATUS_FAILED then this object should be - // discarded and a new one should be created. If the return value is - // DISCARDABLE_MEMORY_LOCK_STATUS_PURGED then the memory is present but any - // data that was in it is gone. - virtual DiscardableMemoryLockStatus Lock() WARN_UNUSED_RESULT = 0; + // true on success. If the return value is false then this object should be + // discarded and a new one should be created. + virtual bool Lock() WARN_UNUSED_RESULT = 0; // Unlocks the memory so that it can be purged by the system. Must be called // after every successful lock call.
diff --git a/base/memory/discardable_memory_android.cc b/base/memory/discardable_memory_android.cc index 2b35587..a36f54e 100644 --- a/base/memory/discardable_memory_android.cc +++ b/base/memory/discardable_memory_android.cc
@@ -4,57 +4,16 @@ #include "base/memory/discardable_memory.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/lazy_instance.h" #include "base/logging.h" -#include "base/memory/discardable_memory_ashmem.h" -#include "base/memory/discardable_memory_ashmem_allocator.h" -#include "base/memory/discardable_memory_emulated.h" #include "base/memory/discardable_memory_shmem.h" -#include "base/sys_info.h" namespace base { -namespace { - -const char kAshmemAllocatorName[] = "DiscardableMemoryAshmemAllocator"; - -// For Ashmem, have the DiscardableMemoryManager trigger userspace eviction -// when address space usage gets too high (e.g. 512 MBytes). -const size_t kAshmemMemoryLimit = 512 * 1024 * 1024; - -size_t GetOptimalAshmemRegionSizeForAllocator() { - // Note that this may do some I/O (without hitting the disk though) so it - // should not be called on the critical path. - return base::SysInfo::AmountOfPhysicalMemory() / 8; -} - -// Holds the shared state used for allocations. -struct SharedState { - SharedState() - : manager(kAshmemMemoryLimit, kAshmemMemoryLimit, TimeDelta::Max()), - allocator(kAshmemAllocatorName, - GetOptimalAshmemRegionSizeForAllocator()) {} - - internal::DiscardableMemoryManager manager; - internal::DiscardableMemoryAshmemAllocator allocator; -}; -LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -// static -bool DiscardableMemory::ReduceMemoryUsage() { - return internal::DiscardableMemoryEmulated::ReduceMemoryUsage(); -} // static void DiscardableMemory::GetSupportedTypes( std::vector<DiscardableMemoryType>* types) { const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM, - DISCARDABLE_MEMORY_TYPE_ASHMEM, - DISCARDABLE_MEMORY_TYPE_EMULATED + DISCARDABLE_MEMORY_TYPE_SHMEM }; types->assign(supported_types, supported_types + arraysize(supported_types)); } @@ -63,34 +22,9 @@ scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( DiscardableMemoryType type, size_t size) { switch (type) { - case DISCARDABLE_MEMORY_TYPE_ASHMEM: { - SharedState* const shared_state = g_shared_state.Pointer(); - scoped_ptr<internal::DiscardableMemoryAshmem> memory( - new internal::DiscardableMemoryAshmem( - size, &shared_state->allocator, &shared_state->manager)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } - case DISCARDABLE_MEMORY_TYPE_EMULATED: { - scoped_ptr<internal::DiscardableMemoryEmulated> memory( - new internal::DiscardableMemoryEmulated(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } - case DISCARDABLE_MEMORY_TYPE_SHMEM: { - scoped_ptr<internal::DiscardableMemoryShmem> memory( - new internal::DiscardableMemoryShmem(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } + case DISCARDABLE_MEMORY_TYPE_SHMEM: + return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); case DISCARDABLE_MEMORY_TYPE_NONE: - case DISCARDABLE_MEMORY_TYPE_MACH: NOTREACHED(); return nullptr; }
diff --git a/base/memory/discardable_memory_ashmem.cc b/base/memory/discardable_memory_ashmem.cc deleted file mode 100644 index a590e53..0000000 --- a/base/memory/discardable_memory_ashmem.cc +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_ashmem.h" - -#include "base/memory/discardable_memory_ashmem_allocator.h" - -namespace base { -namespace internal { - -DiscardableMemoryAshmem::DiscardableMemoryAshmem( - size_t bytes, - DiscardableMemoryAshmemAllocator* allocator, - DiscardableMemoryManager* manager) - : bytes_(bytes), - allocator_(allocator), - manager_(manager), - is_locked_(false) { - manager_->Register(this, bytes_); -} - -DiscardableMemoryAshmem::~DiscardableMemoryAshmem() { - if (is_locked_) - Unlock(); - - manager_->Unregister(this); -} - -bool DiscardableMemoryAshmem::Initialize() { - return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; -} - -DiscardableMemoryLockStatus DiscardableMemoryAshmem::Lock() { - DCHECK(!is_locked_); - - bool purged = false; - if (!manager_->AcquireLock(this, &purged)) - return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; - - is_locked_ = true; - return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED - : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; -} - -void DiscardableMemoryAshmem::Unlock() { - DCHECK(is_locked_); - manager_->ReleaseLock(this); - is_locked_ = false; -} - -void* DiscardableMemoryAshmem::Memory() const { - DCHECK(is_locked_); - DCHECK(ashmem_chunk_); - return ashmem_chunk_->Memory(); -} - -bool DiscardableMemoryAshmem::AllocateAndAcquireLock() { - if (ashmem_chunk_) - return ashmem_chunk_->Lock(); - - ashmem_chunk_ = allocator_->Allocate(bytes_); - return false; -} - -void DiscardableMemoryAshmem::ReleaseLock() { - ashmem_chunk_->Unlock(); -} - -void DiscardableMemoryAshmem::Purge() { - ashmem_chunk_.reset(); -} - -} // namespace internal -} // namespace base
diff --git a/base/memory/discardable_memory_ashmem.h b/base/memory/discardable_memory_ashmem.h deleted file mode 100644 index 1269cc2..0000000 --- a/base/memory/discardable_memory_ashmem.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_H_ - -#include "base/memory/discardable_memory.h" - -#include "base/macros.h" -#include "base/memory/discardable_memory_manager.h" - -namespace base { -namespace internal { - -class DiscardableAshmemChunk; -class DiscardableMemoryAshmemAllocator; -class DiscardableMemoryManager; - -class DiscardableMemoryAshmem - : public DiscardableMemory, - public internal::DiscardableMemoryManagerAllocation { - public: - explicit DiscardableMemoryAshmem(size_t bytes, - DiscardableMemoryAshmemAllocator* allocator, - DiscardableMemoryManager* manager); - - ~DiscardableMemoryAshmem() override; - - bool Initialize(); - - // Overridden from DiscardableMemory: - DiscardableMemoryLockStatus Lock() override; - void Unlock() override; - void* Memory() const override; - - // Overridden from internal::DiscardableMemoryManagerAllocation: - bool AllocateAndAcquireLock() override; - void ReleaseLock() override; - void Purge() override; - - private: - const size_t bytes_; - DiscardableMemoryAshmemAllocator* const allocator_; - DiscardableMemoryManager* const manager_; - bool is_locked_; - scoped_ptr<DiscardableAshmemChunk> ashmem_chunk_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryAshmem); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_H_
diff --git a/base/memory/discardable_memory_ashmem_allocator.cc b/base/memory/discardable_memory_ashmem_allocator.cc deleted file mode 100644 index 3d4af92..0000000 --- a/base/memory/discardable_memory_ashmem_allocator.cc +++ /dev/null
@@ -1,528 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_ashmem_allocator.h" - -#include <sys/mman.h> -#include <unistd.h> - -#include <algorithm> -#include <cmath> -#include <limits> -#include <set> -#include <utility> - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "base/memory/scoped_vector.h" -#include "third_party/ashmem/ashmem.h" - -// The allocator consists of three parts (classes): -// - DiscardableMemoryAshmemAllocator: entry point of all allocations (through -// its Allocate() method) that are dispatched to the AshmemRegion instances -// (which it owns). -// - AshmemRegion: manages allocations and destructions inside a single large -// (e.g. 32 MBytes) ashmem region. -// - DiscardableAshmemChunk: class mimicking the DiscardableMemory interface -// whose instances are returned to the client. - -namespace base { -namespace { - -// Only tolerate fragmentation in used chunks *caused by the client* (as opposed -// to the allocator when a free chunk is reused). The client can cause such -// fragmentation by e.g. requesting 4097 bytes. This size would be rounded up to -// 8192 by the allocator which would cause 4095 bytes of fragmentation (which is -// currently the maximum allowed). If the client requests 4096 bytes and a free -// chunk of 8192 bytes is available then the free chunk gets splitted into two -// pieces to minimize fragmentation (since 8192 - 4096 = 4096 which is greater -// than 4095). -// TODO(pliard): tune this if splitting chunks too often leads to performance -// issues. -const size_t kMaxChunkFragmentationBytes = 4096 - 1; - -const size_t kMinAshmemRegionSize = 32 * 1024 * 1024; - -// Returns 0 if the provided size is too high to be aligned. -size_t AlignToNextPage(size_t size) { - const size_t kPageSize = 4096; - DCHECK_EQ(static_cast<int>(kPageSize), getpagesize()); - if (size > std::numeric_limits<size_t>::max() - kPageSize + 1) - return 0; - const size_t mask = ~(kPageSize - 1); - return (size + kPageSize - 1) & mask; -} - -bool CreateAshmemRegion(const char* name, - size_t size, - int* out_fd, - uintptr_t* out_address) { - base::ScopedFD fd(ashmem_create_region(name, size)); - if (!fd.is_valid()) { - DLOG(ERROR) << "ashmem_create_region() failed"; - return false; - } - - const int err = ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE); - if (err < 0) { - DLOG(ERROR) << "Error " << err << " when setting protection of ashmem"; - return false; - } - - // There is a problem using MAP_PRIVATE here. As we are constantly calling - // Lock() and Unlock(), data could get lost if they are not written to the - // underlying file when Unlock() gets called. - void* const address = mmap( - NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0); - if (address == MAP_FAILED) { - DPLOG(ERROR) << "Failed to map memory."; - return false; - } - - *out_fd = fd.release(); - *out_address = reinterpret_cast<uintptr_t>(address); - return true; -} - -bool CloseAshmemRegion(int fd, size_t size, void* address) { - if (munmap(address, size) == -1) { - DPLOG(ERROR) << "Failed to unmap memory."; - close(fd); - return false; - } - return close(fd) == 0; -} - -bool LockAshmemRegion(int fd, size_t off, size_t size) { - return ashmem_pin_region(fd, off, size) != ASHMEM_WAS_PURGED; -} - -bool UnlockAshmemRegion(int fd, size_t off, size_t size) { - const int failed = ashmem_unpin_region(fd, off, size); - if (failed) - DLOG(ERROR) << "Failed to unpin memory."; - return !failed; -} - -} // namespace - -namespace internal { - -class AshmemRegion { - public: - // Note that |allocator| must outlive |this|. - static scoped_ptr<AshmemRegion> Create( - size_t size, - const std::string& name, - DiscardableMemoryAshmemAllocator* allocator) { - DCHECK_EQ(size, AlignToNextPage(size)); - int fd; - uintptr_t base; - if (!CreateAshmemRegion(name.c_str(), size, &fd, &base)) - return scoped_ptr<AshmemRegion>(); - return make_scoped_ptr(new AshmemRegion(fd, size, base, allocator)); - } - - ~AshmemRegion() { - const bool result = CloseAshmemRegion( - fd_, size_, reinterpret_cast<void*>(base_)); - DCHECK(result); - DCHECK(!highest_allocated_chunk_); - } - - // Returns a new instance of DiscardableAshmemChunk whose size is greater or - // equal than |actual_size| (which is expected to be greater or equal than - // |client_requested_size|). - // Allocation works as follows: - // 1) Reuse a previously freed chunk and return it if it succeeded. See - // ReuseFreeChunk_Locked() below for more information. - // 2) If no free chunk could be reused and the region is not big enough for - // the requested size then NULL is returned. - // 3) If there is enough room in the ashmem region then a new chunk is - // returned. This new chunk starts at |offset_| which is the end of the - // previously highest chunk in the region. - scoped_ptr<DiscardableAshmemChunk> Allocate_Locked( - size_t client_requested_size, - size_t actual_size) { - DCHECK_LE(client_requested_size, actual_size); - allocator_->lock_.AssertAcquired(); - - // Check that the |highest_allocated_chunk_| field doesn't contain a stale - // pointer. It should point to either a free chunk or a used chunk. - DCHECK(!highest_allocated_chunk_ || - address_to_free_chunk_map_.find(highest_allocated_chunk_) != - address_to_free_chunk_map_.end() || - used_to_previous_chunk_map_.find(highest_allocated_chunk_) != - used_to_previous_chunk_map_.end()); - - scoped_ptr<DiscardableAshmemChunk> memory = ReuseFreeChunk_Locked( - client_requested_size, actual_size); - if (memory) - return memory.Pass(); - - if (size_ - offset_ < actual_size) { - // This region does not have enough space left to hold the requested size. - return scoped_ptr<DiscardableAshmemChunk>(); - } - - uintptr_t const address = base_ + offset_; - memory.reset( - new DiscardableAshmemChunk(this, fd_, reinterpret_cast<void*>(address), - offset_, actual_size)); - - used_to_previous_chunk_map_.insert( - std::make_pair(address, highest_allocated_chunk_)); - highest_allocated_chunk_ = reinterpret_cast<uintptr_t>(address); - offset_ += actual_size; - DCHECK_LE(offset_, size_); - return memory.Pass(); - } - - void OnChunkDeletion(uintptr_t chunk, size_t size) { - AutoLock auto_lock(allocator_->lock_); - MergeAndAddFreeChunk_Locked(chunk, size); - // Note that |this| might be deleted beyond this point. - } - - private: - struct FreeChunk { - FreeChunk() : previous_chunk(0), start(0), size(0) {} - - explicit FreeChunk(size_t size) - : previous_chunk(0), - start(0), - size(size) { - } - - FreeChunk(uintptr_t previous_chunk, uintptr_t start, size_t size) - : previous_chunk(previous_chunk), - start(start), - size(size) { - DCHECK_LT(previous_chunk, start); - } - - uintptr_t const previous_chunk; - uintptr_t const start; - const size_t size; - - bool is_null() const { return !start; } - - bool operator<(const FreeChunk& other) const { - return size < other.size; - } - }; - - // Note that |allocator| must outlive |this|. - AshmemRegion(int fd, - size_t size, - uintptr_t base, - DiscardableMemoryAshmemAllocator* allocator) - : fd_(fd), - size_(size), - base_(base), - allocator_(allocator), - highest_allocated_chunk_(0), - offset_(0) { - DCHECK_GE(fd_, 0); - DCHECK_GE(size, kMinAshmemRegionSize); - DCHECK(base); - DCHECK(allocator); - } - - // Tries to reuse a previously freed chunk by doing a closest size match. - scoped_ptr<DiscardableAshmemChunk> ReuseFreeChunk_Locked( - size_t client_requested_size, - size_t actual_size) { - allocator_->lock_.AssertAcquired(); - const FreeChunk reused_chunk = RemoveFreeChunkFromIterator_Locked( - free_chunks_.lower_bound(FreeChunk(actual_size))); - if (reused_chunk.is_null()) - return scoped_ptr<DiscardableAshmemChunk>(); - - used_to_previous_chunk_map_.insert( - std::make_pair(reused_chunk.start, reused_chunk.previous_chunk)); - size_t reused_chunk_size = reused_chunk.size; - // |client_requested_size| is used below rather than |actual_size| to - // reflect the amount of bytes that would not be usable by the client (i.e. - // wasted). Using |actual_size| instead would not allow us to detect - // fragmentation caused by the client if he did misaligned allocations. - DCHECK_GE(reused_chunk.size, client_requested_size); - const size_t fragmentation_bytes = - reused_chunk.size - client_requested_size; - - if (fragmentation_bytes > kMaxChunkFragmentationBytes) { - // Split the free chunk being recycled so that its unused tail doesn't get - // reused (i.e. locked) which would prevent it from being evicted under - // memory pressure. - reused_chunk_size = actual_size; - uintptr_t const new_chunk_start = reused_chunk.start + actual_size; - if (reused_chunk.start == highest_allocated_chunk_) { - // We also need to update the pointer to the highest allocated chunk in - // case we are splitting the highest chunk. - highest_allocated_chunk_ = new_chunk_start; - } - DCHECK_GT(reused_chunk.size, actual_size); - const size_t new_chunk_size = reused_chunk.size - actual_size; - // Note that merging is not needed here since there can't be contiguous - // free chunks at this point. - AddFreeChunk_Locked( - FreeChunk(reused_chunk.start, new_chunk_start, new_chunk_size)); - } - - const size_t offset = reused_chunk.start - base_; - LockAshmemRegion(fd_, offset, reused_chunk_size); - scoped_ptr<DiscardableAshmemChunk> memory( - new DiscardableAshmemChunk(this, fd_, - reinterpret_cast<void*>(reused_chunk.start), - offset, reused_chunk_size)); - return memory.Pass(); - } - - // Makes the chunk identified with the provided arguments free and possibly - // merges this chunk with the previous and next contiguous ones. - // If the provided chunk is the only one used (and going to be freed) in the - // region then the internal ashmem region is closed so that the underlying - // physical pages are immediately released. - // Note that free chunks are unlocked therefore they can be reclaimed by the - // kernel if needed (under memory pressure) but they are not immediately - // released unfortunately since madvise(MADV_REMOVE) and - // fallocate(FALLOC_FL_PUNCH_HOLE) don't seem to work on ashmem. This might - // change in versions of kernel >=3.5 though. The fact that free chunks are - // not immediately released is the reason why we are trying to minimize - // fragmentation in order not to cause "artificial" memory pressure. - void MergeAndAddFreeChunk_Locked(uintptr_t chunk, size_t size) { - allocator_->lock_.AssertAcquired(); - size_t new_free_chunk_size = size; - // Merge with the previous chunk. - uintptr_t first_free_chunk = chunk; - DCHECK(!used_to_previous_chunk_map_.empty()); - const hash_map<uintptr_t, uintptr_t>::iterator previous_chunk_it = - used_to_previous_chunk_map_.find(chunk); - DCHECK(previous_chunk_it != used_to_previous_chunk_map_.end()); - uintptr_t previous_chunk = previous_chunk_it->second; - used_to_previous_chunk_map_.erase(previous_chunk_it); - - if (previous_chunk) { - const FreeChunk free_chunk = RemoveFreeChunk_Locked(previous_chunk); - if (!free_chunk.is_null()) { - new_free_chunk_size += free_chunk.size; - first_free_chunk = previous_chunk; - if (chunk == highest_allocated_chunk_) - highest_allocated_chunk_ = previous_chunk; - - // There should not be more contiguous previous free chunks. - previous_chunk = free_chunk.previous_chunk; - DCHECK(!address_to_free_chunk_map_.count(previous_chunk)); - } - } - - // Merge with the next chunk if free and present. - uintptr_t next_chunk = chunk + size; - const FreeChunk next_free_chunk = RemoveFreeChunk_Locked(next_chunk); - if (!next_free_chunk.is_null()) { - new_free_chunk_size += next_free_chunk.size; - if (next_free_chunk.start == highest_allocated_chunk_) - highest_allocated_chunk_ = first_free_chunk; - - // Same as above. - DCHECK( - !address_to_free_chunk_map_.count(next_chunk + next_free_chunk.size)); - } - - const bool whole_ashmem_region_is_free = - used_to_previous_chunk_map_.empty(); - if (!whole_ashmem_region_is_free) { - AddFreeChunk_Locked( - FreeChunk(previous_chunk, first_free_chunk, new_free_chunk_size)); - return; - } - - // The whole ashmem region is free thus it can be deleted. - DCHECK_EQ(base_, first_free_chunk); - DCHECK_EQ(base_, highest_allocated_chunk_); - DCHECK(free_chunks_.empty()); - DCHECK(address_to_free_chunk_map_.empty()); - DCHECK(used_to_previous_chunk_map_.empty()); - highest_allocated_chunk_ = 0; - allocator_->DeleteAshmemRegion_Locked(this); // Deletes |this|. - } - - void AddFreeChunk_Locked(const FreeChunk& free_chunk) { - allocator_->lock_.AssertAcquired(); - const std::multiset<FreeChunk>::iterator it = free_chunks_.insert( - free_chunk); - address_to_free_chunk_map_.insert(std::make_pair(free_chunk.start, it)); - // Update the next used contiguous chunk, if any, since its previous chunk - // may have changed due to free chunks merging/splitting. - uintptr_t const next_used_contiguous_chunk = - free_chunk.start + free_chunk.size; - hash_map<uintptr_t, uintptr_t>::iterator previous_it = - used_to_previous_chunk_map_.find(next_used_contiguous_chunk); - if (previous_it != used_to_previous_chunk_map_.end()) - previous_it->second = free_chunk.start; - } - - // Finds and removes the free chunk, if any, whose start address is - // |chunk_start|. Returns a copy of the unlinked free chunk or a free chunk - // whose content is null if it was not found. - FreeChunk RemoveFreeChunk_Locked(uintptr_t chunk_start) { - allocator_->lock_.AssertAcquired(); - const hash_map< - uintptr_t, std::multiset<FreeChunk>::iterator>::iterator it = - address_to_free_chunk_map_.find(chunk_start); - if (it == address_to_free_chunk_map_.end()) - return FreeChunk(); - return RemoveFreeChunkFromIterator_Locked(it->second); - } - - // Same as above but takes an iterator in. - FreeChunk RemoveFreeChunkFromIterator_Locked( - std::multiset<FreeChunk>::iterator free_chunk_it) { - allocator_->lock_.AssertAcquired(); - if (free_chunk_it == free_chunks_.end()) - return FreeChunk(); - DCHECK(free_chunk_it != free_chunks_.end()); - const FreeChunk free_chunk(*free_chunk_it); - address_to_free_chunk_map_.erase(free_chunk_it->start); - free_chunks_.erase(free_chunk_it); - return free_chunk; - } - - const int fd_; - const size_t size_; - uintptr_t const base_; - DiscardableMemoryAshmemAllocator* const allocator_; - // Points to the chunk with the highest address in the region. This pointer - // needs to be carefully updated when chunks are merged/split. - uintptr_t highest_allocated_chunk_; - // Points to the end of |highest_allocated_chunk_|. - size_t offset_; - // Allows free chunks recycling (lookup, insertion and removal) in O(log N). - // Note that FreeChunk values are indexed by their size and also note that - // multiple free chunks can have the same size (which is why multiset<> is - // used instead of e.g. set<>). - std::multiset<FreeChunk> free_chunks_; - // Used while merging free contiguous chunks to erase free chunks (from their - // start address) in constant time. Note that multiset<>::{insert,erase}() - // don't invalidate iterators (except the one for the element being removed - // obviously). - hash_map< - uintptr_t, std::multiset<FreeChunk>::iterator> address_to_free_chunk_map_; - // Maps the address of *used* chunks to the address of their previous - // contiguous chunk. - hash_map<uintptr_t, uintptr_t> used_to_previous_chunk_map_; - - DISALLOW_COPY_AND_ASSIGN(AshmemRegion); -}; - -DiscardableAshmemChunk::~DiscardableAshmemChunk() { - if (locked_) - UnlockAshmemRegion(fd_, offset_, size_); - ashmem_region_->OnChunkDeletion(reinterpret_cast<uintptr_t>(address_), size_); -} - -bool DiscardableAshmemChunk::Lock() { - DCHECK(!locked_); - locked_ = true; - return LockAshmemRegion(fd_, offset_, size_); -} - -void DiscardableAshmemChunk::Unlock() { - DCHECK(locked_); - locked_ = false; - UnlockAshmemRegion(fd_, offset_, size_); -} - -void* DiscardableAshmemChunk::Memory() const { - return address_; -} - -// Note that |ashmem_region| must outlive |this|. -DiscardableAshmemChunk::DiscardableAshmemChunk(AshmemRegion* ashmem_region, - int fd, - void* address, - size_t offset, - size_t size) - : ashmem_region_(ashmem_region), - fd_(fd), - address_(address), - offset_(offset), - size_(size), - locked_(true) { -} - -DiscardableMemoryAshmemAllocator::DiscardableMemoryAshmemAllocator( - const std::string& name, - size_t ashmem_region_size) - : name_(name), - ashmem_region_size_( - std::max(kMinAshmemRegionSize, AlignToNextPage(ashmem_region_size))), - last_ashmem_region_size_(0) { - DCHECK_GE(ashmem_region_size_, kMinAshmemRegionSize); -} - -DiscardableMemoryAshmemAllocator::~DiscardableMemoryAshmemAllocator() { - DCHECK(ashmem_regions_.empty()); -} - -scoped_ptr<DiscardableAshmemChunk> DiscardableMemoryAshmemAllocator::Allocate( - size_t size) { - const size_t aligned_size = AlignToNextPage(size); - if (!aligned_size) - return scoped_ptr<DiscardableAshmemChunk>(); - // TODO(pliard): make this function less naive by e.g. moving the free chunks - // multiset to the allocator itself in order to decrease even more - // fragmentation/speedup allocation. Note that there should not be more than a - // couple (=5) of AshmemRegion instances in practice though. - AutoLock auto_lock(lock_); - DCHECK_LE(ashmem_regions_.size(), 5U); - for (ScopedVector<AshmemRegion>::iterator it = ashmem_regions_.begin(); - it != ashmem_regions_.end(); ++it) { - scoped_ptr<DiscardableAshmemChunk> memory( - (*it)->Allocate_Locked(size, aligned_size)); - if (memory) - return memory.Pass(); - } - // The creation of the (large) ashmem region might fail if the address space - // is too fragmented. In case creation fails the allocator retries by - // repetitively dividing the size by 2. - const size_t min_region_size = std::max(kMinAshmemRegionSize, aligned_size); - for (size_t region_size = std::max(ashmem_region_size_, aligned_size); - region_size >= min_region_size; - region_size = AlignToNextPage(region_size / 2)) { - scoped_ptr<AshmemRegion> new_region( - AshmemRegion::Create(region_size, name_.c_str(), this)); - if (!new_region) - continue; - last_ashmem_region_size_ = region_size; - ashmem_regions_.push_back(new_region.release()); - return ashmem_regions_.back()->Allocate_Locked(size, aligned_size); - } - // TODO(pliard): consider adding an histogram to see how often this happens. - return scoped_ptr<DiscardableAshmemChunk>(); -} - -size_t DiscardableMemoryAshmemAllocator::last_ashmem_region_size() const { - AutoLock auto_lock(lock_); - return last_ashmem_region_size_; -} - -void DiscardableMemoryAshmemAllocator::DeleteAshmemRegion_Locked( - AshmemRegion* region) { - lock_.AssertAcquired(); - // Note that there should not be more than a couple of ashmem region instances - // in |ashmem_regions_|. - DCHECK_LE(ashmem_regions_.size(), 5U); - const ScopedVector<AshmemRegion>::iterator it = std::find( - ashmem_regions_.begin(), ashmem_regions_.end(), region); - DCHECK(ashmem_regions_.end() != it); - std::swap(*it, ashmem_regions_.back()); - ashmem_regions_.pop_back(); -} - -} // namespace internal -} // namespace base
diff --git a/base/memory/discardable_memory_ashmem_allocator.h b/base/memory/discardable_memory_ashmem_allocator.h deleted file mode 100644 index 996dde9..0000000 --- a/base/memory/discardable_memory_ashmem_allocator.h +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_ - -#include <string> - -#include "base/base_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/synchronization/lock.h" - -namespace base { -namespace internal { - -class AshmemRegion; - -// Internal class, whose instances are returned to the client of the allocator -// (e.g. DiscardableMemoryAshmem), that mimicks the DiscardableMemory interface. -class BASE_EXPORT_PRIVATE DiscardableAshmemChunk { - public: - ~DiscardableAshmemChunk(); - - // Returns whether the memory is still resident. - bool Lock(); - - void Unlock(); - - void* Memory() const; - - private: - friend class AshmemRegion; - - DiscardableAshmemChunk(AshmemRegion* ashmem_region, - int fd, - void* address, - size_t offset, - size_t size); - - AshmemRegion* const ashmem_region_; - const int fd_; - void* const address_; - const size_t offset_; - const size_t size_; - bool locked_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableAshmemChunk); -}; - -// Ashmem regions are backed by a file (descriptor) therefore they are a limited -// resource. This allocator minimizes the problem by allocating large ashmem -// regions internally and returning smaller chunks to the client. -// Allocated chunks are systematically aligned on a page boundary therefore this -// allocator should not be used for small allocations. -class BASE_EXPORT_PRIVATE DiscardableMemoryAshmemAllocator { - public: - // Note that |name| is only used for debugging/measurement purposes. - // |ashmem_region_size| is the size that will be used to create the underlying - // ashmem regions and is expected to be greater or equal than 32 MBytes. - DiscardableMemoryAshmemAllocator(const std::string& name, - size_t ashmem_region_size); - - ~DiscardableMemoryAshmemAllocator(); - - // Note that the allocator must outlive the returned DiscardableAshmemChunk - // instance. - scoped_ptr<DiscardableAshmemChunk> Allocate(size_t size); - - // Returns the size of the last ashmem region which was created. This is used - // for testing only. - size_t last_ashmem_region_size() const; - - private: - friend class AshmemRegion; - - void DeleteAshmemRegion_Locked(AshmemRegion* region); - - const std::string name_; - const size_t ashmem_region_size_; - mutable Lock lock_; - size_t last_ashmem_region_size_; - ScopedVector<AshmemRegion> ashmem_regions_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryAshmemAllocator); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_
diff --git a/base/memory/discardable_memory_ashmem_allocator_unittest.cc b/base/memory/discardable_memory_ashmem_allocator_unittest.cc deleted file mode 100644 index e9f63ba..0000000 --- a/base/memory/discardable_memory_ashmem_allocator_unittest.cc +++ /dev/null
@@ -1,319 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_ashmem_allocator.h" - -#include <sys/types.h> -#include <unistd.h> - -#include "base/memory/discardable_memory.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/stringprintf.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace internal { - -const char kAllocatorName[] = "allocator-for-testing"; - -const size_t kAshmemRegionSizeForTesting = 32 * 1024 * 1024; -const size_t kPageSize = 4096; - -const size_t kMaxAllowedAllocationSize = - std::numeric_limits<size_t>::max() - kPageSize + 1; - -class DiscardableMemoryAshmemAllocatorTest : public testing::Test { - protected: - DiscardableMemoryAshmemAllocatorTest() - : allocator_(kAllocatorName, kAshmemRegionSizeForTesting) { - } - - DiscardableMemoryAshmemAllocator allocator_; -}; - -void WriteToDiscardableAshmemChunk(DiscardableAshmemChunk* memory, - size_t size) { - // Write to the first and the last pages only to avoid paging in up to 64 - // MBytes. - static_cast<char*>(memory->Memory())[0] = 'a'; - static_cast<char*>(memory->Memory())[size - 1] = 'a'; -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, Basic) { - const size_t size = 128; - scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(size)); - ASSERT_TRUE(memory); - WriteToDiscardableAshmemChunk(memory.get(), size); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, ZeroAllocationIsNotSupported) { - scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(0)); - ASSERT_FALSE(memory); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, TooLargeAllocationFails) { - scoped_ptr<DiscardableAshmemChunk> memory( - allocator_.Allocate(kMaxAllowedAllocationSize + 1)); - // Page-alignment would have caused an overflow resulting in a small - // allocation if the input size wasn't checked correctly. - ASSERT_FALSE(memory); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, - AshmemRegionsAreNotSmallerThanRequestedSize) { - // The creation of the underlying ashmem region is expected to fail since - // there should not be enough room in the address space. When ashmem creation - // fails, the allocator repetitively retries by dividing the size by 2. This - // size should not be smaller than the size the user requested so the - // allocation here should just fail (and not succeed with the minimum ashmem - // region size). - scoped_ptr<DiscardableAshmemChunk> memory( - allocator_.Allocate(kMaxAllowedAllocationSize)); - ASSERT_FALSE(memory); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, - AshmemRegionsAreAlwaysPageAligned) { - // Use a separate allocator here so that we can override the ashmem region - // size. - DiscardableMemoryAshmemAllocator allocator( - kAllocatorName, kMaxAllowedAllocationSize); - scoped_ptr<DiscardableAshmemChunk> memory(allocator.Allocate(kPageSize)); - ASSERT_TRUE(memory); - EXPECT_GT(kMaxAllowedAllocationSize, allocator.last_ashmem_region_size()); - ASSERT_TRUE(allocator.last_ashmem_region_size() % kPageSize == 0); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, LargeAllocation) { - const size_t size = 64 * 1024 * 1024; - scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(size)); - ASSERT_TRUE(memory); - WriteToDiscardableAshmemChunk(memory.get(), size); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, ChunksArePageAligned) { - scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory); - EXPECT_EQ(0U, reinterpret_cast<uint64_t>(memory->Memory()) % kPageSize); - WriteToDiscardableAshmemChunk(memory.get(), kPageSize); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, AllocateFreeAllocate) { - scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(kPageSize)); - // Extra allocation that prevents the region from being deleted when |memory| - // gets deleted. - scoped_ptr<DiscardableAshmemChunk> memory_lock( - allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory); - void* const address = memory->Memory(); - memory->Unlock(); // Tests that the reused chunk is being locked correctly. - memory.reset(); - memory = allocator_.Allocate(kPageSize); - ASSERT_TRUE(memory); - // The previously freed chunk should be reused. - EXPECT_EQ(address, memory->Memory()); - WriteToDiscardableAshmemChunk(memory.get(), kPageSize); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, - FreeingWholeAshmemRegionClosesAshmem) { - scoped_ptr<DiscardableAshmemChunk> memory(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory); - const int kMagic = 0xdeadbeef; - *static_cast<int*>(memory->Memory()) = kMagic; - memory.reset(); - // The previous ashmem region should have been closed thus it should not be - // reused. - memory = allocator_.Allocate(kPageSize); - ASSERT_TRUE(memory); - EXPECT_NE(kMagic, *static_cast<const int*>(memory->Memory())); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, AllocateUsesBestFitAlgorithm) { - scoped_ptr<DiscardableAshmemChunk> memory1( - allocator_.Allocate(3 * kPageSize)); - ASSERT_TRUE(memory1); - scoped_ptr<DiscardableAshmemChunk> memory2( - allocator_.Allocate(2 * kPageSize)); - ASSERT_TRUE(memory2); - scoped_ptr<DiscardableAshmemChunk> memory3( - allocator_.Allocate(1 * kPageSize)); - ASSERT_TRUE(memory3); - void* const address_3 = memory3->Memory(); - memory1.reset(); - // Don't free |memory2| to avoid merging the 3 blocks together. - memory3.reset(); - memory1 = allocator_.Allocate(1 * kPageSize); - ASSERT_TRUE(memory1); - // The chunk whose size is closest to the requested size should be reused. - EXPECT_EQ(address_3, memory1->Memory()); - WriteToDiscardableAshmemChunk(memory1.get(), kPageSize); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, MergeFreeChunks) { - scoped_ptr<DiscardableAshmemChunk> memory1(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory1); - scoped_ptr<DiscardableAshmemChunk> memory2(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory2); - scoped_ptr<DiscardableAshmemChunk> memory3(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory3); - scoped_ptr<DiscardableAshmemChunk> memory4(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory4); - void* const memory1_address = memory1->Memory(); - memory1.reset(); - memory3.reset(); - // Freeing |memory2| (located between memory1 and memory3) should merge the - // three free blocks together. - memory2.reset(); - memory1 = allocator_.Allocate(3 * kPageSize); - EXPECT_EQ(memory1_address, memory1->Memory()); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, MergeFreeChunksAdvanced) { - scoped_ptr<DiscardableAshmemChunk> memory1( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory1); - scoped_ptr<DiscardableAshmemChunk> memory2( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory2); - void* const memory1_address = memory1->Memory(); - memory1.reset(); - memory1 = allocator_.Allocate(2 * kPageSize); - memory2.reset(); - // At this point, the region should be in this state: - // 8 KBytes (used), 24 KBytes (free). - memory2 = allocator_.Allocate(6 * kPageSize); - EXPECT_EQ( - static_cast<const char*>(memory2->Memory()), - static_cast<const char*>(memory1_address) + 2 * kPageSize); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, MergeFreeChunksAdvanced2) { - scoped_ptr<DiscardableAshmemChunk> memory1( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory1); - scoped_ptr<DiscardableAshmemChunk> memory2( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory2); - void* const memory1_address = memory1->Memory(); - memory1.reset(); - memory1 = allocator_.Allocate(2 * kPageSize); - scoped_ptr<DiscardableAshmemChunk> memory3( - allocator_.Allocate(2 * kPageSize)); - // At this point, the region should be in this state: - // 8 KBytes (used), 8 KBytes (used), 16 KBytes (used). - memory3.reset(); - memory2.reset(); - // At this point, the region should be in this state: - // 8 KBytes (used), 24 KBytes (free). - memory2 = allocator_.Allocate(6 * kPageSize); - EXPECT_EQ( - static_cast<const char*>(memory2->Memory()), - static_cast<const char*>(memory1_address) + 2 * kPageSize); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, - MergeFreeChunksAndDeleteAshmemRegion) { - scoped_ptr<DiscardableAshmemChunk> memory1( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory1); - scoped_ptr<DiscardableAshmemChunk> memory2( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory2); - memory1.reset(); - memory1 = allocator_.Allocate(2 * kPageSize); - scoped_ptr<DiscardableAshmemChunk> memory3( - allocator_.Allocate(2 * kPageSize)); - // At this point, the region should be in this state: - // 8 KBytes (used), 8 KBytes (used), 16 KBytes (used). - memory1.reset(); - memory3.reset(); - // At this point, the region should be in this state: - // 8 KBytes (free), 8 KBytes (used), 8 KBytes (free). - const int kMagic = 0xdeadbeef; - *static_cast<int*>(memory2->Memory()) = kMagic; - memory2.reset(); - // The whole region should have been deleted. - memory2 = allocator_.Allocate(2 * kPageSize); - EXPECT_NE(kMagic, *static_cast<int*>(memory2->Memory())); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, - TooLargeFreeChunksDontCauseTooMuchFragmentationWhenRecycled) { - // Keep |memory_1| below allocated so that the ashmem region doesn't get - // closed when |memory_2| is deleted. - scoped_ptr<DiscardableAshmemChunk> memory_1(allocator_.Allocate(64 * 1024)); - ASSERT_TRUE(memory_1); - scoped_ptr<DiscardableAshmemChunk> memory_2(allocator_.Allocate(32 * 1024)); - ASSERT_TRUE(memory_2); - void* const address = memory_2->Memory(); - memory_2.reset(); - const size_t size = 16 * 1024; - memory_2 = allocator_.Allocate(size); - ASSERT_TRUE(memory_2); - EXPECT_EQ(address, memory_2->Memory()); - WriteToDiscardableAshmemChunk(memory_2.get(), size); - scoped_ptr<DiscardableAshmemChunk> memory_3(allocator_.Allocate(size)); - // The unused tail (16 KBytes large) of the previously freed chunk should be - // reused. - EXPECT_EQ(static_cast<char*>(address) + size, memory_3->Memory()); - WriteToDiscardableAshmemChunk(memory_3.get(), size); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, UseMultipleAshmemRegions) { - // Leave one page untouched at the end of the ashmem region. - const size_t size = kAshmemRegionSizeForTesting - kPageSize; - scoped_ptr<DiscardableAshmemChunk> memory1(allocator_.Allocate(size)); - ASSERT_TRUE(memory1); - WriteToDiscardableAshmemChunk(memory1.get(), size); - - scoped_ptr<DiscardableAshmemChunk> memory2( - allocator_.Allocate(kAshmemRegionSizeForTesting)); - ASSERT_TRUE(memory2); - WriteToDiscardableAshmemChunk(memory2.get(), kAshmemRegionSizeForTesting); - // The last page of the first ashmem region should be used for this - // allocation. - scoped_ptr<DiscardableAshmemChunk> memory3(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory3); - WriteToDiscardableAshmemChunk(memory3.get(), kPageSize); - EXPECT_EQ(memory3->Memory(), static_cast<char*>(memory1->Memory()) + size); -} - -TEST_F(DiscardableMemoryAshmemAllocatorTest, - HighestAllocatedChunkPointerIsUpdatedWhenHighestChunkGetsSplit) { - // Prevents the ashmem region from getting closed when |memory2| gets freed. - scoped_ptr<DiscardableAshmemChunk> memory1(allocator_.Allocate(kPageSize)); - ASSERT_TRUE(memory1); - - scoped_ptr<DiscardableAshmemChunk> memory2( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory2); - - memory2.reset(); - memory2 = allocator_.Allocate(kPageSize); - // There should now be a free chunk of size 3 * |kPageSize| starting at offset - // 2 * |kPageSize| and the pointer to the highest allocated chunk should have - // also been updated to |base_| + 2 * |kPageSize|. This pointer is used to - // maintain the container mapping a chunk address to its previous chunk and - // this map is in turn used while merging previous contiguous chunks. - - // Allocate more than 3 * |kPageSize| so that the free chunk of size 3 * - // |kPageSize| is not reused and |highest_allocated_chunk_| gets used instead. - scoped_ptr<DiscardableAshmemChunk> memory3( - allocator_.Allocate(4 * kPageSize)); - ASSERT_TRUE(memory3); - - // Deleting |memory3| (whose size is 4 * |kPageSize|) should result in a merge - // with its previous chunk which is the free chunk of size |3 * kPageSize|. - memory3.reset(); - memory3 = allocator_.Allocate((3 + 4) * kPageSize); - EXPECT_EQ(memory3->Memory(), - static_cast<const char*>(memory2->Memory()) + kPageSize); -} - -} // namespace internal -} // namespace base
diff --git a/base/memory/discardable_memory_emulated.cc b/base/memory/discardable_memory_emulated.cc deleted file mode 100644 index b12d7ce..0000000 --- a/base/memory/discardable_memory_emulated.cc +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_emulated.h" - -#include "base/lazy_instance.h" -#include "base/memory/discardable_memory_manager.h" - -namespace base { -namespace { - -// This is admittedly pretty magical. -const size_t kEmulatedMemoryLimit = 512 * 1024 * 1024; -const size_t kEmulatedSoftMemoryLimit = 32 * 1024 * 1024; -const size_t kEmulatedHardMemoryLimitExpirationTimeMs = 1000; - -// internal::DiscardableMemoryManager has an explicit constructor that takes -// a number of memory limit parameters. The LeakyLazyInstanceTraits doesn't -// handle the case. Thus, we need our own class here. -struct DiscardableMemoryManagerLazyInstanceTraits { - // Leaky as discardable memory clients can use this after the exit handler - // has been called. - static const bool kRegisterOnExit = false; -#ifndef NDEBUG - static const bool kAllowedToAccessOnNonjoinableThread = true; -#endif - - static internal::DiscardableMemoryManager* New(void* instance) { - return new (instance) internal::DiscardableMemoryManager( - kEmulatedMemoryLimit, - kEmulatedSoftMemoryLimit, - TimeDelta::FromMilliseconds(kEmulatedHardMemoryLimitExpirationTimeMs)); - } - static void Delete(internal::DiscardableMemoryManager* instance) { - instance->~DiscardableMemoryManager(); - } -}; - -LazyInstance<internal::DiscardableMemoryManager, - DiscardableMemoryManagerLazyInstanceTraits> - g_manager = LAZY_INSTANCE_INITIALIZER; - -} // namespace - -namespace internal { - -DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t bytes) - : bytes_(bytes), - is_locked_(false) { - g_manager.Pointer()->Register(this, bytes); -} - -DiscardableMemoryEmulated::~DiscardableMemoryEmulated() { - if (is_locked_) - Unlock(); - g_manager.Pointer()->Unregister(this); -} - -// static -bool DiscardableMemoryEmulated::ReduceMemoryUsage() { - return g_manager.Pointer()->ReduceMemoryUsage(); -} - -// static -void DiscardableMemoryEmulated::ReduceMemoryUsageUntilWithinLimit( - size_t bytes) { - g_manager.Pointer()->ReduceMemoryUsageUntilWithinLimit(bytes); -} - -bool DiscardableMemoryEmulated::Initialize() { - return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; -} - -DiscardableMemoryLockStatus DiscardableMemoryEmulated::Lock() { - DCHECK(!is_locked_); - - bool purged = false; - if (!g_manager.Pointer()->AcquireLock(this, &purged)) - return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; - - is_locked_ = true; - return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED - : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; -} - -void DiscardableMemoryEmulated::Unlock() { - DCHECK(is_locked_); - g_manager.Pointer()->ReleaseLock(this); - is_locked_ = false; -} - -void* DiscardableMemoryEmulated::Memory() const { - DCHECK(is_locked_); - DCHECK(memory_); - return memory_.get(); -} - -bool DiscardableMemoryEmulated::AllocateAndAcquireLock() { - if (memory_) - return true; - - memory_.reset(new uint8[bytes_]); - return false; -} - -void DiscardableMemoryEmulated::Purge() { - memory_.reset(); -} - -} // namespace internal -} // namespace base
diff --git a/base/memory/discardable_memory_emulated.h b/base/memory/discardable_memory_emulated.h deleted file mode 100644 index aa01a9d..0000000 --- a/base/memory/discardable_memory_emulated.h +++ /dev/null
@@ -1,52 +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 BASE_MEMORY_DISCARDABLE_MEMORY_EMULATED_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_EMULATED_H_ - -#include "base/memory/discardable_memory.h" - -#include "base/memory/discardable_memory_manager.h" - -namespace base { -namespace internal { - -class DiscardableMemoryEmulated - : public DiscardableMemory, - public internal::DiscardableMemoryManagerAllocation { - public: - explicit DiscardableMemoryEmulated(size_t bytes); - ~DiscardableMemoryEmulated() override; - - static bool ReduceMemoryUsage(); - - // TODO(reveman): Remove this as it is breaking the discardable memory design - // principle that implementations should not rely on information this is - // unavailable in kernel space. crbug.com/400423 - BASE_EXPORT static void ReduceMemoryUsageUntilWithinLimit(size_t bytes); - - bool Initialize(); - - // Overridden from DiscardableMemory: - DiscardableMemoryLockStatus Lock() override; - void Unlock() override; - void* Memory() const override; - - // Overridden from internal::DiscardableMemoryManagerAllocation: - bool AllocateAndAcquireLock() override; - void ReleaseLock() override {} - void Purge() override; - - private: - const size_t bytes_; - scoped_ptr<uint8[]> memory_; - bool is_locked_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryEmulated); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_EMULATED_H_
diff --git a/base/memory/discardable_memory_linux.cc b/base/memory/discardable_memory_linux.cc index 670ad7e..b394e07 100644 --- a/base/memory/discardable_memory_linux.cc +++ b/base/memory/discardable_memory_linux.cc
@@ -5,22 +5,15 @@ #include "base/memory/discardable_memory.h" #include "base/logging.h" -#include "base/memory/discardable_memory_emulated.h" #include "base/memory/discardable_memory_shmem.h" namespace base { // static -bool DiscardableMemory::ReduceMemoryUsage() { - return internal::DiscardableMemoryEmulated::ReduceMemoryUsage(); -} - -// static void DiscardableMemory::GetSupportedTypes( std::vector<DiscardableMemoryType>* types) { const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM, - DISCARDABLE_MEMORY_TYPE_EMULATED + DISCARDABLE_MEMORY_TYPE_SHMEM }; types->assign(supported_types, supported_types + arraysize(supported_types)); } @@ -29,25 +22,9 @@ scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( DiscardableMemoryType type, size_t size) { switch (type) { - case DISCARDABLE_MEMORY_TYPE_EMULATED: { - scoped_ptr<internal::DiscardableMemoryEmulated> memory( - new internal::DiscardableMemoryEmulated(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } - case DISCARDABLE_MEMORY_TYPE_SHMEM: { - scoped_ptr<internal::DiscardableMemoryShmem> memory( - new internal::DiscardableMemoryShmem(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } + case DISCARDABLE_MEMORY_TYPE_SHMEM: + return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); case DISCARDABLE_MEMORY_TYPE_NONE: - case DISCARDABLE_MEMORY_TYPE_ASHMEM: - case DISCARDABLE_MEMORY_TYPE_MACH: NOTREACHED(); return nullptr; }
diff --git a/base/memory/discardable_memory_mac.cc b/base/memory/discardable_memory_mac.cc index 2881f5e..d7e6345 100644 --- a/base/memory/discardable_memory_mac.cc +++ b/base/memory/discardable_memory_mac.cc
@@ -5,26 +5,16 @@ #include "base/memory/discardable_memory.h" #include "base/logging.h" -#include "base/memory/discardable_memory_emulated.h" -#include "base/memory/discardable_memory_mach.h" -#include "base/memory/discardable_memory_manager.h" #include "base/memory/discardable_memory_shmem.h" #include "base/memory/scoped_ptr.h" namespace base { // static -bool DiscardableMemory::ReduceMemoryUsage() { - return internal::DiscardableMemoryEmulated::ReduceMemoryUsage(); -} - -// static void DiscardableMemory::GetSupportedTypes( std::vector<DiscardableMemoryType>* types) { const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM, - DISCARDABLE_MEMORY_TYPE_MACH, - DISCARDABLE_MEMORY_TYPE_EMULATED + DISCARDABLE_MEMORY_TYPE_SHMEM }; types->assign(supported_types, supported_types + arraysize(supported_types)); } @@ -33,32 +23,9 @@ scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( DiscardableMemoryType type, size_t size) { switch (type) { - case DISCARDABLE_MEMORY_TYPE_MACH: { - scoped_ptr<internal::DiscardableMemoryMach> memory( - new internal::DiscardableMemoryMach(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } - case DISCARDABLE_MEMORY_TYPE_EMULATED: { - scoped_ptr<internal::DiscardableMemoryEmulated> memory( - new internal::DiscardableMemoryEmulated(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } - case DISCARDABLE_MEMORY_TYPE_SHMEM: { - scoped_ptr<internal::DiscardableMemoryShmem> memory( - new internal::DiscardableMemoryShmem(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } + case DISCARDABLE_MEMORY_TYPE_SHMEM: + return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); case DISCARDABLE_MEMORY_TYPE_NONE: - case DISCARDABLE_MEMORY_TYPE_ASHMEM: NOTREACHED(); return nullptr; }
diff --git a/base/memory/discardable_memory_mach.cc b/base/memory/discardable_memory_mach.cc deleted file mode 100644 index d96de79..0000000 --- a/base/memory/discardable_memory_mach.cc +++ /dev/null
@@ -1,152 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_mach.h" - -#include <mach/mach.h> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/mac/mach_logging.h" - -namespace base { -namespace { - -// For Mach, have the DiscardableMemoryManager trigger userspace eviction when -// address space usage gets too high (e.g. 512 MBytes). -const size_t kMachMemoryLimit = 512 * 1024 * 1024; - -// internal::DiscardableMemoryManager has an explicit constructor that takes -// a number of memory limit parameters. The LeakyLazyInstanceTraits doesn't -// handle the case. Thus, we need our own class here. -struct DiscardableMemoryManagerLazyInstanceTraits { - // Leaky as discardable memory clients can use this after the exit handler - // has been called. - static const bool kRegisterOnExit = false; -#ifndef NDEBUG - static const bool kAllowedToAccessOnNonjoinableThread = true; -#endif - - static internal::DiscardableMemoryManager* New(void* instance) { - return new (instance) internal::DiscardableMemoryManager( - kMachMemoryLimit, kMachMemoryLimit, TimeDelta::Max()); - } - static void Delete(internal::DiscardableMemoryManager* instance) { - instance->~DiscardableMemoryManager(); - } -}; - -LazyInstance<internal::DiscardableMemoryManager, - DiscardableMemoryManagerLazyInstanceTraits> - g_manager = LAZY_INSTANCE_INITIALIZER; - -// The VM subsystem allows tagging of memory and 240-255 is reserved for -// application use (see mach/vm_statistics.h). Pick 252 (after chromium's atomic -// weight of ~52). -const int kDiscardableMemoryTag = VM_MAKE_TAG(252); - -} // namespace - -namespace internal { - -DiscardableMemoryMach::DiscardableMemoryMach(size_t bytes) - : memory_(0, 0), bytes_(mach_vm_round_page(bytes)), is_locked_(false) { - g_manager.Pointer()->Register(this, bytes); -} - -DiscardableMemoryMach::~DiscardableMemoryMach() { - if (is_locked_) - Unlock(); - g_manager.Pointer()->Unregister(this); -} - -bool DiscardableMemoryMach::Initialize() { - return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; -} - -DiscardableMemoryLockStatus DiscardableMemoryMach::Lock() { - DCHECK(!is_locked_); - - bool purged = false; - if (!g_manager.Pointer()->AcquireLock(this, &purged)) - return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; - - is_locked_ = true; - return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED - : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; -} - -void DiscardableMemoryMach::Unlock() { - DCHECK(is_locked_); - g_manager.Pointer()->ReleaseLock(this); - is_locked_ = false; -} - -void* DiscardableMemoryMach::Memory() const { - DCHECK(is_locked_); - return reinterpret_cast<void*>(memory_.address()); -} - -bool DiscardableMemoryMach::AllocateAndAcquireLock() { - kern_return_t ret; - bool persistent; - if (!memory_.size()) { - vm_address_t address = 0; - ret = vm_allocate( - mach_task_self(), - &address, - bytes_, - VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE | kDiscardableMemoryTag); - MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_allocate"; - memory_.reset(address, bytes_); - - // When making a fresh allocation, it's impossible for |persistent| to - // be true. - persistent = false; - } else { - // |persistent| will be reset to false below if appropriate, but when - // reusing an existing allocation, it's possible for it to be true. - persistent = true; - -#if !defined(NDEBUG) - ret = vm_protect(mach_task_self(), - memory_.address(), - memory_.size(), - FALSE, - VM_PROT_DEFAULT); - MACH_DCHECK(ret == KERN_SUCCESS, ret) << "vm_protect"; -#endif - } - - int state = VM_PURGABLE_NONVOLATILE; - ret = vm_purgable_control( - mach_task_self(), memory_.address(), VM_PURGABLE_SET_STATE, &state); - MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_purgable_control"; - if (state & VM_PURGABLE_EMPTY) - persistent = false; - - return persistent; -} - -void DiscardableMemoryMach::ReleaseLock() { - int state = VM_PURGABLE_VOLATILE | VM_VOLATILE_GROUP_DEFAULT; - kern_return_t ret = vm_purgable_control( - mach_task_self(), memory_.address(), VM_PURGABLE_SET_STATE, &state); - MACH_CHECK(ret == KERN_SUCCESS, ret) << "vm_purgable_control"; - -#if !defined(NDEBUG) - ret = vm_protect( - mach_task_self(), memory_.address(), memory_.size(), FALSE, VM_PROT_NONE); - MACH_DCHECK(ret == KERN_SUCCESS, ret) << "vm_protect"; -#endif -} - -void DiscardableMemoryMach::Purge() { - memory_.reset(); -} - -} // namespace internal -} // namespace base
diff --git a/base/memory/discardable_memory_mach.h b/base/memory/discardable_memory_mach.h deleted file mode 100644 index b3b4b48..0000000 --- a/base/memory/discardable_memory_mach.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_MACH_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_MACH_H_ - -#include "base/memory/discardable_memory.h" - -#include "base/mac/scoped_mach_vm.h" -#include "base/memory/discardable_memory_manager.h" - -namespace base { -namespace internal { - -class DiscardableMemoryMach - : public DiscardableMemory, - public internal::DiscardableMemoryManagerAllocation { - public: - explicit DiscardableMemoryMach(size_t bytes); - ~DiscardableMemoryMach() override; - - bool Initialize(); - - // Overridden from DiscardableMemory: - DiscardableMemoryLockStatus Lock() override; - void Unlock() override; - void* Memory() const override; - - // Overridden from internal::DiscardableMemoryManagerAllocation: - bool AllocateAndAcquireLock() override; - void ReleaseLock() override; - void Purge() override; - - private: - mac::ScopedMachVM memory_; - const size_t bytes_; - bool is_locked_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryMach); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_MACH_H_
diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc deleted file mode 100644 index cbbdb47..0000000 --- a/base/memory/discardable_memory_manager.cc +++ /dev/null
@@ -1,218 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_manager.h" - -#include "base/bind.h" -#include "base/containers/adapters.h" -#include "base/containers/hash_tables.h" -#include "base/containers/mru_cache.h" -#include "base/debug/crash_logging.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/lock.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace internal { - -DiscardableMemoryManager::DiscardableMemoryManager( - size_t memory_limit, - size_t soft_memory_limit, - TimeDelta hard_memory_limit_expiration_time) - : allocations_(AllocationMap::NO_AUTO_EVICT), - bytes_allocated_(0u), - memory_limit_(memory_limit), - soft_memory_limit_(soft_memory_limit), - hard_memory_limit_expiration_time_(hard_memory_limit_expiration_time) { - BytesAllocatedChanged(bytes_allocated_); -} - -DiscardableMemoryManager::~DiscardableMemoryManager() { - DCHECK(allocations_.empty()); - DCHECK_EQ(0u, bytes_allocated_); -} - -void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) { - AutoLock lock(lock_); - memory_limit_ = bytes; - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - Now(), memory_limit_); -} - -void DiscardableMemoryManager::SetSoftMemoryLimit(size_t bytes) { - AutoLock lock(lock_); - soft_memory_limit_ = bytes; -} - -void DiscardableMemoryManager::SetHardMemoryLimitExpirationTime( - TimeDelta hard_memory_limit_expiration_time) { - AutoLock lock(lock_); - hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time; -} - -bool DiscardableMemoryManager::ReduceMemoryUsage() { - return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit(); -} - -void DiscardableMemoryManager::ReduceMemoryUsageUntilWithinLimit(size_t bytes) { - AutoLock lock(lock_); - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(), - bytes); -} - -void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) { - AutoLock lock(lock_); - DCHECK(allocations_.Peek(allocation) == allocations_.end()); - allocations_.Put(allocation, AllocationInfo(bytes)); -} - -void DiscardableMemoryManager::Unregister(Allocation* allocation) { - AutoLock lock(lock_); - AllocationMap::iterator it = allocations_.Peek(allocation); - DCHECK(it != allocations_.end()); - const AllocationInfo& info = it->second; - - if (info.purgable) { - size_t bytes_purgable = info.bytes; - DCHECK_LE(bytes_purgable, bytes_allocated_); - bytes_allocated_ -= bytes_purgable; - BytesAllocatedChanged(bytes_allocated_); - } - allocations_.Erase(it); -} - -bool DiscardableMemoryManager::AcquireLock(Allocation* allocation, - bool* purged) { - AutoLock lock(lock_); - // Note: |allocations_| is an MRU cache, and use of |Get| here updates that - // cache. - AllocationMap::iterator it = allocations_.Get(allocation); - DCHECK(it != allocations_.end()); - AllocationInfo* info = &it->second; - - if (!info->bytes) - return false; - - TimeTicks now = Now(); - size_t bytes_required = info->purgable ? 0u : info->bytes; - - if (memory_limit_) { - size_t limit = 0; - if (bytes_required < memory_limit_) - limit = memory_limit_ - bytes_required; - - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(now, - limit); - } - - // Check for overflow. - if (std::numeric_limits<size_t>::max() - bytes_required < bytes_allocated_) - return false; - - *purged = !allocation->AllocateAndAcquireLock(); - info->purgable = false; - info->last_usage = now; - if (bytes_required) { - bytes_allocated_ += bytes_required; - BytesAllocatedChanged(bytes_allocated_); - } - return true; -} - -void DiscardableMemoryManager::ReleaseLock(Allocation* allocation) { - AutoLock lock(lock_); - // Note: |allocations_| is an MRU cache, and use of |Get| here updates that - // cache. - AllocationMap::iterator it = allocations_.Get(allocation); - DCHECK(it != allocations_.end()); - AllocationInfo* info = &it->second; - - TimeTicks now = Now(); - allocation->ReleaseLock(); - info->purgable = true; - info->last_usage = now; - - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - now, memory_limit_); -} - -void DiscardableMemoryManager::PurgeAll() { - AutoLock lock(lock_); - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(), 0); -} - -bool DiscardableMemoryManager::IsRegisteredForTest( - Allocation* allocation) const { - AutoLock lock(lock_); - AllocationMap::const_iterator it = allocations_.Peek(allocation); - return it != allocations_.end(); -} - -bool DiscardableMemoryManager::CanBePurgedForTest( - Allocation* allocation) const { - AutoLock lock(lock_); - AllocationMap::const_iterator it = allocations_.Peek(allocation); - return it != allocations_.end() && it->second.purgable; -} - -size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const { - AutoLock lock(lock_); - return bytes_allocated_; -} - -bool DiscardableMemoryManager:: - PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit() { - AutoLock lock(lock_); - - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - Now() - hard_memory_limit_expiration_time_, soft_memory_limit_); - - return bytes_allocated_ <= soft_memory_limit_; -} - -void DiscardableMemoryManager:: - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - TimeTicks timestamp, - size_t limit) { - lock_.AssertAcquired(); - - size_t bytes_allocated_before_purging = bytes_allocated_; - for (auto& entry : base::Reversed(allocations_)) { - Allocation* allocation = entry.first; - AllocationInfo* info = &entry.second; - - if (bytes_allocated_ <= limit) - break; - - bool purgable = info->purgable && info->last_usage <= timestamp; - if (!purgable) - continue; - - size_t bytes_purgable = info->bytes; - DCHECK_LE(bytes_purgable, bytes_allocated_); - bytes_allocated_ -= bytes_purgable; - info->purgable = false; - allocation->Purge(); - } - - if (bytes_allocated_ != bytes_allocated_before_purging) - BytesAllocatedChanged(bytes_allocated_); -} - -void DiscardableMemoryManager::BytesAllocatedChanged( - size_t new_bytes_allocated) const { - TRACE_COUNTER_ID1( - "base", "DiscardableMemoryUsage", this, new_bytes_allocated); - - static const char kDiscardableMemoryUsageKey[] = "dm-usage"; - base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey, - Uint64ToString(new_bytes_allocated)); -} - -TimeTicks DiscardableMemoryManager::Now() const { - return TimeTicks::Now(); -} - -} // namespace internal -} // namespace base
diff --git a/base/memory/discardable_memory_manager.h b/base/memory/discardable_memory_manager.h deleted file mode 100644 index 43737f8..0000000 --- a/base/memory/discardable_memory_manager.h +++ /dev/null
@@ -1,166 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_ - -#include "base/base_export.h" -#include "base/containers/hash_tables.h" -#include "base/containers/mru_cache.h" -#include "base/synchronization/lock.h" -#include "base/time/time.h" - -namespace base { -namespace internal { - -// This interface is used by the DiscardableMemoryManager class to provide some -// level of userspace control over discardable memory allocations. -class DiscardableMemoryManagerAllocation { - public: - // Allocate and acquire a lock that prevents the allocation from being purged - // by the system. Returns true if memory was previously allocated and is still - // resident. - virtual bool AllocateAndAcquireLock() = 0; - - // Release a previously acquired lock on the allocation so that it can be - // purged by the system. - virtual void ReleaseLock() = 0; - - // Explicitly purge this allocation. It is illegal to call this while a lock - // is acquired on the allocation. - virtual void Purge() = 0; - - protected: - virtual ~DiscardableMemoryManagerAllocation() {} -}; - -} // namespace internal -} // namespace base - -namespace base { -namespace internal { - -// The DiscardableMemoryManager manages a collection of -// DiscardableMemoryManagerAllocation instances. It is used on platforms that -// need some level of userspace control over discardable memory. It keeps track -// of all allocation instances (in case they need to be purged), and the total -// amount of allocated memory (in case this forces a purge). When memory usage -// reaches the limit, the manager purges the LRU memory. -class BASE_EXPORT_PRIVATE DiscardableMemoryManager { - public: - typedef DiscardableMemoryManagerAllocation Allocation; - - DiscardableMemoryManager(size_t memory_limit, - size_t soft_memory_limit, - TimeDelta hard_memory_limit_expiration_time); - virtual ~DiscardableMemoryManager(); - - // The maximum number of bytes of memory that may be allocated before we force - // a purge. - void SetMemoryLimit(size_t bytes); - - // The number of bytes of memory that may be allocated but unused for the hard - // limit expiration time without getting purged. - void SetSoftMemoryLimit(size_t bytes); - - // Sets the memory usage cutoff time for hard memory limit. - void SetHardMemoryLimitExpirationTime( - TimeDelta hard_memory_limit_expiration_time); - - // This will attempt to reduce memory footprint until within soft memory - // limit. Returns true if there's no need to call this again until allocations - // have been used. - bool ReduceMemoryUsage(); - - // This can be called to attempt to reduce memory footprint until within - // limit for bytes to keep under moderate pressure. - void ReduceMemoryUsageUntilWithinLimit(size_t bytes); - - // Adds the given allocation to the manager's collection. - void Register(Allocation* allocation, size_t bytes); - - // Removes the given allocation from the manager's collection. - void Unregister(Allocation* allocation); - - // Returns false if an error occurred. Otherwise, returns true and sets - // |purged| to indicate whether or not allocation has been purged since last - // use. - bool AcquireLock(Allocation* allocation, bool* purged); - - // Release a previously acquired lock on allocation. This allows the manager - // to purge it if necessary. - void ReleaseLock(Allocation* allocation); - - // Purges all discardable memory. - void PurgeAll(); - - // Returns true if allocation has been added to the manager's collection. This - // should only be used by tests. - bool IsRegisteredForTest(Allocation* allocation) const; - - // Returns true if allocation can be purged. This should only be used by - // tests. - bool CanBePurgedForTest(Allocation* allocation) const; - - // Returns total amount of allocated discardable memory. This should only be - // used by tests. - size_t GetBytesAllocatedForTest() const; - - private: - struct AllocationInfo { - explicit AllocationInfo(size_t bytes) : bytes(bytes), purgable(false) {} - - const size_t bytes; - bool purgable; - TimeTicks last_usage; - }; - typedef HashingMRUCache<Allocation*, AllocationInfo> AllocationMap; - - // Purges memory not used since |hard_memory_limit_expiration_time_| before - // "right now" until usage is less or equal to |soft_memory_limit_|. - // Returns true if total amount of memory is less or equal to soft memory - // limit. - bool PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit(); - - // Purges memory that has not been used since |timestamp| until usage is less - // or equal to |limit|. - // Caller must acquire |lock_| prior to calling this function. - void PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - TimeTicks timestamp, - size_t limit); - - // Called when a change to |bytes_allocated_| has been made. - void BytesAllocatedChanged(size_t new_bytes_allocated) const; - - // Virtual for tests. - virtual TimeTicks Now() const; - - // Needs to be held when accessing members. - mutable Lock lock_; - - // A MRU cache of all allocated bits of memory. Used for purging. - AllocationMap allocations_; - - // The total amount of allocated memory. - size_t bytes_allocated_; - - // The maximum number of bytes of memory that may be allocated. - size_t memory_limit_; - - // The number of bytes of memory that may be allocated but not used for - // |hard_memory_limit_expiration_time_| amount of time when receiving an idle - // notification. - size_t soft_memory_limit_; - - // Amount of time it takes for an allocation to become affected by - // |soft_memory_limit_|. - TimeDelta hard_memory_limit_expiration_time_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryManager); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_
diff --git a/base/memory/discardable_memory_manager_unittest.cc b/base/memory/discardable_memory_manager_unittest.cc deleted file mode 100644 index 6717f09..0000000 --- a/base/memory/discardable_memory_manager_unittest.cc +++ /dev/null
@@ -1,490 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_manager.h" - -#include "base/bind.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace { - -class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation { - public: - TestAllocationImpl() : is_allocated_(false), is_locked_(false) {} - ~TestAllocationImpl() override { DCHECK(!is_locked_); } - - // Overridden from internal::DiscardableMemoryManagerAllocation: - bool AllocateAndAcquireLock() override { - bool was_allocated = is_allocated_; - is_allocated_ = true; - DCHECK(!is_locked_); - is_locked_ = true; - return was_allocated; - } - void ReleaseLock() override { - DCHECK(is_locked_); - is_locked_ = false; - } - void Purge() override { - DCHECK(is_allocated_); - is_allocated_ = false; - } - - bool is_locked() const { return is_locked_; } - - private: - bool is_allocated_; - bool is_locked_; -}; - -// Tests can assume that the default limit is at least 1024. Tests that rely on -// something else needs to explicit set the limit. -const size_t kDefaultMemoryLimit = 1024; -const size_t kDefaultSoftMemoryLimit = kDefaultMemoryLimit; - -class TestDiscardableMemoryManagerImpl - : public internal::DiscardableMemoryManager { - public: - TestDiscardableMemoryManagerImpl() - : DiscardableMemoryManager(kDefaultMemoryLimit, - kDefaultSoftMemoryLimit, - TimeDelta::Max()) {} - - void SetNow(TimeTicks now) { now_ = now; } - - private: - // Overriden from internal::DiscardableMemoryManager: - TimeTicks Now() const override { return now_; } - - TimeTicks now_; -}; - -class DiscardableMemoryManagerTestBase { - public: - DiscardableMemoryManagerTestBase() {} - - protected: - enum LockStatus { - LOCK_STATUS_FAILED, - LOCK_STATUS_PURGED, - LOCK_STATUS_SUCCESS - }; - - size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); } - - void SetMemoryLimit(size_t bytes) { manager_.SetMemoryLimit(bytes); } - - void SetSoftMemoryLimit(size_t bytes) { manager_.SetSoftMemoryLimit(bytes); } - - void SetHardMemoryLimitExpirationTime(TimeDelta time) { - manager_.SetHardMemoryLimitExpirationTime(time); - } - - void Register(TestAllocationImpl* allocation, size_t bytes) { - manager_.Register(allocation, bytes); - } - - void Unregister(TestAllocationImpl* allocation) { - manager_.Unregister(allocation); - } - - bool IsRegistered(TestAllocationImpl* allocation) const { - return manager_.IsRegisteredForTest(allocation); - } - - LockStatus Lock(TestAllocationImpl* allocation) { - bool purged; - if (!manager_.AcquireLock(allocation, &purged)) - return LOCK_STATUS_FAILED; - return purged ? LOCK_STATUS_PURGED : LOCK_STATUS_SUCCESS; - } - - void Unlock(TestAllocationImpl* allocation) { - manager_.ReleaseLock(allocation); - } - - LockStatus RegisterAndLock(TestAllocationImpl* allocation, size_t bytes) { - manager_.Register(allocation, bytes); - return Lock(allocation); - } - - bool CanBePurged(TestAllocationImpl* allocation) const { - return manager_.CanBePurgedForTest(allocation); - } - - void SetNow(TimeTicks now) { manager_.SetNow(now); } - - void PurgeAll() { return manager_.PurgeAll(); } - - bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); } - - void ReduceMemoryUsageUntilWithinLimit(size_t bytes) { - manager_.ReduceMemoryUsageUntilWithinLimit(bytes); - } - - private: - TestDiscardableMemoryManagerImpl manager_; -}; - -class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase, - public testing::Test { - public: - DiscardableMemoryManagerTest() {} -}; - -TEST_F(DiscardableMemoryManagerTest, CreateAndLock) { - size_t size = 1024; - TestAllocationImpl allocation; - Register(&allocation, size); - EXPECT_TRUE(IsRegistered(&allocation)); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); - EXPECT_TRUE(allocation.is_locked()); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, CreateZeroSize) { - size_t size = 0; - TestAllocationImpl allocation; - Register(&allocation, size); - EXPECT_TRUE(IsRegistered(&allocation)); - EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&allocation)); - EXPECT_EQ(0u, BytesAllocated()); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, LockAfterUnlock) { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - - // Now unlock so we can lock later. - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - - EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(&allocation)); - EXPECT_FALSE(CanBePurged(&allocation)); - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, LockAfterPurge) { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - - // Now unlock so we can lock later. - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - - // Force the system to purge. - PurgeAll(); - - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); - EXPECT_FALSE(CanBePurged(&allocation)); - - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - - // Now unlock so we can lock later. - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - - // Set max allowed allocation to 1 byte. This will cause the memory to be - // purged. - SetMemoryLimit(1); - - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); - EXPECT_FALSE(CanBePurged(&allocation)); - - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, Overflow) { - size_t size = 1024; - { - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - - size_t massive_size = std::numeric_limits<size_t>::max(); - TestAllocationImpl massive_allocation; - Register(&massive_allocation, massive_size); - EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&massive_allocation)); - EXPECT_EQ(1024u, BytesAllocated()); - - Unlock(&allocation); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&massive_allocation)); - Unlock(&massive_allocation); - Unregister(&massive_allocation); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -class PermutationTestData { - public: - PermutationTestData(unsigned d0, unsigned d1, unsigned d2) { - ordering_[0] = d0; - ordering_[1] = d1; - ordering_[2] = d2; - } - - const unsigned* ordering() const { return ordering_; } - - private: - unsigned ordering_[3]; -}; - -class DiscardableMemoryManagerPermutationTest - : public DiscardableMemoryManagerTestBase, - public testing::TestWithParam<PermutationTestData> { - public: - DiscardableMemoryManagerPermutationTest() {} - - protected: - // Use memory in order specified by ordering parameter. - void RegisterAndUseAllocations() { - for (int i = 0; i < 3; ++i) { - RegisterAndLock(&allocation_[i], 1024); - Unlock(&allocation_[i]); - } - for (int i = 0; i < 3; ++i) { - int index = GetParam().ordering()[i]; - EXPECT_NE(LOCK_STATUS_FAILED, Lock(&allocation_[index])); - // Leave i == 0 locked. - if (i > 0) - Unlock(&allocation_[index]); - } - } - - TestAllocationImpl* allocation(unsigned position) { - return &allocation_[GetParam().ordering()[position]]; - } - - void UnlockAndUnregisterAllocations() { - for (int i = 0; i < 3; ++i) { - if (allocation_[i].is_locked()) - Unlock(&allocation_[i]); - Unregister(&allocation_[i]); - } - } - - private: - TestAllocationImpl allocation_[3]; -}; - -// Verify that memory was discarded in the correct order after reducing usage to -// limit. -TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscarded) { - RegisterAndUseAllocations(); - - SetMemoryLimit(2048); - - ReduceMemoryUsageUntilWithinLimit(1024); - - EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); - // 0 should still be locked. - EXPECT_TRUE(allocation(0)->is_locked()); - - UnlockAndUnregisterAllocations(); -} - -// Verify that memory was discarded in the correct order after changing -// memory limit. -TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedExceedLimit) { - RegisterAndUseAllocations(); - - SetMemoryLimit(2048); - - EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); - // 0 should still be locked. - EXPECT_TRUE(allocation(0)->is_locked()); - - UnlockAndUnregisterAllocations(); -} - -// Verify that no more memory than necessary was discarded after changing -// memory limit. -TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedAmount) { - SetMemoryLimit(4096); - - RegisterAndUseAllocations(); - - SetMemoryLimit(2048); - - EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(allocation(2))); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); - // 0 should still be locked. - EXPECT_TRUE(allocation(0)->is_locked()); - - UnlockAndUnregisterAllocations(); -} - -TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) { - RegisterAndUseAllocations(); - - PurgeAll(); - - for (int i = 0; i < 3; ++i) { - if (i == 0) - EXPECT_TRUE(allocation(i)->is_locked()); - else - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i))); - } - - UnlockAndUnregisterAllocations(); -} - -INSTANTIATE_TEST_CASE_P(DiscardableMemoryManagerPermutationTests, - DiscardableMemoryManagerPermutationTest, - ::testing::Values(PermutationTestData(0, 1, 2), - PermutationTestData(0, 2, 1), - PermutationTestData(1, 0, 2), - PermutationTestData(1, 2, 0), - PermutationTestData(2, 0, 1), - PermutationTestData(2, 1, 0))); - -TEST_F(DiscardableMemoryManagerTest, NormalDestruction) { - { - size_t size = 1024; - TestAllocationImpl allocation; - Register(&allocation, size); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -TEST_F(DiscardableMemoryManagerTest, DestructionAfterLocked) { - { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - Unlock(&allocation); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -TEST_F(DiscardableMemoryManagerTest, DestructionAfterPurged) { - { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - SetMemoryLimit(0); - EXPECT_EQ(0u, BytesAllocated()); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -TEST_F(DiscardableMemoryManagerTest, ReduceMemoryUsage) { - SetMemoryLimit(3072); - SetSoftMemoryLimit(1024); - SetHardMemoryLimitExpirationTime(TimeDelta::FromInternalValue(1)); - - size_t size = 1024; - TestAllocationImpl allocation[3]; - RegisterAndLock(&allocation[0], size); - RegisterAndLock(&allocation[1], size); - RegisterAndLock(&allocation[2], size); - EXPECT_EQ(3072u, BytesAllocated()); - - // Above soft limit but nothing that can be purged. - EXPECT_FALSE(ReduceMemoryUsage()); - - SetNow(TimeTicks::FromInternalValue(0)); - Unlock(&allocation[0]); - - // Above soft limit but still nothing that can be purged as all unlocked - // allocations are within the hard limit cutoff time. - EXPECT_FALSE(ReduceMemoryUsage()); - - SetNow(TimeTicks::FromInternalValue(1)); - Unlock(&allocation[1]); - - // One unlocked allocation is no longer within the hard limit cutoff time. It - // should be purged and ReduceMemoryUsage() should return false as we're not - // yet within the soft memory limit. - EXPECT_FALSE(ReduceMemoryUsage()); - EXPECT_EQ(2048u, BytesAllocated()); - - // One more unlocked allocation is no longer within the hard limit cutoff - // time. It should be purged and ReduceMemoryUsage() should return true as - // we're now within the soft memory limit. - SetNow(TimeTicks::FromInternalValue(2)); - EXPECT_TRUE(ReduceMemoryUsage()); - EXPECT_EQ(1024u, BytesAllocated()); - - Unlock(&allocation[2]); - - Unregister(&allocation[0]); - Unregister(&allocation[1]); - Unregister(&allocation[2]); -} - -class ThreadedDiscardableMemoryManagerTest - : public DiscardableMemoryManagerTest { - public: - ThreadedDiscardableMemoryManagerTest() - : memory_usage_thread_("memory_usage_thread"), - thread_sync_(true, false) {} - - void SetUp() override { memory_usage_thread_.Start(); } - - void TearDown() override { memory_usage_thread_.Stop(); } - - void UseMemoryHelper() { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - Unlock(&allocation); - Unregister(&allocation); - } - - void SignalHelper() { thread_sync_.Signal(); } - - Thread memory_usage_thread_; - WaitableEvent thread_sync_; -}; - -TEST_F(ThreadedDiscardableMemoryManagerTest, UseMemoryOnThread) { - memory_usage_thread_.message_loop()->PostTask( - FROM_HERE, - Bind(&ThreadedDiscardableMemoryManagerTest::UseMemoryHelper, - Unretained(this))); - memory_usage_thread_.message_loop()->PostTask( - FROM_HERE, - Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper, - Unretained(this))); - thread_sync_.Wait(); -} - -} // namespace -} // namespace base
diff --git a/base/memory/discardable_memory_shmem.cc b/base/memory/discardable_memory_shmem.cc index 9056279..059d84c 100644 --- a/base/memory/discardable_memory_shmem.cc +++ b/base/memory/discardable_memory_shmem.cc
@@ -11,7 +11,10 @@ namespace internal { DiscardableMemoryShmem::DiscardableMemoryShmem(size_t bytes) - : bytes_(bytes), is_locked_(false) { + : chunk_(DiscardableMemoryShmemAllocator::GetInstance() + ->AllocateLockedDiscardableMemory(bytes)), + is_locked_(true) { + DCHECK(chunk_); } DiscardableMemoryShmem::~DiscardableMemoryShmem() { @@ -19,37 +22,27 @@ Unlock(); } -bool DiscardableMemoryShmem::Initialize() { - return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; -} - -DiscardableMemoryLockStatus DiscardableMemoryShmem::Lock() { +bool DiscardableMemoryShmem::Lock() { DCHECK(!is_locked_); + DCHECK(chunk_); - if (chunk_ && chunk_->Lock()) { - is_locked_ = true; - return DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS; + if (!chunk_->Lock()) { + chunk_.reset(); + return false; } - chunk_ = DiscardableMemoryShmemAllocator::GetInstance() - ->AllocateLockedDiscardableMemory(bytes_); - if (!chunk_) - return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED; - is_locked_ = true; - return DISCARDABLE_MEMORY_LOCK_STATUS_PURGED; + return true; } void DiscardableMemoryShmem::Unlock() { DCHECK(is_locked_); - DCHECK(chunk_); chunk_->Unlock(); is_locked_ = false; } void* DiscardableMemoryShmem::Memory() const { DCHECK(is_locked_); - DCHECK(chunk_); return chunk_->Memory(); }
diff --git a/base/memory/discardable_memory_shmem.h b/base/memory/discardable_memory_shmem.h index 98d3b97..f394562 100644 --- a/base/memory/discardable_memory_shmem.h +++ b/base/memory/discardable_memory_shmem.h
@@ -20,12 +20,11 @@ bool Initialize(); // Overridden from DiscardableMemory: - DiscardableMemoryLockStatus Lock() override; + bool Lock() override; void Unlock() override; void* Memory() const override; private: - const size_t bytes_; scoped_ptr<DiscardableMemoryShmemChunk> chunk_; bool is_locked_;
diff --git a/base/memory/discardable_memory_unittest.cc b/base/memory/discardable_memory_unittest.cc index fb1eba6..a769e17 100644 --- a/base/memory/discardable_memory_unittest.cc +++ b/base/memory/discardable_memory_unittest.cc
@@ -38,8 +38,12 @@ } bool IsNativeType(DiscardableMemoryType type) { - return type == DISCARDABLE_MEMORY_TYPE_ASHMEM || - type == DISCARDABLE_MEMORY_TYPE_MACH; +#if defined(OS_ANDROID) + // SHMEM is backed by native discardable memory on Android. + return type == DISCARDABLE_MEMORY_TYPE_SHMEM; +#else + return false; +#endif } TEST_P(DiscardableMemoryTest, SupportedNatively) { @@ -65,14 +69,7 @@ const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize)); ASSERT_TRUE(memory); void* addr = memory->Memory(); - ASSERT_NE(nullptr, addr); - - memory->Unlock(); - - EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, memory->Lock()); - addr = memory->Memory(); - ASSERT_NE(nullptr, addr); - + EXPECT_NE(nullptr, addr); memory->Unlock(); } @@ -107,7 +104,7 @@ memory = CreateLockedMemory(kLargeSize); ASSERT_TRUE(memory); void* addr = memory->Memory(); - ASSERT_NE(nullptr, addr); + EXPECT_NE(nullptr, addr); memory->Unlock(); } }
diff --git a/base/memory/discardable_memory_win.cc b/base/memory/discardable_memory_win.cc index 670ad7e..b394e07 100644 --- a/base/memory/discardable_memory_win.cc +++ b/base/memory/discardable_memory_win.cc
@@ -5,22 +5,15 @@ #include "base/memory/discardable_memory.h" #include "base/logging.h" -#include "base/memory/discardable_memory_emulated.h" #include "base/memory/discardable_memory_shmem.h" namespace base { // static -bool DiscardableMemory::ReduceMemoryUsage() { - return internal::DiscardableMemoryEmulated::ReduceMemoryUsage(); -} - -// static void DiscardableMemory::GetSupportedTypes( std::vector<DiscardableMemoryType>* types) { const DiscardableMemoryType supported_types[] = { - DISCARDABLE_MEMORY_TYPE_SHMEM, - DISCARDABLE_MEMORY_TYPE_EMULATED + DISCARDABLE_MEMORY_TYPE_SHMEM }; types->assign(supported_types, supported_types + arraysize(supported_types)); } @@ -29,25 +22,9 @@ scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemoryWithType( DiscardableMemoryType type, size_t size) { switch (type) { - case DISCARDABLE_MEMORY_TYPE_EMULATED: { - scoped_ptr<internal::DiscardableMemoryEmulated> memory( - new internal::DiscardableMemoryEmulated(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } - case DISCARDABLE_MEMORY_TYPE_SHMEM: { - scoped_ptr<internal::DiscardableMemoryShmem> memory( - new internal::DiscardableMemoryShmem(size)); - if (!memory->Initialize()) - return nullptr; - - return memory.Pass(); - } + case DISCARDABLE_MEMORY_TYPE_SHMEM: + return make_scoped_ptr(new internal::DiscardableMemoryShmem(size)); case DISCARDABLE_MEMORY_TYPE_NONE: - case DISCARDABLE_MEMORY_TYPE_ASHMEM: - case DISCARDABLE_MEMORY_TYPE_MACH: NOTREACHED(); return nullptr; }
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h index f159fb0..6adaeee 100644 --- a/base/memory/memory_pressure_listener.h +++ b/base/memory/memory_pressure_listener.h
@@ -7,8 +7,8 @@ // The app will try to discard buffers that aren't deemed essential (individual // modules will implement their own policy). -#ifndef BASE_MEMORY_PRESSURE_LISTENER_H_ -#define BASE_MEMORY_PRESSURE_LISTENER_H_ +#ifndef BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_ +#define BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_ #include "base/base_export.h" #include "base/basictypes.h" @@ -82,4 +82,4 @@ } // namespace base -#endif // BASE_MEMORY_PRESSURE_LISTENER_H_ +#endif // BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc index fd26ad1..d6c290f 100644 --- a/base/memory/shared_memory_posix.cc +++ b/base/memory/shared_memory_posix.cc
@@ -16,6 +16,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/process/process_metrics.h" +#include "base/profiler/scoped_tracker.h" #include "base/safe_strerror_posix.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" @@ -118,6 +119,11 @@ // In case we want to delete it later, it may be useful to save the value // of mem_filename after FilePathForMemoryName(). bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 + // is fixed. + tracked_objects::ScopedTracker tracking_profile1( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::Start")); DCHECK_EQ(-1, mapped_file_); if (options.size == 0) return false; @@ -140,11 +146,22 @@ // Q: Why not use the shm_open() etc. APIs? // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU FilePath directory; - if (GetShmemTempDir(options.executable, &directory)) + if (GetShmemTempDir(options.executable, &directory)) { + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 + // is fixed. + tracked_objects::ScopedTracker tracking_profile2( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::OpenTemporaryFile")); fp.reset(CreateAndOpenTemporaryFileInDir(directory, &path)); + } if (fp) { if (options.share_read_only) { + // TODO(erikchen): Remove ScopedTracker below once + // http://crbug.com/466437 is fixed. + tracked_objects::ScopedTracker tracking_profile3( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::OpenReadonly")); // Also open as readonly so that we can ShareReadOnlyToProcess. readonly_fd.reset(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY))); if (!readonly_fd.is_valid()) { @@ -153,6 +170,12 @@ return false; } } + + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466437 + // is fixed. + tracked_objects::ScopedTracker tracking_profile4( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "466437 SharedMemory::Create::Unlink")); // Deleting the file prevents anyone else from mapping it in (making it // private), and prevents the need for cleanup (once the last fd is // closed, it is truly freed). @@ -453,7 +476,7 @@ case SHARE_READONLY: // We could imagine re-opening the file from /dev/fd, but that can't make // it readonly on Mac: https://codereview.chromium.org/27265002/#msg10 - CHECK(readonly_mapped_file_ >= 0); + CHECK_GE(readonly_mapped_file_, 0); handle_to_dup = readonly_mapped_file_; break; }
diff --git a/base/message_loop/message_pump_default.h b/base/message_loop/message_pump_default.h index d63e810..8aeaa62 100644 --- a/base/message_loop/message_pump_default.h +++ b/base/message_loop/message_pump_default.h
@@ -38,4 +38,4 @@ } // namespace base -#endif // BASE__MESSAGE_LOOPMESSAGE_PUMP_DEFAULT_H_ +#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_DEFAULT_H_
diff --git a/base/message_loop/message_pump_dispatcher.h b/base/message_loop/message_pump_dispatcher.h index 0dea226..5b1bd55 100644 --- a/base/message_loop/message_pump_dispatcher.h +++ b/base/message_loop/message_pump_dispatcher.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H -#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H +#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H_ +#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H_ #include <stdint.h> @@ -40,4 +40,4 @@ } // namespace base -#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H +#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_DISPATCHER_H_
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc index 5ef3a50..8226495 100644 --- a/base/message_loop/message_pump_win.cc +++ b/base/message_loop/message_pump_win.cc
@@ -673,7 +673,7 @@ // |IOHandler| is at least pointer-size aligned, so the lowest two bits are // always cleared. We use the lowest bit to distinguish completion keys with // and without the associated |IOContext|. - DCHECK((key & 1) == 0); + DCHECK_EQ(key & 1, 0u); // Mark the completion key as context-less. if (!has_valid_io_context)
diff --git a/base/metrics/BUILD.gn b/base/metrics/BUILD.gn new file mode 100644 index 0000000..804e59b --- /dev/null +++ b/base/metrics/BUILD.gn
@@ -0,0 +1,49 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("metrics") { + sources = [ + "bucket_ranges.cc", + "bucket_ranges.h", + "field_trial.cc", + "field_trial.h", + "histogram.cc", + "histogram.h", + "histogram_base.cc", + "histogram_base.h", + "histogram_delta_serialization.", + "histogram_delta_serialization.cc", + "histogram_flattener.h", + "histogram_macros.h", + "histogram_samples.cc", + "histogram_samples.h", + "histogram_snapshot_manager.cc", + "histogram_snapshot_manager.h", + "sample_map.cc", + "sample_map.h", + "sample_vector.cc", + "sample_vector.h", + "sparse_histogram.cc", + "sparse_histogram.h", + "statistics_recorder.cc", + "statistics_recorder.h", + "user_metrics.cc", + "user_metrics.h", + "user_metrics_action.h", + ] + + if (is_nacl) { + sources -= [ "field_trial.cc" ] + } + + defines = [ "BASE_IMPLEMENTATION" ] + + deps = [ + "//base/debug", + "//base/json", + "//base/memory", + ] + + visibility = [ "//base/*" ] +}
diff --git a/base/numerics/safe_conversions.h b/base/numerics/safe_conversions.h index fe85fc6..d9b77f7 100644 --- a/base/numerics/safe_conversions.h +++ b/base/numerics/safe_conversions.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SAFE_CONVERSIONS_H_ -#define BASE_SAFE_CONVERSIONS_H_ +#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_H_ +#define BASE_NUMERICS_SAFE_CONVERSIONS_H_ #include <limits> @@ -60,5 +60,4 @@ } // namespace base -#endif // BASE_SAFE_CONVERSIONS_H_ - +#endif // BASE_NUMERICS_SAFE_CONVERSIONS_H_
diff --git a/base/numerics/safe_conversions_impl.h b/base/numerics/safe_conversions_impl.h index c26757a..504ce7e 100644 --- a/base/numerics/safe_conversions_impl.h +++ b/base/numerics/safe_conversions_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SAFE_CONVERSIONS_IMPL_H_ -#define BASE_SAFE_CONVERSIONS_IMPL_H_ +#ifndef BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ +#define BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ #include <limits> @@ -212,5 +212,4 @@ } // namespace internal } // namespace base -#endif // BASE_SAFE_CONVERSIONS_IMPL_H_ - +#endif // BASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h index ccda1c8..1309446 100644 --- a/base/numerics/safe_math.h +++ b/base/numerics/safe_math.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SAFE_MATH_H_ -#define BASE_SAFE_MATH_H_ +#ifndef BASE_NUMERICS_SAFE_MATH_H_ +#define BASE_NUMERICS_SAFE_MATH_H_ #include "base/numerics/safe_math_impl.h" @@ -269,4 +269,4 @@ } // namespace base -#endif // BASE_SAFE_MATH_H_ +#endif // BASE_NUMERICS_SAFE_MATH_H_
diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h index 663f393..c845189 100644 --- a/base/numerics/safe_math_impl.h +++ b/base/numerics/safe_math_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SAFE_MATH_IMPL_H_ -#define SAFE_MATH_IMPL_H_ +#ifndef BASE_NUMERICS_SAFE_MATH_IMPL_H_ +#define BASE_NUMERICS_SAFE_MATH_IMPL_H_ #include <stdint.h> @@ -498,4 +498,4 @@ } // namespace internal } // namespace base -#endif // SAFE_MATH_IMPL_H_ +#endif // BASE_NUMERICS_SAFE_MATH_IMPL_H_
diff --git a/base/observer_list.h b/base/observer_list.h index ef45269..f7b9267 100644 --- a/base/observer_list.h +++ b/base/observer_list.h
@@ -79,7 +79,7 @@ // also the FOR_EACH_OBSERVER macro defined below. class Iterator { public: - Iterator(ObserverListBase<ObserverType>& list); + explicit Iterator(ObserverListBase<ObserverType>* list); ~Iterator(); ObserverType* GetNext(); @@ -126,12 +126,11 @@ template <class ObserverType> ObserverListBase<ObserverType>::Iterator::Iterator( - ObserverListBase<ObserverType>& list) - : list_(list.AsWeakPtr()), + ObserverListBase<ObserverType>* list) + : list_(list->AsWeakPtr()), index_(0), - max_index_(list.type_ == NOTIFY_ALL ? - std::numeric_limits<size_t>::max() : - list.observers_.size()) { + max_index_(list->type_ == NOTIFY_ALL ? std::numeric_limits<size_t>::max() + : list->observers_.size()) { ++list_->notify_depth_; } @@ -228,15 +227,15 @@ } }; -#define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ - do { \ - if ((observer_list).might_have_observers()) { \ - ObserverListBase<ObserverType>::Iterator \ - it_inside_observer_macro(observer_list); \ - ObserverType* obs; \ - while ((obs = it_inside_observer_macro.GetNext()) != NULL) \ - obs->func; \ - } \ +#define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ + do { \ + if ((observer_list).might_have_observers()) { \ + ObserverListBase<ObserverType>::Iterator it_inside_observer_macro( \ + &observer_list); \ + ObserverType* obs; \ + while ((obs = it_inside_observer_macro.GetNext()) != NULL) \ + obs->func; \ + } \ } while (0) #endif // BASE_OBSERVER_LIST_H__
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h index 1a663337..46ce880 100644 --- a/base/observer_list_threadsafe.h +++ b/base/observer_list_threadsafe.h
@@ -199,6 +199,7 @@ scoped_refptr<base::MessageLoopProxy> loop; ObserverList<ObserverType> list; + private: DISALLOW_COPY_AND_ASSIGN(ObserverListContext); }; @@ -212,7 +213,6 @@ template <class Method, class Params> void NotifyWrapper(ObserverListContext* context, const UnboundMethod<ObserverType, Method, Params>& method) { - // Check that this list still needs notifications. { base::AutoLock lock(list_lock_); @@ -228,7 +228,7 @@ } { - typename ObserverList<ObserverType>::Iterator it(context->list); + typename ObserverList<ObserverType>::Iterator it(&context->list); ObserverType* obs; while ((obs = it.GetNext()) != NULL) method.Run(obs);
diff --git a/base/path_service.cc b/base/path_service.cc index ce4966e..3c437ee 100644 --- a/base/path_service.cc +++ b/base/path_service.cc
@@ -33,7 +33,7 @@ // Mac and Android. bool PathProviderPosix(int key, FilePath* result); #endif -} +} // namespace base namespace {
diff --git a/base/path_service.h b/base/path_service.h index 554eb9e..025550f 100644 --- a/base/path_service.h +++ b/base/path_service.h
@@ -15,7 +15,7 @@ namespace base { class FilePath; class ScopedPathOverride; -} // namespace +} // namespace base // The path service is a global table mapping keys to file system paths. It is // OK to use this service from multiple threads.
diff --git a/base/pending_task.h b/base/pending_task.h index a2edc69..fddfc86 100644 --- a/base/pending_task.h +++ b/base/pending_task.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PENDING_TASK_H_ -#define PENDING_TASK_H_ +#ifndef BASE_PENDING_TASK_H_ +#define BASE_PENDING_TASK_H_ #include <queue> @@ -57,4 +57,4 @@ } // namespace base -#endif // PENDING_TASK_H_ +#endif // BASE_PENDING_TASK_H_
diff --git a/base/pickle.cc b/base/pickle.cc index d461f41..6eb207f 100644 --- a/base/pickle.cc +++ b/base/pickle.cc
@@ -152,15 +152,15 @@ return true; } -bool PickleIterator::ReadWString(std::wstring* result) { +bool PickleIterator::ReadStringPiece(base::StringPiece* result) { int len; if (!ReadInt(&len)) return false; - const char* read_from = GetReadPointerAndAdvance(len, sizeof(wchar_t)); + const char* read_from = GetReadPointerAndAdvance(len); if (!read_from) return false; - result->assign(reinterpret_cast<const wchar_t*>(read_from), len); + *result = base::StringPiece(read_from, len); return true; } @@ -176,6 +176,19 @@ return true; } +bool PickleIterator::ReadStringPiece16(base::StringPiece16* result) { + int len; + if (!ReadInt(&len)) + return false; + const char* read_from = GetReadPointerAndAdvance(len, sizeof(char16)); + if (!read_from) + return false; + + *result = base::StringPiece16(reinterpret_cast<const char16*>(read_from), + len); + return true; +} + bool PickleIterator::ReadData(const char** data, int* length) { *length = 0; *data = 0; @@ -271,22 +284,14 @@ return *this; } -bool Pickle::WriteString(const std::string& value) { +bool Pickle::WriteString(const base::StringPiece& value) { if (!WriteInt(static_cast<int>(value.size()))) return false; return WriteBytes(value.data(), static_cast<int>(value.size())); } -bool Pickle::WriteWString(const std::wstring& value) { - if (!WriteInt(static_cast<int>(value.size()))) - return false; - - return WriteBytes(value.data(), - static_cast<int>(value.size() * sizeof(wchar_t))); -} - -bool Pickle::WriteString16(const string16& value) { +bool Pickle::WriteString16(const base::StringPiece16& value) { if (!WriteInt(static_cast<int>(value.size()))) return false;
diff --git a/base/pickle.h b/base/pickle.h index f2a198e..e6b9d81 100644 --- a/base/pickle.h +++ b/base/pickle.h
@@ -13,6 +13,7 @@ #include "base/gtest_prod_util.h" #include "base/logging.h" #include "base/strings/string16.h" +#include "base/strings/string_piece.h" class Pickle; @@ -39,8 +40,11 @@ bool ReadFloat(float* result) WARN_UNUSED_RESULT; bool ReadDouble(double* result) WARN_UNUSED_RESULT; bool ReadString(std::string* result) WARN_UNUSED_RESULT; - bool ReadWString(std::wstring* result) WARN_UNUSED_RESULT; + // The StringPiece data will only be valid for the lifetime of the message. + bool ReadStringPiece(base::StringPiece* result) WARN_UNUSED_RESULT; bool ReadString16(base::string16* result) WARN_UNUSED_RESULT; + // The StringPiece16 data will only be valid for the lifetime of the message. + bool ReadStringPiece16(base::StringPiece16* result) WARN_UNUSED_RESULT; // A pointer to the data will be placed in |*data|, and the length will be // placed in |*length|. The pointer placed into |*data| points into the @@ -195,9 +199,8 @@ bool WriteDouble(double value) { return WritePOD(value); } - bool WriteString(const std::string& value); - bool WriteWString(const std::wstring& value); - bool WriteString16(const base::string16& value); + bool WriteString(const base::StringPiece& value); + bool WriteString16(const base::StringPiece16& value); // "Data" is a blob with a length. When you read it out you will be given the // length. See also WriteBytes. bool WriteData(const char* data, int length);
diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc index 1fa1f32..a2c405c 100644 --- a/base/pickle_unittest.cc +++ b/base/pickle_unittest.cc
@@ -30,10 +30,13 @@ const std::string teststring("Hello world"); // note non-aligned string length const std::wstring testwstring(L"Hello, world"); const base::string16 teststring16(base::ASCIIToUTF16("Hello, world")); +const char testrawstring[] = "Hello new world"; // Test raw string writing +// Test raw char16 writing, assumes UTF16 encoding is ANSI for alpha chars. +const base::char16 testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0}; const char testdata[] = "AAA\0BBB\0"; const int testdatalen = arraysize(testdata) - 1; -// checks that the result +// checks that the results can be read correctly from the Pickle void VerifyResult(const Pickle& pickle) { PickleIterator iter(pickle); @@ -83,14 +86,18 @@ EXPECT_TRUE(iter.ReadString(&outstring)); EXPECT_EQ(teststring, outstring); - std::wstring outwstring; - EXPECT_TRUE(iter.ReadWString(&outwstring)); - EXPECT_EQ(testwstring, outwstring); - base::string16 outstring16; EXPECT_TRUE(iter.ReadString16(&outstring16)); EXPECT_EQ(teststring16, outstring16); + base::StringPiece outstringpiece; + EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece)); + EXPECT_EQ(testrawstring, outstringpiece); + + base::StringPiece16 outstringpiece16; + EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16)); + EXPECT_EQ(testrawstring16, outstringpiece16); + const char* outdata; int outdatalen; EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen)); @@ -119,8 +126,9 @@ EXPECT_TRUE(pickle.WriteFloat(testfloat)); EXPECT_TRUE(pickle.WriteDouble(testdouble)); EXPECT_TRUE(pickle.WriteString(teststring)); - EXPECT_TRUE(pickle.WriteWString(testwstring)); EXPECT_TRUE(pickle.WriteString16(teststring16)); + EXPECT_TRUE(pickle.WriteString(testrawstring)); + EXPECT_TRUE(pickle.WriteString16(testrawstring16)); EXPECT_TRUE(pickle.WriteData(testdata, testdatalen)); VerifyResult(pickle); @@ -198,9 +206,9 @@ EXPECT_EQ("", outstr); } -TEST(PickleTest, ZeroLenWStr) { +TEST(PickleTest, ZeroLenStr16) { Pickle pickle; - EXPECT_TRUE(pickle.WriteWString(std::wstring())); + EXPECT_TRUE(pickle.WriteString16(base::string16())); PickleIterator iter(pickle); std::string outstr; @@ -217,13 +225,13 @@ EXPECT_FALSE(iter.ReadString(&outstr)); } -TEST(PickleTest, BadLenWStr) { +TEST(PickleTest, BadLenStr16) { Pickle pickle; EXPECT_TRUE(pickle.WriteInt(-1)); PickleIterator iter(pickle); - std::wstring woutstr; - EXPECT_FALSE(iter.ReadWString(&woutstr)); + base::string16 outstr; + EXPECT_FALSE(iter.ReadString16(&outstr)); } TEST(PickleTest, FindNext) { @@ -391,13 +399,6 @@ EXPECT_TRUE(bad_len.WriteInt(1 << 31)); iter = PickleIterator(bad_len); EXPECT_FALSE(iter.ReadString16(&str16)); - - // Check we don't fail in a length check with large WStrings. - Pickle big_len; - EXPECT_TRUE(big_len.WriteInt(1 << 30)); - iter = PickleIterator(big_len); - std::wstring wstr; - EXPECT_FALSE(iter.ReadWString(&wstr)); } // Check we can write zero bytes of data and 'data' can be NULL.
diff --git a/base/posix/unix_domain_socket_linux.cc b/base/posix/unix_domain_socket_linux.cc index 203285b..16d8eaa 100644 --- a/base/posix/unix_domain_socket_linux.cc +++ b/base/posix/unix_domain_socket_linux.cc
@@ -136,8 +136,8 @@ const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0); if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - DCHECK(payload_len % sizeof(int) == 0); - DCHECK(wire_fds == NULL); + DCHECK_EQ(payload_len % sizeof(int), 0u); + DCHECK_EQ(wire_fds, static_cast<void*>(nullptr)); wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); wire_fds_len = payload_len / sizeof(int); } @@ -146,8 +146,8 @@ // SCM_CREDENTIALS. if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) { - DCHECK(payload_len == sizeof(struct ucred)); - DCHECK(pid == -1); + DCHECK_EQ(payload_len, sizeof(struct ucred)); + DCHECK_EQ(pid, -1); pid = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg))->pid; } #endif
diff --git a/base/prefs/base_prefs_switches.cc b/base/prefs/base_prefs_switches.cc deleted file mode 100644 index 304248b..0000000 --- a/base/prefs/base_prefs_switches.cc +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/prefs/base_prefs_switches.h" - -namespace switches { - -// Pretty-prints pref JSON files. -const char kPrettyPrintPrefs[] = "pretty-print-prefs"; - -} // namespace switches
diff --git a/base/prefs/base_prefs_switches.h b/base/prefs/base_prefs_switches.h deleted file mode 100644 index 7a6b665..0000000 --- a/base/prefs/base_prefs_switches.h +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_PREFS_BASE_PREFS_SWITCHES_H_ -#define BASE_PREFS_BASE_PREFS_SWITCHES_H_ - -namespace switches { - -extern const char kPrettyPrintPrefs[]; - -} // namespace switches - -#endif // BASE_PREFS_BASE_PREFS_SWITCHES_H_
diff --git a/base/prefs/json_pref_store.cc b/base/prefs/json_pref_store.cc index 2e34b50..47cd424 100644 --- a/base/prefs/json_pref_store.cc +++ b/base/prefs/json_pref_store.cc
@@ -8,14 +8,12 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/json/json_file_value_serializer.h" #include "base/json/json_string_value_serializer.h" #include "base/memory/ref_counted.h" #include "base/metrics/histogram.h" -#include "base/prefs/base_prefs_switches.h" #include "base/prefs/pref_filter.h" #include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" @@ -400,10 +398,10 @@ pref_filter_->FilterSerializeData(prefs_.get()); JSONStringValueSerializer serializer(output); - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kPrettyPrintPrefs)) { - serializer.set_pretty_print(true); - } + // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain + // readable prefs for debugging purposes, you can dump your prefs into any + // command-line or online JSON pretty printing tool. + serializer.set_pretty_print(false); return serializer.Serialize(*prefs_); }
diff --git a/base/prefs/pref_member.h b/base/prefs/pref_member.h index b47cae2..078be95 100644 --- a/base/prefs/pref_member.h +++ b/base/prefs/pref_member.h
@@ -273,6 +273,7 @@ // tree. mutable ValueType value_; + private: DISALLOW_COPY_AND_ASSIGN(Internal); };
diff --git a/base/prefs/pref_notifier_impl.cc b/base/prefs/pref_notifier_impl.cc index 6bf9603..7ae5fe6 100644 --- a/base/prefs/pref_notifier_impl.cc +++ b/base/prefs/pref_notifier_impl.cc
@@ -22,7 +22,7 @@ // Verify that there are no pref observers when we shut down. for (PrefObserverMap::iterator it = pref_observers_.begin(); it != pref_observers_.end(); ++it) { - PrefObserverList::Iterator obs_iterator(*(it->second)); + PrefObserverList::Iterator obs_iterator(it->second); if (obs_iterator.GetNext()) { LOG(WARNING) << "pref observer found at shutdown " << it->first; }
diff --git a/base/prefs/pref_notifier_impl_unittest.cc b/base/prefs/pref_notifier_impl_unittest.cc index 0ecf138..c3cbf4f 100644 --- a/base/prefs/pref_notifier_impl_unittest.cc +++ b/base/prefs/pref_notifier_impl_unittest.cc
@@ -58,7 +58,7 @@ return false; PrefObserverList* observer_list = observer_iterator->second; - PrefObserverList::Iterator it(*observer_list); + PrefObserverList::Iterator it(observer_list); PrefObserver* existing_obs; size_t count = 0; while ((existing_obs = it.GetNext()) != NULL) {
diff --git a/base/process/BUILD.gn b/base/process/BUILD.gn new file mode 100644 index 0000000..125b451 --- /dev/null +++ b/base/process/BUILD.gn
@@ -0,0 +1,107 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("process") { + sources = [ + "internal_linux.cc", + "internal_linux.h", + "kill.cc", + "kill.h", + "kill_mac.cc", + "kill_posix.cc", + "kill_win.cc", + "launch.cc", + "launch.h", + "launch_ios.cc", + "launch_mac.cc", + "launch_posix.cc", + "launch_win.cc", + "memory.cc", + "memory.h", + "memory_linux.cc", + "memory_mac.mm", + "memory_win.cc", + "process.h", + "process_handle_freebsd.cc", + "process_handle_linux.cc", + "process_handle_mac.cc", + "process_handle_openbsd.cc", + "process_handle_posix.cc", + "process_handle_win.cc", + "process_info.h", + "process_info_linux.cc", + "process_info_mac.cc", + "process_info_win.cc", + "process_iterator.cc", + "process_iterator.h", + "process_iterator_freebsd.cc", + "process_iterator_linux.cc", + "process_iterator_mac.cc", + "process_iterator_openbsd.cc", + "process_iterator_win.cc", + "process_linux.cc", + "process_metrics.cc", + "process_metrics.h", + "process_metrics_freebsd.cc", + "process_metrics_ios.cc", + "process_metrics_linux.cc", + "process_metrics_mac.cc", + "process_metrics_openbsd.cc", + "process_metrics_posix.cc", + "process_metrics_win.cc", + "process_posix.cc", + "process_win.cc", + ] + + sources -= [ + "process_handle_freebsd.cc", + "process_handle_openbsd.cc", + "process_iterator_freebsd.cc", + "process_iterator_openbsd.cc", + "process_metrics_freebsd.cc", + "process_metrics_openbsd.cc", + ] + + if (is_android) { + # Android uses some Linux sources, put those back. + set_sources_assignment_filter([]) + sources += [ + "internal_linux.cc", + "memory_linux.cc", + "process_handle_linux.cc", + "process_iterator_linux.cc", + "process_metrics_linux.cc", + ] + set_sources_assignment_filter(sources_assignment_filter) + } + + if (is_nacl) { + sources -= [ + "kill.cc", + "kill.h", + "kill_posix.cc", + "launch.cc", + "launch.h", + "launch_posix.cc", + "memory.cc", + "memory.h", + "process_iterator.cc", + "process_iterator.h", + "process_metrics.cc", + "process_metrics_posix.cc", + "process_posix.cc", + ] + } + + defines = [ "BASE_IMPLEMENTATION" ] + + deps = [ + "//base/memory", + "//base/third_party/dynamic_annotations", + ] + + allow_circular_includes_from = [ "//base/memory" ] + + visibility = [ "//base/*" ] +}
diff --git a/base/process/internal_linux.h b/base/process/internal_linux.h index 5fc3356..1837f94 100644 --- a/base/process/internal_linux.h +++ b/base/process/internal_linux.h
@@ -5,8 +5,8 @@ // This file contains internal routines that are called by other files in // base/process/. -#ifndef BASE_PROCESS_LINUX_INTERNAL_H_ -#define BASE_PROCESS_LINUX_INTERNAL_H_ +#ifndef BASE_PROCESS_INTERNAL_LINUX_H_ +#define BASE_PROCESS_INTERNAL_LINUX_H_ #include <unistd.h> @@ -87,4 +87,4 @@ } // namespace internal } // namespace base -#endif // BASE_PROCESS_LINUX_INTERNAL_H_ +#endif // BASE_PROCESS_INTERNAL_LINUX_H_
diff --git a/base/process/kill_mac.cc b/base/process/kill_mac.cc index 8c42400..a4e0a14 100644 --- a/base/process/kill_mac.cc +++ b/base/process/kill_mac.cc
@@ -66,8 +66,8 @@ // work in that case, but waitpid won't, and killing a non-child might not be // the best approach. void WaitForChildToDie(pid_t child, int timeout) { - DCHECK(child > 0); - DCHECK(timeout > 0); + DCHECK_GT(child, 0); + DCHECK_GT(timeout, 0); // DON'T ADD ANY EARLY RETURNS TO THIS FUNCTION without ensuring that // |child| has been reaped. Specifically, even if a kqueue, kevent, or other
diff --git a/base/process/memory.cc b/base/process/memory.cc index 1dbc363..8542dc5 100644 --- a/base/process/memory.cc +++ b/base/process/memory.cc
@@ -27,4 +27,4 @@ #endif -} +} // namespace base
diff --git a/base/process/process.h b/base/process/process.h index a834a29..41eef10 100644 --- a/base/process/process.h +++ b/base/process/process.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_PROCESS_PROCESS_PROCESS_H_ -#define BASE_PROCESS_PROCESS_PROCESS_H_ +#ifndef BASE_PROCESS_PROCESS_H_ +#define BASE_PROCESS_PROCESS_H_ #include "base/base_export.h" #include "base/basictypes.h" @@ -92,9 +92,11 @@ void Close(); // Terminates the process with extreme prejudice. The given |result_code| will - // be the exit code of the process. + // be the exit code of the process. If |wait| is true, this method will wait + // for up to one minute for the process to actually terminate. + // Returns true if the process terminates within the allowed time. // NOTE: On POSIX |result_code| is ignored. - void Terminate(int result_code); + bool Terminate(int result_code, bool wait) const; // Waits for the process to exit. Returns true on success. // On POSIX, if the process has been signaled then |exit_code| is set to -1. @@ -130,4 +132,4 @@ } // namespace base -#endif // BASE_PROCESS_PROCESS_PROCESS_H_ +#endif // BASE_PROCESS_PROCESS_H_
diff --git a/base/process/process_linux.cc b/base/process/process_linux.cc index 59ee288..88a310e 100644 --- a/base/process/process_linux.cc +++ b/base/process/process_linux.cc
@@ -103,7 +103,7 @@ &proc)) { std::vector<std::string> proc_parts; base::SplitString(proc, ':', &proc_parts); - DCHECK(proc_parts.size() == 3); + DCHECK_EQ(proc_parts.size(), 3u); bool ret = proc_parts[2] == std::string(kBackground); return ret; } else {
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc index dbfaa1a..76767b0 100644 --- a/base/process/process_metrics_unittest.cc +++ b/base/process/process_metrics_unittest.cc
@@ -143,29 +143,29 @@ "Hugepagesize: 4096 kB\n"; EXPECT_TRUE(ParseProcMeminfo(valid_input1, &meminfo)); - EXPECT_TRUE(meminfo.total == 3981504); - EXPECT_TRUE(meminfo.free == 140764); - EXPECT_TRUE(meminfo.buffers == 116480); - EXPECT_TRUE(meminfo.cached == 406160); - EXPECT_TRUE(meminfo.active_anon == 2972352); - EXPECT_TRUE(meminfo.active_file == 179688); - EXPECT_TRUE(meminfo.inactive_anon == 270108); - EXPECT_TRUE(meminfo.inactive_file == 202748); - EXPECT_TRUE(meminfo.swap_total == 5832280); - EXPECT_TRUE(meminfo.swap_free == 3672368); - EXPECT_TRUE(meminfo.dirty == 184); + EXPECT_EQ(meminfo.total, 3981504); + EXPECT_EQ(meminfo.free, 140764); + EXPECT_EQ(meminfo.buffers, 116480); + EXPECT_EQ(meminfo.cached, 406160); + EXPECT_EQ(meminfo.active_anon, 2972352); + EXPECT_EQ(meminfo.active_file, 179688); + EXPECT_EQ(meminfo.inactive_anon, 270108); + EXPECT_EQ(meminfo.inactive_file, 202748); + EXPECT_EQ(meminfo.swap_total, 5832280); + EXPECT_EQ(meminfo.swap_free, 3672368); + EXPECT_EQ(meminfo.dirty, 184); #if defined(OS_CHROMEOS) - EXPECT_TRUE(meminfo.shmem == 140204); - EXPECT_TRUE(meminfo.slab == 54212); + EXPECT_EQ(meminfo.shmem, 140204); + EXPECT_EQ(meminfo.slab, 54212); #endif EXPECT_TRUE(ParseProcMeminfo(valid_input2, &meminfo)); - EXPECT_TRUE(meminfo.total == 255908); - EXPECT_TRUE(meminfo.free == 69936); - EXPECT_TRUE(meminfo.buffers == 15812); - EXPECT_TRUE(meminfo.cached == 115124); - EXPECT_TRUE(meminfo.swap_total == 524280); - EXPECT_TRUE(meminfo.swap_free == 524200); - EXPECT_TRUE(meminfo.dirty == 4); + EXPECT_EQ(meminfo.total, 255908); + EXPECT_EQ(meminfo.free, 69936); + EXPECT_EQ(meminfo.buffers, 15812); + EXPECT_EQ(meminfo.cached, 115124); + EXPECT_EQ(meminfo.swap_total, 524280); + EXPECT_EQ(meminfo.swap_free, 524200); + EXPECT_EQ(meminfo.dirty, 4); } TEST_F(SystemMetricsTest, ParseVmstat) { @@ -260,13 +260,13 @@ "pgrefill_high 0\n" "pgrefill_movable 0\n"; EXPECT_TRUE(ParseProcVmstat(valid_input1, &meminfo)); - EXPECT_TRUE(meminfo.pswpin == 179); - EXPECT_TRUE(meminfo.pswpout == 406); - EXPECT_TRUE(meminfo.pgmajfault == 487192); + EXPECT_EQ(meminfo.pswpin, 179); + EXPECT_EQ(meminfo.pswpout, 406); + EXPECT_EQ(meminfo.pgmajfault, 487192); EXPECT_TRUE(ParseProcVmstat(valid_input2, &meminfo)); - EXPECT_TRUE(meminfo.pswpin == 12); - EXPECT_TRUE(meminfo.pswpout == 901); - EXPECT_TRUE(meminfo.pgmajfault == 2023); + EXPECT_EQ(meminfo.pswpin, 12); + EXPECT_EQ(meminfo.pswpout, 901); + EXPECT_EQ(meminfo.pgmajfault, 2023); } #endif // defined(OS_LINUX) || defined(OS_ANDROID)
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc index a36bf77..1c4210b 100644 --- a/base/process/process_posix.cc +++ b/base/process/process_posix.cc
@@ -287,12 +287,13 @@ // end up w/ a zombie when it does finally exit. } -void Process::Terminate(int result_code) { +bool Process::Terminate(int result_code, bool wait) const { // result_code isn't supportable. DCHECK(IsValid()); // We don't wait here. It's the responsibility of other code to reap the // child. - KillProcess(process_, result_code, false); + // TODO(rvargas) crbug/417532: Move the implementation here. + return KillProcess(process_, result_code, wait); } bool Process::WaitForExit(int* exit_code) { @@ -324,4 +325,4 @@ return getpriority(PRIO_PROCESS, process_); } -} // namspace base +} // namespace base
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc index 535a36f..ba8e4e6 100644 --- a/base/process/process_unittest.cc +++ b/base/process/process_unittest.cc
@@ -123,7 +123,7 @@ exit_code = kDummyExitCode; int kExpectedExitCode = 250; - process.Terminate(kExpectedExitCode); + process.Terminate(kExpectedExitCode, false); process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), &exit_code); @@ -160,7 +160,7 @@ EXPECT_FALSE(process.WaitForExitWithTimeout(timeout, &exit_code)); EXPECT_EQ(kDummyExitCode, exit_code); - process.Terminate(kDummyExitCode); + process.Terminate(kDummyExitCode, false); } // Ensure that the priority of a process is restored correctly after
diff --git a/base/process/process_win.cc b/base/process/process_win.cc index b62fdb4..32da8ab 100644 --- a/base/process/process_win.cc +++ b/base/process/process_win.cc
@@ -123,17 +123,10 @@ process_.Close(); } -void Process::Terminate(int result_code) { +bool Process::Terminate(int result_code, bool wait) const { DCHECK(IsValid()); - - // Call NtTerminateProcess directly, without going through the import table, - // which might have been hooked with a buggy replacement by third party - // software. http://crbug.com/81449. - HMODULE module = GetModuleHandle(L"ntdll.dll"); - typedef UINT (WINAPI *TerminateProcessPtr)(HANDLE handle, UINT code); - TerminateProcessPtr terminate_process = reinterpret_cast<TerminateProcessPtr>( - GetProcAddress(module, "NtTerminateProcess")); - terminate_process(Handle(), result_code); + // TODO(rvargas) crbug/417532: Move the implementation here. + return KillProcess(Handle(), result_code, wait); } bool Process::WaitForExit(int* exit_code) {
diff --git a/base/scoped_generic.h b/base/scoped_generic.h index da42609..f6807e2 100644 --- a/base/scoped_generic.h +++ b/base/scoped_generic.h
@@ -53,7 +53,7 @@ // typedef ScopedGeneric<int, FooScopedTraits> ScopedFoo; template<typename T, typename Traits> class ScopedGeneric { - MOVE_ONLY_TYPE_FOR_CPP_03(ScopedGeneric, RValue) + MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(ScopedGeneric) private: // This must be first since it's used inline below. @@ -83,15 +83,21 @@ : data_(value, traits) { } - // Move constructor for C++03 move emulation. - ScopedGeneric(RValue rvalue) - : data_(rvalue.object->release(), rvalue.object->get_traits()) { + // Move constructor. Allows initialization from a ScopedGeneric rvalue. + ScopedGeneric(ScopedGeneric<T, Traits>&& rvalue) + : data_(rvalue.release(), rvalue.get_traits()) { } ~ScopedGeneric() { FreeIfNecessary(); } + // operator=. Allows assignment from a ScopedGeneric rvalue. + ScopedGeneric& operator=(ScopedGeneric<T, Traits>&& rvalue) { + reset(rvalue.release()); + return *this; + } + // Frees the currently owned object, if any. Then takes ownership of a new // object, if given. Self-resets are not allowd as on scoped_ptr. See // http://crbug.com/162971
diff --git a/base/scoped_generic_unittest.cc b/base/scoped_generic_unittest.cc index f0dca22..b28e154 100644 --- a/base/scoped_generic_unittest.cc +++ b/base/scoped_generic_unittest.cc
@@ -85,7 +85,7 @@ EXPECT_EQ(kSecond, values_freed[1]); values_freed.clear(); - // Pass. + // Pass constructor. { ScopedInt a(kFirst, traits); ScopedInt b(a.Pass()); @@ -93,8 +93,25 @@ ASSERT_EQ(IntTraits::InvalidValue(), a.get()); ASSERT_EQ(kFirst, b.get()); } + ASSERT_EQ(1u, values_freed.size()); ASSERT_EQ(kFirst, values_freed[0]); + values_freed.clear(); + + // Pass assign. + { + ScopedInt a(kFirst, traits); + ScopedInt b(kSecond, traits); + b = a.Pass(); + ASSERT_EQ(1u, values_freed.size()); + EXPECT_EQ(kSecond, values_freed[0]); + ASSERT_EQ(IntTraits::InvalidValue(), a.get()); + ASSERT_EQ(kFirst, b.get()); + } + + ASSERT_EQ(2u, values_freed.size()); + EXPECT_EQ(kFirst, values_freed[1]); + values_freed.clear(); } TEST(ScopedGenericTest, Operators) {
diff --git a/base/scoped_native_library.h b/base/scoped_native_library.h index e9923f4..c0e93f3 100644 --- a/base/scoped_native_library.h +++ b/base/scoped_native_library.h
@@ -49,4 +49,4 @@ } // namespace base -#endif // BASE_MEMORY_NATIVE_LIBRARY_H_ +#endif // BASE_SCOPED_NATIVE_LIBRARY_H_
diff --git a/base/sequenced_task_runner.h b/base/sequenced_task_runner.h index 71dcf05..6bb3f2b 100644 --- a/base/sequenced_task_runner.h +++ b/base/sequenced_task_runner.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SEQUENCED_TASKRUNNER_H_ -#define BASE_SEQUENCED_TASKRUNNER_H_ +#ifndef BASE_SEQUENCED_TASK_RUNNER_H_ +#define BASE_SEQUENCED_TASK_RUNNER_H_ #include "base/base_export.h" #include "base/sequenced_task_runner_helpers.h" @@ -156,4 +156,4 @@ } // namespace base -#endif // BASE_SEQUENCED_TASKRUNNER_H_ +#endif // BASE_SEQUENCED_TASK_RUNNER_H_
diff --git a/base/stl_util_unittest.cc b/base/stl_util_unittest.cc index 06ea7cd..42004eb 100644 --- a/base/stl_util_unittest.cc +++ b/base/stl_util_unittest.cc
@@ -28,7 +28,7 @@ int value_; }; -} +} // namespace namespace base { namespace {
diff --git a/base/strings/nullable_string16.h b/base/strings/nullable_string16.h index 5997d17..016c25c 100644 --- a/base/strings/nullable_string16.h +++ b/base/strings/nullable_string16.h
@@ -41,6 +41,6 @@ BASE_EXPORT std::ostream& operator<<(std::ostream& out, const NullableString16& value); -} // namespace +} // namespace base #endif // BASE_STRINGS_NULLABLE_STRING16_H_
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc index 7f50cfb..5336603 100644 --- a/base/strings/string_piece_unittest.cc +++ b/base/strings/string_piece_unittest.cc
@@ -602,13 +602,13 @@ // check comparison operations on strings longer than 4 bytes. ASSERT_TRUE(abc == BasicStringPiece<TypeParam>(alphabet)); - ASSERT_TRUE(abc.compare(BasicStringPiece<TypeParam>(alphabet)) == 0); + ASSERT_EQ(abc.compare(BasicStringPiece<TypeParam>(alphabet)), 0); ASSERT_TRUE(abc < BasicStringPiece<TypeParam>(alphabet_z)); - ASSERT_TRUE(abc.compare(BasicStringPiece<TypeParam>(alphabet_z)) < 0); + ASSERT_LT(abc.compare(BasicStringPiece<TypeParam>(alphabet_z)), 0); ASSERT_TRUE(abc > BasicStringPiece<TypeParam>(alphabet_y)); - ASSERT_TRUE(abc.compare(BasicStringPiece<TypeParam>(alphabet_y)) > 0); + ASSERT_GT(abc.compare(BasicStringPiece<TypeParam>(alphabet_y)), 0); } // Test operations only supported by std::string version.
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc index 7ef4760..692f300 100644 --- a/base/strings/string_split.cc +++ b/base/strings/string_split.cc
@@ -138,9 +138,9 @@ char c, std::vector<std::string>* r) { #if CHAR_MIN < 0 - DCHECK(c >= 0); + DCHECK_GE(c, 0); #endif - DCHECK(c < 0x7F); + DCHECK_LT(c, 0x7F); SplitStringT(str, c, true, r); } @@ -195,9 +195,9 @@ std::vector<std::string>* r) { DCHECK(IsStringUTF8(str)); #if CHAR_MIN < 0 - DCHECK(c >= 0); + DCHECK_GE(c, 0); #endif - DCHECK(c < 0x7F); + DCHECK_LT(c, 0x7F); SplitStringT(str, c, false, r); }
diff --git a/base/strings/sys_string_conversions_unittest.cc b/base/strings/sys_string_conversions_unittest.cc index d2d38e4..0cdd428 100644 --- a/base/strings/sys_string_conversions_unittest.cc +++ b/base/strings/sys_string_conversions_unittest.cc
@@ -75,7 +75,9 @@ #if defined(OS_LINUX) // Tests depend on setting a specific Linux locale. TEST(SysStrings, SysWideToNativeMB) { +#if !defined(SYSTEM_NATIVE_UTF8) ScopedLocale locale("en_US.utf-8"); +#endif EXPECT_EQ("Hello, world", SysWideToNativeMB(L"Hello, world")); EXPECT_EQ("\xe4\xbd\xa0\xe5\xa5\xbd", SysWideToNativeMB(L"\x4f60\x597d")); @@ -105,7 +107,9 @@ // We assume the test is running in a UTF8 locale. TEST(SysStrings, SysNativeMBToWide) { +#if !defined(SYSTEM_NATIVE_UTF8) ScopedLocale locale("en_US.utf-8"); +#endif EXPECT_EQ(L"Hello, world", SysNativeMBToWide("Hello, world")); EXPECT_EQ(L"\x4f60\x597d", SysNativeMBToWide("\xe4\xbd\xa0\xe5\xa5\xbd")); // >16 bits @@ -159,7 +163,9 @@ TEST(SysStrings, SysNativeMBAndWide) { +#if !defined(SYSTEM_NATIVE_UTF8) ScopedLocale locale("en_US.utf-8"); +#endif for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) { std::wstring wide = kConvertRoundtripCases[i]; std::wstring trip = SysNativeMBToWide(SysWideToNativeMB(wide));
diff --git a/base/strings/utf_offset_string_conversions_unittest.cc b/base/strings/utf_offset_string_conversions_unittest.cc index 529939f..9398a56 100644 --- a/base/strings/utf_offset_string_conversions_unittest.cc +++ b/base/strings/utf_offset_string_conversions_unittest.cc
@@ -293,4 +293,4 @@ EXPECT_EQ(2u, adjustments_on_adjusted_string[5].output_length); } -} // namaspace base +} // namespace base
diff --git a/base/strings/utf_string_conversions_unittest.cc b/base/strings/utf_string_conversions_unittest.cc index 009af7c..a7b12ff 100644 --- a/base/strings/utf_string_conversions_unittest.cc +++ b/base/strings/utf_string_conversions_unittest.cc
@@ -208,4 +208,4 @@ EXPECT_EQ(expected, converted); } -} // base +} // namespace base
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc index b62aed9..245097f 100644 --- a/base/sys_info_android.cc +++ b/base/sys_info_android.cc
@@ -60,7 +60,7 @@ // version to avoid unnecessarily comparison errors with the latest release. // This should be manually kept up-to-date on each Android release. const int kDefaultAndroidMajorVersion = 5; -const int kDefaultAndroidMinorVersion = 0; +const int kDefaultAndroidMinorVersion = 1; const int kDefaultAndroidBugfixVersion = 99; // Parse out the OS version numbers from the system properties.
diff --git a/base/sys_info_linux.cc b/base/sys_info_linux.cc index 2e679ed..c698f91 100644 --- a/base/sys_info_linux.cc +++ b/base/sys_info_linux.cc
@@ -43,7 +43,7 @@ if (limit > std::numeric_limits<size_t>::max()) { limit = 0; } - DCHECK(limit > 0); + DCHECK_GT(limit, 0u); return static_cast<size_t>(limit); }
diff --git a/base/system_monitor/system_monitor_unittest.cc b/base/system_monitor/system_monitor_unittest.cc index d63bc3d..f3db4c7 100644 --- a/base/system_monitor/system_monitor_unittest.cc +++ b/base/system_monitor/system_monitor_unittest.cc
@@ -23,6 +23,7 @@ MessageLoop message_loop_; scoped_ptr<SystemMonitor> system_monitor_; + private: DISALLOW_COPY_AND_ASSIGN(SystemMonitorTest); };
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index 120159e..55e710d 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn
@@ -8,6 +8,20 @@ import("//build/config/android/rules.gni") } +source_set("test_config") { + # TODO http://crbug.com/412064 enable this flag all the time. + testonly = !is_component_build + sources = [ + "test_switches.cc", + "test_switches.h", + "test_timeouts.cc", + "test_timeouts.h", + ] + deps = [ + "//base", + ] +} + # GYP: //base/base.gyp:test_support_base source_set("test_support") { # TODO http://crbug.com/412064 enable this flag all the time. @@ -94,10 +108,6 @@ "test_support_android.h", "test_support_ios.h", "test_support_ios.mm", - "test_switches.cc", - "test_switches.h", - "test_timeouts.cc", - "test_timeouts.h", "thread_test_helper.cc", "thread_test_helper.h", "trace_event_analyzer.cc", @@ -109,6 +119,7 @@ ] public_deps = [ + ":test_config", "//base", "//base:i18n", "//base:base_static",
diff --git a/base/test/histogram_tester.cc b/base/test/histogram_tester.cc index 412059a..ea738b0 100644 --- a/base/test/histogram_tester.cc +++ b/base/test/histogram_tester.cc
@@ -90,7 +90,7 @@ const std::string& name, base::HistogramBase::Sample sample, base::HistogramBase::Count expected_count, - base::HistogramSamples& samples) const { + const base::HistogramSamples& samples) const { int actual_count = samples.GetCount(sample); std::map<std::string, HistogramSamples*>::const_iterator histogram_data; histogram_data = histograms_snapshot_.find(name); @@ -104,9 +104,10 @@ << ")."; } -void HistogramTester::CheckTotalCount(const std::string& name, - base::HistogramBase::Count expected_count, - base::HistogramSamples& samples) const { +void HistogramTester::CheckTotalCount( + const std::string& name, + base::HistogramBase::Count expected_count, + const base::HistogramSamples& samples) const { int actual_count = samples.TotalCount(); std::map<std::string, HistogramSamples*>::const_iterator histogram_data; histogram_data = histograms_snapshot_.find(name);
diff --git a/base/test/histogram_tester.h b/base/test/histogram_tester.h index b672308..96317f9 100644 --- a/base/test/histogram_tester.h +++ b/base/test/histogram_tester.h
@@ -59,14 +59,14 @@ void CheckBucketCount(const std::string& name, base::HistogramBase::Sample sample, base::Histogram::Count expected_count, - base::HistogramSamples& samples) const; + const base::HistogramSamples& samples) const; // Verifies that the total number of values recorded for the histogram |name| // is |expected_count|. This is checked against |samples| minus the snapshot // that was taken for |name|. void CheckTotalCount(const std::string& name, base::Histogram::Count expected_count, - base::HistogramSamples& samples) const; + const base::HistogramSamples& samples) const; // Used to determine the histogram changes made during this instance's // lifecycle. This instance takes ownership of the samples, which are deleted
diff --git a/base/test/mock_devices_changed_observer.h b/base/test/mock_devices_changed_observer.h index 3ada16b..3255002 100644 --- a/base/test/mock_devices_changed_observer.h +++ b/base/test/mock_devices_changed_observer.h
@@ -21,6 +21,7 @@ MOCK_METHOD1(OnDevicesChanged, void(base::SystemMonitor::DeviceType device_type)); + private: DISALLOW_COPY_AND_ASSIGN(MockDevicesChangedObserver); };
diff --git a/base/test/null_task_runner.cc b/base/test/null_task_runner.cc index bf43e6d..ffa6bdf 100644 --- a/base/test/null_task_runner.cc +++ b/base/test/null_task_runner.cc
@@ -28,4 +28,4 @@ return true; } -} // namespace +} // namespace base
diff --git a/base/test/null_task_runner.h b/base/test/null_task_runner.h index 2cde880..0f44751 100644 --- a/base/test/null_task_runner.h +++ b/base/test/null_task_runner.h
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef BASE_TEST_NULL_TASK_RUNNER_H_ +#define BASE_TEST_NULL_TASK_RUNNER_H_ + #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/single_thread_task_runner.h" @@ -30,4 +33,6 @@ DISALLOW_COPY_AND_ASSIGN(NullTaskRunner); }; -} // namespace +} // namespace base + +#endif // BASE_TEST_NULL_TASK_RUNNER_H_
diff --git a/base/test/sequenced_task_runner_test_template.h b/base/test/sequenced_task_runner_test_template.h index 48f5354..c208d3c 100644 --- a/base/test/sequenced_task_runner_test_template.h +++ b/base/test/sequenced_task_runner_test_template.h
@@ -6,8 +6,8 @@ // pass in order to be conformant. See task_runner_test_template.h for a // description of how to use the constructs in this file; these work the same. -#ifndef BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ -#define BASE_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ +#ifndef BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ +#define BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_ #include <cstddef> #include <iosfwd> @@ -338,4 +338,4 @@ } // namespace base -#endif // BASE_TASK_RUNNER_TEST_TEMPLATE_H_ +#endif // BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
diff --git a/base/test/sequenced_worker_pool_owner.h b/base/test/sequenced_worker_pool_owner.h index b52dd67..bf5f2f7 100644 --- a/base/test/sequenced_worker_pool_owner.h +++ b/base/test/sequenced_worker_pool_owner.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_UNITTEST_H_ -#define BASE_THREADING_SEQUENCED_WORKER_POOL_UNITTEST_H_ +#ifndef BASE_TEST_SEQUENCED_WORKER_POOL_OWNER_H_ +#define BASE_TEST_SEQUENCED_WORKER_POOL_OWNER_H_ #include <cstddef> #include <string> @@ -58,4 +58,4 @@ } // namespace base -#endif // BASE_THREADING_SEQUENCED_WORKER_POOL_UNITTEST_H_ +#endif // BASE_TEST_SEQUENCED_WORKER_POOL_OWNER_H_
diff --git a/base/test/simple_test_clock.h b/base/test/simple_test_clock.h index e8a79c5..a70f99c 100644 --- a/base/test/simple_test_clock.h +++ b/base/test/simple_test_clock.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SIMPLE_TEST_CLOCK_H_ -#define BASE_SIMPLE_TEST_CLOCK_H_ +#ifndef BASE_TEST_SIMPLE_TEST_CLOCK_H_ +#define BASE_TEST_SIMPLE_TEST_CLOCK_H_ #include "base/compiler_specific.h" #include "base/synchronization/lock.h" @@ -38,4 +38,4 @@ } // namespace base -#endif // BASE_SIMPLE_TEST_CLOCK_H_ +#endif // BASE_TEST_SIMPLE_TEST_CLOCK_H_
diff --git a/base/test/simple_test_tick_clock.h b/base/test/simple_test_tick_clock.h index a637543..aebdebc 100644 --- a/base/test/simple_test_tick_clock.h +++ b/base/test/simple_test_tick_clock.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_SIMPLE_TEST_TICK_CLOCK_H_ -#define BASE_SIMPLE_TEST_TICK_CLOCK_H_ +#ifndef BASE_TEST_SIMPLE_TEST_TICK_CLOCK_H_ +#define BASE_TEST_SIMPLE_TEST_TICK_CLOCK_H_ #include "base/compiler_specific.h" #include "base/synchronization/lock.h" @@ -35,4 +35,4 @@ } // namespace base -#endif // BASE_SIMPLE_TEST_TICK_CLOCK_H_ +#endif // BASE_TEST_SIMPLE_TEST_TICK_CLOCK_H_
diff --git a/base/test/task_runner_test_template.h b/base/test/task_runner_test_template.h index 73aa1f4..9bcf70b 100644 --- a/base/test/task_runner_test_template.h +++ b/base/test/task_runner_test_template.h
@@ -212,4 +212,4 @@ } // namespace base -#endif //#define BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_ +#endif // BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
diff --git a/base/test/test_file_util_win.cc b/base/test/test_file_util_win.cc index af8bd76..5496a55 100644 --- a/base/test/test_file_util_win.cc +++ b/base/test/test_file_util_win.cc
@@ -175,7 +175,7 @@ // Move back to the position we just read from. // Note that SetFilePointer will also fail if total_bytes isn't sector // aligned, but that shouldn't happen here. - DCHECK((total_bytes % kOneMB) == 0); + DCHECK_EQ(total_bytes % kOneMB, 0); SetFilePointer(file_handle.Get(), total_bytes, NULL, FILE_BEGIN); if (!::WriteFile(file_handle.Get(), buffer, kOneMB, &bytes_written, NULL) || bytes_written != kOneMB) {
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc index 8e65ccf..6bcab8b 100644 --- a/base/test/test_mock_time_task_runner.cc +++ b/base/test/test_mock_time_task_runner.cc
@@ -100,6 +100,13 @@ ProcessAllTasksNoLaterThan(TimeDelta::Max()); } +void TestMockTimeTaskRunner::ClearPendingTasks() { + DCHECK(thread_checker_.CalledOnValidThread()); + AutoLock scoped_lock(tasks_lock_); + while (!tasks_.empty()) + tasks_.pop(); +} + Time TestMockTimeTaskRunner::Now() const { DCHECK(thread_checker_.CalledOnValidThread()); return now_;
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h index 5f06013..c38fd6d 100644 --- a/base/test/test_mock_time_task_runner.h +++ b/base/test/test_mock_time_task_runner.h
@@ -61,6 +61,9 @@ // elapse. void RunUntilIdle(); + // Clears the queue of pending tasks without running them. + void ClearPendingTasks(); + // Returns the current virtual time (initially starting at the Unix epoch). Time Now() const;
diff --git a/base/test/test_reg_util_win.h b/base/test/test_reg_util_win.h index db71838..5f23b7f 100644 --- a/base/test/test_reg_util_win.h +++ b/base/test/test_reg_util_win.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_TEST_TEST_REG_UTIL_H_ -#define BASE_TEST_TEST_REG_UTIL_H_ +#ifndef BASE_TEST_TEST_REG_UTIL_WIN_H_ +#define BASE_TEST_TEST_REG_UTIL_WIN_H_ // Registry utility functions used only by tests. @@ -74,4 +74,4 @@ } // namespace registry_util -#endif // BASE_TEST_TEST_REG_UTIL_H_ +#endif // BASE_TEST_TEST_REG_UTIL_WIN_H_
diff --git a/base/third_party/dynamic_annotations/BUILD.gn b/base/third_party/dynamic_annotations/BUILD.gn index d6a5123..bc324ae 100644 --- a/base/third_party/dynamic_annotations/BUILD.gn +++ b/base/third_party/dynamic_annotations/BUILD.gn
@@ -6,7 +6,10 @@ # Native client doesn't need dynamic annotations, so we provide a # dummy target in order for clients to not have to special-case the # dependency. - group("dynamic_annotations") { + source_set("dynamic_annotations") { + sources = [ + "dynamic_annotations.h", + ] } } else { source_set("dynamic_annotations") {
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc index 19b81b7..f20d997 100644 --- a/base/threading/sequenced_worker_pool.cc +++ b/base/threading/sequenced_worker_pool.cc
@@ -1091,7 +1091,7 @@ void SequencedWorkerPool::Inner::FinishStartingAdditionalThread( int thread_number) { // Called outside of the lock. - DCHECK(thread_number > 0); + DCHECK_GT(thread_number, 0); // The worker is assigned to the list when the thread actually starts, which // will manage the memory of the pointer.
diff --git a/base/threading/sequenced_worker_pool_unittest.cc b/base/threading/sequenced_worker_pool_unittest.cc index 9d0f607..c132731 100644 --- a/base/threading/sequenced_worker_pool_unittest.cc +++ b/base/threading/sequenced_worker_pool_unittest.cc
@@ -54,7 +54,7 @@ void Unblock(size_t count) { { base::AutoLock lock(lock_); - DCHECK(unblock_counter_ == 0); + DCHECK_EQ(unblock_counter_, 0u); unblock_counter_ = count; } cond_var_.Signal();
diff --git a/base/threading/thread.cc b/base/threading/thread.cc index ad1360b..ea5b174 100644 --- a/base/threading/thread.cc +++ b/base/threading/thread.cc
@@ -6,11 +6,12 @@ #include "base/bind.h" #include "base/lazy_instance.h" +#include "base/profiler/scoped_tracker.h" +#include "base/synchronization/waitable_event.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_local.h" #include "base/threading/thread_restrictions.h" -#include "base/synchronization/waitable_event.h" #if defined(OS_WIN) #include "base/win/scoped_com_initializer.h" @@ -94,6 +95,11 @@ } bool Thread::StartWithOptions(const Options& options) { + // TODO(eroman): Remove once crbug.com/465458 is solved. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "465458 base::Thread::StartWithOptions")); + DCHECK(!message_loop_); #if defined(OS_WIN) DCHECK((com_status_ != STA) || @@ -111,6 +117,11 @@ return false; } + // TODO(eroman): Remove once crbug.com/465458 is solved. + tracked_objects::ScopedTracker tracking_profile_wait( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "465458 base::Thread::StartWithOptions (Wait)")); + // Wait for the thread to start and initialize message_loop_ base::ThreadRestrictions::ScopedAllowWait allow_wait; startup_data.event.Wait();
diff --git a/base/threading/thread_collision_warner_unittest.cc b/base/threading/thread_collision_warner_unittest.cc index 26faff4..d7ce79e 100644 --- a/base/threading/thread_collision_warner_unittest.cc +++ b/base/threading/thread_collision_warner_unittest.cc
@@ -146,24 +146,23 @@ class QueueUser : public base::DelegateSimpleThread::Delegate { public: - explicit QueueUser(NonThreadSafeQueue& queue) - : queue_(queue) {} + explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {} void Run() override { - queue_.push(0); - queue_.pop(); + queue_->push(0); + queue_->pop(); } private: - NonThreadSafeQueue& queue_; + NonThreadSafeQueue* queue_; }; AssertReporter* local_reporter = new AssertReporter(); NonThreadSafeQueue queue(local_reporter); - QueueUser queue_user_a(queue); - QueueUser queue_user_b(queue); + QueueUser queue_user_a(&queue); + QueueUser queue_user_b(&queue); base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b"); @@ -204,24 +203,23 @@ class QueueUser : public base::DelegateSimpleThread::Delegate { public: - explicit QueueUser(NonThreadSafeQueue& queue) - : queue_(queue) {} + explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {} void Run() override { - queue_.push(0); - queue_.pop(); + queue_->push(0); + queue_->pop(); } private: - NonThreadSafeQueue& queue_; + NonThreadSafeQueue* queue_; }; AssertReporter* local_reporter = new AssertReporter(); NonThreadSafeQueue queue(local_reporter); - QueueUser queue_user_a(queue); - QueueUser queue_user_b(queue); + QueueUser queue_user_a(&queue); + QueueUser queue_user_b(&queue); base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b"); @@ -264,23 +262,22 @@ // a lock. class QueueUser : public base::DelegateSimpleThread::Delegate { public: - QueueUser(NonThreadSafeQueue& queue, base::Lock& lock) - : queue_(queue), - lock_(lock) {} + QueueUser(NonThreadSafeQueue* queue, base::Lock* lock) + : queue_(queue), lock_(lock) {} void Run() override { { - base::AutoLock auto_lock(lock_); - queue_.push(0); + base::AutoLock auto_lock(*lock_); + queue_->push(0); } { - base::AutoLock auto_lock(lock_); - queue_.pop(); + base::AutoLock auto_lock(*lock_); + queue_->pop(); } } private: - NonThreadSafeQueue& queue_; - base::Lock& lock_; + NonThreadSafeQueue* queue_; + base::Lock* lock_; }; AssertReporter* local_reporter = new AssertReporter(); @@ -289,8 +286,8 @@ base::Lock lock; - QueueUser queue_user_a(queue, lock); - QueueUser queue_user_b(queue, lock); + QueueUser queue_user_a(&queue, &lock); + QueueUser queue_user_b(&queue, &lock); base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b"); @@ -338,27 +335,26 @@ // a lock. class QueueUser : public base::DelegateSimpleThread::Delegate { public: - QueueUser(NonThreadSafeQueue& queue, base::Lock& lock) - : queue_(queue), - lock_(lock) {} + QueueUser(NonThreadSafeQueue* queue, base::Lock* lock) + : queue_(queue), lock_(lock) {} void Run() override { { - base::AutoLock auto_lock(lock_); - queue_.push(0); + base::AutoLock auto_lock(*lock_); + queue_->push(0); } { - base::AutoLock auto_lock(lock_); - queue_.bar(); + base::AutoLock auto_lock(*lock_); + queue_->bar(); } { - base::AutoLock auto_lock(lock_); - queue_.pop(); + base::AutoLock auto_lock(*lock_); + queue_->pop(); } } private: - NonThreadSafeQueue& queue_; - base::Lock& lock_; + NonThreadSafeQueue* queue_; + base::Lock* lock_; }; AssertReporter* local_reporter = new AssertReporter(); @@ -367,8 +363,8 @@ base::Lock lock; - QueueUser queue_user_a(queue, lock); - QueueUser queue_user_b(queue, lock); + QueueUser queue_user_a(&queue, &lock); + QueueUser queue_user_b(&queue, &lock); base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
diff --git a/base/threading/thread_local_storage.h b/base/threading/thread_local_storage.h index 53ebe55..ea41b34 100644 --- a/base/threading/thread_local_storage.h +++ b/base/threading/thread_local_storage.h
@@ -136,6 +136,7 @@ DISALLOW_COPY_AND_ASSIGN(Slot); }; + private: DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorage); };
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 1e5f510..75d8925 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -43,7 +43,7 @@ class RenderWidgetResizeHelper; class ScopedAllowWaitForAndroidLayoutTests; class TextInputClientMac; -} +} // namespace content namespace dbus { class Bus; }
diff --git a/base/threading/worker_pool_posix.cc b/base/threading/worker_pool_posix.cc index 5aa50ba..32a5e92 100644 --- a/base/threading/worker_pool_posix.cc +++ b/base/threading/worker_pool_posix.cc
@@ -27,14 +27,6 @@ const int kIdleSecondsBeforeExit = 10 * 60; -#ifdef ADDRESS_SANITIZER -const int kWorkerThreadStackSize = 256 * 1024; -#else -// A stack size of 64 KB is too small for the CERT_PKIXVerifyCert -// function of NSS because of NSS bug 439169. -const int kWorkerThreadStackSize = 128 * 1024; -#endif - class WorkerPoolImpl { public: WorkerPoolImpl(); @@ -168,7 +160,7 @@ // which will delete itself on exit. WorkerThread* worker = new WorkerThread(name_prefix_, this); - PlatformThread::CreateNonJoinable(kWorkerThreadStackSize, worker); + PlatformThread::CreateNonJoinable(0, worker); } }
diff --git a/base/time/clock.h b/base/time/clock.h index be389be..507a850 100644 --- a/base/time/clock.h +++ b/base/time/clock.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_CLOCK_H_ -#define BASE_CLOCK_H_ +#ifndef BASE_TIME_CLOCK_H_ +#define BASE_TIME_CLOCK_H_ #include "base/base_export.h" #include "base/time/time.h" @@ -37,4 +37,4 @@ } // namespace base -#endif // BASE_CLOCK_H_ +#endif // BASE_TIME_CLOCK_H_
diff --git a/base/time/default_clock.h b/base/time/default_clock.h index 3d2e947..0b8250e 100644 --- a/base/time/default_clock.h +++ b/base/time/default_clock.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_DEFAULT_CLOCK_H_ -#define BASE_DEFAULT_CLOCK_H_ +#ifndef BASE_TIME_DEFAULT_CLOCK_H_ +#define BASE_TIME_DEFAULT_CLOCK_H_ #include "base/base_export.h" #include "base/compiler_specific.h" @@ -22,4 +22,4 @@ } // namespace base -#endif // BASE_DEFAULT_CLOCK_H_ +#endif // BASE_TIME_DEFAULT_CLOCK_H_
diff --git a/base/time/default_tick_clock.h b/base/time/default_tick_clock.h index a6d6b15..cb041e6 100644 --- a/base/time/default_tick_clock.h +++ b/base/time/default_tick_clock.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_DEFAULT_TICK_CLOCK_H_ -#define BASE_DEFAULT_TICK_CLOCK_H_ +#ifndef BASE_TIME_DEFAULT_TICK_CLOCK_H_ +#define BASE_TIME_DEFAULT_TICK_CLOCK_H_ #include "base/base_export.h" #include "base/compiler_specific.h" @@ -22,4 +22,4 @@ } // namespace base -#endif // BASE_DEFAULT_CLOCK_H_ +#endif // BASE_TIME_DEFAULT_TICK_CLOCK_H_
diff --git a/base/time/tick_clock.h b/base/time/tick_clock.h index 2b8691f..f7aba53 100644 --- a/base/time/tick_clock.h +++ b/base/time/tick_clock.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_TICK_CLOCK_H_ -#define BASE_TICK_CLOCK_H_ +#ifndef BASE_TIME_TICK_CLOCK_H_ +#define BASE_TIME_TICK_CLOCK_H_ #include "base/base_export.h" #include "base/time/time.h" @@ -37,4 +37,4 @@ } // namespace base -#endif // BASE_TICK_CLOCK_H_ +#endif // BASE_TIME_TICK_CLOCK_H_
diff --git a/base/time/time_win.cc b/base/time/time_win.cc index 8ae7640..d2403f2 100644 --- a/base/time/time_win.cc +++ b/base/time/time_win.cc
@@ -203,12 +203,12 @@ UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs : kMinTimerIntervalLowResMs; if (activating) { - DCHECK(g_high_res_timer_count != max); + DCHECK_NE(g_high_res_timer_count, max); ++g_high_res_timer_count; if (g_high_res_timer_count == 1) timeBeginPeriod(period); } else { - DCHECK(g_high_res_timer_count != 0); + DCHECK_NE(g_high_res_timer_count, 0u); --g_high_res_timer_count; if (g_high_res_timer_count == 0) timeEndPeriod(period);
diff --git a/base/timer/mock_timer.h b/base/timer/mock_timer.h index b07c9c0..e18a5c0 100644 --- a/base/timer/mock_timer.h +++ b/base/timer/mock_timer.h
@@ -38,4 +38,4 @@ } // namespace base -#endif // !BASE_TIMER_MOCK_TIMER_H_ +#endif // BASE_TIMER_MOCK_TIMER_H_
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn new file mode 100644 index 0000000..eec607b --- /dev/null +++ b/base/trace_event/BUILD.gn
@@ -0,0 +1,61 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("trace_event") { + sources = [ + "memory_dump_manager.cc", + "memory_dump_manager.h", + "memory_dump_provider.h", + "process_memory_dump.cc", + "process_memory_dump.h", + "process_memory_maps.cc", + "process_memory_maps.h", + "process_memory_maps_dump_provider.cc", + "process_memory_maps_dump_provider.h", + "process_memory_totals.cc", + "process_memory_totals.h", + "process_memory_totals_dump_provider.cc", + "process_memory_totals_dump_provider.h", + "trace_event.h", + "trace_event_android.cc", + "trace_event_argument.cc", + "trace_event_argument.h", + "trace_event_impl.cc", + "trace_event_impl.h", + "trace_event_impl_constants.cc", + "trace_event_memory.cc", + "trace_event_memory.h", + "trace_event_synthetic_delay.cc", + "trace_event_synthetic_delay.h", + "trace_event_system_stats_monitor.cc", + "trace_event_system_stats_monitor.h", + "trace_event_win.cc", + "trace_event_win.h", + ] + + if (is_nacl) { + sources -= [ + "process_memory_totals_dump_provider.cc", + "trace_event_system_stats_monitor.cc", + ] + } + + defines = [ "BASE_IMPLEMENTATION" ] + + deps = [ + "//base/debug", + "//base/json", + "//base/memory", + "//base/process", + "//base/third_party/dynamic_annotations", + ] + + allow_circular_includes_from = [ + "//base/debug", + "//base/memory", + "//base/process", + ] + + visibility = [ "//base/*" ] +}
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index cbed238..8b2d930 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc
@@ -37,7 +37,8 @@ NOTREACHED(); return "UNKNOWN"; } -} + +} // namespace // TODO(primiano): this should be smarter and should do something similar to // trace event synthetic delays.
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc index 78be377..251a92a 100644 --- a/base/trace_event/memory_dump_manager_unittest.cc +++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -148,5 +148,5 @@ DisableTracing(); } -} // namespace trace_Event +} // namespace trace_event } // namespace base
diff --git a/base/trace_event/process_memory_maps_dump_provider.cc b/base/trace_event/process_memory_maps_dump_provider.cc index 93feded..fbe0eb1 100644 --- a/base/trace_event/process_memory_maps_dump_provider.cc +++ b/base/trace_event/process_memory_maps_dump_provider.cc
@@ -47,7 +47,7 @@ region->protection_flags = 0; *smaps >> protection_flags; - CHECK(4UL == protection_flags.size()); + CHECK_EQ(4UL, protection_flags.size()); if (protection_flags[0] == 'r') { region->protection_flags |= ProcessMemoryMaps::VMRegion::kProtectionFlagsRead;
diff --git a/base/trace_event/process_memory_totals_dump_provider_unittest.cc b/base/trace_event/process_memory_totals_dump_provider_unittest.cc index 4a60036..c37e612 100644 --- a/base/trace_event/process_memory_totals_dump_provider_unittest.cc +++ b/base/trace_event/process_memory_totals_dump_provider_unittest.cc
@@ -39,5 +39,5 @@ EXPECT_EQ(rss_after - rss_before, kAllocSize); } -} // namespace trace_Event +} // namespace trace_event } // namespace base
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h index c30a84a..b90a3ea 100644 --- a/base/trace_event/trace_event.h +++ b/base/trace_event/trace_event.h
@@ -1607,4 +1607,4 @@ } // namespace trace_event } // namespace base -#endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */ +#endif // BASE_TRACE_EVENT_TRACE_EVENT_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 445cb6d..72b46f9 100644 --- a/base/trace_event/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc
@@ -430,25 +430,22 @@ // and unlocks at the end of scope if locked. class TraceLog::OptionalAutoLock { public: - explicit OptionalAutoLock(Lock& lock) - : lock_(lock), - locked_(false) { - } + explicit OptionalAutoLock(Lock* lock) : lock_(lock), locked_(false) {} ~OptionalAutoLock() { if (locked_) - lock_.Release(); + lock_->Release(); } void EnsureAcquired() { if (!locked_) { - lock_.Acquire(); + lock_->Acquire(); locked_ = true; } } private: - Lock& lock_; + Lock* lock_; bool locked_; DISALLOW_COPY_AND_ASSIGN(OptionalAutoLock); }; @@ -624,7 +621,7 @@ void TraceEvent::UpdateDuration(const TimeTicks& now, const TimeTicks& thread_now) { - DCHECK(duration_.ToInternalValue() == -1); + DCHECK_EQ(duration_.ToInternalValue(), -1); duration_ = now - timestamp_; thread_duration_ = thread_now - thread_timestamp_; } @@ -1977,7 +1974,7 @@ std::string console_message; if (*category_group_enabled & (ENABLED_FOR_RECORDING | ENABLED_FOR_MONITORING)) { - OptionalAutoLock lock(lock_); + OptionalAutoLock lock(&lock_); TraceEvent* trace_event = NULL; if (thread_local_event_buffer) { @@ -2130,7 +2127,7 @@ std::string console_message; if (*category_group_enabled & ENABLED_FOR_RECORDING) { - OptionalAutoLock lock(lock_); + OptionalAutoLock lock(&lock_); TraceEvent* trace_event = GetEventByHandleInternal(handle, &lock); if (trace_event) { @@ -2490,18 +2487,35 @@ // Do a second pass to check for explicitly disabled categories // (those explicitly enabled have priority due to first pass). category_group_tokens.Reset(); + bool category_group_disabled = false; while (category_group_tokens.GetNext()) { std::string category_group_token = category_group_tokens.token(); for (StringList::const_iterator ci = excluded_.begin(); ci != excluded_.end(); ++ci) { - if (MatchPattern(category_group_token.c_str(), ci->c_str())) - return false; + if (MatchPattern(category_group_token.c_str(), ci->c_str())) { + // Current token of category_group_name is present in excluded_list. + // Flag the exclusion and proceed further to check if any of the + // remaining categories of category_group_name is not present in the + // excluded_ list. + category_group_disabled = true; + break; + } + // One of the category of category_group_name is not present in + // excluded_ list. So, it has to be included_ list. Enable the + // category_group_name for recording. + category_group_disabled = false; } + // One of the categories present in category_group_name is not present in + // excluded_ list. Implies this category_group_name group can be enabled + // for recording, since one of its groups is enabled for recording. + if (!category_group_disabled) + break; } // If the category group is not excluded, and there are no included patterns // we consider this category group enabled, as long as it had categories // other than disabled-by-default. - return included_.empty() && had_enabled_by_default; + return !category_group_disabled && + included_.empty() && had_enabled_by_default; } bool CategoryFilter::IsCategoryEnabled(const char* category_name) const { @@ -2571,7 +2585,7 @@ ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( const char* category_group, const char* name) { // The single atom works because for now the category_group can only be "gpu". - DCHECK(strcmp(category_group, "gpu") == 0); + DCHECK_EQ(strcmp(category_group, "gpu"), 0); static TRACE_EVENT_API_ATOMIC_WORD atomic = 0; INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( category_group, atomic, category_group_enabled_);
diff --git a/base/trace_event/trace_event_synthetic_delay.h b/base/trace_event/trace_event_synthetic_delay.h index 14801be..0df794b 100644 --- a/base/trace_event/trace_event_synthetic_delay.h +++ b/base/trace_event/trace_event_synthetic_delay.h
@@ -163,4 +163,4 @@ } // namespace trace_event_internal -#endif /* BASE_TRACE_EVENT_TRACE_EVENT_SYNTHETIC_DELAY_H_ */ +#endif // BASE_TRACE_EVENT_TRACE_EVENT_SYNTHETIC_DELAY_H_
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index a6bc0d4..0d3b091 100644 --- a/base/trace_event/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc
@@ -1205,8 +1205,8 @@ EndTraceAndFlush(); EXPECT_TRUE(FindMatchingValue("cat", "inc2")); EXPECT_FALSE(FindMatchingValue("cat", "inc")); - EXPECT_FALSE(FindMatchingValue("cat", "inc2,inc")); - EXPECT_FALSE(FindMatchingValue("cat", "inc,inc2")); + EXPECT_TRUE(FindMatchingValue("cat", "inc2,inc")); + EXPECT_TRUE(FindMatchingValue("cat", "inc,inc2")); // Exclude existent wildcard -> all categories not matching wildcard Clear(); @@ -2624,18 +2624,18 @@ EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("not-excluded-category")); EXPECT_FALSE( default_cf.IsCategoryGroupEnabled("disabled-by-default-category")); - EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug")); - EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1")); - EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2")); + EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug")); + EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1")); + EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2")); // Make sure that upon an empty string, we fall back to the default filter. default_cf = CategoryFilter(); category_filter_str = default_cf.ToString(); EXPECT_STREQ("-*Debug,-*Test", category_filter_str.c_str()); EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("not-excluded-category")); - EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug")); - EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1")); - EXPECT_FALSE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2")); + EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("Category1,CategoryDebug")); + EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryDebug,Category1")); + EXPECT_TRUE(default_cf.IsCategoryGroupEnabled("CategoryTest,Category2")); // Using an arbitrary non-empty filter. CategoryFilter cf("included,-excluded,inc_pattern*,-exc_pattern*");
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc index fc29e2e..5359d89 100644 --- a/base/tracked_objects.cc +++ b/base/tracked_objects.cc
@@ -163,11 +163,6 @@ return queue_duration_sample_; } -void DeathData::ResetMax() { - run_duration_max_ = 0; - queue_duration_max_ = 0; -} - void DeathData::Clear() { count_ = 0; run_duration_sum_ = 0; @@ -232,10 +227,6 @@ void Births::RecordBirth() { ++birth_count_; } -void Births::ForgetBirth() { --birth_count_; } - -void Births::Clear() { birth_count_ = 0; } - //------------------------------------------------------------------------------ // ThreadData maintains the central data for all births and deaths on a single // thread. @@ -399,12 +390,12 @@ } // static -void ThreadData::Snapshot(bool reset_max, ProcessDataSnapshot* process_data) { +void ThreadData::Snapshot(ProcessDataSnapshot* process_data) { // Add births that have run to completion to |collected_data|. // |birth_counts| tracks the total number of births recorded at each location // for which we have not seen a death count. BirthCountMap birth_counts; - ThreadData::SnapshotAllExecutedTasks(reset_max, process_data, &birth_counts); + ThreadData::SnapshotAllExecutedTasks(process_data, &birth_counts); // Add births that are still active -- i.e. objects that have tallied a birth, // but have not yet tallied a matching death, and hence must be either @@ -587,8 +578,7 @@ } // static -void ThreadData::SnapshotAllExecutedTasks(bool reset_max, - ProcessDataSnapshot* process_data, +void ThreadData::SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data, BirthCountMap* birth_counts) { if (!kTrackAllTaskObjects) return; // Not compiled in. @@ -605,19 +595,18 @@ for (ThreadData* thread_data = my_list; thread_data; thread_data = thread_data->next()) { - thread_data->SnapshotExecutedTasks(reset_max, process_data, birth_counts); + thread_data->SnapshotExecutedTasks(process_data, birth_counts); } } -void ThreadData::SnapshotExecutedTasks(bool reset_max, - ProcessDataSnapshot* process_data, +void ThreadData::SnapshotExecutedTasks(ProcessDataSnapshot* process_data, BirthCountMap* birth_counts) { // Get copy of data, so that the data will not change during the iterations // and processing. ThreadData::BirthMap birth_map; ThreadData::DeathMap death_map; ThreadData::ParentChildSet parent_child_set; - SnapshotMaps(reset_max, &birth_map, &death_map, &parent_child_set); + SnapshotMaps(&birth_map, &death_map, &parent_child_set); for (ThreadData::DeathMap::const_iterator it = death_map.begin(); it != death_map.end(); ++it) { @@ -641,8 +630,7 @@ } // This may be called from another thread. -void ThreadData::SnapshotMaps(bool reset_max, - BirthMap* birth_map, +void ThreadData::SnapshotMaps(BirthMap* birth_map, DeathMap* death_map, ParentChildSet* parent_child_set) { base::AutoLock lock(map_lock_); @@ -652,8 +640,6 @@ for (DeathMap::iterator it = death_map_.begin(); it != death_map_.end(); ++it) { (*death_map)[it->first] = it->second; - if (reset_max) - it->second.ResetMax(); } if (!kTrackParentChildLinks) @@ -664,26 +650,6 @@ parent_child_set->insert(*it); } -// static -void ThreadData::ResetAllThreadData() { - ThreadData* my_list = first(); - - for (ThreadData* thread_data = my_list; - thread_data; - thread_data = thread_data->next()) - thread_data->Reset(); -} - -void ThreadData::Reset() { - base::AutoLock lock(map_lock_); - for (DeathMap::iterator it = death_map_.begin(); - it != death_map_.end(); ++it) - it->second.Clear(); - for (BirthMap::iterator it = birth_map_.begin(); - it != birth_map_.end(); ++it) - it->second->Clear(); -} - static void OptionallyInitializeAlternateTimer() { NowFunction* alternate_time_source = GetAlternateTimeSource(); if (alternate_time_source)
diff --git a/base/tracked_objects.h b/base/tracked_objects.h index 5196f19..7840fec 100644 --- a/base/tracked_objects.h +++ b/base/tracked_objects.h
@@ -240,13 +240,6 @@ // When we have a birth we update the count for this birthplace. void RecordBirth(); - // When a birthplace is changed (updated), we need to decrement the counter - // for the old instance. - void ForgetBirth(); - - // Hack to quickly reset all counts to zero. - void Clear(); - private: // The number of births on this thread for our location_. int birth_count_; @@ -284,9 +277,6 @@ int32 queue_duration_max() const; int32 queue_duration_sample() const; - // Reset the max values to zero. - void ResetMax(); - // Reset all tallies to zero. This is used as a hack on realtime data. void Clear(); @@ -386,9 +376,7 @@ static ThreadData* Get(); // Fills |process_data| with all the recursive results in our process. - // During the scavenging, if |reset_max| is true, then the DeathData instances - // max-values are reset to zero during this scan. - static void Snapshot(bool reset_max, ProcessDataSnapshot* process_data); + static void Snapshot(ProcessDataSnapshot* process_data); // Finds (or creates) a place to count births from the given location in this // thread, and increment that tally. @@ -427,12 +415,6 @@ const std::string& thread_name() const { return thread_name_; } - // Hack: asynchronously clear all birth counts and death tallies data values - // in all ThreadData instances. The numerical (zeroing) part is done without - // use of a locks or atomics exchanges, and may (for int64 values) produce - // bogus counts VERY rarely. - static void ResetAllThreadData(); - // Initializes all statics if needed (this initialization call should be made // while we are single threaded). Returns false if unable to initialize. static bool Initialize(); @@ -530,11 +512,8 @@ // Snapshot (under a lock) the profiled data for the tasks in each ThreadData // instance. Also updates the |birth_counts| tally for each task to keep - // track of the number of living instances of the task. If |reset_max| is - // true, then the max values in each DeathData instance are reset during the - // scan. - static void SnapshotAllExecutedTasks(bool reset_max, - ProcessDataSnapshot* process_data, + // track of the number of living instances of the task. + static void SnapshotAllExecutedTasks(ProcessDataSnapshot* process_data, BirthCountMap* birth_counts); // Snapshots (under a lock) the profiled data for the tasks for this thread @@ -542,26 +521,17 @@ // with with entries in the death_map_ -- into |process_data|. Also updates // the |birth_counts| tally for each task to keep track of the number of // living instances of the task -- that is, each task maps to the number of - // births for the task that have not yet been balanced by a death. If - // |reset_max| is true, then the max values in each DeathData instance are - // reset during the scan. - void SnapshotExecutedTasks(bool reset_max, - ProcessDataSnapshot* process_data, + // births for the task that have not yet been balanced by a death. + void SnapshotExecutedTasks(ProcessDataSnapshot* process_data, BirthCountMap* birth_counts); // Using our lock, make a copy of the specified maps. This call may be made // on non-local threads, which necessitate the use of the lock to prevent - // the map(s) from being reallocated while they are copied. If |reset_max| is - // true, then, just after we copy the DeathMap, we will set the max values to - // zero in the active DeathMap (not the snapshot). - void SnapshotMaps(bool reset_max, - BirthMap* birth_map, + // the map(s) from being reallocated while they are copied. + void SnapshotMaps(BirthMap* birth_map, DeathMap* death_map, ParentChildSet* parent_child_set); - // Using our lock to protect the iteration, Clear all birth and death data. - void Reset(); - // This method is called by the TLS system when a thread terminates. // The argument may be NULL if this thread has never tracked a birth or death. static void OnThreadTermination(void* thread_data);
diff --git a/base/tracked_objects_unittest.cc b/base/tracked_objects_unittest.cc index e2ea362..7713091 100644 --- a/base/tracked_objects_unittest.cc +++ b/base/tracked_objects_unittest.cc
@@ -138,7 +138,7 @@ ThreadData::BirthMap birth_map; ThreadData::DeathMap death_map; ThreadData::ParentChildSet parent_child_set; - data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); EXPECT_EQ(0u, birth_map.size()); EXPECT_EQ(0u, death_map.size()); EXPECT_EQ(0u, parent_child_set.size()); @@ -158,7 +158,7 @@ birth_map.clear(); death_map.clear(); parent_child_set.clear(); - data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); EXPECT_EQ(0u, birth_map.size()); EXPECT_EQ(0u, death_map.size()); EXPECT_EQ(0u, parent_child_set.size()); @@ -182,7 +182,7 @@ ThreadData::BirthMap birth_map; ThreadData::DeathMap death_map; ThreadData::ParentChildSet parent_child_set; - data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); EXPECT_EQ(1u, birth_map.size()); // 1 birth location. EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. EXPECT_EQ(0u, death_map.size()); // No deaths. @@ -211,7 +211,7 @@ birth_map.clear(); death_map.clear(); parent_child_set.clear(); - data->SnapshotMaps(false, &birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); EXPECT_EQ(1u, birth_map.size()); // 1 birth location. EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. EXPECT_EQ(1u, death_map.size()); // 1 location. @@ -228,7 +228,7 @@ EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ASSERT_EQ(1u, process_data.tasks.size()); EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name); @@ -317,7 +317,7 @@ TallyABirth(location, std::string()); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); EXPECT_EQ(0u, process_data.tasks.size()); EXPECT_EQ(0u, process_data.descendants.size()); EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); @@ -334,7 +334,7 @@ TallyABirth(location, kMainThreadName); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); EXPECT_EQ(0u, process_data.tasks.size()); EXPECT_EQ(0u, process_data.descendants.size()); EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); @@ -351,7 +351,7 @@ TallyABirth(location, std::string()); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName, kStillAlive, 1, 0, 0); } @@ -367,7 +367,7 @@ TallyABirth(location, kMainThreadName); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kStillAlive, 1, 0, 0); } @@ -399,7 +399,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 2, 4); } @@ -439,7 +439,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 2, 4); } @@ -473,76 +473,12 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); EXPECT_EQ(0u, process_data.tasks.size()); EXPECT_EQ(0u, process_data.descendants.size()); EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); } -TEST_F(TrackedObjectsTest, LifeCycleToSnapshotWorkerThread) { - if (!ThreadData::InitializeAndSetTrackingStatus( - ThreadData::PROFILING_CHILDREN_ACTIVE)) { - return; - } - - const char kFunction[] = "LifeCycleToSnapshotWorkerThread"; - Location location(kFunction, kFile, kLineNumber, NULL); - // Do not delete |birth|. We don't own it. - Births* birth = ThreadData::TallyABirthIfActive(location); - EXPECT_NE(reinterpret_cast<Births*>(NULL), birth); - - const unsigned int kTimePosted = 1; - const unsigned int kStartOfRun = 5; - const unsigned int kEndOfRun = 7; - SetTestTime(kStartOfRun); - TaskStopwatch stopwatch; - stopwatch.Start(); - SetTestTime(kEndOfRun); - stopwatch.Stop(); - - ThreadData::TallyRunOnWorkerThreadIfTracking( - birth, TrackedTime() + Duration::FromMilliseconds(kTimePosted), stopwatch); - - // Call for the ToSnapshot, but tell it to not reset the maxes after scanning. - ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); - ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName, - kWorkerThreadName, 1, 2, 4); - - // Call for the ToSnapshot, but tell it to reset the maxes after scanning. - // We'll still get the same values, but the data will be reset (which we'll - // see in a moment). - ProcessDataSnapshot process_data_pre_reset; - ThreadData::Snapshot(true, &process_data_pre_reset); - ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName, - kWorkerThreadName, 1, 2, 4); - - // Call for the ToSnapshot, and now we'll see the result of the last - // translation, as the max will have been pushed back to zero. - ProcessDataSnapshot process_data_post_reset; - ThreadData::Snapshot(true, &process_data_post_reset); - ASSERT_EQ(1u, process_data_post_reset.tasks.size()); - EXPECT_EQ(kFile, process_data_post_reset.tasks[0].birth.location.file_name); - EXPECT_EQ(kFunction, - process_data_post_reset.tasks[0].birth.location.function_name); - EXPECT_EQ(kLineNumber, - process_data_post_reset.tasks[0].birth.location.line_number); - EXPECT_EQ(kWorkerThreadName, - process_data_post_reset.tasks[0].birth.thread_name); - EXPECT_EQ(1, process_data_post_reset.tasks[0].death_data.count); - EXPECT_EQ(2, process_data_post_reset.tasks[0].death_data.run_duration_sum); - EXPECT_EQ(0, process_data_post_reset.tasks[0].death_data.run_duration_max); - EXPECT_EQ(2, process_data_post_reset.tasks[0].death_data.run_duration_sample); - EXPECT_EQ(4, process_data_post_reset.tasks[0].death_data.queue_duration_sum); - EXPECT_EQ(0, process_data_post_reset.tasks[0].death_data.queue_duration_max); - EXPECT_EQ(4, - process_data_post_reset.tasks[0].death_data.queue_duration_sample); - EXPECT_EQ(kWorkerThreadName, - process_data_post_reset.tasks[0].death_thread_name); - EXPECT_EQ(0u, process_data_post_reset.descendants.size()); - EXPECT_EQ(base::GetCurrentProcId(), process_data_post_reset.process_id); -} - TEST_F(TrackedObjectsTest, TwoLives) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { @@ -581,7 +517,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2, stopwatch2); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 2, 2, 4); } @@ -621,7 +557,7 @@ pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ASSERT_EQ(2u, process_data.tasks.size()); EXPECT_EQ(kFile, process_data.tasks[0].birth.location.file_name); @@ -685,7 +621,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 6, 4); } @@ -728,7 +664,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 13, 4); } @@ -781,7 +717,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(false, &process_data); + ThreadData::Snapshot(&process_data); // The order in which the two task follow is platform-dependent. int t0 = (process_data.tasks[0].birth.location.line_number == kLineNumber) ?
diff --git a/base/value_conversions.h b/base/value_conversions.h index fde9a26..452c587 100644 --- a/base/value_conversions.h +++ b/base/value_conversions.h
@@ -24,6 +24,6 @@ BASE_EXPORT StringValue* CreateTimeDeltaValue(const TimeDelta& time); BASE_EXPORT bool GetValueAsTimeDelta(const Value& value, TimeDelta* time); -} // namespace +} // namespace base #endif // BASE_VALUE_CONVERSIONS_H_
diff --git a/base/version.cc b/base/version.cc index 933356e..ede8a45 100644 --- a/base/version.cc +++ b/base/version.cc
@@ -23,7 +23,7 @@ // is the resulting integer vector. Function returns true if all numbers were // parsed successfully, false otherwise. bool ParseVersionNumbers(const std::string& version_str, - std::vector<uint16>* parsed) { + std::vector<uint32_t>* parsed) { std::vector<std::string> numbers; SplitString(version_str, '.', &numbers); if (numbers.empty()) @@ -33,22 +33,18 @@ it != numbers.end(); ++it) { if (StartsWithASCII(*it, "+", false)) return false; - int num; - if (!StringToInt(*it, &num)) - return false; - - if (num < 0) - return false; - - const uint16 max = 0xFFFF; - if (num > max) + unsigned int num; + if (!StringToUint(*it, &num)) return false; // This throws out leading zeros for the first item only. - if (it == numbers.begin() && IntToString(num) != *it) + if (it == numbers.begin() && UintToString(num) != *it) return false; - parsed->push_back(static_cast<uint16>(num)); + // StringToUint returns unsigned int but Version fields are uint32_t. + static_assert(sizeof (uint32_t) == sizeof (unsigned int), + "uint32_t must be same as unsigned int"); + parsed->push_back(num); } return true; } @@ -56,8 +52,8 @@ // Compares version components in |components1| with components in // |components2|. Returns -1, 0 or 1 if |components1| is less than, equal to, // or greater than |components2|, respectively. -int CompareVersionComponents(const std::vector<uint16>& components1, - const std::vector<uint16>& components2) { +int CompareVersionComponents(const std::vector<uint32_t>& components1, + const std::vector<uint32_t>& components2) { const size_t count = std::min(components1.size(), components2.size()); for (size_t i = 0; i < count; ++i) { if (components1[i] > components2[i]) @@ -88,7 +84,7 @@ } Version::Version(const std::string& version_str) { - std::vector<uint16> parsed; + std::vector<uint32_t> parsed; if (!ParseVersionNumbers(version_str, &parsed)) return; @@ -127,7 +123,7 @@ return CompareTo(version); } - std::vector<uint16> parsed; + std::vector<uint32_t> parsed; const bool success = ParseVersionNumbers( wildcard_string.substr(0, wildcard_string.length() - 2), &parsed); DCHECK(success);
diff --git a/base/version.h b/base/version.h index b3012eb..814acaa 100644 --- a/base/version.h +++ b/base/version.h
@@ -5,6 +5,7 @@ #ifndef BASE_VERSION_H_ #define BASE_VERSION_H_ +#include <stdint.h> #include <string> #include <vector> @@ -57,10 +58,10 @@ // Return the string representation of this version. const std::string GetString() const; - const std::vector<uint16>& components() const { return components_; } + const std::vector<uint32_t>& components() const { return components_; } private: - std::vector<uint16> components_; + std::vector<uint32_t> components_; }; } // namespace base
diff --git a/base/version_unittest.cc b/base/version_unittest.cc index 46d8255..f40ed27 100644 --- a/base/version_unittest.cc +++ b/base/version_unittest.cc
@@ -31,39 +31,44 @@ static const struct version_string { const char* input; size_t parts; + uint32_t firstpart; bool success; } cases[] = { - {"", 0, false}, - {" ", 0, false}, - {"\t", 0, false}, - {"\n", 0, false}, - {" ", 0, false}, - {".", 0, false}, - {" . ", 0, false}, - {"0", 1, true}, - {"0.", 0, false}, - {"0.0", 2, true}, - {"65537.0", 0, false}, - {"-1.0", 0, false}, - {"1.-1.0", 0, false}, - {"1,--1.0", 0, false}, - {"+1.0", 0, false}, - {"1.+1.0", 0, false}, - {"1+1.0", 0, false}, - {"++1.0", 0, false}, - {"1.0a", 0, false}, - {"1.2.3.4.5.6.7.8.9.0", 10, true}, - {"02.1", 0, false}, - {"0.01", 2, true}, - {"f.1", 0, false}, - {"15.007.20011", 3, true}, + {"", 0, 0, false}, + {" ", 0, 0, false}, + {"\t", 0, 0, false}, + {"\n", 0, 0, false}, + {" ", 0, 0, false}, + {".", 0, 0, false}, + {" . ", 0, 0, false}, + {"0", 1, 0, true}, + {"0.", 0, 0, false}, + {"0.0", 2, 0, true}, + {"4294967295.0", 2, 4294967295, true}, + {"4294967296.0", 0, 0, false}, + {"-1.0", 0, 0, false}, + {"1.-1.0", 0, 0, false}, + {"1,--1.0", 0, 0, false}, + {"+1.0", 0, 0, false}, + {"1.+1.0", 0, 0, false}, + {"1+1.0", 0, 0, false}, + {"++1.0", 0, 0, false}, + {"1.0a", 0, 0, false}, + {"1.2.3.4.5.6.7.8.9.0", 10, 1, true}, + {"02.1", 0, 0, false}, + {"0.01", 2, 0, true}, + {"f.1", 0, 0, false}, + {"15.007.20011", 3, 15, true}, + {"15.5.28.130162", 4, 15, true}, }; for (size_t i = 0; i < arraysize(cases); ++i) { Version version(cases[i].input); EXPECT_EQ(cases[i].success, version.IsValid()); - if (cases[i].success) + if (cases[i].success) { EXPECT_EQ(cases[i].parts, version.components().size()); + EXPECT_EQ(cases[i].firstpart, version.components()[0]); + } } } @@ -84,6 +89,7 @@ {"1.0.0", "1.0", 0}, {"1.0.3", "1.0.20", -1}, {"11.0.10", "15.007.20011", -1}, + {"11.0.10", "15.5.28.130162", -1}, }; for (size_t i = 0; i < arraysize(cases); ++i) { Version lhs(cases[i].lhs);
diff --git a/base/vlog.cc b/base/vlog.cc index 434a70e..8612071 100644 --- a/base/vlog.cc +++ b/base/vlog.cc
@@ -178,4 +178,4 @@ return false; } -} // namespace +} // namespace logging
diff --git a/base/win/metro.cc b/base/win/metro.cc index 6e443ba..7946698 100644 --- a/base/win/metro.cc +++ b/base/win/metro.cc
@@ -4,10 +4,7 @@ #include "base/win/metro.h" -#include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" -#include "base/win/scoped_comptr.h" -#include "base/win/windows_version.h" namespace base { namespace win { @@ -73,38 +70,6 @@ return dest; } -bool IsParentalControlActivityLoggingOn() { - // Query this info on Windows 7 and above. - if (base::win::GetVersion() < base::win::VERSION_WIN7) - return false; - - static bool parental_control_logging_required = false; - static bool parental_control_status_determined = false; - - if (parental_control_status_determined) - return parental_control_logging_required; - - parental_control_status_determined = true; - - ScopedComPtr<IWindowsParentalControlsCore> parent_controls; - HRESULT hr = parent_controls.CreateInstance( - __uuidof(WindowsParentalControls)); - if (FAILED(hr)) - return false; - - ScopedComPtr<IWPCSettings> settings; - hr = parent_controls->GetUserSettings(NULL, settings.Receive()); - if (FAILED(hr)) - return false; - - unsigned long restrictions = 0; - settings->GetRestrictions(&restrictions); - - parental_control_logging_required = - (restrictions & WPCFLAG_LOGGING_REQUIRED) == WPCFLAG_LOGGING_REQUIRED; - return parental_control_logging_required; -} - // Metro driver exports for getting the launch type, initial url, initial // search term, etc. extern "C" {
diff --git a/base/win/metro.h b/base/win/metro.h index 5894ef0..0696006 100644 --- a/base/win/metro.h +++ b/base/win/metro.h
@@ -6,7 +6,6 @@ #define BASE_WIN_METRO_H_ #include <windows.h> -#include <wpcapi.h> #include "base/base_export.h" #include "base/callback.h" @@ -80,11 +79,6 @@ // copying the src to it. BASE_EXPORT wchar_t* LocalAllocAndCopyString(const string16& src); -// Returns true if Windows Parental control activity logging is enabled. This -// feature is available on Windows Vista and beyond. -// This function should ideally be called on the UI thread. -BASE_EXPORT bool IsParentalControlActivityLoggingOn(); - // Returns the type of launch and the activation params. For example if the // the launch is for METRO_PROTOCOL then the params is a url. BASE_EXPORT MetroLaunchType GetMetroLaunchParams(string16* params);
diff --git a/base/win/object_watcher.h b/base/win/object_watcher.h index ecd0415..0ae2532 100644 --- a/base/win/object_watcher.h +++ b/base/win/object_watcher.h
@@ -103,4 +103,4 @@ } // namespace win } // namespace base -#endif // BASE_OBJECT_WATCHER_H_ +#endif // BASE_WIN_OBJECT_WATCHER_H_
diff --git a/base/win/registry.cc b/base/win/registry.cc index b39b749..d0df48a 100644 --- a/base/win/registry.cc +++ b/base/win/registry.cc
@@ -210,7 +210,7 @@ } HKEY RegKey::Take() { - DCHECK(wow64access_ == 0); + DCHECK_EQ(wow64access_, 0u); HKEY key = key_; key_ = NULL; return key;
diff --git a/base/win/scoped_bstr.h b/base/win/scoped_bstr.h index d703f62..7c9f5df 100644 --- a/base/win/scoped_bstr.h +++ b/base/win/scoped_bstr.h
@@ -94,4 +94,4 @@ } // namespace win } // namespace base -#endif // BASE_SCOPED_BSTR_H_ +#endif // BASE_WIN_SCOPED_BSTR_H_
diff --git a/base/win/scoped_comptr_unittest.cc b/base/win/scoped_comptr_unittest.cc index 711c52f..d38752d 100644 --- a/base/win/scoped_comptr_unittest.cc +++ b/base/win/scoped_comptr_unittest.cc
@@ -31,8 +31,8 @@ } // namespace TEST(ScopedComPtrTest, ScopedComPtr) { - EXPECT_TRUE(memcmp(&ScopedComPtr<IUnknown>::iid(), &IID_IUnknown, - sizeof(IID)) == 0); + EXPECT_EQ(memcmp(&ScopedComPtr<IUnknown>::iid(), &IID_IUnknown, sizeof(IID)), + 0); base::win::ScopedCOMInitializer com_initializer; EXPECT_TRUE(com_initializer.succeeded());
diff --git a/base/win/scoped_handle.h b/base/win/scoped_handle.h index db24f4b..97fd7a5 100644 --- a/base/win/scoped_handle.h +++ b/base/win/scoped_handle.h
@@ -174,4 +174,4 @@ } // namespace win } // namespace base -#endif // BASE_SCOPED_HANDLE_WIN_H_ +#endif // BASE_WIN_SCOPED_HANDLE_H_
diff --git a/base/win/scoped_propvariant.h b/base/win/scoped_propvariant.h index 711d51a..62cc6a6 100644 --- a/base/win/scoped_propvariant.h +++ b/base/win/scoped_propvariant.h
@@ -41,8 +41,7 @@ } const PROPVARIANT& get() const { return pv_; } - - const PROPVARIANT* operator&() const { return &pv_; } + const PROPVARIANT* ptr() const { return &pv_; } private: PROPVARIANT pv_;
diff --git a/base/win/scoped_variant.h b/base/win/scoped_variant.h index b6e6579..322fcf7 100644 --- a/base/win/scoped_variant.h +++ b/base/win/scoped_variant.h
@@ -122,9 +122,7 @@ // This support is necessary for the V_XYZ (e.g. V_BSTR) set of macros to // work properly but still doesn't allow modifications since we want control // over that. - const VARIANT* operator&() const { - return &var_; - } + const VARIANT* ptr() const { return &var_; } // Like other scoped classes (e.g scoped_refptr, ScopedComPtr, ScopedBstr) // we support the assignment operator for the type we wrap. @@ -161,6 +159,6 @@ }; } // namespace win -} // namesoace base +} // namespace base #endif // BASE_WIN_SCOPED_VARIANT_H_
diff --git a/base/win/scoped_variant_unittest.cc b/base/win/scoped_variant_unittest.cc index 1f017cf..284a6ef 100644 --- a/base/win/scoped_variant_unittest.cc +++ b/base/win/scoped_variant_unittest.cc
@@ -72,41 +72,41 @@ TEST(ScopedVariantTest, ScopedVariant) { ScopedVariant var; EXPECT_TRUE(var.type() == VT_EMPTY); - // V_BSTR(&var) = NULL; <- NOTE: Assignment like that is not supported + // V_BSTR(var.ptr()) = NULL; <- NOTE: Assignment like that is not supported. ScopedVariant var_bstr(L"VT_BSTR"); - EXPECT_EQ(VT_BSTR, V_VT(&var_bstr)); - EXPECT_TRUE(V_BSTR(&var_bstr) != NULL); // can't use EXPECT_NE for BSTR + EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr())); + EXPECT_TRUE(V_BSTR(var_bstr.ptr()) != NULL); // can't use EXPECT_NE for BSTR var_bstr.Reset(); - EXPECT_NE(VT_BSTR, V_VT(&var_bstr)); + EXPECT_NE(VT_BSTR, V_VT(var_bstr.ptr())); var_bstr.Set(kTestString2); - EXPECT_EQ(VT_BSTR, V_VT(&var_bstr)); + EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr())); VARIANT tmp = var_bstr.Release(); - EXPECT_EQ(VT_EMPTY, V_VT(&var_bstr)); + EXPECT_EQ(VT_EMPTY, V_VT(var_bstr.ptr())); EXPECT_EQ(VT_BSTR, V_VT(&tmp)); EXPECT_EQ(0, lstrcmp(V_BSTR(&tmp), kTestString2)); var.Reset(tmp); - EXPECT_EQ(VT_BSTR, V_VT(&var)); - EXPECT_EQ(0, lstrcmpW(V_BSTR(&var), kTestString2)); + EXPECT_EQ(VT_BSTR, V_VT(var.ptr())); + EXPECT_EQ(0, lstrcmpW(V_BSTR(var.ptr()), kTestString2)); var_bstr.Swap(var); - EXPECT_EQ(VT_EMPTY, V_VT(&var)); - EXPECT_EQ(VT_BSTR, V_VT(&var_bstr)); - EXPECT_EQ(0, lstrcmpW(V_BSTR(&var_bstr), kTestString2)); + EXPECT_EQ(VT_EMPTY, V_VT(var.ptr())); + EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr())); + EXPECT_EQ(0, lstrcmpW(V_BSTR(var_bstr.ptr()), kTestString2)); var_bstr.Reset(); // Test the Compare and Copy routines. GiveMeAVariant(var_bstr.Receive()); - ScopedVariant var_bstr2(V_BSTR(&var_bstr)); + ScopedVariant var_bstr2(V_BSTR(var_bstr.ptr())); EXPECT_EQ(0, var_bstr.Compare(var_bstr2)); var_bstr2.Reset(); EXPECT_NE(0, var_bstr.Compare(var_bstr2)); var_bstr2.Reset(var_bstr.Copy()); EXPECT_EQ(0, var_bstr.Compare(var_bstr2)); var_bstr2.Reset(); - var_bstr2.Set(V_BSTR(&var_bstr)); + var_bstr2.Set(V_BSTR(var_bstr.ptr())); EXPECT_EQ(0, var_bstr.Compare(var_bstr2)); var_bstr2.Reset(); var_bstr.Reset(); @@ -119,7 +119,7 @@ var.Reset(); var.SetDate(date); EXPECT_EQ(VT_DATE, var.type()); - EXPECT_EQ(date, V_DATE(&var)); + EXPECT_EQ(date, V_DATE(var.ptr())); // Simple setter tests. These do not require resetting the variant // after each test since the variant type is not "leakable" (i.e. doesn't @@ -128,75 +128,75 @@ // We need static cast here since char defaults to int (!?). var.Set(static_cast<int8>('v')); EXPECT_EQ(VT_I1, var.type()); - EXPECT_EQ('v', V_I1(&var)); + EXPECT_EQ('v', V_I1(var.ptr())); var.Set(static_cast<short>(123)); EXPECT_EQ(VT_I2, var.type()); - EXPECT_EQ(123, V_I2(&var)); + EXPECT_EQ(123, V_I2(var.ptr())); var.Set(static_cast<int32>(123)); EXPECT_EQ(VT_I4, var.type()); - EXPECT_EQ(123, V_I4(&var)); + EXPECT_EQ(123, V_I4(var.ptr())); var.Set(static_cast<int64>(123)); EXPECT_EQ(VT_I8, var.type()); - EXPECT_EQ(123, V_I8(&var)); + EXPECT_EQ(123, V_I8(var.ptr())); var.Set(static_cast<uint8>(123)); EXPECT_EQ(VT_UI1, var.type()); - EXPECT_EQ(123, V_UI1(&var)); + EXPECT_EQ(123, V_UI1(var.ptr())); var.Set(static_cast<unsigned short>(123)); EXPECT_EQ(VT_UI2, var.type()); - EXPECT_EQ(123, V_UI2(&var)); + EXPECT_EQ(123, V_UI2(var.ptr())); var.Set(static_cast<uint32>(123)); EXPECT_EQ(VT_UI4, var.type()); - EXPECT_EQ(123, V_UI4(&var)); + EXPECT_EQ(123, V_UI4(var.ptr())); var.Set(static_cast<uint64>(123)); EXPECT_EQ(VT_UI8, var.type()); - EXPECT_EQ(123, V_UI8(&var)); + EXPECT_EQ(123, V_UI8(var.ptr())); var.Set(123.123f); EXPECT_EQ(VT_R4, var.type()); - EXPECT_EQ(123.123f, V_R4(&var)); + EXPECT_EQ(123.123f, V_R4(var.ptr())); var.Set(static_cast<double>(123.123)); EXPECT_EQ(VT_R8, var.type()); - EXPECT_EQ(123.123, V_R8(&var)); + EXPECT_EQ(123.123, V_R8(var.ptr())); var.Set(true); EXPECT_EQ(VT_BOOL, var.type()); - EXPECT_EQ(VARIANT_TRUE, V_BOOL(&var)); + EXPECT_EQ(VARIANT_TRUE, V_BOOL(var.ptr())); var.Set(false); EXPECT_EQ(VT_BOOL, var.type()); - EXPECT_EQ(VARIANT_FALSE, V_BOOL(&var)); + EXPECT_EQ(VARIANT_FALSE, V_BOOL(var.ptr())); // Com interface tests var.Set(static_cast<IDispatch*>(NULL)); EXPECT_EQ(VT_DISPATCH, var.type()); - EXPECT_EQ(NULL, V_DISPATCH(&var)); + EXPECT_EQ(NULL, V_DISPATCH(var.ptr())); var.Reset(); var.Set(static_cast<IUnknown*>(NULL)); EXPECT_EQ(VT_UNKNOWN, var.type()); - EXPECT_EQ(NULL, V_UNKNOWN(&var)); + EXPECT_EQ(NULL, V_UNKNOWN(var.ptr())); var.Reset(); FakeComObject faker; EXPECT_EQ(0, faker.ref_count()); var.Set(static_cast<IDispatch*>(&faker)); EXPECT_EQ(VT_DISPATCH, var.type()); - EXPECT_EQ(&faker, V_DISPATCH(&var)); + EXPECT_EQ(&faker, V_DISPATCH(var.ptr())); EXPECT_EQ(1, faker.ref_count()); var.Reset(); EXPECT_EQ(0, faker.ref_count()); var.Set(static_cast<IUnknown*>(&faker)); EXPECT_EQ(VT_UNKNOWN, var.type()); - EXPECT_EQ(&faker, V_UNKNOWN(&var)); + EXPECT_EQ(&faker, V_UNKNOWN(var.ptr())); EXPECT_EQ(1, faker.ref_count()); var.Reset(); EXPECT_EQ(0, faker.ref_count()); @@ -204,7 +204,7 @@ { ScopedVariant disp_var(&faker); EXPECT_EQ(VT_DISPATCH, disp_var.type()); - EXPECT_EQ(&faker, V_DISPATCH(&disp_var)); + EXPECT_EQ(&faker, V_DISPATCH(disp_var.ptr())); EXPECT_EQ(1, faker.ref_count()); } EXPECT_EQ(0, faker.ref_count()); @@ -223,7 +223,7 @@ { ScopedVariant unk_var(static_cast<IUnknown*>(&faker)); EXPECT_EQ(VT_UNKNOWN, unk_var.type()); - EXPECT_EQ(&faker, V_UNKNOWN(&unk_var)); + EXPECT_EQ(&faker, V_UNKNOWN(unk_var.ptr())); EXPECT_EQ(1, faker.ref_count()); } EXPECT_EQ(0, faker.ref_count()); @@ -240,7 +240,7 @@ { ScopedVariant number(123); EXPECT_EQ(VT_I4, number.type()); - EXPECT_EQ(123, V_I4(&number)); + EXPECT_EQ(123, V_I4(number.ptr())); } // SAFEARRAY tests @@ -253,7 +253,7 @@ var.Set(sa); EXPECT_TRUE(ScopedVariant::IsLeakableVarType(var.type())); EXPECT_EQ(VT_ARRAY | VT_UI1, var.type()); - EXPECT_EQ(sa, V_ARRAY(&var)); + EXPECT_EQ(sa, V_ARRAY(var.ptr())); // The array is destroyed in the destructor of var. }
diff --git a/base/win/startup_information.h b/base/win/startup_information.h index 7cef81f..e7e21cb 100644 --- a/base/win/startup_information.h +++ b/base/win/startup_information.h
@@ -45,5 +45,4 @@ } // namespace win } // namespace base -#endif // BASE_WIN_SCOPED_STARTUP_INFO_EX_H_ - +#endif // BASE_WIN_STARTUP_INFORMATION_H__
diff --git a/base/win/win_util.cc b/base/win/win_util.cc index 957f937..59ae375 100644 --- a/base/win/win_util.cc +++ b/base/win/win_util.cc
@@ -70,6 +70,53 @@ return true; } + // If the device is docked, the user is treating the device as a PC. + if (GetSystemMetrics(SM_SYSTEMDOCKED) != 0) + return true; + + // To determine whether a keyboard is present on the device, we do the + // following:- + // 1. Check whether the device supports auto rotation. If it does then + // it possibly supports flipping from laptop to slate mode. If it + // does not support auto rotation, then we assume it is a desktop + // or a normal laptop and assume that there is a keyboard. + + // 2. If the device supports auto rotation, then we get its platform role + // and check the system metric SM_CONVERTIBLESLATEMODE to see if it is + // being used in slate mode. If yes then we return false here to ensure + // that the OSK is displayed. + + // 3. If step 1 and 2 fail then we check attached keyboards and return true + // if we find ACPI\* or HID\VID* keyboards. + + typedef BOOL (WINAPI* GetAutoRotationState)(PAR_STATE state); + + GetAutoRotationState get_rotation_state = + reinterpret_cast<GetAutoRotationState>(::GetProcAddress( + GetModuleHandle(L"user32.dll"), "GetAutoRotationState")); + + if (get_rotation_state) { + AR_STATE auto_rotation_state = AR_ENABLED; + get_rotation_state(&auto_rotation_state); + if ((auto_rotation_state & AR_NOSENSOR) || + (auto_rotation_state & AR_NOT_SUPPORTED)) { + // If there is no auto rotation sensor or rotation is not supported in + // the current configuration, then we can assume that this is a desktop + // or a traditional laptop. + return true; + } + } + + // Check if the device is being used as a laptop or a tablet. This can be + // checked by first checking the role of the device and then the + // corresponding system metric (SM_CONVERTIBLESLATEMODE). If it is being used + // as a tablet then we want the OSK to show up. + POWER_PLATFORM_ROLE role = PowerDeterminePlatformRole(); + + if (((role == PlatformRoleMobile) || (role == PlatformRoleSlate)) && + (GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 0)) + return false; + const GUID KEYBOARD_CLASS_GUID = { 0x4D36E96B, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } }; @@ -97,10 +144,9 @@ MAX_DEVICE_ID_LEN, 0); if (status == CR_SUCCESS) { - // To reduce the scope of the hack we only look for PNP, MSF and HID - // keyboards. - if (StartsWith(device_id, L"ACPI\\PNP", false) || - StartsWith(device_id, L"ACPI\\MSF", false) || + // To reduce the scope of the hack we only look for ACPI and HID\\VID + // prefixes in the keyboard device ids. + if (StartsWith(device_id, L"ACPI", false) || StartsWith(device_id, L"HID\\VID", false)) { keyboard_count++; }
diff --git a/base/win/win_util_unittest.cc b/base/win/win_util_unittest.cc index 8300c16..24141cd 100644 --- a/base/win/win_util_unittest.cc +++ b/base/win/win_util_unittest.cc
@@ -49,9 +49,9 @@ TEST(BaseWinUtilTest, TestGetNonClientMetrics) { NONCLIENTMETRICS_XP metrics = {0}; GetNonClientMetrics(&metrics); - EXPECT_TRUE(metrics.cbSize > 0); - EXPECT_TRUE(metrics.iScrollWidth > 0); - EXPECT_TRUE(metrics.iScrollHeight > 0); + EXPECT_GT(metrics.cbSize, 0u); + EXPECT_GT(metrics.iScrollWidth, 0); + EXPECT_GT(metrics.iScrollHeight, 0); } } // namespace win
diff --git a/build/OWNERS b/build/OWNERS index da383a1..17d067c 100644 --- a/build/OWNERS +++ b/build/OWNERS
@@ -1,4 +1,5 @@ cjhopman@chromium.org +dpranke@chromium.org jochen@chromium.org scottmg@chromium.org thakis@chromium.org
diff --git a/build/all.gyp b/build/all.gyp index 499fc57..4108962 100644 --- a/build/all.gyp +++ b/build/all.gyp
@@ -66,7 +66,6 @@ '../third_party/mojo/mojo_public.gyp:mojo_public_test_utils', '../third_party/mojo/mojo_public.gyp:mojo_system', '../ui/base/ui_base_tests.gyp:ui_base_unittests', - '../ui/ios/ui_ios_tests.gyp:ui_ios_unittests', '../ui/gfx/gfx_tests.gyp:gfx_unittests', ], }], @@ -642,13 +641,6 @@ ], }, # target_name: chromium_gpu_debug_builder { - 'target_name': 'chromium_builder_perf_av', - 'type': 'none', - 'dependencies': [ - 'blink_tests', # to run layout tests - ], - }, # target_name: chromium_builder_perf_av - { # This target contains everything we need to run tests on the special # device-equipped WebRTC bots. We have device-requiring tests in # browser_tests and content_browsertests. @@ -789,6 +781,7 @@ '../content/content_shell_and_tests.gyp:content_shell_test_apk', '../content/content_shell_and_tests.gyp:content_unittests', '../gpu/gpu.gyp:gl_tests', + '../gpu/gpu.gyp:gpu_perftests_apk', '../gpu/gpu.gyp:gpu_unittests', '../ipc/ipc.gyp:ipc_tests', '../media/media.gyp:media_perftests_apk',
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py index c3c344b..c9be13a 100755 --- a/build/android/buildbot/bb_device_steps.py +++ b/build/android/buildbot/bb_device_steps.py
@@ -466,6 +466,8 @@ provision_cmd.append('--auto-reconnect') if options.skip_wipe: provision_cmd.append('--skip-wipe') + if options.disable_location: + provision_cmd.append('--disable-location') RunCmd(provision_cmd, halt_on_failure=True) @@ -713,6 +715,8 @@ help='Push script to device which restarts adbd on disconnections.') parser.add_option('--skip-wipe', action='store_true', help='Do not wipe devices during provisioning.') + parser.add_option('--disable-location', action='store_true', + help='Disable location settings.') parser.add_option( '--logcat-dump-output', help='The logcat dump output will be "tee"-ed into this file')
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml index fba286d..5060e47 100644 --- a/build/android/findbugs_filter/findbugs_exclude.xml +++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -18,7 +18,16 @@ <Class name="~org\.chromium\..*\.Manifest(\$\w+)?" /> </Match> <!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform --> - + <Match> + <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" /> + <Method name="onCancel" /> + <Bug code="Dm" /> + </Match> + <Match> + <Class name="~org\.chromium\.chrome\.browser\.ChromiumApplication.*" /> + <Method name="onClick" /> + <Bug code="Dm" /> + </Match> <Bug pattern="DM_DEFAULT_ENCODING" /> <!-- Ignore bugs that are often false-positives in test code --> <Match>
diff --git a/build/android/findbugs_filter/findbugs_known_bugs.txt b/build/android/findbugs_filter/findbugs_known_bugs.txt deleted file mode 100644 index 01b546a..0000000 --- a/build/android/findbugs_filter/findbugs_known_bugs.txt +++ /dev/null
@@ -1,10 +0,0 @@ -M M LI: Incorrect lazy initialization of static field org.chromium.chrome.browser.download.DownloadManagerService.sDownloadManagerService in org.chromium.chrome.browser.download.DownloadManagerService.getDownloadManagerService(Context) At DownloadManagerService.java -M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.extraHeaders At DocumentTabModelSelector.java -M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.postData At DocumentTabModelSelector.java -M D UrF: Unread public/protected field: org.chromium.chrome.browser.document.PendingDocumentData.referrer At DocumentTabModelSelector.java -M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.webContents In PendingDocumentData.java -M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.originalIntent In PendingDocumentData.java -M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.url In PendingDocumentData.java -M D UuF: Unused public or protected field: org.chromium.chrome.browser.document.PendingDocumentData.requestId In PendingDocumentData.java -M D BC: Unchecked/unconfirmed cast from android.view.View to org.chromium.chrome.browser.firstrun.AccountFirstRunView in org.chromium.chrome.browser.firstrun.AccountFirstRunFragment.onViewCreated(View, Bundle) At AccountFirstRunFragment.java -M M LI: Incorrect lazy initialization and update of static field org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings.sSettings in org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings.initialize(Context) At DataReductionProxySettings.java
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py index 953ea54..9402780 100755 --- a/build/android/gyp/lint.py +++ b/build/android/gyp/lint.py
@@ -20,7 +20,8 @@ def _RunLint(lint_path, config_path, processed_config_path, manifest_path, - result_path, product_dir, sources, jar_path, resource_dir=None): + result_path, product_dir, sources, jar_path, resource_dir=None, + can_fail_build=False): def _RelativizePath(path): """Returns relative path to top-level src dir. @@ -147,8 +148,7 @@ 'lint', 'suppress.py')), _RelativizePath(result_path))) print >> sys.stderr, msg - # Lint errors do not fail the build. - return 0 + return 1 if can_fail_build else 0 return 0 @@ -167,6 +167,9 @@ parser.add_option('--java-files', help='Paths to java files.') parser.add_option('--jar-path', help='Jar file containing class files.') parser.add_option('--resource-dir', help='Path to resource dir.') + parser.add_option('--can-fail-build', action='store_true', + help='If set, script will exit with nonzero exit status' + ' if lint errors are present') parser.add_option('--stamp', help='Path to touch on success.') parser.add_option('--enable', action='store_true', help='Run lint instead of just touching stamp.') @@ -195,7 +198,7 @@ options.processed_config_path, options.manifest_path, options.result_path, options.product_dir, sources, options.jar_path, - options.resource_dir) + options.resource_dir, options.can_fail_build) if options.depfile: build_utils.WriteDepfile(
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index cfbf858..ba476d5 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -95,9 +95,6 @@ <ignore path="org/chromium/media/VideoCaptureCamera2.class"/> <ignore path="org/chromium/media/VideoCaptureCamera2$*.class"/> <ignore path="org/chromium/media/WebAudioMediaCodecBridge.class"/> - <ignore path="org/chromium/printing/PrintDocumentAdapterWrapper.class"/> - <ignore path="org/chromium/printing/PrintManagerDelegateImpl.class"/> - <ignore path="org/chromium/printing/PrintingControllerImpl.class"/> <ignore path="org/chromium/ui/base/Clipboard.class"/> <ignore path="org/chromium/ui/ColorPickerAdvancedComponent.class"/> <ignore path="org/chromium/ui/gfx/DeviceDisplayInfo.class"/>
diff --git a/build/android/pylib/gtest/filter/content_browsertests_disabled b/build/android/pylib/gtest/filter/content_browsertests_disabled index 613c833..3c36264 100644 --- a/build/android/pylib/gtest/filter/content_browsertests_disabled +++ b/build/android/pylib/gtest/filter/content_browsertests_disabled
@@ -15,10 +15,6 @@ # Crashes RenderFrameHostManagerTest.IgnoreRendererDebugURLsWhenCrashed -# Crashes due to using --disable-gpu. -# Needs to investigate more in http://crbug.com/461624. -ScreenOrientationBrowserTest.* - # Plugins are not supported. BrowserPluginThreadedCompositorPixelTest.* BrowserPluginHostTest.* @@ -74,7 +70,3 @@ # http://crbug.com/343604 MSE_ClearKey/EncryptedMediaTest.ConfigChangeVideo/0 - -# http://crbug.com/463041 -ScreenOrientationBrowserTest.ScreenOrientationChange -ScreenOrientationBrowserTest.WindowOrientationCange
diff --git a/build/android/pylib/host_driven/test_server.py b/build/android/pylib/host_driven/test_server.py index 959e7a9..0783500 100644 --- a/build/android/pylib/host_driven/test_server.py +++ b/build/android/pylib/host_driven/test_server.py
@@ -106,7 +106,8 @@ cmd = ['python', os.path.join(src_dir, test_server_path), '--log-to-console', ('--host=%s' % self.host), - ('--port=%d' % self.port)] + test_server_flags + ('--port=%d' % self.port), + '--on-remote-server'] + test_server_flags self._test_server_process = subprocess.Popen( cmd, env={'PYTHONPATH': python_path}) test_url = 'http://%s:%d/%s' % (self.host, self.port,
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py index 3b0c029..8875096 100644 --- a/build/android/pylib/remote/device/remote_device_environment.py +++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -286,12 +286,22 @@ return 0 logging.critical('Available %s Devices:', self._device_type) - logging.critical(' %s %s %s', 'OS'.ljust(7), - 'Device Name'.ljust(20), '# Available') + logging.critical( + ' %s %s %s %s %s', + 'OS'.ljust(10), + 'Device Name'.ljust(30), + 'Available'.ljust(10), + 'Busy'.ljust(10), + 'All'.ljust(10)) devices = (d for d in device_list if d['os_name'] == self._device_type) for d in sorted(devices, compare_devices): - logging.critical(' %s %s %s', d['os_version'].ljust(7), - d['name'].ljust(20), d['available_devices_count']) + logging.critical( + ' %s %s %s %s %s', + d['os_version'].ljust(10), + d['name'].ljust(30), + str(d['available_devices_count']).ljust(10), + str(d['busy_devices_count']).ljust(10), + str(d['all_devices_count']).ljust(10)) def _GetDeviceList(self): with appurify_sanitized.SanitizeLogging(self._verbose_count,
diff --git a/build/android/pylib/utils/isolator.py b/build/android/pylib/utils/isolator.py index 60d326e..fcbe427 100644 --- a/build/android/pylib/utils/isolator.py +++ b/build/android/pylib/utils/isolator.py
@@ -41,6 +41,7 @@ 'use_instrumented_libraries': '0', 'use_openssl': '0', 'use_ozone': '0', + 'use_x11': '0', 'v8_use_external_startup_data': '1', }
diff --git a/build/common.gypi b/build/common.gypi index d72c76f..043dd92 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -416,6 +416,9 @@ # See https://code.google.com/p/sawbuck/wiki/SyzyASanHowTo 'syzyasan%': 0, + # Enable crash reporting via Kasko. + 'kasko%': 0, + # Enable building with LSan (Clang's -fsanitize=leak option). # -fsanitize=leak only works with clang, but lsan=1 implies clang=1 # See https://sites.google.com/a/chromium.org/dev/developers/testing/leaksanitizer @@ -643,6 +646,10 @@ # Libxkbcommon usage. 'use_xkbcommon%': 0, + # Control Flow Integrity for virtual calls. + # See http://clang.llvm.org/docs/ControlFlowIntegrity.html + 'cfi_vptr%': 0, + 'conditions': [ # A flag for POSIX platforms ['OS=="win"', { @@ -771,7 +778,6 @@ }], ['OS=="mac" or OS=="ios"', { - 'native_discardable_memory%': 1, 'native_memory_pressure_signals%': 1, }], @@ -808,7 +814,6 @@ 'enable_supervised_users%': 0, 'enable_task_manager%': 0, 'use_system_libcxx%': 1, - 'support_pre_M6_history_database%': 0, }], # Use GPU accelerated cross process image transport by default @@ -1063,9 +1068,6 @@ 'google_default_client_secret%': '', # Native Client is enabled by default. 'disable_nacl%': '0', - - # Set to 1 to support old history files - 'support_pre_M6_history_database%': '1', }, # Copy conditionally-set variables out one scope. @@ -1140,6 +1142,7 @@ 'asan_field_padding%': '<(asan_field_padding)', 'use_sanitizer_options%': '<(use_sanitizer_options)', 'syzyasan%': '<(syzyasan)', + 'kasko%': '<(kasko)', 'syzygy_optimize%': '<(syzygy_optimize)', 'lsan%': '<(lsan)', 'msan%': '<(msan)', @@ -1214,8 +1217,8 @@ 'use_lto_o2%': '<(use_lto_o2)', 'gold_icf_level%': '<(gold_icf_level)', 'video_hole%': '<(video_hole)', - 'support_pre_M6_history_database%': '<(support_pre_M6_history_database)', 'v8_use_external_startup_data%': '<(v8_use_external_startup_data)', + 'cfi_vptr%': '<(cfi_vptr)', # Use system protobuf instead of bundled one. 'use_system_protobuf%': 0, @@ -1951,6 +1954,9 @@ ['asan==1 or syzyasan==1', { 'win_use_allocator_shim%': 0, }], + ['syzyasan==1', { + 'kasko%': 1, + }], ['component=="shared_library" and "<(GENERATOR)"=="ninja"', { # Only enabled by default for ninja because it's buggy in VS. # Not enabled for component=static_library because some targets @@ -2162,8 +2168,19 @@ 'enable_service_discovery%': 1 }], ['clang_use_chrome_plugins==1 and OS!="win"', { + 'variables': { + 'conditions': [ + ['OS=="mac" or OS=="ios"', { + 'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib', + }, { # OS != "mac" or OS != "ios" + 'clang_lib_path%': '<!(cd <(DEPTH) && pwd -P)/third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.so', + }], + ], + }, + # If you change these, also change build/config/clang/BUILD.gn. 'clang_chrome_plugins_flags%': - '<!(python <(DEPTH)/tools/clang/scripts/plugin_flags.py)', + '-Xclang -load -Xclang <(clang_lib_path)' + ' -Xclang -add-plugin -Xclang find-bad-constructs', }], ['asan==1 or msan==1 or lsan==1 or tsan==1', { 'clang%': 1, @@ -2376,10 +2393,11 @@ }, { 'use_seccomp_bpf%': 0, }], - ], - # older history files use fts2 instead of fts3 - 'sqlite_enable_fts2%': '<(support_pre_M6_history_database)', + ['cfi_vptr==1', { + 'use_lto%': 1, + }], + ], # The path to the ANGLE library. 'angle_path': '<(DEPTH)/third_party/angle', @@ -2796,6 +2814,11 @@ 'MEMORY_TOOL_REPLACES_ALLOCATOR', 'MEMORY_SANITIZER_INITIAL_SIZE', ], + }], + ['kasko==1', { + 'defines': [ + 'KASKO', + ], 'include_dirs': [ '<(DEPTH)/third_party/kasko/include', ], @@ -2953,9 +2976,6 @@ ['disable_ftp_support==1', { 'defines': ['DISABLE_FTP_SUPPORT=1'], }], - ['use_icu_alternatives_on_android==1', { - 'defines': ['USE_ICU_ALTERNATIVES_ON_ANDROID=1'], - }], ['enable_supervised_users==1', { 'defines': ['ENABLE_SUPERVISED_USERS=1'], }], @@ -3990,6 +4010,7 @@ ['clang==1', { 'cflags!': [ # Clang does not support the following options. + '-mapcs-frame', '-mthumb-interwork', '-finline-limit=64', '-fno-tree-sra', @@ -4461,6 +4482,14 @@ # '-Wl,--threads', # '-Wl,--thread-count=4', ], + 'conditions': [ + # TODO(thestig): Enable this for disabled cases. + [ 'buildtype!="Official" and chromeos==0 and release_valgrind_build==0 and asan==0 and lsan==0 and tsan==0 and msan==0 and ubsan==0 and ubsan_vptr==0', { + 'ldflags': [ + '-Wl,--detect-odr-violations', + ], + }], + ], }], ], 'conditions': [ @@ -5927,6 +5956,20 @@ ], }, }], + ['cfi_vptr==1', { + 'target_defaults': { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags': [ + '-fsanitize=cfi-vptr', + ], + 'ldflags': [ + '-fsanitize=cfi-vptr', + ], + }], + ], + }, + }], ], 'xcode_settings': { # DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn index 49b5cfe..15441a9 100644 --- a/build/config/BUILD.gn +++ b/build/config/BUILD.gn
@@ -14,11 +14,16 @@ # catching bugs but in some cases may cause conflicts or excessive slowness. disable_iterator_debugging = false - # Set to true to not store any build metadata (this isn't working yet but - # this flag will help us to get there). See http://crbug.com/314403. - # TODO(sebmarchand): Update this comment once this flag guarantee that - # there's no build metadata in the build artifacts. - dont_embed_build_metadata = false + # Set to true to not store any build metadata, e.g. ifdef out all __DATE__ + # and __TIME__. Set to 0 to reenable the use of these macros in the code + # base. See http://crbug.com/314403. + # + # Continue to embed build meta data in Official builds, basically the + # time it was built. + # TODO(maruel): This decision should be revisited because having an + # official deterministic build has high value too but MSVC toolset can't + # generate anything deterministic with WPO enabled AFAIK. + dont_embed_build_metadata = is_official_build # Set to true to enable dcheck in Release builds. dcheck_always_on = false @@ -214,6 +219,12 @@ if (v8_use_external_startup_data) { defines += [ "V8_USE_EXTERNAL_STARTUP_DATA" ] } + if (enable_background) { + defines += [ "ENABLE_BACKGROUND=1" ] + } + if (enable_pre_sync_backup) { + defines += [ "ENABLE_PRE_SYNC_BACKUP" ] + } } # Debug/release ---------------------------------------------------------------- @@ -225,6 +236,10 @@ "WTF_USE_DYNAMIC_ANNOTATIONS=1", ] + if (is_nacl) { + defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ] + } + if (is_win) { if (disable_iterator_debugging) { # Iterator debugging is enabled by the compiler on debug builds, and we
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 4397151..f75ad06 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -78,7 +78,7 @@ # # Base compiler configuration. # -# See also "runtime_library" below for related stuff and a discusison about +# See also "runtime_library" below for related stuff and a discussion about # where stuff should go. Put warning related stuff in the "warnings" config. config("compiler") { @@ -100,10 +100,6 @@ "/GS", # Enable buffer security checking. "/FS", # Preserve previous PDB behavior. ] - if (is_component_build) { - cflags += [ "/EHsc" ] # Assume C functions can't throw exceptions and don't catch - # structured exceptions (only C++ ones). - } } else { # Common GCC compiler flags setup. # -------------------------------- @@ -161,7 +157,7 @@ ] } - if (is_clang && !is_win) { + if (is_clang && !is_win && !is_nacl) { # This is here so that all files get recompiled after a clang roll and # when turning clang on or off. (defines are passed via the command line, # and build system rebuild things when their commandline changes). Nothing @@ -403,6 +399,13 @@ #"-Wl,--threads", #"-Wl,--thread-count=4", ] + + # TODO(thestig): Make this flag work with GN. + #if (!is_official_build && !is_chromeos && !(is_asan || is_lsan || is_tsan || is_msan)) { + # ldflags += [ + # "-Wl,--detect-odr-violations", + # ] + #} } if (linux_use_bundled_binutils) { @@ -534,9 +537,6 @@ } else { # Static CRT. if (is_win) { - # We don't use exceptions, and when we link statically we can just get - # rid of them entirely. - defines += [ "_HAS_EXCEPTIONS=0" ] if (is_debug) { cflags += [ "/MTd" ] } else { @@ -548,10 +548,9 @@ if (is_win) { defines += [ "__STD_C", - "__STDC_CONSTANT_MACROS", - "__STDC_FORMAT_MACROS", "_CRT_RAND_S", "_CRT_SECURE_NO_DEPRECATE", + "_HAS_EXCEPTIONS=0", "_SCL_SECURE_NO_DEPRECATE", ] } @@ -727,7 +726,6 @@ if (is_win) { cflags = [ "/WX", # Treat warnings as errors. - # Warnings permanently disabled: # TODO(GYP) The GYP build doesn't have this globally enabled but disabled @@ -782,7 +780,6 @@ # have to turn off this warning (and be careful about how object # destruction happens in such cases). "/wd4611", - # Warnings to evaluate and possibly fix/reenable later: "/wd4100", # Unreferenced formal function parameter.
diff --git a/build/config/features.gni b/build/config/features.gni index 4d01a87..ee61da5 100644 --- a/build/config/features.gni +++ b/build/config/features.gni
@@ -178,3 +178,6 @@ # For official GYP builds, this flag is set, it will likely need to be # parameterized in the future for a similar use. enable_hangout_services_extension = false + +# Whether to back up data before sync. +enable_pre_sync_backup = is_win || is_mac || (is_linux && !is_chromeos)
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 201d45b..3e98c1a 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -17,6 +17,9 @@ "PSAPI_VERSION=1", "WIN32", "_SECURE_ATL", + + # This is required for ATL to use XP-safe versions of its functions. + "_USING_V110_SDK71_", ] }
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 273c38e..92c050f 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi
@@ -34,60 +34,145 @@ 'target_name': 'gn_all', 'type': 'none', 'dependencies': [ + '../base/base.gyp:base_i18n_perftests', + '../base/base.gyp:base_perftests', '../base/base.gyp:base_unittests', + '../base/base.gyp:build_utf8_validator_tables#host', + '../base/base.gyp:check_example', + '../base/base.gyp:protect_file_posix', + '../breakpad/breakpad.gyp:core-2-minidump', + '../breakpad/breakpad.gyp:microdump_stackwalk', + '../breakpad/breakpad.gyp:minidump_dump', + '../breakpad/breakpad.gyp:minidump_stackwalk', + '../build/sanitizers/sanitizers.gyp:llvm-symbolizer', + '../cc/cc_tests.gyp:cc_perftests', '../cc/cc_tests.gyp:cc_unittests', + '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests', '../chrome/chrome.gyp:chrome', '../chrome/chrome.gyp:browser_tests', + '../chrome/chrome.gyp:chrome_app_unittests', + '../chrome/chrome.gyp:chromedriver', + '../chrome/chrome.gyp:chromedriver_tests', + '../chrome/chrome.gyp:chromedriver_unittests', '../chrome/chrome.gyp:interactive_ui_tests', + '../chrome/chrome.gyp:load_library_perf_tests', + '../chrome/chrome.gyp:service_discovery_sniffer', '../chrome/chrome.gyp:sync_integration_tests', + '../chrome/chrome.gyp:sync_performance_tests', '../chrome/chrome.gyp:unit_tests', + '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler', + '../components/components.gyp:network_hints_browser', + '../components/components.gyp:webui_generator', + '../components/components_tests.gyp:components_perftests', '../components/components_tests.gyp:components_unittests', - '../content/content_shell_and_tests.gyp:content_shell', + '../components/nacl.gyp:nacl_loader_unittests', + '../content/content.gyp:content_app_browser', + '../content/content.gyp:content_app_child', '../content/content_shell_and_tests.gyp:content_browsertests', + '../content/content_shell_and_tests.gyp:content_gl_benchmark', + '../content/content_shell_and_tests.gyp:content_gl_tests', '../content/content_shell_and_tests.gyp:content_perftests', + '../content/content_shell_and_tests.gyp:content_shell', '../content/content_shell_and_tests.gyp:content_unittests', + '../courgette/courgette.gyp:courgette', + '../courgette/courgette.gyp:courgette_fuzz', + '../courgette/courgette.gyp:courgette_minimal_tool', + '../courgette/courgette.gyp:courgette_unittests', '../crypto/crypto.gyp:crypto_unittests', '../extensions/extensions_tests.gyp:extensions_browsertests', '../extensions/extensions_tests.gyp:extensions_unittests', + '../device/device_tests.gyp:device_unittests', + '../gin/gin.gyp:gin_v8_snapshot_fingerprint', + '../gin/gin.gyp:gin_shell', + '../gin/gin.gyp:gin_unittests', '../google_apis/gcm/gcm.gyp:gcm_unit_tests', + '../google_apis/gcm/gcm.gyp:mcs_probe', + '../google_apis/google_apis.gyp:google_apis_unittests', + '../gpu/gpu.gyp:angle_unittests', + '../gpu/gpu.gyp:gl_tests', + '../gpu/gpu.gyp:gpu_perftests', '../gpu/gpu.gyp:gpu_unittests', + '../ipc/ipc.gyp:ipc_perftests', '../ipc/ipc.gyp:ipc_tests', '../ipc/mojo/ipc_mojo.gyp:ipc_mojo_unittests', '../jingle/jingle.gyp:jingle_unittests', + '../media/media.gyp:ffmpeg_regression_tests', # TODO(GYP) this should be conditional on media_use_ffmpeg + '../media/media.gyp:media_perftests', '../media/media.gyp:media_unittests', + '../media/cast/cast.gyp:cast_benchmarks', '../media/cast/cast.gyp:cast_unittests', + '../media/cast/cast.gyp:generate_barcode_video', + '../media/cast/cast.gyp:generate_timecode_audio', '../mojo/mojo.gyp:mojo', + '../mojo/mojo_base.gyp:mojo_application_chromium', '../mojo/mojo_base.gyp:mojo_common_unittests', + '../net/net.gyp:crash_cache', + '../net/net.gyp:crl_set_dump', + '../net/net.gyp:dns_fuzz_stub', + '../net/net.gyp:dump_cache', + '../net/net.gyp:gdig', + '../net/net.gyp:get_server_time', '../net/net.gyp:net_unittests', + '../net/net.gyp:net_watcher', # TODO(GYP): This should be conditional on use_v8_in_net + '../net/net.gyp:run_testserver', + '../net/net.gyp:stress_cache', + '../net/net.gyp:tld_cleanup', + '../ppapi/ppapi_internal.gyp:*', # TODO(GYP) - list all of the examples explicitly. + '../ppapi/ppapi_internal.gyp:ppapi_tests', # TODO(GYP): Split out the examples and tests + '../ppapi/ppapi_internal.gyp:ppapi_unittests', '../printing/printing.gyp:printing_unittests', '../skia/skia_tests.gyp:skia_unittests', + '../skia/skia.gyp:filter_fuzz_stub', + '../skia/skia.gyp:image_operations_bench', '../sql/sql.gyp:sql_unittests', + '../sync/sync.gyp:run_sync_testserver', + '../sync/sync.gyp:sync_endtoend_tests', '../sync/sync.gyp:sync_unit_tests', - '../third_party/WebKit/public/all.gyp:all_blink', + '../sync/tools/sync_tools.gyp:sync_client', + '../sync/tools/sync_tools.gyp:sync_listen_notifications', + '../testing/gmock.gyp:gmock_main', + '../third_party/WebKit/public/all.gyp:blink_tests', '../third_party/cacheinvalidation/cacheinvalidation.gyp:cacheinvalidation_unittests', '../third_party/codesighs/codesighs.gyp:codesighs', + '../third_party/codesighs/codesighs.gyp:maptsvdifftool', + '../third_party/leveldatabase/leveldatabase.gyp:env_chromium_unittests', + '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber_unittests', + '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_unittests', '../third_party/mojo/mojo_edk_tests.gyp:mojo_system_unittests', '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_bindings_unittests', '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_environment_unittests', + '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests', '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_unittests', '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_utility_unittests', '../third_party/pdfium/samples/samples.gyp:pdfium_test', '../third_party/smhasher/smhasher.gyp:pmurhash', '../third_party/sqlite/sqlite.gyp:sqlite_shell', '../tools/gn/gn.gyp:gn', + '../tools/gn/gn.gyp:generate_test_gn_data', '../tools/gn/gn.gyp:gn_unittests', + '../tools/imagediff/image_diff.gyp:image_diff', + '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache', + '../tools/telemetry/telemetry.gyp:bitmaptools#host', '../ui/accessibility/accessibility.gyp:accessibility_unittests', '../ui/app_list/app_list.gyp:app_list_unittests', '../ui/base/ui_base_tests.gyp:ui_base_unittests', + '../ui/compositor/compositor.gyp:compositor_unittests', '../ui/display/display.gyp:display_unittests', '../ui/events/events.gyp:events_unittests', '../ui/gfx/gfx_tests.gyp:gfx_unittests', + '../ui/keyboard/keyboard.gyp:keyboard_unittests', + '../ui/message_center/message_center.gyp:message_center_unittests', + '../ui/snapshot/snapshot.gyp:snapshot_unittests', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests', + '../ui/views/examples/examples.gyp:views_examples_with_content_exe', '../url/url.gyp:url_unittests', + '../v8/tools/gyp/v8.gyp:v8_snapshot', + '../v8/tools/gyp/v8.gyp:postmortem-metadata', ], 'conditions': [ ['enable_extensions==1 and OS!="mac"', { 'dependencies': [ + '../extensions/shell/app_shell.gyp:app_shell', '../extensions/shell/app_shell.gyp:app_shell_unittests', ], }], @@ -98,16 +183,35 @@ }], ['use_x11==1', { 'dependencies': [ + '../media/media.gyp:player_x11', '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck', ], + 'conditions': [ + ['target_arch!="arm"', { + 'dependencies': [ + '../gpu/tools/tools.gyp:compositor_model_bench', + ], + }], + ], }], ['toolkit_views==1', { 'dependencies': [ + '../ui/app_list/app_list.gyp:app_list_demo', '../ui/views/views.gyp:views_unittests', ], }], + ['use_ash==1', { + 'dependencies': [ + '../ash/ash.gyp:ash_shell', + '../ash/ash.gyp:ash_shell_unittests', + '../ash/ash.gyp:ash_unittests', + ], + }], ['use_aura==1', { 'dependencies': [ + '../ui/aura/aura.gyp:aura_bench', + '../ui/aura/aura.gyp:aura_demo', + '../ui/aura/aura.gyp:aura_unittests', '../ui/wm/wm.gyp:wm_unittests', ], }], @@ -124,11 +228,12 @@ ['OS=="android"', { 'dependencies': [ '../base/base.gyp:chromium_android_linker', + '../breakpad/breakpad.gyp:dump_syms', '../build/android/rezip.gyp:rezip_apk_jar', '../chrome/chrome.gyp:chrome_shell_apk', '../chrome/chrome.gyp:chromedriver_webview_shell_apk', #"//clank" TODO(GYP) - conditional somehow? - '../tools/imagediff/imagediff.gyp:imagediff#host', + '../tools/imagediff/image_diff.gyp:image_diff#host', '../tools/telemetry/telemetry.gyp:bitmaptools#host', # TODO(GYP): Remove these when the components_unittests work. @@ -163,6 +268,8 @@ 'dependencies!': [ '../breakpad/breakpad.gyp:symupload', '../chrome/chrome.gyp:browser_tests', + '../chrome/chrome.gyp:chromedriver', + '../chrome/chrome.gyp:chromedriver_unitests', '../chrome/chrome.gyp:interactive_ui_tests', '../chrome/chrome.gyp:sync_integration_tests', '../chrome/chrome.gyp:unit_tests', @@ -176,64 +283,87 @@ '../third_party/pdfium/samples/samples.gyp:pdfium_test', '../tools/gn/gn.gyp:gn', '../tools/gn/gn.gyp:gn_unittests', + '../tools/imagediff/image_diff.gyp:image_diff', + '../tools/gn/gn.gyp:gn', + '../tools/gn/gn.gyp:gn_unittests', '../ui/app_list/app_list.gyp:app_list_unittests', '../url/url.gyp:url_unittests', ], }], ['OS=="linux"', { 'dependencies': [ + '../breakpad/breakpad.gyp:breakpad_unittests', + '../breakpad/breakpad.gyp:dump_syms', + '../breakpad/breakpad.gyp:generate_test_dump', + '../breakpad/breakpad.gyp:minidump-2-core', + '../dbus/dbus.gyp:dbus_test_server', + '../dbus/dbus.gyp:dbus_unittests', + '../media/cast/cast.gyp:tap_proxy', + '../net/net.gyp:disk_cache_memory_test', + '../net/net.gyp:flip_in_mem_edsm_server', + '../net/net.gyp:flip_in_mem_edsm_server_unittests', + '../net/net.gyp:hpack_example_generator', + '../net/net.gyp:hpack_fuzz_mutator', + '../net/net.gyp:hpack_fuzz_wrapper', + '../net/net.gyp:net_perftests', + '../net/net.gyp:quic_client', + '../net/net.gyp:quic_server', '../sandbox/sandbox.gyp:chrome_sandbox', '../sandbox/sandbox.gyp:sandbox_linux_unittests', + '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests', ], }], ['OS=="mac"', { 'dependencies': [ + '../breakpad/breakpad.gyp:crash_inspector', + '../breakpad/breakpad.gyp:dump_syms', + '../breakpad/breakpad.gyp:symupload', '../third_party/apple_sample_code/apple_sample_code.gyp:apple_sample_code', '../third_party/molokocacao/molokocacao.gyp:molokocacao', # TODO(GYP): remove these when the corresponding root targets work. - "//cc/blink", - "//components/ui/zoom:ui_zoom", - "//content", - "//content/test:test_support", - "//device/battery", - "//device/bluetooth", - "//device/nfc", - "//device/usb", - "//device/vibration", - "//media/blink", - "//pdf", - "//storage/browser", - "//third_party/brotli", - "//third_party/flac", - "//third_party/hunspell", - "//third_party/iccjpeg", - "//third_party/libphonenumber", - "//third_party/ots", - "//third_party/qcms", - "//third_party/smhasher:murmurhash3", - "//third_party/speex", - "//third_party/webrtc/system_wrappers", - "//ui/native_theme", - "//ui/snapshot", - "//ui/surface", + #"//cc/blink", + #"//components/ui/zoom:ui_zoom", + #"//content", + #"//content/test:test_support", + #"//device/battery", + #"//device/bluetooth", + #"//device/nfc", + #"//device/usb", + #"//device/vibration", + #"//media/blink", + #"//pdf", + #"//storage/browser", + #"//third_party/brotli", + #"//third_party/flac", + #"//third_party/hunspell", + #//third_party/iccjpeg", + #"//third_party/libphonenumber", + #"//third_party/ots", + #"//third_party/qcms", + #"//third_party/smhasher:murmurhash3", + #"//third_party/speex", + #"//third_party/webrtc/system_wrappers", + #"//ui/native_theme", + #"//ui/snapshot", + #"//ui/surface", ], 'dependencies!': [ - "//chrome", # TODO(GYP) - "//chrome/test:browser_tests", # TODO(GYP) - "//chrome/test:interactive_ui_tests", # TODO(GYP) - "//chrome/test:sync_integration_tests", # TODO(GYP) - "//chrome/test:unit_tests", # TODO(GYP) - "//components:components_unittests", # TODO(GYP) - "//content/test:content_browsertests", # TODO(GYP) - "//content/test:content_perftests", # TODO(GYP) - "//content/test:content_unittests", # TODO(GYP) - "//extensions:extensions_browsertests", # TODO(GYP) - "//extensions:extensions_unittests", # TODO(GYP) - "//net:net_unittests", # TODO(GYP) - "//third_party/usrsctp", # TODO(GYP) - "//ui/app_list:app_list_unittests", # TODO(GYP) - "//ui/gfx:gfx_unittests", # TODO(GYP) + #"//chrome", # TODO(GYP) + #"//chrome/test:browser_tests", # TODO(GYP) + #"//chrome/test:interactive_ui_tests", # TODO(GYP) + #"//chrome/test:sync_integration_tests", # TODO(GYP) + #"//chrome/test:unit_tests", # TODO(GYP) + #"//components:components_unittests", # TODO(GYP) + #"//content/test:content_browsertests", # TODO(GYP) + #"//content/test:content_perftests", # TODO(GYP) + #"//content/test:content_unittests", # TODO(GYP) + #"//extensions:extensions_browsertests", # TODO(GYP) + #"//extensions:extensions_unittests", # TODO(GYP) + #"//net:net_unittests", # TODO(GYP) + #"//third_party/usrsctp", # TODO(GYP) + #"//ui/app_list:app_list_unittests", # TODO(GYP) + #"//ui/gfx:gfx_unittests", # TODO(GYP) ], }], ['OS=="win"', { @@ -245,93 +375,11 @@ "//crypto:crypto_unittests", # TODO(GYP) "//net:net_unittests", # TODO(GYP) ], - }], - ], - }, - { - # This target contains a list of things that actually currently - # build in GN, but aren't listed in //:gn_all - 'target_name': 'add_to_gn_all', - 'type': 'none', - 'dependencies': [ - '../breakpad/breakpad.gyp:microdump_stackwalk', - '../breakpad/breakpad.gyp:minidump_dump', - '../breakpad/breakpad.gyp:minidump_stackwalk', - '../cc/cc_tests.gyp:cc_perftests', - '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests', - '../chrome/chrome.gyp:sync_performance_tests', - '../chrome/tools/profile_reset/jtl_compiler.gyp:jtl_compiler', - '../courgette/courgette.gyp:courgette_minimal_tool', - '../courgette/courgette.gyp:courgette_unittests', - '../extensions/shell/app_shell.gyp:app_shell', - '../gin/gin.gyp:gin_unittests', - '../google_apis/google_apis.gyp:google_apis_unittests', - '../gpu/gpu.gyp:angle_unittests', - '../gpu/gpu.gyp:gpu_perftests', - '../ipc/ipc.gyp:ipc_perftests', - '../media/media.gyp:ffmpeg_regression_tests', # TODO(GYP) this should be conditional on media_use_ffmpeg - '../media/media.gyp:media_perftests', - '../net/net.gyp:crash_cache', - '../net/net.gyp:crl_set_dump', - '../net/net.gyp:dns_fuzz_stub', - '../net/net.gyp:dump_cache', - '../net/net.gyp:gdig', - '../net/net.gyp:get_server_time', - '../net/net.gyp:net_watcher', # TODO(GYP): This should be conditional on use_v8_in_net - '../net/net.gyp:run_testserver', - '../net/net.gyp:stress_cache', - '../net/net.gyp:tld_cleanup', - '../ppapi/ppapi_internal.gyp:ppapi_tests', # TODO(GYP): Split out the examples and tests - '../third_party/codesighs/codesighs.gyp:maptsvdifftool', - '../third_party/mojo/mojo_edk_tests.gyp:mojo_public_system_perftests', - '../ui/compositor/compositor.gyp:compositor_unittests', - '../ui/keyboard/keyboard.gyp:keyboard_unittests', - '../ui/snapshot/snapshot.gyp:snapshot_unittests', - ], - 'conditions': [ - ['use_aura==1', { - 'dependencies': [ - '../ui/aura/aura.gyp:aura_bench', - ], - }], - ['use_ash==1', { - 'dependencies': [ - '../ash/ash.gyp:ash_shell', - '../ash/ash.gyp:ash_shell_unittests', - '../ash/ash.gyp:ash_unittests', - ], - }], - ['OS=="android"', { - 'dependencies': [ - '../breakpad/breakpad.gyp:dump_syms', - ], - }], - ['OS=="linux"', { - 'dependencies': [ - '../breakpad/breakpad.gyp:breakpad_unittests', - '../breakpad/breakpad.gyp:dump_syms', - '../breakpad/breakpad.gyp:generate_test_dump', - '../breakpad/breakpad.gyp:minidump-2-core', - '../net/net.gyp:disk_cache_memory_test', - '../net/net.gyp:flip_in_mem_edsm_server', - '../net/net.gyp:flip_in_mem_edsm_server_unittests', - '../net/net.gyp:quic_client', - '../net/net.gyp:quic_server', - '../dbus/dbus.gyp:dbus_unittests', - ], - }], - ['OS!="win"', { + }, { 'dependencies': [ '../third_party/codesighs/codesighs.gyp:nm2tsv', ], }], - ['OS=="mac"', { - 'dependencies': [ - '../breakpad/breakpad.gyp:crash_inspector', - '../breakpad/breakpad.gyp:dump_syms', - '../breakpad/breakpad.gyp:symupload', - ], - }], ['OS=="android" or OS=="linux"', { 'dependencies': [ '../net/net.gyp:disk_cache_memory_test', @@ -342,30 +390,12 @@ { 'target_name': 'gyp_remaining', 'type': 'none', - 'dependencies': [ - ':add_to_gn_all', - ], 'conditions': [ ['OS=="linux"', { 'dependencies': [ - '../base/base.gyp:base_i18n_perftests', - '../base/base.gyp:base_perftests', - '../base/base.gyp:build_utf8_validator_tables#host', - '../base/base.gyp:check_example', - '../base/base.gyp:protect_file_posix', - '../breakpad/breakpad.gyp:core-2-minidump', - '../build/sanitizers/sanitizers.gyp:llvm-symbolizer', - '../chrome/chrome.gyp:chrome_app_unittests', - '../chrome/chrome.gyp:chromedriver', - '../chrome/chrome.gyp:chromedriver_tests', - '../chrome/chrome.gyp:chromedriver_unittests', - '../chrome/chrome.gyp:load_library_perf_tests', '../chrome/chrome.gyp:performance_browser_tests', - '../chrome/chrome.gyp:service_discovery_sniffer', '../cloud_print/cloud_print.gyp:cloud_print_unittests', - '../components/components.gyp:network_hints_browser', '../components/components.gyp:policy_templates', - '../components/components.gyp:session_manager_component', '../components/components_tests.gyp:components_browsertests', '../components/components_tests.gyp:components_perftests', '../content/content.gyp:content_app_browser', @@ -380,7 +410,6 @@ '../gin/gin.gyp:gin_shell', '../google_apis/gcm/gcm.gyp:mcs_probe', '../gpu/gpu.gyp:gl_tests', - '../gpu/tools/tools.gyp:compositor_model_bench', '../gpu/gles2_conform_support/gles2_conform_support.gyp:gles2_conform_support', '../gpu/gles2_conform_support/gles2_conform_test.gyp:gles2_conform_test', '../gpu/khronos_glcts_support/khronos_glcts_test.gyp:khronos_glcts_test', @@ -388,7 +417,6 @@ '../media/cast/cast.gyp:generate_barcode_video', '../media/cast/cast.gyp:generate_timecode_audio', '../media/cast/cast.gyp:tap_proxy', - '../media/media.gyp:player_x11', '../mojo/mojo_base.gyp:mojo_application_chromium', '../net/net.gyp:hpack_example_generator', '../net/net.gyp:hpack_fuzz_mutator', @@ -396,15 +424,6 @@ '../net/net.gyp:net_perftests', '../ppapi/ppapi_internal.gyp:ppapi_unittests', '../ppapi/tools/ppapi_tools.gyp:pepper_hash_for_uma', - '../remoting/app_remoting_webapp.gyp:ar_sample_app', - '../remoting/remoting.gyp:remoting_host', - '../remoting/remoting.gyp:remoting_it2me_native_messaging_host', - '../remoting/remoting.gyp:remoting_me2me_host', - '../remoting/remoting.gyp:remoting_me2me_native_messaging_host', - '../remoting/remoting.gyp:remoting_native_messaging_manifests', - '../remoting/remoting.gyp:remoting_perftests', - '../remoting/remoting.gyp:remoting_start_host', - '../remoting/remoting.gyp:remoting_unittests', '../sandbox/sandbox.gyp:sandbox_linux_jni_unittests', '../skia/skia.gyp:filter_fuzz_stub', '../skia/skia.gyp:image_operations_bench', @@ -421,7 +440,6 @@ '../tools/gn/gn.gyp:generate_test_gn_data', '../tools/perf/clear_system_cache/clear_system_cache.gyp:clear_system_cache', #'../tools/telemetry/telemetry.gyp:bitmaptools', TODO(GYP) should this be #host ? - '../ui/app_list/app_list.gyp:app_list_demo', '../ui/compositor/compositor.gyp:compositor_unittests', '../ui/message_center/message_center.gyp:message_center_unittests', '../ui/views/examples/examples.gyp:views_examples_with_content_exe', @@ -435,13 +453,42 @@ ['disable_nacl==0 and disable_nacl_untrusted==0', { 'dependencies': [ '../components/nacl.gyp:nacl_loader_unittests', - '../mojo/mojo_nacl.gyp:monacl_shell', + '../mojo/mojo_nacl.gyp:monacl_shell', # TODO(GYP) This will be deleted; don't port '../remoting/remoting.gyp:remoting_key_tester', ] }], + ['chromeos== 1 or use_ash==1', { + 'dependencies': [ + '../components/components.gyp:session_manager_component', + ], + }], + ['use_x11==1', { + 'dependencies': [ + '../gpu/tools/tools.gyp:compositor_model_bench', + '../media/media.gyp:player_x11', + ], + }], + ['remoting==1', { + 'dependencies': [ + '../remoting/app_remoting_webapp.gyp:ar_sample_app', + '../remoting/remoting.gyp:remoting_host', + '../remoting/remoting.gyp:remoting_it2me_native_messaging_host', + '../remoting/remoting.gyp:remoting_key_tester', + '../remoting/remoting.gyp:remoting_me2me_host', + '../remoting/remoting.gyp:remoting_me2me_native_messaging_host', + '../remoting/remoting.gyp:remoting_native_messaging_manifests', + '../remoting/remoting.gyp:remoting_perftests', + '../remoting/remoting.gyp:remoting_start_host', + '../remoting/remoting.gyp:remoting_unittests', + ], + }], + ['toolkit_views==1', { + 'dependencies': [ + '../ui/app_list/app_list.gyp:app_list_demo', + ], + }], ['test_isolation_mode!="noop"', { 'dependencies': [ - '../ash/ash.gyp:ash_unittests_run', '../base/base.gyp:base_unittests_run', '../cc/cc_tests.gyp:cc_unittests_run', '../chrome/chrome.gyp:browser_tests_run', @@ -468,15 +515,16 @@ '../ui/message_center/message_center.gyp:message_center_unittests_run', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests_run', ], + 'conditions': [ + ['use_ash==1', { + 'dependencies': [ + '../ash/ash.gyp:ash_unittests_run', + ], + }], + ], }], ], }], - ['use_aura==1', { - 'dependencies': [ - '../ui/aura/aura.gyp:aura_demo', - '../ui/aura/aura.gyp:aura_unittests', - ], - }], ], }, { @@ -497,6 +545,6 @@ 'chromium_gpu_debug_builder', ], }, - ] + ] }
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index 484f806..0d19361 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt
@@ -46,6 +46,7 @@ IDR_NET_INTERNALS_INDEX_JS IDR_OMAHA_HTML IDR_OMAHA_JS +IDR_OMNIBOX_CALCULATOR IDR_OMNIBOX_CLEAR_IOS IDR_OMNIBOX_CLEAR_OTR_IOS IDR_OMNIBOX_CLEAR_OTR_PRESSED_IOS @@ -323,10 +324,10 @@ IDS_EDIT_FIND_MAC IDS_EMPTY_KEYWORD_VALUE IDS_ERRORPAGES_BUTTON_LESS -IDS_ERRORPAGES_BUTTON_LOAD_STALE -IDS_ERRORPAGES_BUTTON_LOAD_STALE_HELP IDS_ERRORPAGES_BUTTON_MORE IDS_ERRORPAGES_BUTTON_RELOAD +IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY +IDS_ERRORPAGES_BUTTON_SHOW_SAVED_COPY_HELP IDS_ERRORPAGES_DETAILS_ADDRESS_UNREACHABLE IDS_ERRORPAGES_DETAILS_BAD_GATEWAY IDS_ERRORPAGES_DETAILS_BAD_SSL_CLIENT_AUTH_CERT
diff --git a/build/isolate.gypi b/build/isolate.gypi index fbb6d3c..5fa1e67 100644 --- a/build/isolate.gypi +++ b/build/isolate.gypi
@@ -95,6 +95,7 @@ '--config-variable', 'use_instrumented_libraries=<(use_instrumented_libraries)', '--config-variable', 'use_openssl=<(use_openssl)', '--config-variable', 'use_ozone=<(use_ozone)', + '--config-variable', 'use_x11=<(use_x11)', '--config-variable', 'v8_use_external_startup_data=<(v8_use_external_startup_data)', ], 'conditions': [
diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni index d42babd..05b673b 100644 --- a/build/module_args/v8.gni +++ b/build/module_args/v8.gni
@@ -6,6 +6,9 @@ import("//build/config/android/config.gni") } +# TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456. +enable_correct_v8_arch = false + # Many V8 users in mojo do not support external startup data for V8, so # we disable it. If enabled, special care should be taken to ensure the # appropriate startup data is correctly bundled for apps.
diff --git a/build/sanitizers/BUILD.gn b/build/sanitizers/BUILD.gn new file mode 100644 index 0000000..4f81f3e --- /dev/null +++ b/build/sanitizers/BUILD.gn
@@ -0,0 +1,24 @@ +# Copyright (c) 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +if (is_linux && !is_chromeos) { + # TODO(GYP): Figure out which of these work and are needed on other platforms. + copy("copy_llvm_symbolizer") { + if (is_win) { + sources = [ + "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer.exe", + ] + outputs = [ + "$root_out_dir/llvm-symbolizer.exe", + ] + } else { + sources = [ + "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer", + ] + outputs = [ + "$root_out_dir/llvm-symbolizer", + ] + } + } +}
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index 4659a3f..43db731 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -137,9 +137,6 @@ // http://crbug.com/272095 "race:base::g_top_manager\n" -// http://crbug.com/272987 -"race:webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>::set_enabled\n" - // http://crbug.com/273047 "race:base::*::g_lazy_tls_ptr\n" "race:IPC::SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_\n"
diff --git a/build/secondary/third_party/cacheinvalidation/BUILD.gn b/build/secondary/third_party/cacheinvalidation/BUILD.gn index 2e02633..17e4d1c 100644 --- a/build/secondary/third_party/cacheinvalidation/BUILD.gn +++ b/build/secondary/third_party/cacheinvalidation/BUILD.gn
@@ -81,8 +81,11 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] public_configs = [ ":cacheinvalidation_config" ] - deps = [ + public_deps = [ "src/google/cacheinvalidation:cacheinvalidation_proto_cpp", + ] + + deps = [ "//base", ] }
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index e217b12..4ee07db 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -246,6 +246,8 @@ "output/delegating_renderer.h", "output/direct_renderer.cc", "output/direct_renderer.h", + "output/dynamic_geometry_binding.cc", + "output/dynamic_geometry_binding.h", "output/filter_operation.cc", "output/filter_operation.h", "output/filter_operations.cc", @@ -286,6 +288,8 @@ "output/software_output_device.h", "output/software_renderer.cc", "output/software_renderer.h", + "output/static_geometry_binding.cc", + "output/static_geometry_binding.h", "output/viewport_selection_bound.cc", "output/viewport_selection_bound.h", "output/vsync_parameter_observer.h", @@ -386,6 +390,8 @@ "resources/picture_pile_impl.h", "resources/pixel_buffer_tile_task_worker_pool.cc", "resources/pixel_buffer_tile_task_worker_pool.h", + "resources/pixel_ref_map.cc", + "resources/pixel_ref_map.h", "resources/platform_color.h", "resources/prioritized_resource.cc", "resources/prioritized_resource.h", @@ -493,8 +499,6 @@ "trees/damage_tracker.h", "trees/draw_property_utils.cc", "trees/draw_property_utils.h", - "trees/layer_sorter.cc", - "trees/layer_sorter.h", "trees/layer_tree_host.cc", "trees/layer_tree_host.h", "trees/layer_tree_host_client.h", @@ -502,6 +506,7 @@ "trees/layer_tree_host_common.h", "trees/layer_tree_host_impl.cc", "trees/layer_tree_host_impl.h", + "trees/layer_tree_host_single_thread_client.h", "trees/layer_tree_impl.cc", "trees/layer_tree_impl.h", "trees/layer_tree_settings.cc", @@ -791,6 +796,7 @@ "resources/picture_pile_impl_unittest.cc", "resources/picture_pile_unittest.cc", "resources/picture_unittest.cc", + "resources/pixel_ref_map_unittest.cc", "resources/platform_color_unittest.cc", "resources/prioritized_resource_unittest.cc", "resources/resource_provider_unittest.cc", @@ -812,7 +818,6 @@ "test/test_web_graphics_context_3d_unittest.cc", "trees/blocking_task_runner_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", @@ -906,3 +911,5 @@ "//ui/gl", ] } +# When adding support for isolates, please have a look at run-time dependencies +# in the cc_unittests_run target in cc_tests.gyp.
diff --git a/cc/animation/animation_registrar.cc b/cc/animation/animation_registrar.cc index 5327926..3fb8055 100644 --- a/cc/animation/animation_registrar.cc +++ b/cc/animation/animation_registrar.cc
@@ -4,6 +4,7 @@ #include "cc/animation/animation_registrar.h" +#include "base/trace_event/trace_event_argument.h" #include "cc/animation/layer_animation_controller.h" namespace cc { @@ -55,4 +56,75 @@ DidDeactivateAnimationController(controller); } +bool AnimationRegistrar::ActivateAnimations() { + if (!needs_animate_layers()) + return false; + + TRACE_EVENT0("cc", "AnimationRegistrar::ActivateAnimations"); + AnimationControllerMap active_controllers_copy = + active_animation_controllers_; + for (auto& it : active_controllers_copy) + it.second->ActivateAnimations(); + + return true; +} + +bool AnimationRegistrar::AnimateLayers(base::TimeTicks monotonic_time) { + if (!needs_animate_layers()) + return false; + + TRACE_EVENT0("cc", "AnimationRegistrar::AnimateLayers"); + AnimationControllerMap controllers_copy = active_animation_controllers_; + for (auto& it : controllers_copy) + it.second->Animate(monotonic_time); + + return true; +} + +bool AnimationRegistrar::UpdateAnimationState(bool start_ready_animations, + AnimationEventsVector* events) { + if (!needs_animate_layers()) + return false; + + TRACE_EVENT0("cc", "AnimationRegistrar::UpdateAnimationState"); + AnimationControllerMap active_controllers_copy = + active_animation_controllers_; + for (auto& it : active_controllers_copy) + it.second->UpdateState(start_ready_animations, events); + + return true; +} + +void AnimationRegistrar::SetAnimationEvents( + scoped_ptr<AnimationEventsVector> events) { + for (size_t event_index = 0; event_index < events->size(); ++event_index) { + int event_layer_id = (*events)[event_index].layer_id; + + // Use the map of all controllers, not just active ones, since non-active + // controllers may still receive events for impl-only animations. + const AnimationRegistrar::AnimationControllerMap& animation_controllers = + all_animation_controllers_; + auto iter = animation_controllers.find(event_layer_id); + if (iter != animation_controllers.end()) { + switch ((*events)[event_index].type) { + case AnimationEvent::STARTED: + (*iter).second->NotifyAnimationStarted((*events)[event_index]); + break; + + case AnimationEvent::FINISHED: + (*iter).second->NotifyAnimationFinished((*events)[event_index]); + break; + + case AnimationEvent::ABORTED: + (*iter).second->NotifyAnimationAborted((*events)[event_index]); + break; + + case AnimationEvent::PROPERTY_UPDATE: + (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]); + break; + } + } + } +} + } // namespace cc
diff --git a/cc/animation/animation_registrar.h b/cc/animation/animation_registrar.h index 36c45c7..5302390 100644 --- a/cc/animation/animation_registrar.h +++ b/cc/animation/animation_registrar.h
@@ -8,6 +8,7 @@ #include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "cc/animation/animation_events.h" #include "cc/base/cc_export.h" namespace cc { @@ -43,11 +44,12 @@ // Unregisters the given controller as alive. void UnregisterAnimationController(LayerAnimationController* controller); - const AnimationControllerMap& active_animation_controllers() const { + const AnimationControllerMap& active_animation_controllers_for_testing() + const { return active_animation_controllers_; } - const AnimationControllerMap& all_animation_controllers() const { + const AnimationControllerMap& all_animation_controllers_for_testing() const { return all_animation_controllers_; } @@ -57,6 +59,21 @@ bool supports_scroll_animations() { return supports_scroll_animations_; } + bool needs_animate_layers() const { + return !active_animation_controllers_.empty(); + } + + bool ActivateAnimations(); + bool AnimateLayers(base::TimeTicks monotonic_time); + bool UpdateAnimationState(bool start_ready_animations, + AnimationEventsVector* events); + + scoped_ptr<AnimationEventsVector> CreateEvents() { + return make_scoped_ptr(new AnimationEventsVector()); + } + + void SetAnimationEvents(scoped_ptr<AnimationEventsVector> events); + private: AnimationRegistrar();
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc index c253dae..25e38cc 100644 --- a/cc/animation/layer_animation_controller.cc +++ b/cc/animation/layer_animation_controller.cc
@@ -955,7 +955,7 @@ bool notify_pending_observers) { if (value_observers_.might_have_observers()) { ObserverListBase<LayerAnimationValueObserver>::Iterator it( - value_observers_); + &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { if ((notify_active_observers && notify_pending_observers) || @@ -972,7 +972,7 @@ bool notify_pending_observers) { if (value_observers_.might_have_observers()) { ObserverListBase<LayerAnimationValueObserver>::Iterator it( - value_observers_); + &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { if ((notify_active_observers && notify_pending_observers) || @@ -989,7 +989,7 @@ bool notify_pending_observers) { if (value_observers_.might_have_observers()) { ObserverListBase<LayerAnimationValueObserver>::Iterator it( - value_observers_); + &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { if ((notify_active_observers && notify_pending_observers) || @@ -1006,7 +1006,7 @@ bool notify_pending_observers) { if (value_observers_.might_have_observers()) { ObserverListBase<LayerAnimationValueObserver>::Iterator it( - value_observers_); + &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) { if ((notify_active_observers && notify_pending_observers) || @@ -1026,7 +1026,7 @@ bool LayerAnimationController::HasValueObserver() { if (value_observers_.might_have_observers()) { ObserverListBase<LayerAnimationValueObserver>::Iterator it( - value_observers_); + &value_observers_); return it.GetNext() != nullptr; } return false; @@ -1035,7 +1035,7 @@ bool LayerAnimationController::HasActiveValueObserver() { if (value_observers_.might_have_observers()) { ObserverListBase<LayerAnimationValueObserver>::Iterator it( - value_observers_); + &value_observers_); LayerAnimationValueObserver* obs; while ((obs = it.GetNext()) != nullptr) if (obs->IsActive())
diff --git a/cc/animation/layer_animation_controller_unittest.cc b/cc/animation/layer_animation_controller_unittest.cc index d8d0b05..48e9e92 100644 --- a/cc/animation/layer_animation_controller_unittest.cc +++ b/cc/animation/layer_animation_controller_unittest.cc
@@ -171,40 +171,43 @@ 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()); + EXPECT_EQ(1u, registrar->all_animation_controllers_for_testing().size()); + EXPECT_EQ(1u, registrar_impl->all_animation_controllers_for_testing().size()); // Initially, both controllers should be inactive. - EXPECT_EQ(0u, registrar->active_animation_controllers().size()); - EXPECT_EQ(0u, registrar_impl->active_animation_controllers().size()); + EXPECT_EQ(0u, registrar->active_animation_controllers_for_testing().size()); + EXPECT_EQ(0u, + registrar_impl->active_animation_controllers_for_testing().size()); AddOpacityTransitionToController(controller.get(), 1, 0, 1, false); // The main thread controller should now be active. - EXPECT_EQ(1u, registrar->active_animation_controllers().size()); + EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size()); controller->PushAnimationUpdatesTo(controller_impl.get()); controller_impl->ActivateAnimations(); // Both controllers should now be active. - EXPECT_EQ(1u, registrar->active_animation_controllers().size()); - EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size()); + EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size()); + EXPECT_EQ(1u, + registrar_impl->active_animation_controllers_for_testing().size()); controller_impl->Animate(kInitialTickTime); controller_impl->UpdateState(true, events.get()); EXPECT_EQ(1u, events->size()); controller->NotifyAnimationStarted((*events)[0]); - EXPECT_EQ(1u, registrar->active_animation_controllers().size()); - EXPECT_EQ(1u, registrar_impl->active_animation_controllers().size()); + EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size()); + EXPECT_EQ(1u, + registrar_impl->active_animation_controllers_for_testing().size()); controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(500)); controller->UpdateState(true, nullptr); - EXPECT_EQ(1u, registrar->active_animation_controllers().size()); + EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size()); controller->Animate(kInitialTickTime + TimeDelta::FromMilliseconds(1000)); controller->UpdateState(true, nullptr); EXPECT_EQ(Animation::FINISHED, controller->GetAnimation(Animation::OPACITY)->run_state()); - EXPECT_EQ(1u, registrar->active_animation_controllers().size()); + EXPECT_EQ(1u, registrar->active_animation_controllers_for_testing().size()); events.reset(new AnimationEventsVector); controller_impl->Animate(kInitialTickTime + @@ -214,7 +217,8 @@ EXPECT_EQ(Animation::WAITING_FOR_DELETION, 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(0u, + registrar_impl->active_animation_controllers_for_testing().size()); EXPECT_EQ(1u, events->size()); controller->NotifyAnimationFinished((*events)[0]); @@ -224,14 +228,15 @@ EXPECT_EQ(Animation::WAITING_FOR_DELETION, controller->GetAnimation(Animation::OPACITY)->run_state()); // The main thread controller should have de-activated. - EXPECT_EQ(0u, registrar->active_animation_controllers().size()); + EXPECT_EQ(0u, registrar->active_animation_controllers_for_testing().size()); controller->PushAnimationUpdatesTo(controller_impl.get()); controller_impl->ActivateAnimations(); 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()); + EXPECT_EQ(0u, registrar->active_animation_controllers_for_testing().size()); + EXPECT_EQ(0u, + registrar_impl->active_animation_controllers_for_testing().size()); controller->SetAnimationRegistrar(nullptr); controller_impl->SetAnimationRegistrar(nullptr);
diff --git a/cc/cc.gyp b/cc/cc.gyp index 0c4ee74..bc83b1f 100644 --- a/cc/cc.gyp +++ b/cc/cc.gyp
@@ -279,6 +279,8 @@ 'output/delegating_renderer.h', 'output/direct_renderer.cc', 'output/direct_renderer.h', + 'output/dynamic_geometry_binding.cc', + 'output/dynamic_geometry_binding.h', 'output/filter_operation.cc', 'output/filter_operation.h', 'output/filter_operations.cc', @@ -319,6 +321,8 @@ 'output/software_output_device.h', 'output/software_renderer.cc', 'output/software_renderer.h', + 'output/static_geometry_binding.cc', + 'output/static_geometry_binding.h', 'output/viewport_selection_bound.cc', 'output/viewport_selection_bound.h', 'output/vsync_parameter_observer.h', @@ -419,6 +423,8 @@ 'resources/picture_pile_impl.h', 'resources/pixel_buffer_tile_task_worker_pool.cc', 'resources/pixel_buffer_tile_task_worker_pool.h', + 'resources/pixel_ref_map.cc', + 'resources/pixel_ref_map.h', 'resources/platform_color.h', 'resources/prioritized_resource.cc', 'resources/prioritized_resource.h', @@ -529,8 +535,6 @@ 'trees/damage_tracker.h', 'trees/draw_property_utils.cc', 'trees/draw_property_utils.h', - 'trees/layer_sorter.cc', - 'trees/layer_sorter.h', 'trees/layer_tree_host.cc', 'trees/layer_tree_host.h', 'trees/layer_tree_host_client.h', @@ -538,6 +542,7 @@ 'trees/layer_tree_host_common.h', 'trees/layer_tree_host_impl.cc', 'trees/layer_tree_host_impl.h', + 'trees/layer_tree_host_single_thread_client.h', 'trees/layer_tree_impl.cc', 'trees/layer_tree_impl.h', 'trees/layer_tree_settings.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 4d29a60..bafd747 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp
@@ -83,6 +83,7 @@ 'resources/picture_pile_impl_unittest.cc', 'resources/picture_pile_unittest.cc', 'resources/picture_unittest.cc', + 'resources/pixel_ref_map_unittest.cc', 'resources/platform_color_unittest.cc', 'resources/prioritized_resource_unittest.cc', 'resources/resource_provider_unittest.cc', @@ -105,7 +106,6 @@ 'test/test_web_graphics_context_3d_unittest.cc', 'trees/blocking_task_runner_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', @@ -460,6 +460,17 @@ 'sources': [ 'cc_unittests.isolate', ], + 'conditions': [ + # crbug.com/464062 xdisplaycheck is used to run cc_unittests_run on + # the linux try bots when using X11. + ['OS=="linux" and use_ozone==0', + { + 'dependencies': [ + '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck', + ], + } + ], + ], }, ], }],
diff --git a/cc/cc_unittests.isolate b/cc/cc_unittests.isolate index eab3396..7c359d0 100644 --- a/cc/cc_unittests.isolate +++ b/cc/cc_unittests.isolate
@@ -3,16 +3,20 @@ # found in the LICENSE file. { 'conditions': [ - ['OS=="linux" or OS=="mac" or OS=="win"', { + ['use_x11==0', { 'variables': { - 'files': [ - 'test/data/', + 'command': [ '../testing/test_env.py', '<(PRODUCT_DIR)/cc_unittests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--msan=<(msan)', + '--tsan=<(tsan)', ], }, }], - ['OS=="linux"', { + ['use_x11==1', { 'variables': { 'command': [ '../testing/xvfb.py', @@ -26,29 +30,29 @@ ], 'files': [ '../testing/xvfb.py', + '<(PRODUCT_DIR)/xdisplaycheck', + ], + }, + }], + ['OS=="linux" or OS=="mac" or OS=="win"', { + 'variables': { + 'files': [ + 'test/data/', + '../testing/test_env.py', + '<(PRODUCT_DIR)/cc_unittests<(EXECUTABLE_SUFFIX)', + ], + }, + }], + ['OS=="linux"', { + 'variables': { + 'files': [ '<(PRODUCT_DIR)/libffmpegsumo.so', '<(PRODUCT_DIR)/libosmesa.so', ], }, }], - ['OS=="linux" and use_ozone==0', { - 'variables': { - 'files': [ - '<(PRODUCT_DIR)/xdisplaycheck', - ], - }, - }], ['OS=="mac"', { 'variables': { - 'command': [ - '../testing/test_env.py', - '<(PRODUCT_DIR)/cc_unittests', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--msan=<(msan)', - '--tsan=<(tsan)', - ], 'files': [ '<(PRODUCT_DIR)/ffmpegsumo.so', '<(PRODUCT_DIR)/osmesa.so', @@ -57,15 +61,6 @@ }], ['OS=="win"', { 'variables': { - 'command': [ - '../testing/test_env.py', - '<(PRODUCT_DIR)/cc_unittests.exe', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--msan=<(msan)', - '--tsan=<(tsan)', - ], 'files': [ '<(PRODUCT_DIR)/ffmpegsumo.dll', '<(PRODUCT_DIR)/osmesa.dll', @@ -89,5 +84,6 @@ ], 'includes': [ '../base/base.isolate', + '../third_party/angle/angle.isolate', ], }
diff --git a/cc/input/top_controls_manager.cc b/cc/input/top_controls_manager.cc index c8bd534..56c9d8f 100644 --- a/cc/input/top_controls_manager.cc +++ b/cc/input/top_controls_manager.cc
@@ -107,6 +107,9 @@ if (pinch_gesture_active_) return pending_delta; + if (!TopControlsHeight()) + return pending_delta; + if (permitted_state_ == SHOWN && pending_delta.y() > 0) return pending_delta; else if (permitted_state_ == HIDDEN && pending_delta.y() < 0)
diff --git a/cc/input/top_controls_manager_unittest.cc b/cc/input/top_controls_manager_unittest.cc index 4befa15..4145cac 100644 --- a/cc/input/top_controls_manager_unittest.cc +++ b/cc/input/top_controls_manager_unittest.cc
@@ -5,7 +5,9 @@ #include "cc/input/top_controls_manager.h" #include <algorithm> +#include <cmath> +#include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "cc/input/top_controls_manager_client.h" @@ -51,6 +53,9 @@ float TopControlsHeight() const override { return top_controls_height_; } void SetCurrentTopControlsShownRatio(float ratio) override { + ASSERT_FALSE(std::isnan(ratio)); + ASSERT_FALSE(ratio == std::numeric_limits<float>::infinity()); + ASSERT_FALSE(ratio == -std::numeric_limits<float>::infinity()); ratio = std::max(ratio, 0.f); ratio = std::min(ratio, 1.f); top_controls_shown_ratio_ = ratio; @@ -446,50 +451,20 @@ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); } -TEST(TopControlsManagerTest, ZeroTopControlsHeightScrolling) { +TEST(TopControlsManagerTest, ScrollByWithZeroHeightControlsIsNoop) { MockTopControlsManagerClient client(0.f, 0.5f, 0.5f); - client.SetCurrentTopControlsShownRatio(0.f); TopControlsManager* manager = client.manager(); manager->UpdateTopControlsState(BOTH, BOTH, false); manager->ScrollBegin(); - EXPECT_FLOAT_EQ(-10.f, manager->ScrollBy(gfx::Vector2dF(0.f, -10.f)).y()); - EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio()); - - client.SetTopControlsHeight(20.f); - EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio()); - - EXPECT_FLOAT_EQ(0.f, manager->ScrollBy(gfx::Vector2dF(0.f, -15.f)).y()); - EXPECT_FLOAT_EQ(0.75f, manager->TopControlsShownRatio()); - client.SetTopControlsHeight(0.f); + gfx::Vector2dF pending = manager->ScrollBy(gfx::Vector2dF(0.f, 20.f)); + EXPECT_FLOAT_EQ(20.f, pending.y()); + EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset()); + EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset()); + EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio()); manager->ScrollEnd(); - - EXPECT_FALSE(manager->animation()); - EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio()); } -TEST(TopControlsManagerTest, ZeroTopControlsHeightAnimating) { - MockTopControlsManagerClient client(0.f, 0.5f, 0.5f); - client.SetCurrentTopControlsShownRatio(0.f); - TopControlsManager* manager = client.manager(); - - manager->UpdateTopControlsState(BOTH, HIDDEN, false); - EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio()); - manager->UpdateTopControlsState(BOTH, SHOWN, false); - EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio()); - - manager->UpdateTopControlsState(BOTH, HIDDEN, true); - EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio()); - EXPECT_FALSE(manager->animation()); - manager->UpdateTopControlsState(BOTH, SHOWN, true); - EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio()); - EXPECT_FALSE(manager->animation()); - - client.SetCurrentTopControlsShownRatio(0.3f); - manager->MainThreadHasStoppedFlinging(); - EXPECT_FALSE(manager->animation()); - EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio()); -} } // namespace } // namespace cc
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc index 04e1b85..87e559a 100644 --- a/cc/layers/delegated_renderer_layer_impl_unittest.cc +++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -9,10 +9,10 @@ #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/solid_color_draw_quad.h" #include "cc/test/fake_delegated_renderer_layer_impl.h" +#include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/fake_layer_tree_host_impl_client.h" #include "cc/test/fake_output_surface.h" -#include "cc/test/fake_proxy.h" #include "cc/test/geometry_test_utils.h" #include "cc/test/layer_test_common.h" #include "cc/test/render_pass_test_common.h" @@ -44,7 +44,7 @@ } protected: - FakeProxy proxy_; + FakeImplProxy proxy_; DebugScopedSetImplThreadAndMainThreadBlocked always_impl_thread_and_main_thread_blocked_; TestSharedBitmapManager shared_bitmap_manager_;
diff --git a/cc/layers/draw_properties.h b/cc/layers/draw_properties.h index ff5abd9..930f7bf 100644 --- a/cc/layers/draw_properties.h +++ b/cc/layers/draw_properties.h
@@ -32,6 +32,7 @@ num_unclipped_descendants(0), layer_or_descendant_has_copy_request(false), layer_or_descendant_has_input_handler(false), + layer_or_descendant_is_drawn(false), has_child_with_a_scroll_parent(false), sorted_for_recursion(false), visited(false), @@ -114,6 +115,9 @@ // If true, the layer or one of its descendants has a wheel or touch handler. bool layer_or_descendant_has_input_handler; + // If true, the layer or one of its descendants is drawn + bool layer_or_descendant_is_drawn; + // 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
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 2ed00a6..e1a9daf 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -20,15 +20,13 @@ #include "cc/trees/layer_tree_host_impl.h" #include "cc/trees/layer_tree_impl.h" #include "skia/ext/platform_canvas.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" -#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/hud_font.h" namespace cc { @@ -70,12 +68,15 @@ HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl, int id) : LayerImpl(tree_impl, id), - typeface_(skia::AdoptRef( - SkTypeface::CreateFromName("monospace", SkTypeface::kBold))), + typeface_(gfx::GetHudTypeface()), internal_contents_scale_(1.f), fps_graph_(60.0, 80.0), paint_time_graph_(16.0, 48.0), fade_step_(0) { + if (!typeface_) { + typeface_ = skia::AdoptRef( + SkTypeface::CreateFromName("monospace", SkTypeface::kBold)); + } } HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {}
diff --git a/cc/layers/io_surface_layer_impl.cc b/cc/layers/io_surface_layer_impl.cc index 6bd03fd..4f52674 100644 --- a/cc/layers/io_surface_layer_impl.cc +++ b/cc/layers/io_surface_layer_impl.cc
@@ -5,15 +5,10 @@ #include "cc/layers/io_surface_layer_impl.h" #include "base/strings/stringprintf.h" -#include "cc/output/gl_renderer.h" // For the GLC() macro. #include "cc/output/output_surface.h" #include "cc/quads/io_surface_draw_quad.h" #include "cc/trees/layer_tree_impl.h" #include "cc/trees/occlusion.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "gpu/command_buffer/client/gles2_interface.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" namespace cc {
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index 1cfe1f1..80d36d8 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc
@@ -79,20 +79,23 @@ void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { Layer::SetLayerTreeHost(host); - if (host) { - if (!recording_source_) { - if (host->settings().use_display_lists) { - recording_source_.reset(new DisplayListRecordingSource); - } else { - recording_source_.reset( - new PicturePile(host->settings().minimum_contents_scale, - host->settings().default_tile_grid_size)); - } + if (!host) + return; + + if (!recording_source_) { + if (host->settings().use_display_lists) { + recording_source_.reset(new DisplayListRecordingSource); + } else { + recording_source_.reset( + new PicturePile(host->settings().minimum_contents_scale, + host->settings().default_tile_grid_size)); } - recording_source_->DidMoveToNewCompositor(); - recording_source_->SetSlowdownRasterScaleFactor( - host->debug_state().slow_down_raster_scale_factor); } + recording_source_->DidMoveToNewCompositor(); + recording_source_->SetSlowdownRasterScaleFactor( + host->debug_state().slow_down_raster_scale_factor); + + DCHECK(host->settings().raster_enabled); } void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
diff --git a/cc/layers/tiled_layer.cc b/cc/layers/tiled_layer.cc index 2a32741..55143be 100644 --- a/cc/layers/tiled_layer.cc +++ b/cc/layers/tiled_layer.cc
@@ -18,7 +18,6 @@ #include "cc/resources/priority_calculator.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/occlusion_tracker.h" -#include "third_party/khronos/GLES2/gl2.h" #include "ui/gfx/geometry/rect_conversions.h" namespace cc {
diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc index b78a1d8..04aad2d 100644 --- a/cc/layers/tiled_layer_impl.cc +++ b/cc/layers/tiled_layer_impl.cc
@@ -17,7 +17,6 @@ #include "cc/quads/tile_draw_quad.h" #include "cc/resources/layer_tiling_data.h" #include "cc/trees/occlusion.h" -#include "third_party/khronos/GLES2/gl2.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/quad_f.h"
diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc index 03d9b19..99cc0ca 100644 --- a/cc/layers/tiled_layer_unittest.cc +++ b/cc/layers/tiled_layer_unittest.cc
@@ -87,6 +87,7 @@ settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max(); settings_.layer_transforms_should_scale_layer_contents = true; settings_.verify_property_trees = true; + settings_.impl_side_painting = false; } void SetUp() override {
diff --git a/cc/output/bsp_tree.cc b/cc/output/bsp_tree.cc index f2318ce..4eb87cb 100644 --- a/cc/output/bsp_tree.cc +++ b/cc/output/bsp_tree.cc
@@ -62,10 +62,9 @@ scoped_ptr<DrawPolygon> polygon; scoped_ptr<DrawPolygon> new_front; scoped_ptr<DrawPolygon> new_back; - bool split_result = false; // Time to split this geometry, *it needs to be split by node_data. polygon = polygon_list->take_front(); - split_result = + bool split_result = polygon->Split(*(node->node_data), &new_front, &new_back); DCHECK(split_result); if (!split_result) {
diff --git a/cc/output/bsp_walk_action.cc b/cc/output/bsp_walk_action.cc index da5ada5..9ffc299 100644 --- a/cc/output/bsp_walk_action.cc +++ b/cc/output/bsp_walk_action.cc
@@ -9,15 +9,37 @@ #include "base/memory/scoped_ptr.h" #include "cc/output/direct_renderer.h" #include "cc/quads/draw_polygon.h" +#include "cc/quads/draw_quad.h" namespace cc { -void BspWalkActionToVector::operator()(DrawPolygon* item) { - list_->push_back(item); +BspWalkActionDrawPolygon::BspWalkActionDrawPolygon( + DirectRenderer* renderer, + DirectRenderer::DrawingFrame* frame, + const gfx::Rect& render_pass_scissor, + bool using_scissor_as_optimization) + : renderer_(renderer), + frame_(frame), + render_pass_scissor_(render_pass_scissor), + using_scissor_as_optimization_(using_scissor_as_optimization) { +} + +void BspWalkActionDrawPolygon::operator()(DrawPolygon* item) { + gfx::Transform inverse_transform; + bool invertible = + item->original_ref()->quadTransform().GetInverse(&inverse_transform); + DCHECK(invertible); + item->TransformToLayerSpace(inverse_transform); + renderer_->DoDrawPolygon(*item, frame_, render_pass_scissor_, + using_scissor_as_optimization_); } BspWalkActionToVector::BspWalkActionToVector(std::vector<DrawPolygon*>* in_list) : list_(in_list) { } +void BspWalkActionToVector::operator()(DrawPolygon* item) { + list_->push_back(item); +} + } // namespace cc
diff --git a/cc/output/bsp_walk_action.h b/cc/output/bsp_walk_action.h index ac8fa41..a89d8ea 100644 --- a/cc/output/bsp_walk_action.h +++ b/cc/output/bsp_walk_action.h
@@ -20,6 +20,22 @@ // The BspTree class takes ownership of all the DrawPolygons returned in list_ // so the BspTree must be preserved while elements in that vector are in use. +class CC_EXPORT BspWalkActionDrawPolygon : public BspWalkAction { + public: + void operator()(DrawPolygon* item) override; + + BspWalkActionDrawPolygon(DirectRenderer* renderer, + DirectRenderer::DrawingFrame* frame, + const gfx::Rect& render_pass_scissor, + bool using_scissor_as_optimization); + + private: + DirectRenderer* renderer_; + DirectRenderer::DrawingFrame* frame_; + const gfx::Rect& render_pass_scissor_; + bool using_scissor_as_optimization_; +}; + class CC_EXPORT BspWalkActionToVector : public BspWalkAction { public: explicit BspWalkActionToVector(std::vector<DrawPolygon*>* in_list);
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc index 5867fce..0ae4179 100644 --- a/cc/output/direct_renderer.cc +++ b/cc/output/direct_renderer.cc
@@ -12,6 +12,8 @@ #include "base/metrics/histogram.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" +#include "cc/output/bsp_tree.h" +#include "cc/output/bsp_walk_action.h" #include "cc/output/copy_output_request.h" #include "cc/quads/draw_quad.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -299,22 +301,27 @@ EnsureScissorTestDisabled(); } +bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad, + const gfx::Rect& render_pass_scissor) { + if (render_pass_scissor.IsEmpty()) + return true; + + if (quad.isClipped()) { + gfx::Rect r = quad.clipRect(); + r.Intersect(render_pass_scissor); + return r.IsEmpty(); + } + + return false; +} + void DirectRenderer::SetScissorStateForQuadWithRenderPassScissor( const DrawingFrame* frame, const DrawQuad& quad, - const gfx::Rect& render_pass_scissor, - bool* should_skip_quad) { + const gfx::Rect& render_pass_scissor) { gfx::Rect quad_scissor_rect = render_pass_scissor; - if (quad.isClipped()) quad_scissor_rect.Intersect(quad.clipRect()); - - if (quad_scissor_rect.IsEmpty()) { - *should_skip_quad = true; - return; - } - - *should_skip_quad = false; SetScissorTestRectInDrawSpace(frame, quad_scissor_rect); } @@ -330,6 +337,46 @@ void DirectRenderer::FinishDrawingQuadList() {} +void DirectRenderer::DoDrawPolygon(const DrawPolygon& poly, + DrawingFrame* frame, + const gfx::Rect& render_pass_scissor, + bool using_scissor_as_optimization) { + if (using_scissor_as_optimization) { + SetScissorStateForQuadWithRenderPassScissor(frame, *poly.original_ref(), + render_pass_scissor); + } else { + SetScissorStateForQuad(frame, *poly.original_ref()); + } + + // If the poly has not been split, then it is just a normal DrawQuad, + // and we should save any extra processing that would have to be done. + if (!poly.is_split()) { + DoDrawQuad(frame, poly.original_ref(), NULL); + return; + } + + std::vector<gfx::QuadF> quads; + poly.ToQuads2D(&quads); + for (size_t i = 0; i < quads.size(); ++i) { + DoDrawQuad(frame, poly.original_ref(), &quads[i]); + } +} + +void DirectRenderer::FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list, + DrawingFrame* frame, + const gfx::Rect& render_pass_scissor, + bool using_scissor_as_optimization) { + if (poly_list->empty()) { + return; + } + + BspTree bsp_tree(poly_list); + BspWalkActionDrawPolygon action_handler(this, frame, render_pass_scissor, + using_scissor_as_optimization); + bsp_tree.TraverseWithActionHandler(&action_handler); + DCHECK(poly_list->empty()); +} + void DirectRenderer::DrawRenderPass(DrawingFrame* frame, const RenderPass* render_pass) { TRACE_EVENT0("cc", "DirectRenderer::DrawRenderPass"); @@ -369,21 +416,49 @@ } const QuadList& quad_list = render_pass->quad_list; + ScopedPtrDeque<DrawPolygon> poly_list; + + int next_polygon_id = 0; + int last_sorting_context_id = 0; for (auto it = quad_list.BackToFrontBegin(); it != quad_list.BackToFrontEnd(); ++it) { const DrawQuad& quad = **it; - bool should_skip_quad = false; + gfx::QuadF send_quad(quad.visible_rect); + if (using_scissor_as_optimization && + ShouldSkipQuad(quad, render_pass_scissor)) { + continue; + } + + if (last_sorting_context_id != quad.shared_quad_state->sorting_context_id) { + last_sorting_context_id = quad.shared_quad_state->sorting_context_id; + FlushPolygons(&poly_list, frame, render_pass_scissor, + using_scissor_as_optimization); + } + + // This layer is in a 3D sorting context so we add it to the list of + // polygons to go into the BSP tree. + if (quad.shared_quad_state->sorting_context_id != 0) { + scoped_ptr<DrawPolygon> new_polygon(new DrawPolygon( + *it, quad.visible_rect, quad.quadTransform(), next_polygon_id++)); + if (new_polygon->points().size() > 2u) { + poly_list.push_back(new_polygon.Pass()); + } + continue; + } + + // We are not in a 3d sorting context, so we should draw the quad normally. if (using_scissor_as_optimization) { - SetScissorStateForQuadWithRenderPassScissor( - frame, quad, render_pass_scissor, &should_skip_quad); + SetScissorStateForQuadWithRenderPassScissor(frame, quad, + render_pass_scissor); } else { SetScissorStateForQuad(frame, quad); } - if (!should_skip_quad) - DoDrawQuad(frame, &quad); + DoDrawQuad(frame, &quad, nullptr); } + FlushPolygons(&poly_list, frame, render_pass_scissor, + using_scissor_as_optimization); FinishDrawingQuadList(); }
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h index e07cb93..3399491 100644 --- a/cc/output/direct_renderer.h +++ b/cc/output/direct_renderer.h
@@ -9,13 +9,17 @@ #include "base/callback.h" #include "base/containers/scoped_ptr_hash_map.h" #include "cc/base/cc_export.h" +#include "cc/base/scoped_ptr_deque.h" #include "cc/output/overlay_processor.h" #include "cc/output/renderer.h" #include "cc/resources/resource_provider.h" #include "cc/resources/scoped_resource.h" +#include "cc/resources/task_graph_runner.h" +#include "ui/gfx/geometry/quad_f.h" namespace cc { +class DrawPolygon; class ResourceProvider; // This is the base class for code shared between the GL and software @@ -56,6 +60,10 @@ }; void SetEnlargePassTextureAmountForTesting(const gfx::Vector2d& amount); + void DoDrawPolygon(const DrawPolygon& poly, + DrawingFrame* frame, + const gfx::Rect& render_pass_scissor, + bool using_scissor_as_optimization); protected: DirectRenderer(RendererClient* client, @@ -78,16 +86,21 @@ gfx::Rect DeviceClipRectInWindowSpace(const DrawingFrame* frame) const; static gfx::Rect ComputeScissorRectForRenderPass(const DrawingFrame* frame); void SetScissorStateForQuad(const DrawingFrame* frame, const DrawQuad& quad); + bool ShouldSkipQuad(const DrawQuad& quad, + const gfx::Rect& render_pass_scissor); void SetScissorStateForQuadWithRenderPassScissor( const DrawingFrame* frame, const DrawQuad& quad, - const gfx::Rect& render_pass_scissor, - bool* should_skip_quad); + const gfx::Rect& render_pass_scissor); void SetScissorTestRectInDrawSpace(const DrawingFrame* frame, const gfx::Rect& draw_space_rect); static gfx::Size RenderPassTextureSize(const RenderPass* render_pass); + void FlushPolygons(ScopedPtrDeque<DrawPolygon>* poly_list, + DrawingFrame* frame, + const gfx::Rect& render_pass_scissor, + bool using_scissor_as_optimization); void DrawRenderPass(DrawingFrame* frame, const RenderPass* render_pass); bool UseRenderPass(DrawingFrame* frame, const RenderPass* render_pass); @@ -101,7 +114,12 @@ bool draw_rect_covers_full_surface) = 0; virtual void ClearFramebuffer(DrawingFrame* frame, bool has_external_stencil_test) = 0; - virtual void DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) = 0; + // clip_region is a (possibly null) pointer to a quad in the same + // space as the quad. When non-null only the area of the quad that overlaps + // with clip_region will be drawn. + virtual void DoDrawQuad(DrawingFrame* frame, + const DrawQuad* quad, + const gfx::QuadF* clip_region) = 0; virtual void BeginDrawingFrame(DrawingFrame* frame) = 0; virtual void FinishDrawingFrame(DrawingFrame* frame) = 0; virtual void FinishDrawingQuadList();
diff --git a/cc/output/dynamic_geometry_binding.cc b/cc/output/dynamic_geometry_binding.cc new file mode 100644 index 0000000..9e25892 --- /dev/null +++ b/cc/output/dynamic_geometry_binding.cc
@@ -0,0 +1,67 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/output/dynamic_geometry_binding.h" + +#include "cc/output/gl_renderer.h" // For the GLC() macro. +#include "gpu/command_buffer/client/gles2_interface.h" +#include "ui/gfx/geometry/rect_f.h" + +namespace cc { + +DynamicGeometryBinding::DynamicGeometryBinding(gpu::gles2::GLES2Interface* gl) + : gl_(gl), quad_vertices_vbo_(0), quad_elements_vbo_(0) { + GeometryBindingQuad quads[1]; + GeometryBindingQuadIndex quad_indices[1]; + + static_assert(sizeof(GeometryBindingQuad) == 24 * sizeof(float), + "struct Quad should be densely packed"); + static_assert(sizeof(GeometryBindingQuadIndex) == 6 * sizeof(uint16_t), + "struct QuadIndex should be densely packed"); + + GLC(gl_, gl_->GenBuffers(1, &quad_vertices_vbo_)); + GLC(gl_, gl_->GenBuffers(1, &quad_elements_vbo_)); + + GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_)); + GLC(gl_, gl_->BufferData(GL_ARRAY_BUFFER, sizeof(GeometryBindingQuad) * 1, + quads, GL_DYNAMIC_DRAW)); + + GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_)); + GLC(gl_, gl_->BufferData(GL_ELEMENT_ARRAY_BUFFER, + sizeof(GeometryBindingQuadIndex) * 1, &quad_indices, + GL_DYNAMIC_DRAW)); +} + +void DynamicGeometryBinding::InitializeCustomQuad(const gfx::QuadF& quad) { + float uv[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; + InitializeCustomQuadWithUVs(quad, uv); +} + +void DynamicGeometryBinding::InitializeCustomQuadWithUVs(const gfx::QuadF& quad, + const float uv[8]) { + GeometryBindingVertex v0 = { + {quad.p1().x(), quad.p1().y(), 0.0f}, {uv[0], uv[1]}, 0.0f}; + GeometryBindingVertex v1 = { + {quad.p2().x(), quad.p2().y(), 0.0f}, {uv[2], uv[3]}, 1.0f}; + GeometryBindingVertex v2 = { + {quad.p3().x(), quad.p3().y(), 0.0f}, {uv[4], uv[5]}, 2.0f}; + GeometryBindingVertex v3 = { + {quad.p4().x(), quad.p4().y(), 0.0f}, {uv[6], uv[7]}, 3.0f}; + + GeometryBindingQuad local_quad = {v0, v1, v2, v3}; + GeometryBindingQuadIndex quad_index( + static_cast<uint16>(0), static_cast<uint16>(1), static_cast<uint16>(2), + static_cast<uint16>(3), static_cast<uint16>(0), static_cast<uint16>(2)); + + GLC(gl_, gl_->BufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GeometryBindingQuad), + &local_quad)); + GLC(gl_, gl_->BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, + sizeof(GeometryBindingQuadIndex), &quad_index)); +} + +void DynamicGeometryBinding::PrepareForDraw() { + SetupGLContext(gl_, quad_elements_vbo_, quad_vertices_vbo_); +} + +} // namespace cc
diff --git a/cc/output/dynamic_geometry_binding.h b/cc/output/dynamic_geometry_binding.h new file mode 100644 index 0000000..4e4ea3d --- /dev/null +++ b/cc/output/dynamic_geometry_binding.h
@@ -0,0 +1,30 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_OUTPUT_DYNAMIC_GEOMETRY_BINDING_H_ +#define CC_OUTPUT_DYNAMIC_GEOMETRY_BINDING_H_ + +#include "cc/output/geometry_binding.h" + +namespace cc { + +class DynamicGeometryBinding { + public: + explicit DynamicGeometryBinding(gpu::gles2::GLES2Interface* gl); + void PrepareForDraw(); + void InitializeCustomQuad(const gfx::QuadF& quad); + void InitializeCustomQuadWithUVs(const gfx::QuadF& quad, const float uv[8]); + + private: + gpu::gles2::GLES2Interface* gl_; + + GLuint quad_vertices_vbo_; + GLuint quad_elements_vbo_; + + DISALLOW_COPY_AND_ASSIGN(DynamicGeometryBinding); +}; + +} // namespace cc + +#endif // CC_OUTPUT_DYNAMIC_GEOMETRY_BINDING_H_
diff --git a/cc/output/geometry_binding.cc b/cc/output/geometry_binding.cc index eda2a5c..88a37de 100644 --- a/cc/output/geometry_binding.cc +++ b/cc/output/geometry_binding.cc
@@ -10,70 +10,12 @@ namespace cc { -GeometryBinding::GeometryBinding(gpu::gles2::GLES2Interface* gl, - const gfx::RectF& quad_vertex_rect) - : gl_(gl), quad_vertices_vbo_(0), quad_elements_vbo_(0) { - struct Vertex { - float a_position[3]; - float a_texCoord[2]; - // Index of the vertex, divide by 4 to have the matrix for this quad. - float a_index; - }; - struct Quad { - Vertex v0, v1, v2, v3; - }; - struct QuadIndex { - uint16 data[6]; - }; +void SetupGLContext(gpu::gles2::GLES2Interface* gl, + GLuint quad_elements_vbo, + GLuint quad_vertices_vbo) { + GLC(gl, gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo)); - static_assert(sizeof(Quad) == 24 * sizeof(float), - "struct Quad should be densely packed"); - static_assert(sizeof(QuadIndex) == 6 * sizeof(uint16_t), - "struct QuadIndex should be densely packed"); - - 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}; - 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)}}; - quad_index_list[i] = y; - } - - 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(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() { - gl_->DeleteBuffers(1, &quad_vertices_vbo_); - gl_->DeleteBuffers(1, &quad_elements_vbo_); -} - -void GeometryBinding::PrepareForDraw() { - GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_)); - - GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_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. @@ -83,15 +25,56 @@ reinterpret_cast<const void*>(5 * sizeof(float)), }; - GLC(gl_, gl_->VertexAttribPointer(PositionAttribLocation(), 3, GL_FLOAT, - false, 6 * sizeof(float), offsets[0])); - GLC(gl_, gl_->VertexAttribPointer(TexCoordAttribLocation(), 2, GL_FLOAT, - false, 6 * sizeof(float), offsets[1])); - GLC(gl_, gl_->VertexAttribPointer(TriangleIndexAttribLocation(), 1, GL_FLOAT, - false, 6 * sizeof(float), offsets[2])); - GLC(gl_, gl_->EnableVertexAttribArray(PositionAttribLocation())); - GLC(gl_, gl_->EnableVertexAttribArray(TexCoordAttribLocation())); - GLC(gl_, gl_->EnableVertexAttribArray(TriangleIndexAttribLocation())); + GLC(gl, + gl->VertexAttribPointer(GeometryBinding::PositionAttribLocation(), 3, + GL_FLOAT, false, 6 * sizeof(float), offsets[0])); + GLC(gl, + gl->VertexAttribPointer(GeometryBinding::TexCoordAttribLocation(), 2, + GL_FLOAT, false, 6 * sizeof(float), offsets[1])); + GLC(gl, + gl->VertexAttribPointer(GeometryBinding::TriangleIndexAttribLocation(), 1, + GL_FLOAT, false, 6 * sizeof(float), offsets[2])); + GLC(gl, + gl->EnableVertexAttribArray(GeometryBinding::PositionAttribLocation())); + GLC(gl, + gl->EnableVertexAttribArray(GeometryBinding::TexCoordAttribLocation())); + GLC(gl, gl->EnableVertexAttribArray( + GeometryBinding::TriangleIndexAttribLocation())); +} + +GeometryBindingQuad::GeometryBindingQuad() { + v0 = {{0, 0, 0}, {0, 0}, 0}; + v1 = {{0, 0, 0}, {0, 0}, 0}; + v2 = {{0, 0, 0}, {0, 0}, 0}; + v3 = {{0, 0, 0}, {0, 0}, 0}; +} + +GeometryBindingQuad::GeometryBindingQuad(const GeometryBindingVertex& vert0, + const GeometryBindingVertex& vert1, + const GeometryBindingVertex& vert2, + const GeometryBindingVertex& vert3) { + v0 = vert0; + v1 = vert1; + v2 = vert2; + v3 = vert3; +} + +GeometryBindingQuadIndex::GeometryBindingQuadIndex() { + memset(data, 0x0, sizeof(data)); +} + +GeometryBindingQuadIndex::GeometryBindingQuadIndex(uint16 index0, + uint16 index1, + uint16 index2, + uint16 index3, + uint16 index4, + uint16 index5) { + data[0] = index0; + data[1] = index1; + data[2] = index2; + data[3] = index3; + data[4] = index4; + data[5] = index5; } } // namespace cc
diff --git a/cc/output/geometry_binding.h b/cc/output/geometry_binding.h index cfa21ef..ae68687 100644 --- a/cc/output/geometry_binding.h +++ b/cc/output/geometry_binding.h
@@ -6,43 +6,65 @@ #define CC_OUTPUT_GEOMETRY_BINDING_H_ #include "base/basictypes.h" +#include "cc/output/gl_renderer.h" // For the GLC() macro. +#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/geometry/rect_f.h" namespace gfx { -class RectF; -} -namespace gpu { -namespace gles2 { -class GLES2Interface; -} +class QuadF; +class Quad; +class QuadIndex; +class PointF; } namespace cc { -class GeometryBinding { - public: - GeometryBinding(gpu::gles2::GLES2Interface* gl, - const gfx::RectF& quad_vertex_rect); - ~GeometryBinding(); +struct GeometryBindingVertex { + float a_position[3]; + float a_texCoord[2]; + // Index of the vertex, divide by 4 to have the matrix for this quad. + float a_index; +}; - void PrepareForDraw(); +struct GeometryBindingQuad { + GeometryBindingQuad(); + GeometryBindingQuad(const GeometryBindingVertex& vert0, + const GeometryBindingVertex& vert1, + const GeometryBindingVertex& vert2, + const GeometryBindingVertex& vert3); + GeometryBindingVertex v0, v1, v2, v3; +}; +struct GeometryBindingQuadIndex { + GeometryBindingQuadIndex(); + GeometryBindingQuadIndex(uint16 index0, + uint16 index1, + uint16 index2, + uint16 index3, + uint16 index4, + uint16 index5); + + uint16 data[6]; +}; + +class DrawQuad; +class DrawPolygon; + +struct GeometryBinding { // All layer shaders share the same attribute locations for the vertex // positions and texture coordinates. This allows switching shaders without // rebinding attribute arrays. static int PositionAttribLocation() { return 0; } static int TexCoordAttribLocation() { return 1; } static int TriangleIndexAttribLocation() { return 2; } - - private: - gpu::gles2::GLES2Interface* gl_; - - GLuint quad_vertices_vbo_; - GLuint quad_elements_vbo_; - - DISALLOW_COPY_AND_ASSIGN(GeometryBinding); }; +void SetupGLContext(gpu::gles2::GLES2Interface* gl, + GLuint quad_elements_vbo, + GLuint quad_vertices_vbo); + } // namespace cc #endif // CC_OUTPUT_GEOMETRY_BINDING_H_
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 578faa9..3813e1d 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc
@@ -11,16 +11,23 @@ #include <vector> #include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "build/build_config.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" #include "cc/output/compositor_frame.h" #include "cc/output/compositor_frame_metadata.h" #include "cc/output/context_provider.h" #include "cc/output/copy_output_request.h" -#include "cc/output/geometry_binding.h" +#include "cc/output/dynamic_geometry_binding.h" #include "cc/output/gl_frame_data.h" #include "cc/output/output_surface.h" #include "cc/output/render_surface_filters.h" +#include "cc/output/static_geometry_binding.h" +#include "cc/quads/draw_polygon.h" #include "cc/quads/picture_draw_quad.h" #include "cc/quads/render_pass.h" #include "cc/quads/stream_video_draw_quad.h" @@ -323,7 +330,8 @@ highp_threshold_min_(highp_threshold_min), highp_threshold_cache_(0), use_sync_query_(false), - on_demand_tile_raster_resource_id_(0) { + on_demand_tile_raster_resource_id_(0), + bound_geometry_(NO_BINDING) { DCHECK(gl_); DCHECK(context_support_); @@ -493,10 +501,12 @@ GLC(gl_, gl_->Flush()); } -void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { +void GLRenderer::DoDrawQuad(DrawingFrame* frame, + const DrawQuad* quad, + const gfx::QuadF* clip_region) { DCHECK(quad->rect.Contains(quad->visible_rect)); if (quad->material != DrawQuad::TEXTURE_CONTENT) { - FlushTextureQuadCache(); + FlushTextureQuadCache(SHARED_BINDING); } switch (quad->material) { @@ -504,26 +514,31 @@ NOTREACHED(); break; case DrawQuad::CHECKERBOARD: - DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad)); + DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad), + clip_region); break; case DrawQuad::DEBUG_BORDER: DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad)); break; case DrawQuad::IO_SURFACE_CONTENT: - DrawIOSurfaceQuad(frame, IOSurfaceDrawQuad::MaterialCast(quad)); + DrawIOSurfaceQuad(frame, IOSurfaceDrawQuad::MaterialCast(quad), + clip_region); break; case DrawQuad::PICTURE_CONTENT: // PictureDrawQuad should only be used for resourceless software draws. NOTREACHED(); break; case DrawQuad::RENDER_PASS: - DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad)); + DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad), + clip_region); break; case DrawQuad::SOLID_COLOR: - DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad)); + DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad), + clip_region); break; case DrawQuad::STREAM_VIDEO_CONTENT: - DrawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad)); + DrawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad), + clip_region); break; case DrawQuad::SURFACE_CONTENT: // Surface content should be fully resolved to other quad types before @@ -531,19 +546,28 @@ NOTREACHED(); break; case DrawQuad::TEXTURE_CONTENT: - EnqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad)); + EnqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad), + clip_region); break; case DrawQuad::TILED_CONTENT: - DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad)); + DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad), clip_region); break; case DrawQuad::YUV_VIDEO_CONTENT: - DrawYUVVideoQuad(frame, YUVVideoDrawQuad::MaterialCast(quad)); + DrawYUVVideoQuad(frame, YUVVideoDrawQuad::MaterialCast(quad), + clip_region); break; } } void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame, - const CheckerboardDrawQuad* quad) { + const CheckerboardDrawQuad* quad, + const gfx::QuadF* clip_region) { + // TODO(enne) For now since checkerboards shouldn't be part of a 3D + // context, clipping regions aren't supported so we skip drawing them + // if this becomes the case. + if (clip_region) { + return; + } SetBlendEnabled(quad->ShouldDrawWithBlending()); const TileCheckerboardProgram* program = GetTileCheckerboardProgram(); @@ -587,6 +611,9 @@ program->vertex_shader().matrix_location()); } +// This function does not handle 3D sorting right now, since the debug border +// quads are just drawn as their original quads and not in split pieces. This +// results in some debug border quads drawing over foreground quads. void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame, const DebugBorderDrawQuad* quad) { SetBlendEnabled(quad->ShouldDrawWithBlending()); @@ -818,13 +845,56 @@ return true; } +// This takes a gfx::Rect and a clip region quad in the same space, +// and returns a quad with the same proportions in the space -0.5->0.5. +bool GetScaledRegion(const gfx::Rect& rect, + const gfx::QuadF* clip, + gfx::QuadF* scaled_region) { + if (!clip) + return false; + + gfx::PointF p1(((clip->p1().x() - rect.x()) / rect.width()) - 0.5f, + ((clip->p1().y() - rect.y()) / rect.height()) - 0.5f); + gfx::PointF p2(((clip->p2().x() - rect.x()) / rect.width()) - 0.5f, + ((clip->p2().y() - rect.y()) / rect.height()) - 0.5f); + gfx::PointF p3(((clip->p3().x() - rect.x()) / rect.width()) - 0.5f, + ((clip->p3().y() - rect.y()) / rect.height()) - 0.5f); + gfx::PointF p4(((clip->p4().x() - rect.x()) / rect.width()) - 0.5f, + ((clip->p4().y() - rect.y()) / rect.height()) - 0.5f); + *scaled_region = gfx::QuadF(p1, p2, p3, p4); + return true; +} + +// This takes a gfx::Rect and a clip region quad in the same space, +// and returns the proportional uv's in the space 0->1. +bool GetScaledUVs(const gfx::Rect& rect, const gfx::QuadF* clip, float uvs[8]) { + if (!clip) + return false; + + uvs[0] = ((clip->p1().x() - rect.x()) / rect.width()); + uvs[1] = ((clip->p1().y() - rect.y()) / rect.height()); + uvs[2] = ((clip->p2().x() - rect.x()) / rect.width()); + uvs[3] = ((clip->p2().y() - rect.y()) / rect.height()); + uvs[4] = ((clip->p3().x() - rect.x()) / rect.width()); + uvs[5] = ((clip->p3().y() - rect.y()) / rect.height()); + uvs[6] = ((clip->p4().x() - rect.x()) / rect.width()); + uvs[7] = ((clip->p4().y() - rect.y()) / rect.height()); + return true; +} + gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad( DrawingFrame* frame, const RenderPassDrawQuad* quad, const gfx::Transform& contents_device_transform, + const gfx::QuadF* clip_region, bool use_aa) { + gfx::QuadF scaled_region; + if (!GetScaledRegion(quad->rect, clip_region, &scaled_region)) { + scaled_region = SharedGeometryQuad().BoundingBox(); + } + gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( - contents_device_transform, SharedGeometryQuad().BoundingBox())); + contents_device_transform, scaled_region.BoundingBox())); if (ShouldApplyBackgroundFilters(frame, quad)) { int top, right, bottom, left; @@ -873,7 +943,8 @@ } void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, - const RenderPassDrawQuad* quad) { + const RenderPassDrawQuad* quad, + const gfx::QuadF* clip_region) { ScopedResource* contents_texture = render_pass_textures_.get(quad->render_pass_id); if (!contents_texture || !contents_texture->id()) @@ -895,10 +966,8 @@ ShouldAntialiasQuad(contents_device_transform, quad, settings_->force_antialiasing); - if (use_aa) - SetupQuadForAntialiasing(contents_device_transform, quad, - &surface_quad, edge); - + SetupQuadForClippingAndAntialiasing(contents_device_transform, quad, use_aa, + clip_region, &surface_quad, edge); SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode; bool use_shaders_for_blending = !CanApplyBlendModeUsingBlendFunc(blend_mode) || @@ -912,7 +981,7 @@ // Compute a bounding box around the pixels that will be visible through // the quad. background_rect = GetBackdropBoundingBoxForRenderPassQuad( - frame, quad, contents_device_transform, use_aa); + frame, quad, contents_device_transform, clip_region, use_aa); if (!background_rect.IsEmpty()) { // The pixels from the filtered background should completely replace the @@ -1237,15 +1306,78 @@ uniforms->color_location = program->fragment_shader().color_location(); } +namespace { +// These functions determine if a quad, clipped by a clip_region contains +// the entire {top|bottom|left|right} edge. +bool is_top(const gfx::QuadF* clip_region, const DrawQuad* quad) { + if (!quad->IsTopEdge()) + return false; + if (!clip_region) + return true; + + return std::abs(clip_region->p1().y()) < kAntiAliasingEpsilon && + std::abs(clip_region->p2().y()) < kAntiAliasingEpsilon; +} + +bool is_bottom(const gfx::QuadF* clip_region, const DrawQuad* quad) { + if (!quad->IsBottomEdge()) + return false; + if (!clip_region) + return true; + + return std::abs(clip_region->p3().y() - + quad->shared_quad_state->content_bounds.height()) < + kAntiAliasingEpsilon && + std::abs(clip_region->p4().y() - + quad->shared_quad_state->content_bounds.height()) < + kAntiAliasingEpsilon; +} + +bool is_left(const gfx::QuadF* clip_region, const DrawQuad* quad) { + if (!quad->IsLeftEdge()) + return false; + if (!clip_region) + return true; + + return std::abs(clip_region->p1().x()) < kAntiAliasingEpsilon && + std::abs(clip_region->p4().x()) < kAntiAliasingEpsilon; +} + +bool is_right(const gfx::QuadF* clip_region, const DrawQuad* quad) { + if (!quad->IsRightEdge()) + return false; + if (!clip_region) + return true; + + return std::abs(clip_region->p2().x() - + quad->shared_quad_state->content_bounds.width()) < + kAntiAliasingEpsilon && + std::abs(clip_region->p3().x() - + quad->shared_quad_state->content_bounds.width()) < + kAntiAliasingEpsilon; +} +} // anonymous namespace + static gfx::QuadF GetDeviceQuadWithAntialiasingOnExteriorEdges( const LayerQuad& device_layer_edges, const gfx::Transform& device_transform, + const gfx::QuadF* clip_region, const DrawQuad* quad) { - gfx::Rect tile_rect = quad->visible_rect; - gfx::PointF bottom_right = tile_rect.bottom_right(); - gfx::PointF bottom_left = tile_rect.bottom_left(); - gfx::PointF top_left = tile_rect.origin(); - gfx::PointF top_right = tile_rect.top_right(); + gfx::RectF tile_rect = quad->visible_rect; + gfx::QuadF tile_quad(tile_rect); + + if (clip_region) { + if (quad->material != DrawQuad::RENDER_PASS) { + tile_quad = *clip_region; + } else { + GetScaledRegion(quad->rect, clip_region, &tile_quad); + } + } + + gfx::PointF bottom_right = tile_quad.p3(); + gfx::PointF bottom_left = tile_quad.p4(); + gfx::PointF top_left = tile_quad.p1(); + gfx::PointF top_right = tile_quad.p2(); bool clipped = false; // Map points to device space. We ignore |clipped|, since the result of @@ -1262,16 +1394,26 @@ LayerQuad::Edge right_edge(top_right, bottom_right); // Only apply anti-aliasing to edges not clipped by culling or scissoring. - if (quad->IsTopEdge() && tile_rect.y() == quad->rect.y()) + // If an edge is degenerate we do not want to replace it with a "proper" edge + // as that will cause the quad to possibly expand is strange ways. + if (!top_edge.degenerate() && is_top(clip_region, quad) && + tile_rect.y() == quad->rect.y()) { top_edge = device_layer_edges.top(); - if (quad->IsLeftEdge() && tile_rect.x() == quad->rect.x()) + } + if (!left_edge.degenerate() && is_left(clip_region, quad) && + tile_rect.x() == quad->rect.x()) { left_edge = device_layer_edges.left(); - if (quad->IsRightEdge() && tile_rect.right() == quad->rect.right()) + } + if (!right_edge.degenerate() && is_right(clip_region, quad) && + tile_rect.right() == quad->rect.right()) { right_edge = device_layer_edges.right(); - if (quad->IsBottomEdge() && tile_rect.bottom() == quad->rect.bottom()) + } + if (!bottom_edge.degenerate() && is_bottom(clip_region, quad) && + tile_rect.bottom() == quad->rect.bottom()) { bottom_edge = device_layer_edges.bottom(); + } - float sign = gfx::QuadF(tile_rect).IsCounterClockwise() ? -1 : 1; + float sign = tile_quad.IsCounterClockwise() ? -1 : 1; bottom_edge.scale(sign); left_edge.scale(sign); top_edge.scale(sign); @@ -1281,6 +1423,32 @@ return LayerQuad(left_edge, top_edge, right_edge, bottom_edge).ToQuadF(); } +float GetTotalQuadError(const gfx::QuadF* clipped_quad, + const gfx::QuadF* ideal_rect) { + return (clipped_quad->p1() - ideal_rect->p1()).LengthSquared() + + (clipped_quad->p2() - ideal_rect->p2()).LengthSquared() + + (clipped_quad->p3() - ideal_rect->p3()).LengthSquared() + + (clipped_quad->p4() - ideal_rect->p4()).LengthSquared(); +} + +// Attempt to rotate the clipped quad until it lines up the most +// correctly. This is necessary because we check the edges of this +// quad against the expected left/right/top/bottom for anti-aliasing. +void AlignQuadToBoundingBox(gfx::QuadF* clipped_quad) { + gfx::QuadF bounding_quad = gfx::QuadF(clipped_quad->BoundingBox()); + gfx::QuadF best_rotation = *clipped_quad; + float least_error_amount = GetTotalQuadError(clipped_quad, &bounding_quad); + for (size_t i = 1; i < 4; ++i) { + clipped_quad->Realign(1); + float new_error = GetTotalQuadError(clipped_quad, &bounding_quad); + if (new_error < least_error_amount) { + least_error_amount = new_error; + best_rotation = *clipped_quad; + } + } + *clipped_quad = best_rotation; +} + // static bool GLRenderer::ShouldAntialiasQuad(const gfx::Transform& device_transform, const DrawQuad* quad, @@ -1312,18 +1480,39 @@ } // static -void GLRenderer::SetupQuadForAntialiasing( +void GLRenderer::SetupQuadForClippingAndAntialiasing( const gfx::Transform& device_transform, const DrawQuad* quad, + bool use_aa, + const gfx::QuadF* clip_region, gfx::QuadF* local_quad, float edge[24]) { bool is_render_pass_quad = (quad->material == DrawQuad::RENDER_PASS); - gfx::RectF content_rect = - is_render_pass_quad ? QuadVertexRect() : quad->visibleContentRect(); + gfx::QuadF rotated_clip; + const gfx::QuadF* local_clip_region = clip_region; + if (local_clip_region) { + rotated_clip = *clip_region; + AlignQuadToBoundingBox(&rotated_clip); + local_clip_region = &rotated_clip; + } + gfx::QuadF content_rect = is_render_pass_quad + ? gfx::QuadF(QuadVertexRect()) + : gfx::QuadF(quad->visibleContentRect()); + if (!use_aa) { + if (local_clip_region) { + if (!is_render_pass_quad) { + content_rect = *local_clip_region; + } else { + GetScaledRegion(quad->rect, local_clip_region, &content_rect); + } + *local_quad = content_rect; + } + return; + } bool clipped = false; gfx::QuadF device_layer_quad = - MathUtil::MapQuad(device_transform, gfx::QuadF(content_rect), &clipped); + MathUtil::MapQuad(device_transform, content_rect, &clipped); LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox())); device_layer_bounds.InflateAntiAliasingDistance(); @@ -1334,16 +1523,25 @@ device_layer_edges.ToFloatArray(edge); device_layer_bounds.ToFloatArray(&edge[12]); + // If we have a clip region then we are split, and therefore + // by necessity, at least one of our edges is not an external + // one. + bool is_full_rect = quad->visible_rect == quad->rect; + + bool region_contains_all_outside_edges = + is_full_rect && + (is_top(local_clip_region, quad) && is_left(local_clip_region, quad) && + is_bottom(local_clip_region, quad) && is_right(local_clip_region, quad)); + bool use_aa_on_all_four_edges = - is_render_pass_quad || - (quad->IsTopEdge() && quad->IsLeftEdge() && quad->IsBottomEdge() && - quad->IsRightEdge() && quad->visible_rect == quad->rect); + !local_clip_region && + (is_render_pass_quad || region_contains_all_outside_edges); gfx::QuadF device_quad = use_aa_on_all_four_edges ? device_layer_edges.ToQuadF() : GetDeviceQuadWithAntialiasingOnExteriorEdges( - device_layer_edges, device_transform, quad); + device_layer_edges, device_transform, local_clip_region, quad); // 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 @@ -1359,7 +1557,8 @@ } void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame, - const SolidColorDrawQuad* quad) { + const SolidColorDrawQuad* quad, + const gfx::QuadF* clip_region) { gfx::Rect tile_rect = quad->visible_rect; SkColor color = quad->color; @@ -1383,10 +1582,11 @@ bool use_aa = settings_->allow_antialiasing && !quad->force_anti_aliasing_off && ShouldAntialiasQuad(device_transform, quad, force_aa); + SetupQuadForClippingAndAntialiasing(device_transform, quad, use_aa, + clip_region, &local_quad, edge); SolidColorProgramUniforms uniforms; if (use_aa) { - SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge); SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms); } else { SolidColorUniformLocation(GetSolidColorProgram(), &uniforms); @@ -1457,13 +1657,15 @@ } void GLRenderer::DrawTileQuad(const DrawingFrame* frame, - const TileDrawQuad* quad) { - DrawContentQuad(frame, quad, quad->resource_id); + const TileDrawQuad* quad, + const gfx::QuadF* clip_region) { + DrawContentQuad(frame, quad, quad->resource_id, clip_region); } void GLRenderer::DrawContentQuad(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id) { + ResourceProvider::ResourceId resource_id, + const gfx::QuadF* clip_region) { gfx::Transform device_transform = frame->window_matrix * frame->projection_matrix * quad->quadTransform(); device_transform.FlattenTo2d(); @@ -1475,15 +1677,16 @@ // similar to the way DrawContentQuadNoAA works and then consider // combining DrawContentQuadAA and DrawContentQuadNoAA into one method. if (use_aa) - DrawContentQuadAA(frame, quad, resource_id, device_transform); + DrawContentQuadAA(frame, quad, resource_id, device_transform, clip_region); else - DrawContentQuadNoAA(frame, quad, resource_id); + DrawContentQuadNoAA(frame, quad, resource_id, clip_region); } void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, ResourceProvider::ResourceId resource_id, - const gfx::Transform& device_transform) { + const gfx::Transform& device_transform, + const gfx::QuadF* clip_region) { if (!device_transform.IsInvertible()) return; @@ -1528,8 +1731,8 @@ gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect)); float edge[24]; - SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge); - + SetupQuadForClippingAndAntialiasing(device_transform, quad, true, clip_region, + &local_quad, edge); ResourceProvider::ScopedSamplerGL quad_resource_lock( resource_provider_, resource_id, quad->nearest_neighbor ? GL_NEAREST : GL_LINEAR); @@ -1607,7 +1810,8 @@ void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id) { + ResourceProvider::ResourceId resource_id, + const gfx::QuadF* clip_region) { gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional( quad->tex_coord_rect, quad->rect, quad->visible_rect); float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width(); @@ -1681,17 +1885,37 @@ // does, then vertices will match the texture mapping in the vertex buffer. // The method SetShaderQuadF() changes the order of vertices and so it's // not used here. - - gfx::RectF tile_rect = quad->visible_rect; + gfx::QuadF tile_rect(quad->visible_rect); + float width = quad->visible_rect.width(); + float height = quad->visible_rect.height(); + gfx::PointF top_left = quad->visible_rect.origin(); + if (clip_region) { + tile_rect = *clip_region; + float gl_uv[8] = { + (tile_rect.p4().x() - top_left.x()) / width, + (tile_rect.p4().y() - top_left.y()) / height, + (tile_rect.p1().x() - top_left.x()) / width, + (tile_rect.p1().y() - top_left.y()) / height, + (tile_rect.p2().x() - top_left.x()) / width, + (tile_rect.p2().y() - top_left.y()) / height, + (tile_rect.p3().x() - top_left.x()) / width, + (tile_rect.p3().y() - top_left.y()) / height, + }; + PrepareGeometry(CLIPPED_BINDING); + clipped_geometry_->InitializeCustomQuadWithUVs( + gfx::QuadF(quad->visible_rect), gl_uv); + } else { + PrepareGeometry(SHARED_BINDING); + } float gl_quad[8] = { - tile_rect.x(), - tile_rect.bottom(), - tile_rect.x(), - tile_rect.y(), - tile_rect.right(), - tile_rect.y(), - tile_rect.right(), - tile_rect.bottom(), + tile_rect.p4().x(), + tile_rect.p4().y(), + tile_rect.p1().x(), + tile_rect.p1().y(), + tile_rect.p2().x(), + tile_rect.p2().y(), + tile_rect.p3().x(), + tile_rect.p3().y(), }; GLC(gl_, gl_->Uniform2fv(uniforms.quad_location, 4, gl_quad)); @@ -1704,7 +1928,8 @@ } void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame, - const YUVVideoDrawQuad* quad) { + const YUVVideoDrawQuad* quad, + const gfx::QuadF* clip_region) { SetBlendEnabled(quad->ShouldDrawWithBlending()); TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( @@ -1844,15 +2069,31 @@ break; } + // The transform and vertex data are used to figure out the extents that the + // un-antialiased quad should have and which vertex this is and the float + // quad passed in via uniform is the actual geometry that gets used to draw + // it. This is why this centered rect is used and not the original quad_rect. + gfx::RectF tile_rect = quad->visible_rect; GLC(gl_, gl_->UniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb)); GLC(gl_, gl_->Uniform3fv(yuv_adj_location, 1, yuv_adjust)); SetShaderOpacity(quad->opacity(), alpha_location); - DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, matrix_location); + if (!clip_region) { + DrawQuadGeometry(frame, quad->quadTransform(), tile_rect, matrix_location); + } else { + float uvs[8] = {0}; + GetScaledUVs(quad->visible_rect, clip_region, uvs); + gfx::QuadF region_quad = *clip_region; + region_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height()); + region_quad -= gfx::Vector2dF(0.5f, 0.5f); + DrawQuadGeometryClippedByQuadF(frame, quad->quadTransform(), tile_rect, + region_quad, matrix_location, uvs); + } } void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame, - const StreamVideoDrawQuad* quad) { + const StreamVideoDrawQuad* quad, + const gfx::QuadF* clip_region) { SetBlendEnabled(quad->ShouldDrawWithBlending()); static float gl_matrix[16]; @@ -1883,10 +2124,19 @@ SetShaderOpacity(quad->opacity(), program->fragment_shader().alpha_location()); - DrawQuadGeometry(frame, - quad->quadTransform(), - quad->rect, - program->vertex_shader().matrix_location()); + if (!clip_region) { + DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, + program->vertex_shader().matrix_location()); + } else { + gfx::QuadF region_quad(*clip_region); + region_quad.Scale(1.0f / quad->rect.width(), 1.0f / quad->rect.height()); + region_quad -= gfx::Vector2dF(0.5f, 0.5f); + float uvs[8] = {0}; + GetScaledUVs(quad->visible_rect, clip_region, uvs); + DrawQuadGeometryClippedByQuadF( + frame, quad->quadTransform(), quad->rect, region_quad, + program->vertex_shader().matrix_location(), uvs); + } } struct TextureProgramBinding { @@ -1902,6 +2152,7 @@ int program_id; int sampler_location; int matrix_location; + int transform_location; int background_color_location; }; @@ -1917,11 +2168,13 @@ int vertex_opacity_location; }; -void GLRenderer::FlushTextureQuadCache() { +void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) { // Check to see if we have anything to draw. if (draw_cache_.program_id == -1) return; + PrepareGeometry(flush_binding); + // Set the correct blending mode. SetBlendEnabled(draw_cache_.needs_blending); @@ -1982,10 +2235,26 @@ draw_cache_.uv_xform_data.resize(0); draw_cache_.vertex_opacity_data.resize(0); draw_cache_.matrix_data.resize(0); + + // If we had a clipped binding, prepare the shared binding for the + // next inserts. + if (flush_binding == CLIPPED_BINDING) { + PrepareGeometry(SHARED_BINDING); + } } void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame, - const TextureDrawQuad* quad) { + const TextureDrawQuad* quad, + const gfx::QuadF* clip_region) { + // If we have a clip_region then we have to render the next quad + // with dynamic geometry, therefore we must flush all pending + // texture quads. + if (clip_region) { + // We send in false here because we want to flush what's currently in the + // queue using the shared_geometry and not clipped_geometry + FlushTextureQuadCache(SHARED_BINDING); + } + TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( gl_, &highp_threshold_cache_, @@ -2017,7 +2286,7 @@ draw_cache_.nearest_neighbor != quad->nearest_neighbor || draw_cache_.background_color != quad->background_color || draw_cache_.matrix_data.size() >= 8) { - FlushTextureQuadCache(); + FlushTextureQuadCache(SHARED_BINDING); draw_cache_.program_id = binding.program_id; draw_cache_.resource_id = resource_id; draw_cache_.needs_blending = quad->ShouldDrawWithBlending(); @@ -2032,7 +2301,12 @@ } // Generate the uv-transform - draw_cache_.uv_xform_data.push_back(UVTransform(quad)); + if (!clip_region) { + draw_cache_.uv_xform_data.push_back(UVTransform(quad)); + } else { + Float4 uv_transform = {{0.0f, 0.0f, 1.0f, 1.0f}}; + draw_cache_.uv_xform_data.push_back(uv_transform); + } // Generate the vertex opacity const float opacity = quad->opacity(); @@ -2049,10 +2323,32 @@ Float16 m; quad_rect_matrix.matrix().asColMajorf(m.data); draw_cache_.matrix_data.push_back(m); + + if (clip_region) { + gfx::QuadF scaled_region; + if (!GetScaledRegion(quad->rect, clip_region, &scaled_region)) { + scaled_region = SharedGeometryQuad().BoundingBox(); + } + // Both the scaled region and the SharedGeomtryQuad are in the space + // -0.5->0.5. We need to move that to the space 0->1. + float uv[8]; + uv[0] = scaled_region.p1().x() + 0.5f; + uv[1] = scaled_region.p1().y() + 0.5f; + uv[2] = scaled_region.p2().x() + 0.5f; + uv[3] = scaled_region.p2().y() + 0.5f; + uv[4] = scaled_region.p3().x() + 0.5f; + uv[5] = scaled_region.p3().y() + 0.5f; + uv[6] = scaled_region.p4().x() + 0.5f; + uv[7] = scaled_region.p4().y() + 0.5f; + PrepareGeometry(CLIPPED_BINDING); + clipped_geometry_->InitializeCustomQuadWithUVs(scaled_region, uv); + FlushTextureQuadCache(CLIPPED_BINDING); + } } void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame, - const IOSurfaceDrawQuad* quad) { + const IOSurfaceDrawQuad* quad, + const gfx::QuadF* clip_region) { SetBlendEnabled(quad->ShouldDrawWithBlending()); TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( @@ -2091,8 +2387,15 @@ DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_)); GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, lock.texture_id())); - DrawQuadGeometry( - frame, quad->quadTransform(), quad->rect, binding.matrix_location); + if (!clip_region) { + DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, + binding.matrix_location); + } else { + float uvs[8] = {0}; + GetScaledUVs(quad->visible_rect, clip_region, uvs); + DrawQuadGeometryClippedByQuadF(frame, quad->quadTransform(), quad->rect, + *clip_region, binding.matrix_location, uvs); + } GLC(gl_, gl_->BindTexture(GL_TEXTURE_RECTANGLE_ARB, 0)); } @@ -2113,7 +2416,9 @@ ScheduleOverlays(frame); } -void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); } +void GLRenderer::FinishDrawingQuadList() { + FlushTextureQuadCache(SHARED_BINDING); +} bool GLRenderer::FlippedFramebuffer(const DrawingFrame* frame) const { if (frame->current_render_pass != frame->root_render_pass) @@ -2130,7 +2435,7 @@ if (is_scissor_enabled_) return; - FlushTextureQuadCache(); + FlushTextureQuadCache(SHARED_BINDING); GLC(gl_, gl_->Enable(GL_SCISSOR_TEST)); is_scissor_enabled_ = true; } @@ -2139,7 +2444,7 @@ if (!is_scissor_enabled_) return; - FlushTextureQuadCache(); + FlushTextureQuadCache(SHARED_BINDING); GLC(gl_, gl_->Disable(GL_SCISSOR_TEST)); is_scissor_enabled_ = false; } @@ -2208,10 +2513,34 @@ program_shadow_ = program; } +void GLRenderer::DrawQuadGeometryClippedByQuadF( + const DrawingFrame* frame, + const gfx::Transform& draw_transform, + const gfx::RectF& quad_rect, + const gfx::QuadF& clipping_region_quad, + int matrix_location, + const float* uvs) { + PrepareGeometry(CLIPPED_BINDING); + if (uvs) { + clipped_geometry_->InitializeCustomQuadWithUVs(clipping_region_quad, uvs); + } else { + clipped_geometry_->InitializeCustomQuad(clipping_region_quad); + } + gfx::Transform quad_rect_matrix; + QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect); + static float gl_matrix[16]; + ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad_rect_matrix); + GLC(gl_, gl_->UniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0])); + + GLC(gl_, gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, + reinterpret_cast<const void*>(0))); +} + void GLRenderer::DrawQuadGeometry(const DrawingFrame* frame, const gfx::Transform& draw_transform, const gfx::RectF& quad_rect, int matrix_location) { + PrepareGeometry(SHARED_BINDING); gfx::Transform quad_rect_matrix; QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect); static float gl_matrix[16]; @@ -2274,6 +2603,7 @@ output_surface_->context_provider()->DeleteCachedResources(); GLC(gl_, gl_->Flush()); } + PrepareGeometry(NO_BINDING); } void GLRenderer::DiscardBackbuffer() { @@ -2605,7 +2935,7 @@ return; scissor_rect_ = scissor_rect; - FlushTextureQuadCache(); + FlushTextureQuadCache(SHARED_BINDING); GLC(gl_, gl_->Scissor(scissor_rect.x(), scissor_rect.y(), @@ -2630,8 +2960,27 @@ // Create an FBO for doing offscreen rendering. GLC(gl_, gl_->GenFramebuffers(1, &offscreen_framebuffer_id_)); - shared_geometry_ = make_scoped_ptr( - new GeometryBinding(gl_, QuadVertexRect())); + shared_geometry_ = + make_scoped_ptr(new StaticGeometryBinding(gl_, QuadVertexRect())); + clipped_geometry_ = make_scoped_ptr(new DynamicGeometryBinding(gl_)); +} + +void GLRenderer::PrepareGeometry(BoundGeometry binding) { + if (binding == bound_geometry_) { + return; + } + + switch (binding) { + case SHARED_BINDING: + shared_geometry_->PrepareForDraw(); + break; + case CLIPPED_BINDING: + clipped_geometry_->PrepareForDraw(); + break; + case NO_BINDING: + break; + } + bound_geometry_ = binding; } const GLRenderer::TileCheckerboardProgram* @@ -3111,8 +3460,8 @@ void GLRenderer::RestoreGLState() { // This restores the current GLRenderer state to the GL context. - - shared_geometry_->PrepareForDraw(); + bound_geometry_ = NO_BINDING; + PrepareGeometry(SHARED_BINDING); GLC(gl_, gl_->Disable(GL_DEPTH_TEST)); GLC(gl_, gl_->Disable(GL_CULL_FACE));
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h index 01668ab..27f2c42 100644 --- a/cc/output/gl_renderer.h +++ b/cc/output/gl_renderer.h
@@ -39,7 +39,8 @@ class StreamVideoDrawQuad; class TextureDrawQuad; class TextureMailboxDeleter; -class GeometryBinding; +class StaticGeometryBinding; +class DynamicGeometryBinding; class ScopedEnsureFramebufferAllocation; // Class that handles drawing of composited render layers using GL. @@ -85,7 +86,7 @@ bool IsBackbufferDiscarded() const { return is_backbuffer_discarded_; } const gfx::QuadF& SharedGeometryQuad() const { return shared_geometry_quad_; } - const GeometryBinding* SharedGeometry() const { + const StaticGeometryBinding* SharedGeometry() const { return shared_geometry_.get(); } @@ -96,7 +97,8 @@ ResourceFormat texture_format, const gfx::Rect& device_rect); void ReleaseRenderPassTextures(); - + enum BoundGeometry { NO_BINDING, SHARED_BINDING, CLIPPED_BINDING }; + void PrepareGeometry(BoundGeometry geometry_to_bind); void SetStencilEnabled(bool enabled); bool stencil_enabled() const { return stencil_shadow_; } void SetBlendEnabled(bool enabled); @@ -112,7 +114,9 @@ bool draw_rect_covers_full_surface) override; void ClearFramebuffer(DrawingFrame* frame, bool has_external_stencil_test) override; - void DoDrawQuad(DrawingFrame* frame, const class DrawQuad*) override; + void DoDrawQuad(DrawingFrame* frame, + const class DrawQuad*, + const gfx::QuadF* draw_region) override; void BeginDrawingFrame(DrawingFrame* frame) override; void FinishDrawingFrame(DrawingFrame* frame) override; bool FlippedFramebuffer(const DrawingFrame* frame) const override; @@ -132,10 +136,13 @@ // Inflate the quad and fill edge array for fragment shader. // |local_quad| is set to inflated quad. |edge| array is filled with // inflated quad's edge data. - static void SetupQuadForAntialiasing(const gfx::Transform& device_transform, - const DrawQuad* quad, - gfx::QuadF* local_quad, - float edge[24]); + static void SetupQuadForClippingAndAntialiasing( + const gfx::Transform& device_transform, + const DrawQuad* quad, + bool use_aa, + const gfx::QuadF* clip_region, + gfx::QuadF* local_quad, + float edge[24]); private: friend class GLRendererShaderPixelTest; @@ -144,7 +151,8 @@ static void ToGLMatrix(float* gl_matrix, const gfx::Transform& transform); void DrawCheckerboardQuad(const DrawingFrame* frame, - const CheckerboardDrawQuad* quad); + const CheckerboardDrawQuad* quad, + const gfx::QuadF* clip_region); void DrawDebugBorderQuad(const DrawingFrame* frame, const DebugBorderDrawQuad* quad); static bool IsDefaultBlendMode(SkXfermode::Mode blend_mode) { @@ -158,6 +166,7 @@ DrawingFrame* frame, const RenderPassDrawQuad* quad, const gfx::Transform& contents_device_transform, + const gfx::QuadF* clip_region, bool use_aa); scoped_ptr<ScopedResource> GetBackdropTexture(const gfx::Rect& bounding_rect); @@ -168,34 +177,56 @@ const RenderPassDrawQuad* quad, ScopedResource* background_texture); - void DrawRenderPassQuad(DrawingFrame* frame, const RenderPassDrawQuad* quad); + void DrawRenderPassQuad(DrawingFrame* frame, + const RenderPassDrawQuad* quadi, + const gfx::QuadF* clip_region); void DrawSolidColorQuad(const DrawingFrame* frame, - const SolidColorDrawQuad* quad); + const SolidColorDrawQuad* quad, + const gfx::QuadF* clip_region); void DrawStreamVideoQuad(const DrawingFrame* frame, - const StreamVideoDrawQuad* quad); + const StreamVideoDrawQuad* quad, + const gfx::QuadF* clip_region); + void DrawTextureQuad(const DrawingFrame* frame, + const TextureDrawQuad* quad, + const gfx::QuadF* clip_region); void EnqueueTextureQuad(const DrawingFrame* frame, - const TextureDrawQuad* quad); - void FlushTextureQuadCache(); + const TextureDrawQuad* quad, + const gfx::QuadF* clip_region); + void FlushTextureQuadCache(BoundGeometry flush_binding); void DrawIOSurfaceQuad(const DrawingFrame* frame, - const IOSurfaceDrawQuad* quad); - void DrawTileQuad(const DrawingFrame* frame, const TileDrawQuad* quad); + const IOSurfaceDrawQuad* quad, + const gfx::QuadF* clip_region); + void DrawTileQuad(const DrawingFrame* frame, + const TileDrawQuad* quad, + const gfx::QuadF* clip_region); void DrawContentQuad(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id); + ResourceProvider::ResourceId resource_id, + const gfx::QuadF* clip_region); void DrawContentQuadAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, ResourceProvider::ResourceId resource_id, - const gfx::Transform& device_transform); + const gfx::Transform& device_transform, + const gfx::QuadF* clip_region); void DrawContentQuadNoAA(const DrawingFrame* frame, const ContentDrawQuadBase* quad, - ResourceProvider::ResourceId resource_id); + ResourceProvider::ResourceId resource_id, + const gfx::QuadF* clip_region); void DrawYUVVideoQuad(const DrawingFrame* frame, - const YUVVideoDrawQuad* quad); + const YUVVideoDrawQuad* quad, + const gfx::QuadF* clip_region); void DrawPictureQuad(const DrawingFrame* frame, - const PictureDrawQuad* quad); + const PictureDrawQuad* quad, + const gfx::QuadF* clip_region); void SetShaderOpacity(float opacity, int alpha_location); void SetShaderQuadF(const gfx::QuadF& quad, int quad_location); + void DrawQuadGeometryClippedByQuadF(const DrawingFrame* frame, + const gfx::Transform& draw_transform, + const gfx::RectF& quad_rect, + const gfx::QuadF& clipping_region_quad, + int matrix_location, + const float uv[8]); void DrawQuadGeometry(const DrawingFrame* frame, const gfx::Transform& draw_transform, const gfx::RectF& quad_rect, @@ -237,7 +268,8 @@ unsigned offscreen_framebuffer_id_; - scoped_ptr<GeometryBinding> shared_geometry_; + scoped_ptr<StaticGeometryBinding> shared_geometry_; + scoped_ptr<DynamicGeometryBinding> clipped_geometry_; gfx::QuadF shared_geometry_quad_; // This block of bindings defines all of the programs used by the compositor @@ -480,7 +512,7 @@ SkBitmap on_demand_tile_raster_bitmap_; ResourceProvider::ResourceId on_demand_tile_raster_resource_id_; - + BoundGeometry bound_geometry_; DISALLOW_COPY_AND_ASSIGN(GLRenderer); };
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc index 5590ec3..9090621 100644 --- a/cc/output/overlay_unittest.cc +++ b/cc/output/overlay_unittest.cc
@@ -775,7 +775,10 @@ 0), expect_overlays_(false) {} - MOCK_METHOD2(DoDrawQuad, void(DrawingFrame* frame, const DrawQuad* quad)); + MOCK_METHOD3(DoDrawQuad, + void(DrawingFrame* frame, + const DrawQuad* quad, + const gfx::QuadF* draw_region)); using GLRenderer::BeginDrawingFrame; @@ -875,7 +878,7 @@ // Candidate pass was taken out and extra skipped pass added, // so only draw 2 quads. - EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2); + EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(2); EXPECT_CALL(scheduler_, Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, @@ -913,7 +916,7 @@ pass_list.push_back(pass.Pass()); // 3 quads in the pass, all should draw. - EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3); + EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3); EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0); renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false); @@ -946,7 +949,7 @@ pass_list.push_back(pass.Pass()); // Should see no overlays. - EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3); + EXPECT_CALL(*renderer_, DoDrawQuad(_, _, _)).Times(3); EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0); renderer_->DrawFrame(&pass_list, 1.f, viewport_rect, viewport_rect, false);
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index 81ad842..ebda8d6 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc
@@ -110,6 +110,52 @@ FilterOperations()); // background filters } +void CreateTestTwoColoredTextureDrawQuad(const gfx::Rect& rect, + SkColor texel_color, + SkColor texel_stripe_color, + SkColor background_color, + bool premultiplied_alpha, + const SharedQuadState* shared_state, + ResourceProvider* resource_provider, + RenderPass* render_pass) { + SkPMColor pixel_color = premultiplied_alpha + ? SkPreMultiplyColor(texel_color) + : SkPackARGB32NoCheck(SkColorGetA(texel_color), + SkColorGetR(texel_color), + SkColorGetG(texel_color), + SkColorGetB(texel_color)); + SkPMColor pixel_stripe_color = + premultiplied_alpha + ? SkPreMultiplyColor(texel_stripe_color) + : SkPackARGB32NoCheck(SkColorGetA(texel_stripe_color), + SkColorGetR(texel_stripe_color), + SkColorGetG(texel_stripe_color), + SkColorGetB(texel_stripe_color)); + std::vector<uint32_t> pixels(rect.size().GetArea(), pixel_color); + for (int i = rect.height() / 4; i < (rect.height() * 3 / 4); ++i) { + for (int k = rect.width() / 4; k < (rect.width() * 3 / 4); ++k) { + pixels[i * rect.width() + k] = pixel_stripe_color; + } + } + ResourceProvider::ResourceId resource = resource_provider->CreateResource( + rect.size(), GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, + RGBA_8888); + resource_provider->SetPixels(resource, + reinterpret_cast<uint8_t*>(&pixels.front()), + rect, rect, gfx::Vector2d()); + + float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const gfx::PointF uv_top_left(0.0f, 0.0f); + const gfx::PointF uv_bottom_right(1.0f, 1.0f); + const bool flipped = false; + const bool nearest_neighbor = false; + TextureDrawQuad* quad = + render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); + quad->SetNew(shared_state, rect, gfx::Rect(), rect, resource, + premultiplied_alpha, uv_top_left, uv_bottom_right, + background_color, vertex_opacity, flipped, nearest_neighbor); +} + void CreateTestTextureDrawQuad(const gfx::Rect& rect, SkColor texel_color, SkColor background_color, @@ -134,20 +180,216 @@ float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const gfx::PointF uv_top_left(0.0f, 0.0f); + const gfx::PointF uv_bottom_right(1.0f, 1.0f); + const bool flipped = false; + const bool nearest_neighbor = false; TextureDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); - quad->SetNew(shared_state, - rect, - gfx::Rect(), - rect, - resource, - premultiplied_alpha, - gfx::PointF(0.0f, 0.0f), // uv_top_left - gfx::PointF(1.0f, 1.0f), // uv_bottom_right - background_color, - vertex_opacity, - false, // flipped - false); // nearest_neighbor + quad->SetNew(shared_state, rect, gfx::Rect(), rect, resource, + premultiplied_alpha, uv_top_left, uv_bottom_right, + background_color, vertex_opacity, flipped, nearest_neighbor); +} + +void CreateTestYUVVideoDrawQuad_FromVideoFrame( + const SharedQuadState* shared_state, + scoped_refptr<media::VideoFrame> video_frame, + uint8 alpha_value, + const gfx::RectF& tex_coord_rect, + RenderPass* render_pass, + VideoResourceUpdater* video_resource_updater, + const gfx::Rect& rect, + ResourceProvider* resource_provider) { + const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A); + const YUVVideoDrawQuad::ColorSpace color_space = + (video_frame->format() == media::VideoFrame::YV12J + ? YUVVideoDrawQuad::JPEG + : YUVVideoDrawQuad::REC_601); + const gfx::Rect opaque_rect(0, 0, 0, 0); + + if (with_alpha) { + memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value, + video_frame->stride(media::VideoFrame::kAPlane) * + video_frame->rows(media::VideoFrame::kAPlane)); + } + + VideoFrameExternalResources resources = + video_resource_updater->CreateExternalResourcesFromVideoFrame( + video_frame); + + EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); + EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()), + resources.mailboxes.size()); + EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()), + resources.release_callbacks.size()); + + ResourceProvider::ResourceId y_resource = + resource_provider->CreateResourceFromTextureMailbox( + resources.mailboxes[media::VideoFrame::kYPlane], + SingleReleaseCallbackImpl::Create( + resources.release_callbacks[media::VideoFrame::kYPlane])); + ResourceProvider::ResourceId u_resource = + resource_provider->CreateResourceFromTextureMailbox( + resources.mailboxes[media::VideoFrame::kUPlane], + SingleReleaseCallbackImpl::Create( + resources.release_callbacks[media::VideoFrame::kUPlane])); + ResourceProvider::ResourceId v_resource = + resource_provider->CreateResourceFromTextureMailbox( + resources.mailboxes[media::VideoFrame::kVPlane], + SingleReleaseCallbackImpl::Create( + resources.release_callbacks[media::VideoFrame::kVPlane])); + ResourceProvider::ResourceId a_resource = 0; + if (with_alpha) { + a_resource = resource_provider->CreateResourceFromTextureMailbox( + resources.mailboxes[media::VideoFrame::kAPlane], + SingleReleaseCallbackImpl::Create( + resources.release_callbacks[media::VideoFrame::kAPlane])); + } + + YUVVideoDrawQuad* yuv_quad = + render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); + yuv_quad->SetNew(shared_state, rect, opaque_rect, rect, tex_coord_rect, + video_frame->coded_size(), y_resource, u_resource, + v_resource, a_resource, color_space); +} + +void CreateTestYUVVideoDrawQuad_Striped( + const SharedQuadState* shared_state, + media::VideoFrame::Format format, + bool is_transparent, + const gfx::RectF& tex_coord_rect, + RenderPass* render_pass, + VideoResourceUpdater* video_resource_updater, + const gfx::Rect& rect, + ResourceProvider* resource_provider) { + scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame( + format, rect.size(), rect, rect.size(), base::TimeDelta()); + + // YUV values representing a striped pattern, for validating texture + // coordinates for sampling. + uint8_t y_value = 0; + uint8_t u_value = 0; + uint8_t v_value = 0; + for (int i = 0; i < video_frame->rows(media::VideoFrame::kYPlane); ++i) { + uint8_t* y_row = video_frame->data(media::VideoFrame::kYPlane) + + video_frame->stride(media::VideoFrame::kYPlane) * i; + for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kYPlane); + ++j) { + y_row[j] = (y_value += 1); + } + } + for (int i = 0; i < video_frame->rows(media::VideoFrame::kUPlane); ++i) { + uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) + + video_frame->stride(media::VideoFrame::kUPlane) * i; + uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) + + video_frame->stride(media::VideoFrame::kVPlane) * i; + for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane); + ++j) { + u_row[j] = (u_value += 3); + v_row[j] = (v_value += 5); + } + } + uint8 alpha_value = is_transparent ? 0 : 128; + CreateTestYUVVideoDrawQuad_FromVideoFrame( + shared_state, video_frame, alpha_value, tex_coord_rect, render_pass, + video_resource_updater, rect, resource_provider); +} + +// Creates a video frame of size background_size filled with yuv_background, +// and then draws a foreground rectangle in a different color on top of +// that. The foreground rectangle must have coordinates that are divisible +// by 2 because YUV is a block format. +void CreateTestYUVVideoDrawQuad_TwoColor( + const SharedQuadState* shared_state, + media::VideoFrame::Format format, + bool is_transparent, + const gfx::RectF& tex_coord_rect, + const gfx::Size& background_size, + uint8 y_background, + uint8 u_background, + uint8 v_background, + const gfx::Rect& foreground_rect, + uint8 y_foreground, + uint8 u_foreground, + uint8 v_foreground, + RenderPass* render_pass, + VideoResourceUpdater* video_resource_updater, + ResourceProvider* resource_provider) { + const gfx::Rect rect(background_size); + + scoped_refptr<media::VideoFrame> video_frame = + media::VideoFrame::CreateFrame(format, background_size, foreground_rect, + foreground_rect.size(), base::TimeDelta()); + + int planes[] = {media::VideoFrame::kYPlane, + media::VideoFrame::kUPlane, + media::VideoFrame::kVPlane}; + uint8 yuv_background[] = {y_background, u_background, v_background}; + uint8 yuv_foreground[] = {y_foreground, u_foreground, v_foreground}; + int sample_size[] = {1, 2, 2}; + + for (int i = 0; i < 3; ++i) { + memset(video_frame->data(planes[i]), yuv_background[i], + video_frame->stride(planes[i]) * video_frame->rows(planes[i])); + } + + for (int i = 0; i < 3; ++i) { + // Since yuv encoding uses block encoding, widths have to be divisible + // by the sample size in order for this function to behave properly. + DCHECK_EQ(foreground_rect.x() % sample_size[i], 0); + DCHECK_EQ(foreground_rect.y() % sample_size[i], 0); + DCHECK_EQ(foreground_rect.width() % sample_size[i], 0); + DCHECK_EQ(foreground_rect.height() % sample_size[i], 0); + + gfx::Rect sample_rect(foreground_rect.x() / sample_size[i], + foreground_rect.y() / sample_size[i], + foreground_rect.width() / sample_size[i], + foreground_rect.height() / sample_size[i]); + for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) { + for (int x = sample_rect.x(); x < sample_rect.right(); ++x) { + size_t offset = y * video_frame->stride(planes[i]) + x; + video_frame->data(planes[i])[offset] = yuv_foreground[i]; + } + } + } + + uint8 alpha_value = 255; + CreateTestYUVVideoDrawQuad_FromVideoFrame( + shared_state, video_frame, alpha_value, tex_coord_rect, render_pass, + video_resource_updater, rect, resource_provider); +} + +void CreateTestYUVVideoDrawQuad_Solid( + const SharedQuadState* shared_state, + media::VideoFrame::Format format, + bool is_transparent, + const gfx::RectF& tex_coord_rect, + uint8 y, + uint8 u, + uint8 v, + RenderPass* render_pass, + VideoResourceUpdater* video_resource_updater, + const gfx::Rect& rect, + ResourceProvider* resource_provider) { + scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame( + format, rect.size(), rect, rect.size(), base::TimeDelta()); + + // YUV values of a solid, constant, color. Useful for testing that color + // space/color range are being handled properly. + memset(video_frame->data(media::VideoFrame::kYPlane), y, + video_frame->stride(media::VideoFrame::kYPlane) * + video_frame->rows(media::VideoFrame::kYPlane)); + memset(video_frame->data(media::VideoFrame::kUPlane), u, + video_frame->stride(media::VideoFrame::kUPlane) * + video_frame->rows(media::VideoFrame::kUPlane)); + memset(video_frame->data(media::VideoFrame::kVPlane), v, + video_frame->stride(media::VideoFrame::kVPlane) * + video_frame->rows(media::VideoFrame::kVPlane)); + + uint8 alpha_value = is_transparent ? 0 : 128; + CreateTestYUVVideoDrawQuad_FromVideoFrame( + shared_state, video_frame, alpha_value, tex_coord_rect, render_pass, + video_resource_updater, rect, resource_provider); } typedef ::testing::Types<GLRenderer, @@ -322,6 +564,278 @@ FuzzyPixelOffByOneComparator(true))); } +template <typename QuadType> +static const base::FilePath::CharType* IntersectingQuadImage() { + return FILE_PATH_LITERAL("intersecting_blue_green_squares.png"); +} +template <> +const base::FilePath::CharType* IntersectingQuadImage<SolidColorDrawQuad>() { + return FILE_PATH_LITERAL("intersecting_blue_green.png"); +} +template <> +const base::FilePath::CharType* IntersectingQuadImage<YUVVideoDrawQuad>() { + return FILE_PATH_LITERAL("intersecting_blue_green_squares_video.png"); +} + +template <typename TypeParam> +class IntersectingQuadPixelTest : public RendererPixelTest<TypeParam> { + protected: + void SetupQuadStateAndRenderPass() { + // This sets up a pair of draw quads. They are both rotated + // relative to the root plane, they are also rotated relative to each other. + // The intersect in the middle at a non-perpendicular angle so that any + // errors are hopefully magnified. + // The quads should intersect correctly, as in the front quad should only + // be partially in front of the back quad, and partially behind. + + viewport_rect_ = gfx::Rect(this->device_viewport_size_); + quad_rect_ = gfx::Rect(0, 0, this->device_viewport_size_.width(), + this->device_viewport_size_.height() / 2.0); + + RenderPassId id(1, 1); + render_pass_ = CreateTestRootRenderPass(id, viewport_rect_); + + // Create the front quad rotated on the Z and Y axis. + gfx::Transform trans; + trans.Translate3d(0, 0, 0.707 * this->device_viewport_size_.width() / 2.0); + trans.RotateAboutZAxis(45.0); + trans.RotateAboutYAxis(45.0); + front_quad_state_ = + CreateTestSharedQuadState(trans, viewport_rect_, render_pass_.get()); + front_quad_state_->clip_rect = quad_rect_; + // Make sure they end up in a 3d sorting context. + front_quad_state_->sorting_context_id = 1; + + // Create the back quad, and rotate on just the y axis. This will intersect + // the first quad partially. + trans = gfx::Transform(); + trans.Translate3d(0, 0, -0.707 * this->device_viewport_size_.width() / 2.0); + trans.RotateAboutYAxis(-45.0); + back_quad_state_ = + CreateTestSharedQuadState(trans, viewport_rect_, render_pass_.get()); + back_quad_state_->sorting_context_id = 1; + back_quad_state_->clip_rect = quad_rect_; + } + template <typename T> + void AppendBackgroundAndRunTest(const PixelComparator& comparator) { + SharedQuadState* background_quad_state = CreateTestSharedQuadState( + gfx::Transform(), viewport_rect_, render_pass_.get()); + SolidColorDrawQuad* background_quad = + render_pass_->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + background_quad->SetNew(background_quad_state, viewport_rect_, + viewport_rect_, SK_ColorWHITE, false); + pass_list_.push_back(render_pass_.Pass()); + const base::FilePath::CharType* fileName = IntersectingQuadImage<T>(); + EXPECT_TRUE( + this->RunPixelTest(&pass_list_, base::FilePath(fileName), comparator)); + } + template <typename T> + T* CreateAndAppendDrawQuad() { + return render_pass_->CreateAndAppendDrawQuad<T>(); + } + + scoped_ptr<RenderPass> render_pass_; + gfx::Rect viewport_rect_; + SharedQuadState* front_quad_state_; + SharedQuadState* back_quad_state_; + gfx::Rect quad_rect_; + RenderPassList pass_list_; +}; + +template <typename TypeParam> +class IntersectingQuadGLPixelTest + : public IntersectingQuadPixelTest<TypeParam> { + public: + void SetUp() override { + IntersectingQuadPixelTest<TypeParam>::SetUp(); + video_resource_updater_.reset( + new VideoResourceUpdater(this->output_surface_->context_provider(), + this->resource_provider_.get())); + video_resource_updater2_.reset( + new VideoResourceUpdater(this->output_surface_->context_provider(), + this->resource_provider_.get())); + } + + protected: + scoped_ptr<VideoResourceUpdater> video_resource_updater_; + scoped_ptr<VideoResourceUpdater> video_resource_updater2_; +}; + +template <typename TypeParam> +class IntersectingQuadSoftwareTest + : public IntersectingQuadPixelTest<TypeParam> {}; + +typedef ::testing::Types<SoftwareRenderer, SoftwareRendererWithExpandedViewport> + SoftwareRendererTypes; +typedef ::testing::Types<GLRenderer, GLRendererWithExpandedViewport> + GLRendererTypes; + +TYPED_TEST_CASE(IntersectingQuadPixelTest, RendererTypes); +TYPED_TEST_CASE(IntersectingQuadGLPixelTest, GLRendererTypes); +TYPED_TEST_CASE(IntersectingQuadSoftwareTest, SoftwareRendererTypes); + +TYPED_TEST(IntersectingQuadPixelTest, SolidColorQuads) { + this->SetupQuadStateAndRenderPass(); + + SolidColorDrawQuad* quad = + this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + SolidColorDrawQuad* quad2 = + this->template CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + + quad->SetNew(this->front_quad_state_, this->quad_rect_, this->quad_rect_, + SK_ColorBLUE, false); + quad2->SetNew(this->back_quad_state_, this->quad_rect_, this->quad_rect_, + SK_ColorGREEN, false); + SCOPED_TRACE("IntersectingSolidColorQuads"); + this->template AppendBackgroundAndRunTest<SolidColorDrawQuad>( + FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f)); +} + +template <typename TypeParam> +SkColor GetColor(const SkColor& color) { + return color; +} + +template <> +SkColor GetColor<GLRenderer>(const SkColor& color) { + return SkColorSetARGB(SkColorGetA(color), SkColorGetB(color), + SkColorGetG(color), SkColorGetR(color)); +} +template <> +SkColor GetColor<GLRendererWithExpandedViewport>(const SkColor& color) { + return GetColor<GLRenderer>(color); +} + +TYPED_TEST(IntersectingQuadPixelTest, TexturedQuads) { + this->SetupQuadStateAndRenderPass(); + CreateTestTwoColoredTextureDrawQuad( + this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), + GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT, + true, this->front_quad_state_, this->resource_provider_.get(), + this->render_pass_.get()); + CreateTestTwoColoredTextureDrawQuad( + this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)), + GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT, + true, this->back_quad_state_, this->resource_provider_.get(), + this->render_pass_.get()); + + SCOPED_TRACE("IntersectingTexturedQuads"); + this->template AppendBackgroundAndRunTest<TextureDrawQuad>( + FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f)); +} + +TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) { + this->SetupQuadStateAndRenderPass(); + gfx::RectF outer_rect(this->quad_rect_); + gfx::RectF inner_rect(this->quad_rect_.x() + (this->quad_rect_.width() / 4), + this->quad_rect_.y() + (this->quad_rect_.height() / 4), + this->quad_rect_.width() / 2, + this->quad_rect_.height() / 2); + + SkPaint black_paint; + black_paint.setColor(SK_ColorBLACK); + SkPaint blue_paint; + blue_paint.setColor(SK_ColorBLUE); + SkPaint green_paint; + green_paint.setColor(SK_ColorGREEN); + + scoped_ptr<FakePicturePile> blue_recording = + FakePicturePile::CreateFilledPile(gfx::Size(1000, 1000), + this->quad_rect_.size()); + blue_recording->add_draw_rect_with_paint(outer_rect, black_paint); + blue_recording->add_draw_rect_with_paint(inner_rect, blue_paint); + blue_recording->RerecordPile(); + scoped_refptr<FakePicturePileImpl> blue_pile = + FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr); + + PictureDrawQuad* blue_quad = + this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>(); + + blue_quad->SetNew(this->front_quad_state_, this->quad_rect_, gfx::Rect(), + this->quad_rect_, this->quad_rect_, this->quad_rect_.size(), + false, RGBA_8888, this->quad_rect_, 1.f, blue_pile); + + scoped_ptr<FakePicturePile> green_recording = + FakePicturePile::CreateFilledPile(this->quad_rect_.size(), + this->quad_rect_.size()); + green_recording->add_draw_rect_with_paint(outer_rect, green_paint); + green_recording->add_draw_rect_with_paint(inner_rect, black_paint); + green_recording->RerecordPile(); + scoped_refptr<FakePicturePileImpl> green_pile = + FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr); + + PictureDrawQuad* green_quad = + this->render_pass_->template CreateAndAppendDrawQuad<PictureDrawQuad>(); + green_quad->SetNew(this->back_quad_state_, this->quad_rect_, gfx::Rect(), + this->quad_rect_, this->quad_rect_, + this->quad_rect_.size(), false, RGBA_8888, + this->quad_rect_, 1.f, green_pile); + SCOPED_TRACE("IntersectingPictureQuadsPass"); + this->template AppendBackgroundAndRunTest<PictureDrawQuad>( + FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f)); +} + +TYPED_TEST(IntersectingQuadPixelTest, RenderPassQuads) { + this->SetupQuadStateAndRenderPass(); + RenderPassId child_pass_id1(2, 2); + RenderPassId child_pass_id2(2, 3); + scoped_ptr<RenderPass> child_pass1 = + CreateTestRenderPass(child_pass_id1, this->quad_rect_, gfx::Transform()); + SharedQuadState* child1_quad_state = CreateTestSharedQuadState( + gfx::Transform(), this->quad_rect_, child_pass1.get()); + scoped_ptr<RenderPass> child_pass2 = + CreateTestRenderPass(child_pass_id2, this->quad_rect_, gfx::Transform()); + SharedQuadState* child2_quad_state = CreateTestSharedQuadState( + gfx::Transform(), this->quad_rect_, child_pass2.get()); + + CreateTestTwoColoredTextureDrawQuad( + this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), + GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT, + true, child1_quad_state, this->resource_provider_.get(), + child_pass1.get()); + CreateTestTwoColoredTextureDrawQuad( + this->quad_rect_, GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)), + GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT, + true, child2_quad_state, this->resource_provider_.get(), + child_pass2.get()); + + CreateTestRenderPassDrawQuad(this->front_quad_state_, this->quad_rect_, + child_pass_id1, this->render_pass_.get()); + CreateTestRenderPassDrawQuad(this->back_quad_state_, this->quad_rect_, + child_pass_id2, this->render_pass_.get()); + + this->pass_list_.push_back(child_pass1.Pass()); + this->pass_list_.push_back(child_pass2.Pass()); + SCOPED_TRACE("IntersectingRenderQuadsPass"); + this->template AppendBackgroundAndRunTest<RenderPassDrawQuad>( + FuzzyPixelComparator(false, 2.f, 0.f, 256.f, 256, 0.f)); +} + +TYPED_TEST(IntersectingQuadGLPixelTest, YUVVideoQuads) { + this->SetupQuadStateAndRenderPass(); + gfx::Rect inner_rect( + ((this->quad_rect_.x() + (this->quad_rect_.width() / 4)) & ~0xF), + ((this->quad_rect_.y() + (this->quad_rect_.height() / 4)) & ~0xF), + (this->quad_rect_.width() / 2) & ~0xF, + (this->quad_rect_.height() / 2) & ~0xF); + + CreateTestYUVVideoDrawQuad_TwoColor( + this->front_quad_state_, media::VideoFrame::YV12J, false, + gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(), 0, 128, 128, + inner_rect, 29, 255, 107, this->render_pass_.get(), + this->video_resource_updater_.get(), this->resource_provider_.get()); + + CreateTestYUVVideoDrawQuad_TwoColor( + this->back_quad_state_, media::VideoFrame::YV12J, false, + gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(), 149, 43, 21, + inner_rect, 0, 128, 128, this->render_pass_.get(), + this->video_resource_updater2_.get(), this->resource_provider_.get()); + + SCOPED_TRACE("IntersectingVideoQuads"); + this->template AppendBackgroundAndRunTest<YUVVideoDrawQuad>( + FuzzyPixelOffByOneComparator(false)); +} + // TODO(skaslev): The software renderer does not support non-premultplied alpha. TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithoutBackground) { gfx::Rect rect(this->device_viewport_size_);
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index a4b5428..19c4fa3 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc
@@ -25,6 +25,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkMatrix.h" +#include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/effects/SkLayerRasterizer.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -235,7 +236,13 @@ return false; } -void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) { +void SoftwareRenderer::DoDrawQuad(DrawingFrame* frame, + const DrawQuad* quad, + const gfx::QuadF* draw_region) { + if (draw_region) { + current_canvas_->save(); + } + TRACE_EVENT0("cc", "SoftwareRenderer::DoDrawQuad"); gfx::Transform quad_rect_matrix; QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect); @@ -270,9 +277,31 @@ current_paint_.setXfermodeMode(SkXfermode::kSrc_Mode); } + if (draw_region) { + gfx::QuadF local_draw_region(*draw_region); + SkPath draw_region_clip_path; + local_draw_region -= + gfx::Vector2dF(quad->visible_rect.x(), quad->visible_rect.y()); + local_draw_region.Scale(1.0f / quad->visible_rect.width(), + 1.0f / quad->visible_rect.height()); + local_draw_region -= gfx::Vector2dF(0.5f, 0.5f); + + SkPoint clip_points[4]; + QuadFToSkPoints(local_draw_region, clip_points); + draw_region_clip_path.addPoly(clip_points, 4, true); + + current_canvas_->clipPath(draw_region_clip_path, SkRegion::kIntersect_Op, + false); + } + switch (quad->material) { case DrawQuad::CHECKERBOARD: - DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad)); + // TODO(enne) For now since checkerboards shouldn't be part of a 3D + // context, clipping regions aren't supported so we skip drawing them + // if this becomes the case. + if (!draw_region) { + DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad)); + } break; case DrawQuad::DEBUG_BORDER: DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad)); @@ -307,6 +336,9 @@ } current_canvas_->resetMatrix(); + if (draw_region) { + current_canvas_->restore(); + } } void SoftwareRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
diff --git a/cc/output/software_renderer.h b/cc/output/software_renderer.h index 99868c3..dc8e2fb 100644 --- a/cc/output/software_renderer.h +++ b/cc/output/software_renderer.h
@@ -52,7 +52,10 @@ bool draw_rect_covers_full_surface) override; void ClearFramebuffer(DrawingFrame* frame, bool has_external_stencil_test) override; - void DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) override; + + void DoDrawQuad(DrawingFrame* frame, + const DrawQuad* quad, + const gfx::QuadF* draw_region) override; void BeginDrawingFrame(DrawingFrame* frame) override; void FinishDrawingFrame(DrawingFrame* frame) override; bool FlippedFramebuffer(const DrawingFrame* frame) const override;
diff --git a/cc/output/static_geometry_binding.cc b/cc/output/static_geometry_binding.cc new file mode 100644 index 0000000..683db2d --- /dev/null +++ b/cc/output/static_geometry_binding.cc
@@ -0,0 +1,72 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/output/static_geometry_binding.h" + +#include "cc/output/gl_renderer.h" // For the GLC() macro. +#include "gpu/command_buffer/client/gles2_interface.h" +#include "ui/gfx/geometry/rect_f.h" + +namespace cc { + +StaticGeometryBinding::StaticGeometryBinding(gpu::gles2::GLES2Interface* gl, + const gfx::RectF& quad_vertex_rect) + : gl_(gl), quad_vertices_vbo_(0), quad_elements_vbo_(0) { + GeometryBindingQuad quads[8]; + GeometryBindingQuadIndex quad_indices[8]; + + static_assert(sizeof(GeometryBindingQuad) == 24 * sizeof(float), + "struct Quad should be densely packed"); + static_assert(sizeof(GeometryBindingQuadIndex) == 6 * sizeof(uint16_t), + "struct QuadIndex should be densely packed"); + + for (size_t i = 0; i < 8; i++) { + GeometryBindingVertex v0 = { + {quad_vertex_rect.x(), quad_vertex_rect.bottom(), 0.0f}, + {0.0f, 1.0f}, + i * 4.0f + 0.0f}; + GeometryBindingVertex v1 = { + {quad_vertex_rect.x(), quad_vertex_rect.y(), 0.0f}, + {0.0f, 0.0f}, + i * 4.0f + 1.0f}; + GeometryBindingVertex v2 = { + {quad_vertex_rect.right(), quad_vertex_rect.y(), 0.0f}, + {1.0f, 0.0f}, + i * 4.0f + 2.0f}; + GeometryBindingVertex v3 = { + {quad_vertex_rect.right(), quad_vertex_rect.bottom(), 0.0f}, + {1.0f, 1.0f}, + i * 4.0f + 3.0f}; + GeometryBindingQuad x(v0, v1, v2, v3); + quads[i] = x; + GeometryBindingQuadIndex 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_indices[i] = y; + } + + GLC(gl_, gl_->GenBuffers(1, &quad_vertices_vbo_)); + GLC(gl_, gl_->GenBuffers(1, &quad_elements_vbo_)); + + GLC(gl_, gl_->BindBuffer(GL_ARRAY_BUFFER, quad_vertices_vbo_)); + GLC(gl_, gl_->BufferData(GL_ARRAY_BUFFER, sizeof(GeometryBindingQuad) * 8, + quads, GL_STATIC_DRAW)); + + GLC(gl_, gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, quad_elements_vbo_)); + GLC(gl_, gl_->BufferData(GL_ELEMENT_ARRAY_BUFFER, + sizeof(GeometryBindingQuadIndex) * 8, &quad_indices, + GL_STATIC_DRAW)); +} + +StaticGeometryBinding::~StaticGeometryBinding() { + gl_->DeleteBuffers(1, &quad_vertices_vbo_); + gl_->DeleteBuffers(1, &quad_elements_vbo_); +} + +void StaticGeometryBinding::PrepareForDraw() { + SetupGLContext(gl_, quad_elements_vbo_, quad_vertices_vbo_); +} + +} // namespace cc
diff --git a/cc/output/static_geometry_binding.h b/cc/output/static_geometry_binding.h new file mode 100644 index 0000000..bd6bfcc --- /dev/null +++ b/cc/output/static_geometry_binding.h
@@ -0,0 +1,33 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_OUTPUT_STATIC_GEOMETRY_BINDING_H_ +#define CC_OUTPUT_STATIC_GEOMETRY_BINDING_H_ + +#include "cc/output/geometry_binding.h" + +using gpu::gles2::GLES2Interface; + +namespace cc { + +class StaticGeometryBinding { + public: + StaticGeometryBinding(gpu::gles2::GLES2Interface* gl, + const gfx::RectF& quad_vertex_rect); + ~StaticGeometryBinding(); + + void PrepareForDraw(); + + private: + gpu::gles2::GLES2Interface* gl_; + + GLuint quad_vertices_vbo_; + GLuint quad_elements_vbo_; + + DISALLOW_COPY_AND_ASSIGN(StaticGeometryBinding); +}; + +} // namespace cc + +#endif // CC_OUTPUT_STATIC_GEOMETRY_BINDING_H_
diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h index 8dcd2b9..f80e06c 100644 --- a/cc/quads/content_draw_quad_base.h +++ b/cc/quads/content_draw_quad_base.h
@@ -8,7 +8,6 @@ #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" #include "cc/quads/draw_quad.h" -#include "third_party/khronos/GLES2/gl2.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h"
diff --git a/cc/quads/draw_polygon.cc b/cc/quads/draw_polygon.cc index 026be2c..6544b64 100644 --- a/cc/quads/draw_polygon.cc +++ b/cc/quads/draw_polygon.cc
@@ -12,7 +12,7 @@ namespace { // This allows for some imperfection in the normal comparison when checking if // two pieces of geometry are coplanar. -static const float coplanar_dot_epsilon = 0.01f; +static const float coplanar_dot_epsilon = 0.001f; // This threshold controls how "thick" a plane is. If a point's distance is // <= |compare_threshold|, then it is considered on the plane. Only when this // boundary is crossed do we consider doing splitting. @@ -25,21 +25,23 @@ // points that SHOULD be intersecting the "thick plane", but actually fail to // test positively for it because |split_threshold| allowed them to be outside // this range. +// This is really supposd to be compare_threshold / 2.0f, but that would +// create another static initializer. static const float split_threshold = 0.5f; + +static const float normalized_threshold = 0.001f; } // namespace namespace cc { -gfx::Vector3dF DrawPolygon::default_normal = gfx::Vector3dF(0.0f, 0.0f, -1.0f); - DrawPolygon::DrawPolygon() { } -DrawPolygon::DrawPolygon(DrawQuad* original, +DrawPolygon::DrawPolygon(const DrawQuad* original, const std::vector<gfx::Point3F>& in_points, const gfx::Vector3dF& normal, int draw_order_index) - : order_index_(draw_order_index), original_ref_(original) { + : order_index_(draw_order_index), original_ref_(original), is_split_(true) { for (size_t i = 0; i < in_points.size(); i++) { points_.push_back(in_points[i]); } @@ -49,12 +51,14 @@ // This takes the original DrawQuad that this polygon should be based on, // a visible content rect to make the 4 corner points from, and a transformation // to move it and its normal into screen space. -DrawPolygon::DrawPolygon(DrawQuad* original_ref, +DrawPolygon::DrawPolygon(const DrawQuad* original_ref, const gfx::RectF& visible_content_rect, const gfx::Transform& transform, int draw_order_index) - : order_index_(draw_order_index), original_ref_(original_ref) { - normal_ = default_normal; + : normal_(0.0f, 0.0f, 1.0f), + order_index_(draw_order_index), + original_ref_(original_ref), + is_split_(false) { gfx::Point3F points[8]; int num_vertices_in_clipped_quad; gfx::QuadF send_quad(visible_content_rect); @@ -97,6 +101,9 @@ // Assumes that layers are split and there are no intersecting planes. BspCompareResult DrawPolygon::SideCompare(const DrawPolygon& a, const DrawPolygon& b) { + // Let's make sure that both of these are normalized. + DCHECK_GE(normalized_threshold, std::abs(a.normal_.LengthSquared() - 1.0f)); + DCHECK_GE(normalized_threshold, std::abs(b.normal_.LengthSquared() - 1.0f)); // Right away let's check if they're coplanar double dot = gfx::DotProduct(a.normal_, b.normal_); float sign = 0.0f; @@ -105,7 +112,7 @@ if (std::abs(dot) >= 1.0f - coplanar_dot_epsilon) { normal_match = true; // The normals are matching enough that we only have to test one point. - sign = gfx::DotProduct(a.points_[0] - b.points_[0], b.normal_); + sign = b.SignedPointDistance(a.points_[0]); // Is it on either side of the splitter? if (sign < -compare_threshold) { return BSP_BACK; @@ -168,7 +175,7 @@ // The case where one vertex lies on the thick-plane and the other // is outside of it. - if (std::abs(start_distance) < distance_threshold && + if (std::abs(start_distance) <= distance_threshold && std::abs(end_distance) > distance_threshold) { intersection->SetPoint(line_start.x(), line_start.y(), line_start.z()); return true; @@ -270,7 +277,7 @@ break; } } - if (current_vertex++ > points_size) { + if (current_vertex++ > (points_size)) { break; } } @@ -284,6 +291,7 @@ // First polygon. out_points[0].push_back(intersections[0]); + DCHECK_GE(vertex_before[1], start1); for (size_t i = start1; i <= vertex_before[1]; i++) { out_points[0].push_back(points_[i]); --points_remaining; @@ -306,6 +314,9 @@ scoped_ptr<DrawPolygon> poly2( new DrawPolygon(original_ref_, out_points[1], normal_, order_index_)); + DCHECK_GE(poly1->points().size(), 3u); + DCHECK_GE(poly2->points().size(), 3u); + if (SideCompare(*poly1, splitter) == BSP_FRONT) { *front = poly1.Pass(); *back = poly2.Pass();
diff --git a/cc/quads/draw_polygon.h b/cc/quads/draw_polygon.h index 32643ee..b94ff1e 100644 --- a/cc/quads/draw_polygon.h +++ b/cc/quads/draw_polygon.h
@@ -24,11 +24,11 @@ DrawPolygon(); ~DrawPolygon(); - DrawPolygon(DrawQuad* original_ref, + DrawPolygon(const DrawQuad* original_ref, const std::vector<gfx::Point3F>& in_points, const gfx::Vector3dF& normal, int draw_order_index = 0); - DrawPolygon(DrawQuad* original_ref, + DrawPolygon(const DrawQuad* original_ref, const gfx::RectF& visible_content_rect, const gfx::Transform& transform, int draw_order_index = 0); @@ -56,11 +56,9 @@ const gfx::Vector3dF& normal() const { return normal_; } const DrawQuad* original_ref() const { return original_ref_; } int order_index() const { return order_index_; } - + bool is_split() const { return is_split_; } scoped_ptr<DrawPolygon> CreateCopy(); - static gfx::Vector3dF default_normal; - private: void ApplyTransform(const gfx::Transform& transform); void ApplyTransformToNormal(const gfx::Transform& transform); @@ -76,7 +74,8 @@ // we need. // This DrawQuad is owned by the caller and its lifetime must be preserved // as long as this DrawPolygon is alive. - DrawQuad* original_ref_; + const DrawQuad* original_ref_; + bool is_split_; }; } // namespace cc
diff --git a/cc/quads/draw_quad.cc b/cc/quads/draw_quad.cc index 8b8fd78..ac1b43e 100644 --- a/cc/quads/draw_quad.cc +++ b/cc/quads/draw_quad.cc
@@ -25,9 +25,7 @@ namespace cc { DrawQuad::DrawQuad() - : material(INVALID), - needs_blending(false), - shared_quad_state() { + : material(INVALID), needs_blending(false), shared_quad_state(0) { } void DrawQuad::SetAll(const SharedQuadState* shared_quad_state,
diff --git a/cc/quads/tile_draw_quad.cc b/cc/quads/tile_draw_quad.cc index fbdae88..aa8f748 100644 --- a/cc/quads/tile_draw_quad.cc +++ b/cc/quads/tile_draw_quad.cc
@@ -7,7 +7,6 @@ #include "base/logging.h" #include "base/trace_event/trace_event_argument.h" #include "base/values.h" -#include "third_party/khronos/GLES2/gl2.h" namespace cc {
diff --git a/cc/resources/display_item_list.cc b/cc/resources/display_item_list.cc index ac6ab57..48f8c66 100644 --- a/cc/resources/display_item_list.cc +++ b/cc/resources/display_item_list.cc
@@ -10,8 +10,12 @@ #include "base/trace_event/trace_event_argument.h" #include "cc/base/math_util.h" #include "cc/debug/picture_debug_util.h" +#include "cc/debug/traced_picture.h" +#include "cc/debug/traced_value.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkDrawPictureCallback.h" #include "third_party/skia/include/core/SkPictureRecorder.h" +#include "third_party/skia/include/utils/SkPictureUtils.h" #include "ui/gfx/skia_util.h" namespace cc { @@ -30,12 +34,46 @@ void DisplayItemList::Raster(SkCanvas* canvas, SkDrawPictureCallback* callback, float contents_scale) const { - canvas->save(); - canvas->scale(contents_scale, contents_scale); - for (size_t i = 0; i < items_.size(); ++i) { - items_[i]->Raster(canvas, callback); + if (!picture_) { + canvas->save(); + canvas->scale(contents_scale, contents_scale); + for (size_t i = 0; i < items_.size(); ++i) { + items_[i]->Raster(canvas, callback); + } + canvas->restore(); + } else { + DCHECK(picture_); + + canvas->save(); + canvas->scale(contents_scale, contents_scale); + if (callback) { + // If we have a callback, we need to call |draw()|, |drawPicture()| + // doesn't take a callback. This is used by |AnalysisCanvas| to early + // out. + picture_->playback(canvas, callback); + } else { + // Prefer to call |drawPicture()| on the canvas since it could place the + // entire picture on the canvas instead of parsing the skia operations. + canvas->drawPicture(picture_.get()); + } + canvas->restore(); } - canvas->restore(); +} + +void DisplayItemList::CreateAndCacheSkPicture() { + // Convert to an SkPicture for faster rasterization. Code is identical to + // that in Picture::Record. + SkRTreeFactory factory; + SkPictureRecorder recorder; + skia::RefPtr<SkCanvas> canvas; + canvas = skia::SharePtr(recorder.beginRecording( + layer_rect_.width(), layer_rect_.height(), &factory)); + canvas->translate(-layer_rect_.x(), -layer_rect_.y()); + canvas->clipRect(gfx::RectToSkRect(layer_rect_)); + for (size_t i = 0; i < items_.size(); ++i) + items_[i]->Raster(canvas.get(), NULL); + picture_ = skia::AdoptRef(recorder.endRecording()); + DCHECK(picture_); } void DisplayItemList::AppendItem(scoped_ptr<DisplayItem> item) { @@ -62,6 +100,9 @@ total_size += item->PictureMemoryUsage(); } + if (picture_) + total_size += SkPictureUtils::ApproximateBytesUsed(picture_.get()); + return total_size; }
diff --git a/cc/resources/display_item_list.h b/cc/resources/display_item_list.h index e16b8b8..39694d7 100644 --- a/cc/resources/display_item_list.h +++ b/cc/resources/display_item_list.h
@@ -11,6 +11,8 @@ #include "cc/base/cc_export.h" #include "cc/base/scoped_ptr_vector.h" #include "cc/resources/display_item.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkPicture.h" #include "ui/gfx/geometry/rect.h" class SkCanvas; @@ -32,6 +34,8 @@ void set_layer_rect(gfx::Rect layer_rect) { layer_rect_ = layer_rect; } gfx::Rect layer_rect() const { return layer_rect_; } + void CreateAndCacheSkPicture(); + bool IsSuitableForGpuRasterization() const; int ApproximateOpCount() const; size_t PictureMemoryUsage() const; @@ -44,6 +48,8 @@ DisplayItemList(); ~DisplayItemList(); ScopedPtrVector<DisplayItem> items_; + skia::RefPtr<SkPicture> picture_; + gfx::Rect layer_rect_; bool is_suitable_for_gpu_rasterization_; int approximate_op_count_;
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc index 8d2dc3e..367b23d 100644 --- a/cc/resources/display_list_recording_source.cc +++ b/cc/resources/display_list_recording_source.cc
@@ -112,6 +112,9 @@ DetermineIfSolidColor(); display_list_->EmitTraceSnapshot(); + + display_list_->CreateAndCacheSkPicture(); + return true; }
diff --git a/cc/resources/gpu_rasterizer.cc b/cc/resources/gpu_rasterizer.cc index 6e318ed..d810386 100644 --- a/cc/resources/gpu_rasterizer.cc +++ b/cc/resources/gpu_rasterizer.cc
@@ -120,9 +120,16 @@ write_lock->InitSkSurface(use_worker_context, use_distance_field_text, raster_source->CanUseLCDText(), msaa_sample_count_); + + SkSurface* sk_surface = write_lock->sk_surface(); + + // Allocating an SkSurface will fail after a lost context. Pretend we + // rasterized, as the contents of the resource don't matter anymore. + if (!sk_surface) + return; + SkMultiPictureDraw multi_picture_draw; - multi_picture_draw.add(write_lock->sk_surface()->getCanvas(), - picture.get()); + multi_picture_draw.add(sk_surface->getCanvas(), picture.get()); multi_picture_draw.draw(msaa_sample_count_ > 0); write_lock->ReleaseSkSurface(); } @@ -169,6 +176,9 @@ msaa_sample_count_); SkSurface* sk_surface = lock->sk_surface(); + + // Allocating an SkSurface will fail after a lost context. Pretend we + // rasterized, as the contents of the resource don't matter anymore. if (!sk_surface) return;
diff --git a/cc/resources/layer_quad.cc b/cc/resources/layer_quad.cc index 38ec7b3..ba92314 100644 --- a/cc/resources/layer_quad.cc +++ b/cc/resources/layer_quad.cc
@@ -10,8 +10,11 @@ namespace cc { LayerQuad::Edge::Edge(const gfx::PointF& p, const gfx::PointF& q) { - DCHECK(p != q); - + if (p == q) { + degenerate_ = true; + return; + } + degenerate_ = false; gfx::Vector2dF tangent(p.y() - q.y(), q.x() - p.x()); float cross2 = p.x() * q.y() - q.x() * p.y(); @@ -43,6 +46,22 @@ bottom_(bottom) {} gfx::QuadF LayerQuad::ToQuadF() const { + if (left_.degenerate()) { + return gfx::QuadF(top_.Intersect(bottom_), top_.Intersect(right_), + right_.Intersect(bottom_), bottom_.Intersect(top_)); + } + if (right_.degenerate()) { + return gfx::QuadF(left_.Intersect(top_), top_.Intersect(bottom_), + bottom_.Intersect(top_), bottom_.Intersect(left_)); + } + if (top_.degenerate()) { + return gfx::QuadF(left_.Intersect(right_), right_.Intersect(left_), + right_.Intersect(bottom_), bottom_.Intersect(left_)); + } + if (bottom_.degenerate()) { + return gfx::QuadF(left_.Intersect(top_), top_.Intersect(right_), + right_.Intersect(left_), left_.Intersect(right_)); + } return gfx::QuadF(left_.Intersect(top_), top_.Intersect(right_), right_.Intersect(bottom_), @@ -50,18 +69,42 @@ } void LayerQuad::ToFloatArray(float flattened[12]) const { - flattened[0] = left_.x(); - flattened[1] = left_.y(); - flattened[2] = left_.z(); - flattened[3] = top_.x(); - flattened[4] = top_.y(); - flattened[5] = top_.z(); - flattened[6] = right_.x(); - flattened[7] = right_.y(); - flattened[8] = right_.z(); - flattened[9] = bottom_.x(); - flattened[10] = bottom_.y(); - flattened[11] = bottom_.z(); + if (left_.degenerate()) { + flattened[0] = bottom_.x(); + flattened[1] = bottom_.y(); + flattened[2] = bottom_.z(); + } else { + flattened[0] = left_.x(); + flattened[1] = left_.y(); + flattened[2] = left_.z(); + } + if (top_.degenerate()) { + flattened[3] = left_.x(); + flattened[4] = left_.y(); + flattened[5] = left_.z(); + } else { + flattened[3] = top_.x(); + flattened[4] = top_.y(); + flattened[5] = top_.z(); + } + if (right_.degenerate()) { + flattened[6] = top_.x(); + flattened[7] = top_.y(); + flattened[8] = top_.z(); + } else { + flattened[6] = right_.x(); + flattened[7] = right_.y(); + flattened[8] = right_.z(); + } + if (bottom_.degenerate()) { + flattened[9] = right_.x(); + flattened[10] = right_.y(); + flattened[11] = right_.z(); + } else { + flattened[9] = bottom_.x(); + flattened[10] = bottom_.y(); + flattened[11] = bottom_.z(); + } } } // namespace cc
diff --git a/cc/resources/layer_quad.h b/cc/resources/layer_quad.h index ed1db10..7433645 100644 --- a/cc/resources/layer_quad.h +++ b/cc/resources/layer_quad.h
@@ -22,7 +22,7 @@ public: class Edge { public: - Edge() : x_(0), y_(0), z_(0) {} + Edge() : x_(0), y_(0), z_(0), degenerate_(false) {} Edge(const gfx::PointF& p, const gfx::PointF& q); float x() const { return x_; } @@ -57,6 +57,8 @@ } void scale(float s) { scale(s, s, s); } + bool degenerate() const { return degenerate_; } + gfx::PointF Intersect(const Edge& e) const { return gfx::PointF( (y() * e.z() - e.y() * z()) / (x() * e.y() - e.x() * y()), @@ -67,6 +69,7 @@ float x_; float y_; float z_; + bool degenerate_; }; LayerQuad(const Edge& left,
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc index 30c5845..867a86a 100644 --- a/cc/resources/picture.cc +++ b/cc/resources/picture.cc
@@ -4,9 +4,8 @@ #include "cc/resources/picture.h" -#include <algorithm> -#include <limits> #include <set> +#include <string> #include "base/base64.h" #include "base/trace_event/trace_event.h" @@ -59,18 +58,18 @@ const gfx::Size& tile_grid_size, bool gather_pixel_refs, RecordingSource::RecordingMode recording_mode) { - scoped_refptr<Picture> picture = make_scoped_refptr(new Picture(layer_rect)); + scoped_refptr<Picture> picture = + make_scoped_refptr(new Picture(layer_rect, tile_grid_size)); - picture->Record(client, tile_grid_size, recording_mode); + picture->Record(client, recording_mode); if (gather_pixel_refs) - picture->GatherPixelRefs(tile_grid_size); + picture->GatherPixelRefs(); return picture; } -Picture::Picture(const gfx::Rect& layer_rect) - : layer_rect_(layer_rect), - cell_size_(layer_rect.size()) { +Picture::Picture(const gfx::Rect& layer_rect, const gfx::Size& tile_grid_size) + : layer_rect_(layer_rect), pixel_refs_(tile_grid_size) { // Instead of recording a trace event for object creation here, we wait for // the picture to be recorded in Picture::Record. } @@ -127,16 +126,13 @@ Picture::Picture(SkPicture* picture, const gfx::Rect& layer_rect) : layer_rect_(layer_rect), picture_(skia::AdoptRef(picture)), - cell_size_(layer_rect.size()) { + pixel_refs_(layer_rect.size()) { } Picture::Picture(const skia::RefPtr<SkPicture>& picture, const gfx::Rect& layer_rect, - const PixelRefMap& pixel_refs) : - layer_rect_(layer_rect), - picture_(picture), - pixel_refs_(pixel_refs), - cell_size_(layer_rect.size()) { + const PixelRefMap& pixel_refs) + : layer_rect_(layer_rect), picture_(picture), pixel_refs_(pixel_refs) { } Picture::~Picture() { @@ -169,7 +165,6 @@ } void Picture::Record(ContentLayerClient* painter, - const gfx::Size& tile_grid_size, RecordingSource::RecordingMode recording_mode) { TRACE_EVENT2("cc", "Picture::Record", @@ -179,9 +174,7 @@ recording_mode); DCHECK(!picture_); - DCHECK(!tile_grid_size.IsEmpty()); - // TODO(mtklein): If SkRTree sticks, clean up tile_grid_info. skbug.com/3085 SkRTreeFactory factory; SkPictureRecorder recorder; @@ -235,7 +228,7 @@ EmitTraceSnapshot(); } -void Picture::GatherPixelRefs(const gfx::Size& tile_grid_size) { +void Picture::GatherPixelRefs() { TRACE_EVENT2("cc", "Picture::GatherPixelRefs", "width", layer_rect_.width(), "height", layer_rect_.height()); @@ -244,46 +237,8 @@ DCHECK(pixel_refs_.empty()); if (!WillPlayBackBitmaps()) return; - cell_size_ = tile_grid_size; - DCHECK_GT(cell_size_.width(), 0); - DCHECK_GT(cell_size_.height(), 0); - int min_x = std::numeric_limits<int>::max(); - int min_y = std::numeric_limits<int>::max(); - int max_x = 0; - int max_y = 0; - - skia::DiscardablePixelRefList pixel_refs; - skia::PixelRefUtils::GatherDiscardablePixelRefs(picture_.get(), &pixel_refs); - for (skia::DiscardablePixelRefList::const_iterator it = pixel_refs.begin(); - it != pixel_refs.end(); - ++it) { - gfx::Point min( - RoundDown(static_cast<int>(it->pixel_ref_rect.x()), - cell_size_.width()), - RoundDown(static_cast<int>(it->pixel_ref_rect.y()), - cell_size_.height())); - gfx::Point max( - RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.right())), - cell_size_.width()), - RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())), - cell_size_.height())); - - for (int y = min.y(); y <= max.y(); y += cell_size_.height()) { - for (int x = min.x(); x <= max.x(); x += cell_size_.width()) { - PixelRefMapKey key(x, y); - pixel_refs_[key].push_back(it->pixel_ref); - } - } - - min_x = std::min(min_x, min.x()); - min_y = std::min(min_y, min.y()); - max_x = std::max(max_x, max.x()); - max_y = std::max(max_y, max.y()); - } - - min_pixel_cell_ = gfx::Point(min_x, min_y); - max_pixel_cell_ = gfx::Point(max_x, max_y); + pixel_refs_.GatherPixelRefsFromPicture(picture_.get()); } int Picture::Raster(SkCanvas* canvas, @@ -361,104 +316,9 @@ TracedPicture::AsTraceablePictureAlias(original)); } -base::LazyInstance<Picture::PixelRefs> - Picture::PixelRefIterator::empty_pixel_refs_; - -Picture::PixelRefIterator::PixelRefIterator() - : picture_(NULL), - current_pixel_refs_(empty_pixel_refs_.Pointer()), - current_index_(0), - min_point_(-1, -1), - max_point_(-1, -1), - current_x_(0), - current_y_(0) { -} - -Picture::PixelRefIterator::PixelRefIterator( - const gfx::Rect& rect, - const Picture* picture) - : picture_(picture), - current_pixel_refs_(empty_pixel_refs_.Pointer()), - current_index_(0) { - gfx::Rect layer_rect = picture->layer_rect_; - gfx::Size cell_size = picture->cell_size_; - DCHECK(!cell_size.IsEmpty()); - - gfx::Rect query_rect(rect); - // 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); - current_x_ = 1; - current_y_ = 1; - return; - } - - // First, subtract the layer origin as cells are stored in layer space. - query_rect.Offset(-layer_rect.OffsetFromOrigin()); - - // We have to find a cell_size aligned point that corresponds to - // query_rect. Point is a multiple of cell_size. - min_point_ = gfx::Point( - RoundDown(query_rect.x(), cell_size.width()), - RoundDown(query_rect.y(), cell_size.height())); - max_point_ = gfx::Point( - RoundDown(query_rect.right() - 1, cell_size.width()), - RoundDown(query_rect.bottom() - 1, cell_size.height())); - - // Limit the points to known pixel ref boundaries. - min_point_ = gfx::Point( - std::max(min_point_.x(), picture->min_pixel_cell_.x()), - std::max(min_point_.y(), picture->min_pixel_cell_.y())); - max_point_ = gfx::Point( - std::min(max_point_.x(), picture->max_pixel_cell_.x()), - std::min(max_point_.y(), picture->max_pixel_cell_.y())); - - // Make the current x be cell_size.width() less than min point, so that - // the first increment will point at min_point_. - current_x_ = min_point_.x() - cell_size.width(); - current_y_ = min_point_.y(); - if (current_y_ <= max_point_.y()) - ++(*this); -} - -Picture::PixelRefIterator::~PixelRefIterator() { -} - -Picture::PixelRefIterator& Picture::PixelRefIterator::operator++() { - ++current_index_; - // If we're not at the end of the list, then we have the next item. - if (current_index_ < current_pixel_refs_->size()) - return *this; - - DCHECK(current_y_ <= max_point_.y()); - while (true) { - gfx::Size cell_size = picture_->cell_size_; - - // Advance the current grid cell. - current_x_ += cell_size.width(); - if (current_x_ > max_point_.x()) { - current_y_ += cell_size.height(); - current_x_ = min_point_.x(); - if (current_y_ > max_point_.y()) { - current_pixel_refs_ = empty_pixel_refs_.Pointer(); - current_index_ = 0; - break; - } - } - - // If there are no pixel refs at this grid cell, keep incrementing. - PixelRefMapKey key(current_x_, current_y_); - PixelRefMap::const_iterator iter = picture_->pixel_refs_.find(key); - if (iter == picture_->pixel_refs_.end()) - continue; - - // We found a non-empty list: store it and get the first pixel ref. - current_pixel_refs_ = &iter->second; - current_index_ = 0; - break; - } - return *this; +PixelRefMap::Iterator Picture::GetPixelRefMapIterator( + const gfx::Rect& layer_rect) const { + return PixelRefMap::Iterator(layer_rect, this); } scoped_refptr<base::trace_event::ConvertableToTraceFormat>
diff --git a/cc/resources/picture.h b/cc/resources/picture.h index 089838c..ecbbaee 100644 --- a/cc/resources/picture.h +++ b/cc/resources/picture.h
@@ -5,10 +5,6 @@ #ifndef CC_RESOURCES_PICTURE_H_ #define CC_RESOURCES_PICTURE_H_ -#include <string> -#include <utility> -#include <vector> - #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/lazy_instance.h" @@ -18,6 +14,7 @@ #include "base/trace_event/trace_event.h" #include "cc/base/cc_export.h" #include "cc/base/region.h" +#include "cc/resources/pixel_ref_map.h" #include "cc/resources/recording_source.h" #include "skia/ext/refptr.h" #include "third_party/skia/include/core/SkPicture.h" @@ -40,10 +37,6 @@ class CC_EXPORT Picture : public base::RefCountedThreadSafe<Picture> { public: - typedef std::pair<int, int> PixelRefMapKey; - typedef std::vector<SkPixelRef*> PixelRefs; - typedef base::hash_map<PixelRefMapKey, PixelRefs> PixelRefMap; - static scoped_refptr<Picture> Create( const gfx::Rect& layer_rect, ContentLayerClient* client, @@ -79,49 +72,16 @@ scoped_ptr<base::Value> AsValue() const; - // This iterator imprecisely returns the set of pixel refs that are needed to - // raster this layer rect from this picture. Internally, pixel refs are - // clumped into tile grid buckets, so there may be false positives. - class CC_EXPORT PixelRefIterator { - public: - PixelRefIterator(); - PixelRefIterator(const gfx::Rect& layer_rect, const Picture* picture); - ~PixelRefIterator(); - - SkPixelRef* operator->() const { - DCHECK_LT(current_index_, current_pixel_refs_->size()); - return (*current_pixel_refs_)[current_index_]; - } - - SkPixelRef* operator*() const { - DCHECK_LT(current_index_, current_pixel_refs_->size()); - return (*current_pixel_refs_)[current_index_]; - } - - PixelRefIterator& operator++(); - operator bool() const { - return current_index_ < current_pixel_refs_->size(); - } - - private: - static base::LazyInstance<PixelRefs> empty_pixel_refs_; - const Picture* picture_; - const PixelRefs* current_pixel_refs_; - unsigned current_index_; - - gfx::Point min_point_; - gfx::Point max_point_; - int current_x_; - int current_y_; - }; - void EmitTraceSnapshot() const; void EmitTraceSnapshotAlias(Picture* original) const; bool WillPlayBackBitmaps() const { return picture_->willPlayBackBitmaps(); } + PixelRefMap::Iterator GetPixelRefMapIterator( + const gfx::Rect& layer_rect) const; + private: - explicit Picture(const gfx::Rect& layer_rect); + Picture(const gfx::Rect& layer_rect, const gfx::Size& tile_grid_size); // This constructor assumes SkPicture is already ref'd and transfers // ownership to this picture. Picture(const skia::RefPtr<SkPicture>&, @@ -134,19 +94,15 @@ // 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 gfx::Size& tile_grid_size, RecordingSource::RecordingMode recording_mode); // Gather pixel refs from recording. - void GatherPixelRefs(const gfx::Size& tile_grid_info); + void GatherPixelRefs(); gfx::Rect layer_rect_; skia::RefPtr<SkPicture> picture_; PixelRefMap pixel_refs_; - gfx::Point min_pixel_cell_; - gfx::Point max_pixel_cell_; - gfx::Size cell_size_; scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsTraceableRasterData(float scale) const; @@ -154,7 +110,7 @@ AsTraceableRecordData() const; friend class base::RefCountedThreadSafe<Picture>; - friend class PixelRefIterator; + friend class PixelRefMap::Iterator; DISALLOW_COPY_AND_ASSIGN(Picture); };
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc index a9bad90..e5f217b 100644 --- a/cc/resources/picture_pile_impl.cc +++ b/cc/resources/picture_pile_impl.cc
@@ -455,7 +455,7 @@ continue; processed_pictures_.insert(picture); - pixel_ref_iterator_ = Picture::PixelRefIterator(layer_rect_, picture); + pixel_ref_iterator_ = picture->GetPixelRefMapIterator(layer_rect_); if (pixel_ref_iterator_) break; }
diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h index c35dd0f..b144a79 100644 --- a/cc/resources/picture_pile_impl.h +++ b/cc/resources/picture_pile_impl.h
@@ -13,6 +13,7 @@ #include "cc/base/cc_export.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/resources/picture_pile.h" +#include "cc/resources/pixel_ref_map.h" #include "cc/resources/raster_source.h" #include "skia/ext/analysis_canvas.h" #include "skia/ext/refptr.h" @@ -87,7 +88,7 @@ const PicturePileImpl* picture_pile_; gfx::Rect layer_rect_; TilingData::Iterator tile_iterator_; - Picture::PixelRefIterator pixel_ref_iterator_; + PixelRefMap::Iterator pixel_ref_iterator_; std::set<const void*> processed_pictures_; };
diff --git a/cc/resources/picture_unittest.cc b/cc/resources/picture_unittest.cc index 1e2ba44..b53765c 100644 --- a/cc/resources/picture_unittest.cc +++ b/cc/resources/picture_unittest.cc
@@ -85,269 +85,6 @@ EXPECT_EQ(0, memcmp(two_rect_buffer, two_rect_buffer_check, 4 * 100 * 100)); } -TEST(PictureTest, PixelRefIterator) { - gfx::Rect layer_rect(2048, 2048); - - gfx::Size tile_grid_size(512, 512); - - FakeContentLayerClient content_layer_client; - - // Discardable pixel refs are found in the following grids: - // |---|---|---|---| - // | | x | | x | - // |---|---|---|---| - // | x | | x | | - // |---|---|---|---| - // | | x | | x | - // |---|---|---|---| - // | x | | x | | - // |---|---|---|---| - SkBitmap discardable_bitmap[4][4]; - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - if ((x + y) & 1) { - CreateBitmap( - gfx::Size(500, 500), "discardable", &discardable_bitmap[y][x]); - SkPaint paint; - content_layer_client.add_draw_bitmap( - discardable_bitmap[y][x], - gfx::Point(x * 512 + 6, y * 512 + 6), paint); - } - } - } - - scoped_refptr<Picture> picture = - Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true, - RecordingSource::RECORD_NORMALLY); - - // Default iterator does not have any pixel refs - { - Picture::PixelRefIterator iterator; - EXPECT_FALSE(iterator); - } - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - Picture::PixelRefIterator iterator(gfx::Rect(x * 512, y * 512, 500, 500), - picture.get()); - if ((x + y) & 1) { - EXPECT_TRUE(iterator) << x << " " << y; - EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef()) << x << - " " << y; - EXPECT_FALSE(++iterator) << x << " " << y; - } else { - EXPECT_FALSE(iterator) << x << " " << y; - } - } - } - // Capture 4 pixel refs. - { - Picture::PixelRefIterator iterator(gfx::Rect(512, 512, 2048, 2048), - picture.get()); - EXPECT_TRUE(iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); - EXPECT_FALSE(++iterator); - } - - // Copy test. - Picture::PixelRefIterator iterator(gfx::Rect(512, 512, 2048, 2048), - picture.get()); - EXPECT_TRUE(iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); - - // copy now points to the same spot as iterator, - // but both can be incremented independently. - Picture::PixelRefIterator copy = iterator; - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); - EXPECT_FALSE(++iterator); - - EXPECT_TRUE(copy); - EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef()); - EXPECT_TRUE(++copy); - EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef()); - EXPECT_TRUE(++copy); - EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef()); - EXPECT_FALSE(++copy); -} - -TEST(PictureTest, PixelRefIteratorNonZeroLayer) { - gfx::Rect layer_rect(1024, 0, 2048, 2048); - - gfx::Size tile_grid_size(512, 512); - - FakeContentLayerClient content_layer_client; - - // Discardable pixel refs are found in the following grids: - // |---|---|---|---| - // | | x | | x | - // |---|---|---|---| - // | x | | x | | - // |---|---|---|---| - // | | x | | x | - // |---|---|---|---| - // | x | | x | | - // |---|---|---|---| - SkBitmap discardable_bitmap[4][4]; - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - if ((x + y) & 1) { - CreateBitmap( - gfx::Size(500, 500), "discardable", &discardable_bitmap[y][x]); - SkPaint paint; - content_layer_client.add_draw_bitmap( - discardable_bitmap[y][x], - gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint); - } - } - } - - scoped_refptr<Picture> picture = - Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true, - RecordingSource::RECORD_NORMALLY); - - // Default iterator does not have any pixel refs - { - Picture::PixelRefIterator iterator; - EXPECT_FALSE(iterator); - } - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - Picture::PixelRefIterator iterator( - gfx::Rect(1024 + x * 512, y * 512, 500, 500), picture.get()); - if ((x + y) & 1) { - EXPECT_TRUE(iterator) << x << " " << y; - EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef()); - EXPECT_FALSE(++iterator) << x << " " << y; - } else { - EXPECT_FALSE(iterator) << x << " " << y; - } - } - } - // Capture 4 pixel refs. - { - Picture::PixelRefIterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048), - picture.get()); - EXPECT_TRUE(iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); - EXPECT_FALSE(++iterator); - } - - // Copy test. - { - Picture::PixelRefIterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048), - picture.get()); - EXPECT_TRUE(iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); - - // copy now points to the same spot as iterator, - // but both can be incremented independently. - Picture::PixelRefIterator copy = iterator; - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); - EXPECT_TRUE(++iterator); - EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); - EXPECT_FALSE(++iterator); - - EXPECT_TRUE(copy); - EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef()); - EXPECT_TRUE(++copy); - EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef()); - EXPECT_TRUE(++copy); - EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef()); - EXPECT_FALSE(++copy); - } - - // Non intersecting rects - { - Picture::PixelRefIterator iterator(gfx::Rect(0, 0, 1000, 1000), - picture.get()); - EXPECT_FALSE(iterator); - } - { - Picture::PixelRefIterator iterator(gfx::Rect(3500, 0, 1000, 1000), - picture.get()); - EXPECT_FALSE(iterator); - } - { - Picture::PixelRefIterator iterator(gfx::Rect(0, 1100, 1000, 1000), - picture.get()); - EXPECT_FALSE(iterator); - } - { - Picture::PixelRefIterator iterator(gfx::Rect(3500, 1100, 1000, 1000), - picture.get()); - EXPECT_FALSE(iterator); - } -} - -TEST(PictureTest, PixelRefIteratorOnePixelQuery) { - gfx::Rect layer_rect(2048, 2048); - - gfx::Size tile_grid_size(512, 512); - - FakeContentLayerClient content_layer_client; - - // Discardable pixel refs are found in the following grids: - // |---|---|---|---| - // | | x | | x | - // |---|---|---|---| - // | x | | x | | - // |---|---|---|---| - // | | x | | x | - // |---|---|---|---| - // | x | | x | | - // |---|---|---|---| - SkBitmap discardable_bitmap[4][4]; - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - if ((x + y) & 1) { - CreateBitmap( - gfx::Size(500, 500), "discardable", &discardable_bitmap[y][x]); - SkPaint paint; - content_layer_client.add_draw_bitmap( - discardable_bitmap[y][x], - gfx::Point(x * 512 + 6, y * 512 + 6), paint); - } - } - } - - scoped_refptr<Picture> picture = - Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true, - RecordingSource::RECORD_NORMALLY); - - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - Picture::PixelRefIterator iterator( - gfx::Rect(x * 512, y * 512 + 256, 1, 1), picture.get()); - if ((x + y) & 1) { - EXPECT_TRUE(iterator) << x << " " << y; - EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef()); - EXPECT_FALSE(++iterator) << x << " " << y; - } else { - EXPECT_FALSE(iterator) << x << " " << y; - } - } - } -} - TEST(PictureTest, CreateFromSkpValue) { SkGraphics::Init();
diff --git a/cc/resources/pixel_ref_map.cc b/cc/resources/pixel_ref_map.cc new file mode 100644 index 0000000..dc50851 --- /dev/null +++ b/cc/resources/pixel_ref_map.cc
@@ -0,0 +1,158 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/pixel_ref_map.h" + +#include <algorithm> +#include <limits> + +#include "cc/base/util.h" +#include "cc/resources/picture.h" +#include "skia/ext/pixel_ref_utils.h" + +namespace cc { + +PixelRefMap::PixelRefMap(const gfx::Size& cell_size) : cell_size_(cell_size) { + DCHECK(!cell_size.IsEmpty()); +} + +PixelRefMap::~PixelRefMap() { +} + +void PixelRefMap::GatherPixelRefsFromPicture(SkPicture* picture) { + DCHECK(picture); + + int min_x = std::numeric_limits<int>::max(); + int min_y = std::numeric_limits<int>::max(); + int max_x = 0; + int max_y = 0; + + skia::DiscardablePixelRefList pixel_refs; + skia::PixelRefUtils::GatherDiscardablePixelRefs(picture, &pixel_refs); + for (skia::DiscardablePixelRefList::const_iterator it = pixel_refs.begin(); + it != pixel_refs.end(); ++it) { + gfx::Point min( + RoundDown(static_cast<int>(it->pixel_ref_rect.x()), cell_size_.width()), + RoundDown(static_cast<int>(it->pixel_ref_rect.y()), + cell_size_.height())); + gfx::Point max( + RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.right())), + cell_size_.width()), + RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())), + cell_size_.height())); + + for (int y = min.y(); y <= max.y(); y += cell_size_.height()) { + for (int x = min.x(); x <= max.x(); x += cell_size_.width()) { + PixelRefMapKey key(x, y); + data_hash_map_[key].push_back(it->pixel_ref); + } + } + + min_x = std::min(min_x, min.x()); + min_y = std::min(min_y, min.y()); + max_x = std::max(max_x, max.x()); + max_y = std::max(max_y, max.y()); + } + + min_pixel_cell_ = gfx::Point(min_x, min_y); + max_pixel_cell_ = gfx::Point(max_x, max_y); +} + +base::LazyInstance<PixelRefs> PixelRefMap::Iterator::empty_pixel_refs_; + +PixelRefMap::Iterator::Iterator() + : target_pixel_ref_map_(NULL), + current_pixel_refs_(empty_pixel_refs_.Pointer()), + current_index_(0), + min_point_(-1, -1), + max_point_(-1, -1), + current_x_(0), + current_y_(0) { +} + +PixelRefMap::Iterator::Iterator(const gfx::Rect& rect, const Picture* picture) + : target_pixel_ref_map_(&(picture->pixel_refs_)), + current_pixel_refs_(empty_pixel_refs_.Pointer()), + current_index_(0) { + gfx::Rect layer_rect = picture->layer_rect_; + gfx::Size cell_size = target_pixel_ref_map_->cell_size_; + DCHECK(!cell_size.IsEmpty()); + gfx::Rect query_rect(rect); + // 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); + current_x_ = 1; + current_y_ = 1; + return; + } + + // First, subtract the layer origin as cells are stored in layer space. + query_rect.Offset(-layer_rect.OffsetFromOrigin()); + + // We have to find a cell_size aligned point that corresponds to + // query_rect. Point is a multiple of cell_size. + min_point_ = gfx::Point(RoundDown(query_rect.x(), cell_size.width()), + RoundDown(query_rect.y(), cell_size.height())); + max_point_ = + gfx::Point(RoundDown(query_rect.right() - 1, cell_size.width()), + RoundDown(query_rect.bottom() - 1, cell_size.height())); + + // Limit the points to known pixel ref boundaries. + min_point_ = gfx::Point( + std::max(min_point_.x(), target_pixel_ref_map_->min_pixel_cell_.x()), + std::max(min_point_.y(), target_pixel_ref_map_->min_pixel_cell_.y())); + max_point_ = gfx::Point( + std::min(max_point_.x(), target_pixel_ref_map_->max_pixel_cell_.x()), + std::min(max_point_.y(), target_pixel_ref_map_->max_pixel_cell_.y())); + + // Make the current x be cell_size.width() less than min point, so that + // the first increment will point at min_point_. + current_x_ = min_point_.x() - cell_size.width(); + current_y_ = min_point_.y(); + if (current_y_ <= max_point_.y()) + ++(*this); +} + +PixelRefMap::Iterator::~Iterator() { +} + +PixelRefMap::Iterator& PixelRefMap::Iterator::operator++() { + ++current_index_; + // If we're not at the end of the list, then we have the next item. + if (current_index_ < current_pixel_refs_->size()) + return *this; + + DCHECK(current_y_ <= max_point_.y()); + while (true) { + gfx::Size cell_size = target_pixel_ref_map_->cell_size_; + + // Advance the current grid cell. + current_x_ += cell_size.width(); + if (current_x_ > max_point_.x()) { + current_y_ += cell_size.height(); + current_x_ = min_point_.x(); + if (current_y_ > max_point_.y()) { + current_pixel_refs_ = empty_pixel_refs_.Pointer(); + current_index_ = 0; + break; + } + } + + // If there are no pixel refs at this grid cell, keep incrementing. + PixelRefMapKey key(current_x_, current_y_); + PixelRefHashmap::const_iterator iter = + target_pixel_ref_map_->data_hash_map_.find(key); + if (iter == target_pixel_ref_map_->data_hash_map_.end()) + continue; + + // We found a non-empty list: store it and get the first pixel ref. + current_pixel_refs_ = &iter->second; + current_index_ = 0; + break; + } + return *this; +} + +} // namespace cc
diff --git a/cc/resources/pixel_ref_map.h b/cc/resources/pixel_ref_map.h new file mode 100644 index 0000000..f50a841 --- /dev/null +++ b/cc/resources/pixel_ref_map.h
@@ -0,0 +1,90 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_RESOURCES_PIXEL_REF_MAP_H_ +#define CC_RESOURCES_PIXEL_REF_MAP_H_ + +#include <utility> +#include <vector> + +#include "base/containers/hash_tables.h" +#include "base/lazy_instance.h" +#include "base/memory/ref_counted.h" +#include "cc/base/cc_export.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" + +class SkPixelRef; + +namespace cc { + +class Picture; + +typedef std::pair<int, int> PixelRefMapKey; +typedef std::vector<SkPixelRef*> PixelRefs; +typedef base::hash_map<PixelRefMapKey, PixelRefs> PixelRefHashmap; + +// This class is used and owned by cc Picture class. It is used to gather pixel +// refs which would happen after record. It takes in |cell_size| to decide how +// big each grid cell should be. +class CC_EXPORT PixelRefMap { + public: + explicit PixelRefMap(const gfx::Size& cell_size); + ~PixelRefMap(); + void GatherPixelRefsFromPicture(SkPicture* picture); + + bool empty() const { return data_hash_map_.empty(); } + + // This iterator imprecisely returns the set of pixel refs that are needed to + // raster this layer rect from this picture. Internally, pixel refs are + // clumped into tile grid buckets, so there may be false positives. + class CC_EXPORT Iterator { + public: + // Default iterator constructor that is used as place holder for invalid + // Iterator. + Iterator(); + Iterator(const gfx::Rect& layer_rect, const Picture* picture); + ~Iterator(); + + SkPixelRef* operator->() const { + DCHECK_LT(current_index_, current_pixel_refs_->size()); + return (*current_pixel_refs_)[current_index_]; + } + + SkPixelRef* operator*() const { + DCHECK_LT(current_index_, current_pixel_refs_->size()); + return (*current_pixel_refs_)[current_index_]; + } + + Iterator& operator++(); + operator bool() const { + return current_index_ < current_pixel_refs_->size(); + } + + private: + static base::LazyInstance<PixelRefs> empty_pixel_refs_; + const PixelRefMap* target_pixel_ref_map_; + const PixelRefs* current_pixel_refs_; + unsigned current_index_; + + gfx::Rect layer_rect_; + + gfx::Point min_point_; + gfx::Point max_point_; + int current_x_; + int current_y_; + }; + + private: + gfx::Point min_pixel_cell_; + gfx::Point max_pixel_cell_; + gfx::Size cell_size_; + + PixelRefHashmap data_hash_map_; +}; + +} // namespace cc + +#endif // CC_RESOURCES_PIXEL_REF_MAP_H_
diff --git a/cc/resources/pixel_ref_map_unittest.cc b/cc/resources/pixel_ref_map_unittest.cc new file mode 100644 index 0000000..4c40336 --- /dev/null +++ b/cc/resources/pixel_ref_map_unittest.cc
@@ -0,0 +1,292 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/resources/pixel_ref_map.h" + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/values.h" +#include "cc/resources/picture.h" +#include "cc/test/fake_content_layer_client.h" +#include "cc/test/skia_common.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkGraphics.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/skia_util.h" + +namespace cc { +namespace { + +TEST(PixelRefMapTest, PixelRefMapIterator) { + gfx::Rect layer_rect(2048, 2048); + + gfx::Size tile_grid_size(512, 512); + + FakeContentLayerClient content_layer_client; + + // Discardable pixel refs are found in the following grids: + // |---|---|---|---| + // | | x | | x | + // |---|---|---|---| + // | x | | x | | + // |---|---|---|---| + // | | x | | x | + // |---|---|---|---| + // | x | | x | | + // |---|---|---|---| + SkBitmap discardable_bitmap[4][4]; + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + if ((x + y) & 1) { + CreateBitmap(gfx::Size(500, 500), "discardable", + &discardable_bitmap[y][x]); + SkPaint paint; + content_layer_client.add_draw_bitmap( + discardable_bitmap[y][x], gfx::Point(x * 512 + 6, y * 512 + 6), + paint); + } + } + } + + scoped_refptr<Picture> picture = + Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true, + RecordingSource::RECORD_NORMALLY); + + // Default iterator does not have any pixel refs. + { + PixelRefMap::Iterator iterator; + EXPECT_FALSE(iterator); + } + + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + PixelRefMap::Iterator iterator(gfx::Rect(x * 512, y * 512, 500, 500), + picture.get()); + if ((x + y) & 1) { + EXPECT_TRUE(iterator) << x << " " << y; + EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef()) + << x << " " << y; + EXPECT_FALSE(++iterator) << x << " " << y; + } else { + EXPECT_FALSE(iterator) << x << " " << y; + } + } + } + // Capture 4 pixel refs. + { + PixelRefMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048), + picture.get()); + EXPECT_TRUE(iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); + EXPECT_FALSE(++iterator); + } + + // Copy test. + PixelRefMap::Iterator iterator(gfx::Rect(512, 512, 2048, 2048), + picture.get()); + EXPECT_TRUE(iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); + + // copy now points to the same spot as iterator, + // but both can be incremented independently. + PixelRefMap::Iterator copy = iterator; + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); + EXPECT_FALSE(++iterator); + + EXPECT_TRUE(copy); + EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef()); + EXPECT_TRUE(++copy); + EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef()); + EXPECT_TRUE(++copy); + EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef()); + EXPECT_FALSE(++copy); +} + +TEST(PixelRefMapTest, PixelRefMapIteratorNonZeroLayer) { + gfx::Rect layer_rect(1024, 0, 2048, 2048); + + gfx::Size tile_grid_size(512, 512); + + FakeContentLayerClient content_layer_client; + + // Discardable pixel refs are found in the following grids: + // |---|---|---|---| + // | | x | | x | + // |---|---|---|---| + // | x | | x | | + // |---|---|---|---| + // | | x | | x | + // |---|---|---|---| + // | x | | x | | + // |---|---|---|---| + SkBitmap discardable_bitmap[4][4]; + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + if ((x + y) & 1) { + CreateBitmap(gfx::Size(500, 500), "discardable", + &discardable_bitmap[y][x]); + SkPaint paint; + content_layer_client.add_draw_bitmap( + discardable_bitmap[y][x], + gfx::Point(1024 + x * 512 + 6, y * 512 + 6), paint); + } + } + } + + scoped_refptr<Picture> picture = + Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true, + RecordingSource::RECORD_NORMALLY); + + // Default iterator does not have any pixel refs. + { + PixelRefMap::Iterator iterator; + EXPECT_FALSE(iterator); + } + + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + PixelRefMap::Iterator iterator( + gfx::Rect(1024 + x * 512, y * 512, 500, 500), picture.get()); + if ((x + y) & 1) { + EXPECT_TRUE(iterator) << x << " " << y; + EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef()); + EXPECT_FALSE(++iterator) << x << " " << y; + } else { + EXPECT_FALSE(iterator) << x << " " << y; + } + } + } + // Capture 4 pixel refs. + { + PixelRefMap::Iterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048), + picture.get()); + EXPECT_TRUE(iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); + EXPECT_FALSE(++iterator); + } + + // Copy test. + { + PixelRefMap::Iterator iterator(gfx::Rect(1024 + 512, 512, 2048, 2048), + picture.get()); + EXPECT_TRUE(iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[1][2].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][1].pixelRef()); + + // copy now points to the same spot as iterator, + // but both can be incremented independently. + PixelRefMap::Iterator copy = iterator; + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[2][3].pixelRef()); + EXPECT_TRUE(++iterator); + EXPECT_TRUE(*iterator == discardable_bitmap[3][2].pixelRef()); + EXPECT_FALSE(++iterator); + + EXPECT_TRUE(copy); + EXPECT_TRUE(*copy == discardable_bitmap[2][1].pixelRef()); + EXPECT_TRUE(++copy); + EXPECT_TRUE(*copy == discardable_bitmap[2][3].pixelRef()); + EXPECT_TRUE(++copy); + EXPECT_TRUE(*copy == discardable_bitmap[3][2].pixelRef()); + EXPECT_FALSE(++copy); + } + + // Non intersecting rects + { + PixelRefMap::Iterator iterator(gfx::Rect(0, 0, 1000, 1000), picture.get()); + EXPECT_FALSE(iterator); + } + { + PixelRefMap::Iterator iterator(gfx::Rect(3500, 0, 1000, 1000), + picture.get()); + EXPECT_FALSE(iterator); + } + { + PixelRefMap::Iterator iterator(gfx::Rect(0, 1100, 1000, 1000), + picture.get()); + EXPECT_FALSE(iterator); + } + { + PixelRefMap::Iterator iterator(gfx::Rect(3500, 1100, 1000, 1000), + picture.get()); + EXPECT_FALSE(iterator); + } +} + +TEST(PixelRefMapTest, PixelRefMapIteratorOnePixelQuery) { + gfx::Rect layer_rect(2048, 2048); + + gfx::Size tile_grid_size(512, 512); + + FakeContentLayerClient content_layer_client; + + // Discardable pixel refs are found in the following grids: + // |---|---|---|---| + // | | x | | x | + // |---|---|---|---| + // | x | | x | | + // |---|---|---|---| + // | | x | | x | + // |---|---|---|---| + // | x | | x | | + // |---|---|---|---| + SkBitmap discardable_bitmap[4][4]; + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + if ((x + y) & 1) { + CreateBitmap(gfx::Size(500, 500), "discardable", + &discardable_bitmap[y][x]); + SkPaint paint; + content_layer_client.add_draw_bitmap( + discardable_bitmap[y][x], gfx::Point(x * 512 + 6, y * 512 + 6), + paint); + } + } + } + + scoped_refptr<Picture> picture = + Picture::Create(layer_rect, &content_layer_client, tile_grid_size, true, + RecordingSource::RECORD_NORMALLY); + + // Default iterator does not have any pixel refs. + { + PixelRefMap::Iterator iterator; + EXPECT_FALSE(iterator); + } + + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + PixelRefMap::Iterator iterator(gfx::Rect(x * 512, y * 512 + 256, 1, 1), + picture.get()); + if ((x + y) & 1) { + EXPECT_TRUE(iterator) << x << " " << y; + EXPECT_TRUE(*iterator == discardable_bitmap[y][x].pixelRef()); + EXPECT_FALSE(++iterator) << x << " " << y; + } else { + EXPECT_FALSE(iterator) << x << " " << y; + } + } + } +} + +} // namespace +} // namespace cc
diff --git a/cc/resources/platform_color.h b/cc/resources/platform_color.h index 4945dcc..17eddc1 100644 --- a/cc/resources/platform_color.h +++ b/cc/resources/platform_color.h
@@ -8,8 +8,6 @@ #include "base/basictypes.h" #include "base/logging.h" #include "cc/resources/resource_format.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/skia/include/core/SkTypes.h" namespace cc {
diff --git a/cc/resources/resource.h b/cc/resources/resource.h index 707d77e..edafaef 100644 --- a/cc/resources/resource.h +++ b/cc/resources/resource.h
@@ -7,7 +7,6 @@ #include "cc/base/cc_export.h" #include "cc/resources/resource_provider.h" -#include "third_party/khronos/GLES2/gl2.h" #include "ui/gfx/geometry/size.h" namespace cc {
diff --git a/cc/resources/tile.cc b/cc/resources/tile.cc index 1576047..f86330e 100644 --- a/cc/resources/tile.cc +++ b/cc/resources/tile.cc
@@ -10,7 +10,6 @@ #include "cc/base/math_util.h" #include "cc/debug/traced_value.h" #include "cc/resources/tile_manager.h" -#include "third_party/khronos/GLES2/gl2.h" namespace cc {
diff --git a/cc/resources/tile_task_worker_pool_unittest.cc b/cc/resources/tile_task_worker_pool_unittest.cc index d7cb155..72f9d20 100644 --- a/cc/resources/tile_task_worker_pool_unittest.cc +++ b/cc/resources/tile_task_worker_pool_unittest.cc
@@ -28,6 +28,7 @@ #include "cc/test/test_gpu_memory_buffer_manager.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_web_graphics_context_3d.h" +#include "gpu/GLES2/gl2extchromium.h" #include "testing/gtest/include/gtest/gtest.h" namespace cc { @@ -275,6 +276,14 @@ return completed_tasks_; } + void LoseContext(ContextProvider* context_provider) { + if (!context_provider) + return; + context_provider->ContextGL()->LoseContextCHROMIUM( + GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); + context_provider->ContextGL()->Flush(); + } + private: void Create3dOutputSurfaceAndResourceProvider() { output_surface_ = FakeOutputSurface::Create3d( @@ -404,6 +413,21 @@ RunMessageLoopUntilAllTasksHaveCompleted(); } +TEST_P(TileTaskWorkerPoolTest, LostContext) { + LoseContext(output_surface_->context_provider()); + LoseContext(output_surface_->worker_context_provider()); + + AppendTask(0u); + AppendTask(1u); + ScheduleTasks(); + + RunMessageLoopUntilAllTasksHaveCompleted(); + + ASSERT_EQ(2u, completed_tasks().size()); + EXPECT_FALSE(completed_tasks()[0].canceled); + EXPECT_FALSE(completed_tasks()[1].canceled); +} + INSTANTIATE_TEST_CASE_P( TileTaskWorkerPoolTests, TileTaskWorkerPoolTest,
diff --git a/cc/resources/tiling_set_raster_queue_all.cc b/cc/resources/tiling_set_raster_queue_all.cc index c4d949c..2ccba67 100644 --- a/cc/resources/tiling_set_raster_queue_all.cc +++ b/cc/resources/tiling_set_raster_queue_all.cc
@@ -112,6 +112,137 @@ } } +// OnePriorityRectIterator +TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator() + : tile_(nullptr), tiling_(nullptr), tiling_data_(nullptr) { +} + +TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator( + PictureLayerTiling* tiling, + TilingData* tiling_data) + : tile_(nullptr), tiling_(tiling), tiling_data_(tiling_data) { +} + +template <typename TilingIteratorType> +void TilingSetRasterQueueAll::OnePriorityRectIterator::AdvanceToNextTile( + TilingIteratorType* iterator) { + tile_ = nullptr; + while (!tile_ || !TileNeedsRaster(tile_)) { + ++(*iterator); + if (!(*iterator)) { + tile_ = nullptr; + return; + } + tile_ = tiling_->TileAt(iterator->index_x(), iterator->index_y()); + } + tiling_->UpdateTileAndTwinPriority(tile_); +} + +template <typename TilingIteratorType> +bool TilingSetRasterQueueAll::OnePriorityRectIterator:: + GetFirstTileAndCheckIfValid(TilingIteratorType* iterator) { + tile_ = tiling_->TileAt(iterator->index_x(), iterator->index_y()); + if (!tile_ || !TileNeedsRaster(tile_)) { + tile_ = nullptr; + return false; + } + tiling_->UpdateTileAndTwinPriority(tile_); + return true; +} + +// VisibleTilingIterator. +TilingSetRasterQueueAll::VisibleTilingIterator::VisibleTilingIterator( + PictureLayerTiling* tiling, + TilingData* tiling_data) + : OnePriorityRectIterator(tiling, tiling_data) { + if (!tiling_->has_visible_rect_tiles()) + return; + iterator_ = + TilingData::Iterator(tiling_data_, tiling_->current_visible_rect(), + false /* include_borders */); + if (!iterator_) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) + ++(*this); +} + +TilingSetRasterQueueAll::VisibleTilingIterator& + TilingSetRasterQueueAll::VisibleTilingIterator:: + operator++() { + AdvanceToNextTile(&iterator_); + return *this; +} + +// SkewportTilingIterator. +TilingSetRasterQueueAll::SkewportTilingIterator::SkewportTilingIterator( + PictureLayerTiling* tiling, + TilingData* tiling_data) + : OnePriorityRectIterator(tiling, tiling_data) { + if (!tiling_->has_skewport_rect_tiles()) + return; + iterator_ = TilingData::SpiralDifferenceIterator( + tiling_data_, tiling_->current_skewport_rect(), + tiling_->current_visible_rect(), tiling_->current_visible_rect()); + if (!iterator_) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) + ++(*this); +} + +TilingSetRasterQueueAll::SkewportTilingIterator& + TilingSetRasterQueueAll::SkewportTilingIterator:: + operator++() { + AdvanceToNextTile(&iterator_); + return *this; +} + +// SoonBorderTilingIterator. +TilingSetRasterQueueAll::SoonBorderTilingIterator::SoonBorderTilingIterator( + PictureLayerTiling* tiling, + TilingData* tiling_data) + : OnePriorityRectIterator(tiling, tiling_data) { + if (!tiling_->has_soon_border_rect_tiles()) + return; + iterator_ = TilingData::SpiralDifferenceIterator( + tiling_data_, tiling_->current_soon_border_rect(), + tiling_->current_skewport_rect(), tiling_->current_visible_rect()); + if (!iterator_) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) + ++(*this); +} + +TilingSetRasterQueueAll::SoonBorderTilingIterator& + TilingSetRasterQueueAll::SoonBorderTilingIterator:: + operator++() { + AdvanceToNextTile(&iterator_); + return *this; +} + +// EventuallyTilingIterator. +TilingSetRasterQueueAll::EventuallyTilingIterator::EventuallyTilingIterator( + PictureLayerTiling* tiling, + TilingData* tiling_data) + : OnePriorityRectIterator(tiling, tiling_data) { + if (!tiling_->has_eventually_rect_tiles()) + return; + iterator_ = TilingData::SpiralDifferenceIterator( + tiling_data_, tiling_->current_eventually_rect(), + tiling_->current_skewport_rect(), tiling_->current_soon_border_rect()); + if (!iterator_) + return; + if (!GetFirstTileAndCheckIfValid(&iterator_)) + ++(*this); +} + +TilingSetRasterQueueAll::EventuallyTilingIterator& + TilingSetRasterQueueAll::EventuallyTilingIterator:: + operator++() { + AdvanceToNextTile(&iterator_); + return *this; +} + +// TilingIterator TilingSetRasterQueueAll::TilingIterator::TilingIterator() : tiling_(NULL), current_tile_(NULL) { } @@ -123,125 +254,80 @@ tiling_data_(tiling_data), phase_(VISIBLE_RECT), current_tile_(NULL) { - if (!tiling_->has_visible_rect_tiles()) { + visible_iterator_ = VisibleTilingIterator(tiling_, tiling_data_); + if (visible_iterator_.done()) { AdvancePhase(); return; } - - visible_iterator_ = - TilingData::Iterator(tiling_data_, tiling_->current_visible_rect(), - false /* include_borders */); - if (!visible_iterator_) { - AdvancePhase(); - return; - } - - current_tile_ = - tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); - if (!current_tile_ || !TileNeedsRaster(current_tile_)) { - ++(*this); - return; - } - tiling_->UpdateTileAndTwinPriority(current_tile_); -} - -TilingSetRasterQueueAll::TilingIterator::~TilingIterator() { + current_tile_ = *visible_iterator_; } void TilingSetRasterQueueAll::TilingIterator::AdvancePhase() { DCHECK_LT(phase_, EVENTUALLY_RECT); - do { + current_tile_ = nullptr; + while (!current_tile_ && phase_ < EVENTUALLY_RECT) { phase_ = static_cast<Phase>(phase_ + 1); switch (phase_) { case VISIBLE_RECT: NOTREACHED(); return; case SKEWPORT_RECT: - if (!tiling_->has_skewport_rect_tiles()) - continue; - - spiral_iterator_ = TilingData::SpiralDifferenceIterator( - tiling_data_, tiling_->current_skewport_rect(), - tiling_->current_visible_rect(), tiling_->current_visible_rect()); + skewport_iterator_ = SkewportTilingIterator(tiling_, tiling_data_); + if (!skewport_iterator_.done()) + current_tile_ = *skewport_iterator_; break; case SOON_BORDER_RECT: - if (!tiling_->has_soon_border_rect_tiles()) - continue; - - spiral_iterator_ = TilingData::SpiralDifferenceIterator( - tiling_data_, tiling_->current_soon_border_rect(), - tiling_->current_skewport_rect(), tiling_->current_visible_rect()); + soon_border_iterator_ = SoonBorderTilingIterator(tiling_, tiling_data_); + if (!soon_border_iterator_.done()) + current_tile_ = *soon_border_iterator_; break; case EVENTUALLY_RECT: - if (!tiling_->has_eventually_rect_tiles()) { - current_tile_ = NULL; - return; - } - - spiral_iterator_ = TilingData::SpiralDifferenceIterator( - tiling_data_, tiling_->current_eventually_rect(), - tiling_->current_skewport_rect(), - tiling_->current_soon_border_rect()); + eventually_iterator_ = EventuallyTilingIterator(tiling_, tiling_data_); + if (!eventually_iterator_.done()) + current_tile_ = *eventually_iterator_; break; } - - while (spiral_iterator_) { - current_tile_ = tiling_->TileAt(spiral_iterator_.index_x(), - spiral_iterator_.index_y()); - if (current_tile_ && TileNeedsRaster(current_tile_)) - break; - ++spiral_iterator_; - } - - if (!spiral_iterator_ && phase_ == EVENTUALLY_RECT) { - current_tile_ = NULL; - break; - } - } while (!spiral_iterator_); - - if (current_tile_) - tiling_->UpdateTileAndTwinPriority(current_tile_); + } } TilingSetRasterQueueAll::TilingIterator& TilingSetRasterQueueAll::TilingIterator:: operator++() { - current_tile_ = NULL; - while (!current_tile_ || !TileNeedsRaster(current_tile_)) { - std::pair<int, int> next_index; - switch (phase_) { - case VISIBLE_RECT: - ++visible_iterator_; - if (!visible_iterator_) { - AdvancePhase(); - return *this; - } - next_index = visible_iterator_.index(); - break; - case SKEWPORT_RECT: - case SOON_BORDER_RECT: - ++spiral_iterator_; - if (!spiral_iterator_) { - AdvancePhase(); - return *this; - } - next_index = spiral_iterator_.index(); - break; - case EVENTUALLY_RECT: - ++spiral_iterator_; - if (!spiral_iterator_) { - current_tile_ = NULL; - return *this; - } - next_index = spiral_iterator_.index(); - break; - } - current_tile_ = tiling_->TileAt(next_index.first, next_index.second); + switch (phase_) { + case VISIBLE_RECT: + ++visible_iterator_; + if (visible_iterator_.done()) { + AdvancePhase(); + return *this; + } + current_tile_ = *visible_iterator_; + break; + case SKEWPORT_RECT: + ++skewport_iterator_; + if (skewport_iterator_.done()) { + AdvancePhase(); + return *this; + } + current_tile_ = *skewport_iterator_; + break; + case SOON_BORDER_RECT: + ++soon_border_iterator_; + if (soon_border_iterator_.done()) { + AdvancePhase(); + return *this; + } + current_tile_ = *soon_border_iterator_; + break; + case EVENTUALLY_RECT: + ++eventually_iterator_; + if (eventually_iterator_.done()) { + current_tile_ = nullptr; + return *this; + } + current_tile_ = *eventually_iterator_; + break; } - - if (current_tile_) - tiling_->UpdateTileAndTwinPriority(current_tile_); return *this; }
diff --git a/cc/resources/tiling_set_raster_queue_all.h b/cc/resources/tiling_set_raster_queue_all.h index 5577c6c..ebca838 100644 --- a/cc/resources/tiling_set_raster_queue_all.h +++ b/cc/resources/tiling_set_raster_queue_all.h
@@ -26,12 +26,90 @@ bool IsEmpty() const; private: + // Helper base class for individual region iterators. + class OnePriorityRectIterator { + public: + OnePriorityRectIterator(); + OnePriorityRectIterator(PictureLayerTiling* tiling, + TilingData* tiling_data); + + bool done() const { return !tile_; } + Tile* operator*() const { return tile_; } + + protected: + ~OnePriorityRectIterator() = default; + bool TileNeedsRaster(Tile* tile) const { + return tile->NeedsRaster() && !tiling_->IsTileOccluded(tile); + } + + template <typename TilingIteratorType> + void AdvanceToNextTile(TilingIteratorType* iterator); + template <typename TilingIteratorType> + bool GetFirstTileAndCheckIfValid(TilingIteratorType* iterator); + + Tile* tile_; + PictureLayerTiling* tiling_; + TilingData* tiling_data_; + }; + + // Iterates over visible rect only, left to right top to bottom order. + class VisibleTilingIterator : public OnePriorityRectIterator { + public: + VisibleTilingIterator() = default; + VisibleTilingIterator(PictureLayerTiling* tiling, TilingData* tiling_data); + + VisibleTilingIterator& operator++(); + + private: + TilingData::Iterator iterator_; + }; + + // Iterates over skewport only, spiral around the visible rect. + class SkewportTilingIterator : public OnePriorityRectIterator { + public: + SkewportTilingIterator() = default; + SkewportTilingIterator(PictureLayerTiling* tiling, TilingData* tiling_data); + + SkewportTilingIterator& operator++(); + + private: + TilingData::SpiralDifferenceIterator iterator_; + }; + + // Iterates over soon border only, spiral around the visible rect. + class SoonBorderTilingIterator : public OnePriorityRectIterator { + public: + SoonBorderTilingIterator() = default; + SoonBorderTilingIterator(PictureLayerTiling* tiling, + TilingData* tiling_data); + + SoonBorderTilingIterator& operator++(); + + private: + TilingData::SpiralDifferenceIterator iterator_; + }; + + // Iterates over eventually rect only, spiral around the soon rect. + class EventuallyTilingIterator : public OnePriorityRectIterator { + public: + EventuallyTilingIterator() = default; + EventuallyTilingIterator(PictureLayerTiling* tiling, + TilingData* tiling_data); + + EventuallyTilingIterator& operator++(); + + private: + TilingData::SpiralDifferenceIterator iterator_; + }; + + // Iterates over all of the above phases in the following order: visible, + // skewport, soon border, eventually. class TilingIterator { public: TilingIterator(); explicit TilingIterator(PictureLayerTiling* tiling, TilingData* tiling_data); - ~TilingIterator(); + ~TilingIterator() = default; bool done() const { return current_tile_ == nullptr; } const Tile* operator*() const { return current_tile_; } @@ -61,9 +139,6 @@ }; void AdvancePhase(); - bool TileNeedsRaster(Tile* tile) const { - return tile->NeedsRaster() && !tiling_->IsTileOccluded(tile); - } PictureLayerTiling* tiling_; TilingData* tiling_data_; @@ -71,8 +146,10 @@ Phase phase_; Tile* current_tile_; - TilingData::Iterator visible_iterator_; - TilingData::SpiralDifferenceIterator spiral_iterator_; + VisibleTilingIterator visible_iterator_; + SkewportTilingIterator skewport_iterator_; + SoonBorderTilingIterator soon_border_iterator_; + EventuallyTilingIterator eventually_iterator_; }; enum IteratorType { LOW_RES, HIGH_RES, NUM_ITERATORS };
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h index 1bccf79..df9951a 100644 --- a/cc/resources/video_resource_updater.h +++ b/cc/resources/video_resource_updater.h
@@ -61,13 +61,13 @@ ~VideoFrameExternalResources(); }; -// VideoResourceUpdater is by the video system to produce frame content as +// VideoResourceUpdater is used by the video system to produce frame content as // resources consumable by the compositor. class CC_EXPORT VideoResourceUpdater : public base::SupportsWeakPtr<VideoResourceUpdater> { public: - explicit VideoResourceUpdater(ContextProvider* context_provider, - ResourceProvider* resource_provider); + VideoResourceUpdater(ContextProvider* context_provider, + ResourceProvider* resource_provider); ~VideoResourceUpdater(); VideoFrameExternalResources CreateExternalResourcesFromVideoFrame(
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index a6f15f0..4f00ff3 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -251,12 +251,12 @@ // Contributing passes aggregated in to the pass list need to take the // transform of the surface quad into account to update their transform to // the root surface. - // TODO(jamesr): Make sure this is sufficient for surfaces nested several - // levels deep and add tests. copy_pass->transform_to_root_target.ConcatTransform( surface_quad->quadTransform()); copy_pass->transform_to_root_target.ConcatTransform( content_to_target_transform); + copy_pass->transform_to_root_target.ConcatTransform( + dest_pass->transform_to_root_target); CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, gfx::Transform(), ClipData(), copy_pass.get(), surface_id);
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc index 1dff7ec..cf54568 100644 --- a/cc/surfaces/surface_aggregator_unittest.cc +++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -939,9 +939,13 @@ } // Root surface. - test::Quad root_quads[] = {test::Quad::SolidColorQuad(1), - test::Quad::SurfaceQuad(middle_surface_id, 1.f)}; - test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; + test::Quad secondary_quads[] = { + test::Quad::SolidColorQuad(1), + test::Quad::SurfaceQuad(middle_surface_id, 1.f)}; + test::Quad root_quads[] = {test::Quad::SolidColorQuad(1)}; + test::Pass root_passes[] = { + test::Pass(secondary_quads, arraysize(secondary_quads)), + test::Pass(root_quads, arraysize(root_quads))}; RenderPassList root_pass_list; AddPasses(&root_pass_list, @@ -958,6 +962,8 @@ root_pass_list.at(0)->quad_list.ElementAt(1)->visible_rect = gfx::Rect(0, 0, 8, 100); + root_pass_list[0]->transform_to_root_target.Translate(10, 5); + scoped_ptr<DelegatedFrameData> root_frame_data(new DelegatedFrameData); root_pass_list.swap(root_frame_data->render_pass_list); @@ -977,17 +983,19 @@ const RenderPassList& aggregated_pass_list = frame_data->render_pass_list; - ASSERT_EQ(2u, aggregated_pass_list.size()); + ASSERT_EQ(3u, aggregated_pass_list.size()); ASSERT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size()); // The first pass should have one shared quad state for the one solid color // quad. EXPECT_EQ(1u, aggregated_pass_list[0]->shared_quad_state_list.size()); - // The second (root) pass should have just two shared quad states. We'll + // The second pass should have just two shared quad states. We'll // verify the properties through the quads. EXPECT_EQ(2u, aggregated_pass_list[1]->shared_quad_state_list.size()); + EXPECT_EQ(1u, aggregated_pass_list[2]->shared_quad_state_list.size()); + SharedQuadState* aggregated_first_pass_sqs = aggregated_pass_list[0]->shared_quad_state_list.front(); @@ -999,8 +1007,9 @@ aggregated_first_pass_sqs->content_to_target_transform.ToString()); // The first pass's transform to the root target should include the aggregated - // transform. + // transform, including the transform from the child pass to the root. gfx::Transform expected_first_pass_transform_to_root_target; + expected_first_pass_transform_to_root_target.Translate(10, 5); expected_first_pass_transform_to_root_target.Translate(0, 10); expected_first_pass_transform_to_root_target.Scale(2, 3); expected_first_pass_transform_to_root_target.Translate(8, 0);
diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc index 88e166c..ac60271 100644 --- a/cc/surfaces/surface_display_output_surface.cc +++ b/cc/surfaces/surface_display_output_surface.cc
@@ -25,9 +25,6 @@ capabilities_.delegated_rendering = true; capabilities_.max_frames_pending = 1; capabilities_.can_force_reclaim_resources = true; - // Frame always needs to be swapped because forced resource reclaiming - // destroys the Display's copy. - capabilities_.draw_and_swap_full_viewport_every_frame = true; } SurfaceDisplayOutputSurface::~SurfaceDisplayOutputSurface() {
diff --git a/cc/test/data/anti_aliasing.png b/cc/test/data/anti_aliasing.png index 4abe9e1..eba7436 100644 --- a/cc/test/data/anti_aliasing.png +++ b/cc/test/data/anti_aliasing.png Binary files differ
diff --git a/cc/test/data/background_filter_blur_off_axis.png b/cc/test/data/background_filter_blur_off_axis.png index 5077171..5e9a0c2 100644 --- a/cc/test/data/background_filter_blur_off_axis.png +++ b/cc/test/data/background_filter_blur_off_axis.png Binary files differ
diff --git a/cc/test/data/intersecting_blue_green.png b/cc/test/data/intersecting_blue_green.png new file mode 100644 index 0000000..8262071 --- /dev/null +++ b/cc/test/data/intersecting_blue_green.png Binary files differ
diff --git a/cc/test/data/intersecting_blue_green_squares.png b/cc/test/data/intersecting_blue_green_squares.png new file mode 100644 index 0000000..22da4d3 --- /dev/null +++ b/cc/test/data/intersecting_blue_green_squares.png Binary files differ
diff --git a/cc/test/data/intersecting_blue_green_squares_video.png b/cc/test/data/intersecting_blue_green_squares_video.png new file mode 100644 index 0000000..e1bea4f --- /dev/null +++ b/cc/test/data/intersecting_blue_green_squares_video.png Binary files differ
diff --git a/cc/test/data/mask_of_background_filter.png b/cc/test/data/mask_of_background_filter.png index 2a96d49..35a9b93 100644 --- a/cc/test/data/mask_of_background_filter.png +++ b/cc/test/data/mask_of_background_filter.png Binary files differ
diff --git a/cc/test/data/mask_of_layer_with_blend.png b/cc/test/data/mask_of_layer_with_blend.png index 35faaba..1f2bedd 100644 --- a/cc/test/data/mask_of_layer_with_blend.png +++ b/cc/test/data/mask_of_layer_with_blend.png Binary files differ
diff --git a/cc/test/fake_impl_proxy.h b/cc/test/fake_impl_proxy.h index b9408c8..69eb5d2 100644 --- a/cc/test/fake_impl_proxy.h +++ b/cc/test/fake_impl_proxy.h
@@ -12,7 +12,9 @@ class FakeImplProxy : public FakeProxy { public: - FakeImplProxy() : set_impl_thread_(this) {} + FakeImplProxy() + : FakeProxy(base::MessageLoopProxy::current(), nullptr), + set_impl_thread_(this) {} explicit FakeImplProxy( scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
diff --git a/cc/test/fake_proxy.cc b/cc/test/fake_proxy.cc index b288c07..9c24162 100644 --- a/cc/test/fake_proxy.cc +++ b/cc/test/fake_proxy.cc
@@ -42,7 +42,4 @@ return false; } -void FakeProxy::AsValueInto(base::trace_event::TracedValue*) const { -} - } // namespace cc
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h index 2309fef..d5ad313 100644 --- a/cc/test/fake_proxy.h +++ b/cc/test/fake_proxy.h
@@ -46,7 +46,6 @@ bool SupportsImplScrolling() const override; void SetDebugState(const LayerTreeDebugState& debug_state) override {} bool MainFrameWillHappenForTesting() override; - void AsValueInto(base::trace_event::TracedValue* state) const override; void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override {} virtual RendererCapabilities& GetRendererCapabilities();
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 9690362..3c6ff57 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -350,7 +350,7 @@ LayerTreeHostImpl::UpdateAnimationState(start_ready_animations); bool has_unfinished_animation = false; for (const auto& it : - animation_registrar()->active_animation_controllers()) { + animation_registrar()->active_animation_controllers_for_testing()) { if (it.second->HasActiveAnimation()) { has_unfinished_animation = true; break;
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc index bf85ea3..7c9bb2c 100644 --- a/cc/test/test_context_provider.cc +++ b/cc/test/test_context_provider.cc
@@ -104,6 +104,11 @@ gl_context->makeCurrent(); gr_context_ = skia::AdoptRef(GrContext::Create( kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(gl_context->gl()))); + + // If GlContext is already lost, also abandon the new GrContext. + if (IsContextLost()) + gr_context_->abandonContext(); + return gr_context_.get(); } @@ -151,6 +156,8 @@ } if (!lost_context_callback_.is_null()) base::ResetAndReturn(&lost_context_callback_).Run(); + if (gr_context_) + gr_context_->abandonContext(); } TestWebGraphicsContext3D* TestContextProvider::TestContext3d() {
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index 9f20bb8..6d8ccf7 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc
@@ -71,6 +71,7 @@ bound_buffer_(0), weak_ptr_factory_(this) { CreateNamespace(); + set_support_image(true); } TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index 1e6d2c7..41aa81b 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -38,7 +38,7 @@ const TransformNode* clip_transform_node = transform_tree.Node(clip_node->data.transform_id); const TransformNode* target_node = - transform_tree.Node(transform_node->data.target_id); + transform_tree.Node(transform_node->data.content_target_id); gfx::Transform clip_to_target; gfx::Transform content_to_target;
diff --git a/cc/trees/layer_sorter.cc b/cc/trees/layer_sorter.cc deleted file mode 100644 index bde4920..0000000 --- a/cc/trees/layer_sorter.cc +++ /dev/null
@@ -1,470 +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/trees/layer_sorter.h" - -#include <algorithm> -#include <deque> -#include <limits> -#include <vector> - -#include "base/logging.h" -#include "cc/base/math_util.h" -#include "cc/layers/render_surface_impl.h" -#include "ui/gfx/transform.h" - -namespace cc { - -// This epsilon is used to determine if two layers are too close to each other -// to be able to tell which is in front of the other. It's a relative epsilon -// so it is robust to changes in scene scale. This value was chosen by picking -// a value near machine epsilon and then increasing it until the flickering on -// the test scene went away. -const float k_layer_epsilon = 1e-4f; - -inline static float PerpProduct(const gfx::Vector2dF& u, - const gfx::Vector2dF& v) { - return u.x() * v.y() - u.y() * v.x(); -} - -// Tests if two edges defined by their endpoints (a,b) and (c,d) intersect. -// Returns true and the point of intersection if they do and false otherwise. -static bool EdgeEdgeTest(const gfx::PointF& a, - const gfx::PointF& b, - const gfx::PointF& c, - const gfx::PointF& d, - gfx::PointF* r) { - gfx::Vector2dF u = b - a; - gfx::Vector2dF v = d - c; - gfx::Vector2dF w = a - c; - - float denom = PerpProduct(u, v); - - // If denom == 0 then the edges are parallel. While they could be overlapping - // we don't bother to check here as the we'll find their intersections from - // the corner to quad tests. - if (!denom) - return false; - - float s = PerpProduct(v, w) / denom; - if (s < 0.f || s > 1.f) - return false; - - float t = PerpProduct(u, w) / denom; - if (t < 0.f || t > 1.f) - return false; - - u.Scale(s); - *r = a + u; - return true; -} - -GraphNode::GraphNode(LayerImpl* layer_impl) - : layer(layer_impl), - incoming_edge_weight(0.f) {} - -GraphNode::~GraphNode() {} - -LayerSorter::LayerSorter() - : z_range_(0.f) {} - -LayerSorter::~LayerSorter() {} - -static float CheckFloatingPointNumericAccuracy(float a, float b) { - float abs_dif = std::abs(b - a); - float abs_max = std::max(std::abs(b), std::abs(a)); - // Check to see if we've got a result with a reasonable amount of error. - return abs_dif / abs_max; -} - -// Checks whether layer "a" draws on top of layer "b". The weight value returned -// is an indication of the maximum z-depth difference between the layers or zero -// if the layers are found to be intesecting (some features are in front and -// some are behind). -LayerSorter::ABCompareResult LayerSorter::CheckOverlap(LayerShape* a, - LayerShape* b, - float z_threshold, - float* weight) { - *weight = 0.f; - - // Early out if the projected bounds don't overlap. - if (!a->projected_bounds.Intersects(b->projected_bounds)) - return NONE; - - gfx::PointF aPoints[4] = { a->projected_quad.p1(), - a->projected_quad.p2(), - a->projected_quad.p3(), - a->projected_quad.p4() }; - gfx::PointF bPoints[4] = { b->projected_quad.p1(), - b->projected_quad.p2(), - b->projected_quad.p3(), - b->projected_quad.p4() }; - - // Make a list of points that inside both layer quad projections. - std::vector<gfx::PointF> overlap_points; - - // Check all four corners of one layer against the other layer's quad. - for (int i = 0; i < 4; ++i) { - if (a->projected_quad.Contains(bPoints[i])) - overlap_points.push_back(bPoints[i]); - if (b->projected_quad.Contains(aPoints[i])) - overlap_points.push_back(aPoints[i]); - } - - // Check all the edges of one layer for intersection with the other layer's - // edges. - gfx::PointF r; - for (int ea = 0; ea < 4; ++ea) - for (int eb = 0; eb < 4; ++eb) - if (EdgeEdgeTest(aPoints[ea], aPoints[(ea + 1) % 4], - bPoints[eb], bPoints[(eb + 1) % 4], - &r)) - overlap_points.push_back(r); - - if (overlap_points.empty()) - return NONE; - - // Check the corresponding layer depth value for all overlap points to - // determine which layer is in front. - float max_positive = 0.f; - float max_negative = 0.f; - - // This flag tracks the existance of a numerically accurate seperation - // between two layers. If there is no accurate seperation, the layers - // cannot be effectively sorted. - bool accurate = false; - - for (size_t o = 0; o < overlap_points.size(); o++) { - float za = a->LayerZFromProjectedPoint(overlap_points[o]); - float zb = b->LayerZFromProjectedPoint(overlap_points[o]); - - // Here we attempt to avoid numeric issues with layers that are too - // close together. If we have 2-sided quads that are very close - // together then we will draw them in document order to avoid - // flickering. The correct solution is for the content maker to turn - // on back-face culling or move the quads apart (if they're not two - // sides of one object). - if (CheckFloatingPointNumericAccuracy(za, zb) > k_layer_epsilon) - accurate = true; - - float diff = za - zb; - if (diff > max_positive) - max_positive = diff; - if (diff < max_negative) - max_negative = diff; - } - - // If we can't tell which should come first, we use document order. - if (!accurate) - return A_BEFORE_B; - - float max_diff = - std::abs(max_positive) > std::abs(max_negative) ? - max_positive : max_negative; - - // If the results are inconsistent (and the z difference substantial to rule - // out numerical errors) then the layers are intersecting. We will still - // return an order based on the maximum depth difference but with an edge - // weight of zero these layers will get priority if a graph cycle is present - // and needs to be broken. - if (max_positive > z_threshold && max_negative < -z_threshold) - *weight = 0.f; - else - *weight = std::abs(max_diff); - - // Maintain relative order if the layers have the same depth at all - // intersection points. - if (max_diff <= 0.f) - return A_BEFORE_B; - - return B_BEFORE_A; -} - -LayerShape::LayerShape() {} - -LayerShape::LayerShape(float width, - float height, - const gfx::Transform& draw_transform) { - gfx::QuadF layer_quad(gfx::RectF(0.f, 0.f, width, height)); - - // Compute the projection of the layer quad onto the z = 0 plane. - - gfx::PointF clipped_quad[8]; - int num_vertices_in_clipped_quad; - MathUtil::MapClippedQuad(draw_transform, - layer_quad, - clipped_quad, - &num_vertices_in_clipped_quad); - - if (num_vertices_in_clipped_quad < 3) { - projected_bounds = gfx::RectF(); - return; - } - - projected_bounds = - MathUtil::ComputeEnclosingRectOfVertices(clipped_quad, - num_vertices_in_clipped_quad); - - // NOTE: it will require very significant refactoring and overhead to deal - // with generalized polygons or multiple quads per layer here. For the sake of - // layer sorting it is equally correct to take a subsection of the polygon - // that can be made into a quad. This will only be incorrect in the case of - // intersecting layers, which are not supported yet anyway. - projected_quad.set_p1(clipped_quad[0]); - projected_quad.set_p2(clipped_quad[1]); - projected_quad.set_p3(clipped_quad[2]); - if (num_vertices_in_clipped_quad >= 4) { - projected_quad.set_p4(clipped_quad[3]); - } else { - // This will be a degenerate quad that is actually a triangle. - projected_quad.set_p4(clipped_quad[2]); - } - - // Compute the normal of the layer's plane. - bool clipped = false; - gfx::Point3F c1 = - MathUtil::MapPoint(draw_transform, gfx::Point3F(0.f, 0.f, 0.f), &clipped); - gfx::Point3F c2 = - MathUtil::MapPoint(draw_transform, gfx::Point3F(0.f, 1.f, 0.f), &clipped); - gfx::Point3F c3 = - MathUtil::MapPoint(draw_transform, gfx::Point3F(1.f, 0.f, 0.f), &clipped); - // TODO(shawnsingh): Deal with clipping. - gfx::Vector3dF c12 = c2 - c1; - gfx::Vector3dF c13 = c3 - c1; - layer_normal = gfx::CrossProduct(c13, c12); - - transform_origin = c1; -} - -LayerShape::~LayerShape() {} - -// Returns the Z coordinate of a point on the layer that projects -// to point p which lies on the z = 0 plane. It does it by computing the -// intersection of a line starting from p along the Z axis and the plane -// of the layer. -float LayerShape::LayerZFromProjectedPoint(const gfx::PointF& p) const { - gfx::Vector3dF z_axis(0.f, 0.f, 1.f); - gfx::Vector3dF w = gfx::Point3F(p) - transform_origin; - - float d = gfx::DotProduct(layer_normal, z_axis); - float n = -gfx::DotProduct(layer_normal, w); - - // Check if layer is parallel to the z = 0 axis which will make it - // invisible and hence returning zero is fine. - if (!d) - return 0.f; - - // The intersection point would be given by: - // p + (n / d) * u but since we are only interested in the - // z coordinate and p's z coord is zero, all we need is the value of n/d. - return n / d; -} - -void LayerSorter::CreateGraphNodes(LayerImplList::iterator first, - LayerImplList::iterator last) { - DVLOG(2) << "Creating graph nodes:"; - float min_z = FLT_MAX; - float max_z = -FLT_MAX; - for (LayerImplList::const_iterator it = first; it < last; it++) { - nodes_.push_back(GraphNode(*it)); - GraphNode& node = nodes_.at(nodes_.size() - 1); - RenderSurfaceImpl* render_surface = node.layer->render_surface(); - if (!node.layer->DrawsContent() && !render_surface) - continue; - - DVLOG(2) << "Layer " << node.layer->id() << - " (" << node.layer->bounds().width() << - " x " << node.layer->bounds().height() << ")"; - - gfx::Transform draw_transform; - float layer_width, layer_height; - if (render_surface) { - draw_transform = render_surface->draw_transform(); - layer_width = render_surface->content_rect().width(); - layer_height = render_surface->content_rect().height(); - } else { - draw_transform = node.layer->draw_transform(); - layer_width = node.layer->content_bounds().width(); - layer_height = node.layer->content_bounds().height(); - } - - node.shape = LayerShape(layer_width, layer_height, draw_transform); - - max_z = std::max(max_z, node.shape.transform_origin.z()); - min_z = std::min(min_z, node.shape.transform_origin.z()); - } - - z_range_ = std::abs(max_z - min_z); -} - -void LayerSorter::CreateGraphEdges() { - DVLOG(2) << "Edges:"; - // Fraction of the total z_range below which z differences - // are not considered reliable. - const float z_threshold_factor = 0.01f; - float z_threshold = z_range_ * z_threshold_factor; - - for (size_t na = 0; na < nodes_.size(); na++) { - GraphNode& node_a = nodes_[na]; - if (!node_a.layer->DrawsContent() && !node_a.layer->render_surface()) - continue; - for (size_t nb = na + 1; nb < nodes_.size(); nb++) { - GraphNode& node_b = nodes_[nb]; - if (!node_b.layer->DrawsContent() && !node_b.layer->render_surface()) - continue; - float weight = 0.f; - ABCompareResult overlap_result = CheckOverlap(&node_a.shape, - &node_b.shape, - z_threshold, - &weight); - GraphNode* start_node = NULL; - GraphNode* end_node = NULL; - if (overlap_result == A_BEFORE_B) { - start_node = &node_a; - end_node = &node_b; - } else if (overlap_result == B_BEFORE_A) { - start_node = &node_b; - end_node = &node_a; - } - - if (start_node) { - DVLOG(2) << start_node->layer->id() << " -> " << end_node->layer->id(); - edges_.push_back(GraphEdge(start_node, end_node, weight)); - } - } - } - - for (size_t i = 0; i < edges_.size(); i++) { - GraphEdge& edge = edges_[i]; - active_edges_[&edge] = &edge; - edge.from->outgoing.push_back(&edge); - edge.to->incoming.push_back(&edge); - edge.to->incoming_edge_weight += edge.weight; - } -} - -// Finds and removes an edge from the list by doing a swap with the -// last element of the list. -void LayerSorter::RemoveEdgeFromList(GraphEdge* edge, - std::vector<GraphEdge*>* list) { - std::vector<GraphEdge*>::iterator iter = - std::find(list->begin(), list->end(), edge); - DCHECK(iter != list->end()); - list->erase(iter); -} - -// Sorts the given list of layers such that they can be painted in a -// back-to-front order. Sorting produces correct results for non-intersecting -// layers that don't have cyclical order dependencies. Cycles and intersections -// are broken (somewhat) aribtrarily. Sorting of layers is done via a -// topological sort of a directed graph whose nodes are the layers themselves. -// An edge from node A to node B signifies that layer A needs to be drawn before -// layer B. If A and B have no dependency between each other, then we preserve -// the ordering of those layers as they were in the original list. -// -// The draw order between two layers is determined by projecting the two -// triangles making up each layer quad to the Z = 0 plane, finding points of -// intersection between the triangles and backprojecting those points to the -// plane of the layer to determine the corresponding Z coordinate. The layer -// with the lower Z coordinate (farther from the eye) needs to be rendered -// first. -// -// If the layer projections don't intersect, then no edges (dependencies) are -// created between them in the graph. HOWEVER, in this case we still need to -// preserve the ordering of the original list of layers, since that list should -// already have proper z-index ordering of layers. -// -void LayerSorter::Sort(LayerImplList::iterator first, - LayerImplList::iterator last) { - DVLOG(2) << "Sorting start ----"; - CreateGraphNodes(first, last); - - CreateGraphEdges(); - - std::vector<GraphNode*> sorted_list; - std::deque<GraphNode*> no_incoming_edge_node_list; - - // Find all the nodes that don't have incoming edges. - for (NodeList::iterator la = nodes_.begin(); la < nodes_.end(); la++) { - if (!la->incoming.size()) - no_incoming_edge_node_list.push_back(&(*la)); - } - - DVLOG(2) << "Sorted list: "; - while (active_edges_.size() || no_incoming_edge_node_list.size()) { - while (no_incoming_edge_node_list.size()) { - // It is necessary to preserve the existing ordering of layers, when there - // are no explicit dependencies (because this existing ordering has - // correct z-index/layout ordering). To preserve this ordering, we process - // Nodes in the same order that they were added to the list. - GraphNode* from_node = no_incoming_edge_node_list.front(); - no_incoming_edge_node_list.pop_front(); - - // Add it to the final list. - sorted_list.push_back(from_node); - - DVLOG(2) << from_node->layer->id() << ", "; - - // Remove all its outgoing edges from the graph. - for (size_t i = 0; i < from_node->outgoing.size(); i++) { - GraphEdge* outgoing_edge = from_node->outgoing[i]; - - active_edges_.erase(outgoing_edge); - RemoveEdgeFromList(outgoing_edge, &outgoing_edge->to->incoming); - outgoing_edge->to->incoming_edge_weight -= outgoing_edge->weight; - - if (!outgoing_edge->to->incoming.size()) - no_incoming_edge_node_list.push_back(outgoing_edge->to); - } - from_node->outgoing.clear(); - } - - if (!active_edges_.size()) - break; - - // If there are still active edges but the list of nodes without incoming - // edges is empty then we have run into a cycle. Break the cycle by finding - // the node with the smallest overall incoming edge weight and use it. This - // will favor nodes that have zero-weight incoming edges i.e. layers that - // are being occluded by a layer that intersects them. - float min_incoming_edge_weight = FLT_MAX; - GraphNode* next_node = NULL; - for (size_t i = 0; i < nodes_.size(); i++) { - if (nodes_[i].incoming.size() && - nodes_[i].incoming_edge_weight < min_incoming_edge_weight) { - min_incoming_edge_weight = nodes_[i].incoming_edge_weight; - next_node = &nodes_[i]; - } - } - DCHECK(next_node); - // Remove all its incoming edges. - for (size_t e = 0; e < next_node->incoming.size(); e++) { - GraphEdge* incoming_edge = next_node->incoming[e]; - - active_edges_.erase(incoming_edge); - RemoveEdgeFromList(incoming_edge, &incoming_edge->from->outgoing); - } - next_node->incoming.clear(); - next_node->incoming_edge_weight = 0.f; - no_incoming_edge_node_list.push_back(next_node); - DVLOG(2) << "Breaking cycle by cleaning up incoming edges from " << - next_node->layer->id() << - " (weight = " << min_incoming_edge_weight << ")"; - } - - // Note: The original elements of the list are in no danger of having their - // ref count go to zero here as they are all nodes of the layer hierarchy and - // are kept alive by their parent nodes. - int count = 0; - for (LayerImplList::iterator it = first; it < last; it++) - *it = sorted_list[count++]->layer; - - DVLOG(2) << "Sorting end ----"; - - nodes_.clear(); - edges_.clear(); - active_edges_.clear(); -} - -} // namespace cc
diff --git a/cc/trees/layer_sorter.h b/cc/trees/layer_sorter.h deleted file mode 100644 index 4cfa8fe..0000000 --- a/cc/trees/layer_sorter.h +++ /dev/null
@@ -1,97 +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_TREES_LAYER_SORTER_H_ -#define CC_TREES_LAYER_SORTER_H_ - -#include <vector> - -#include "base/basictypes.h" -#include "base/containers/hash_tables.h" -#include "cc/base/cc_export.h" -#include "cc/layers/layer_impl.h" -#include "ui/gfx/geometry/point3_f.h" -#include "ui/gfx/geometry/quad_f.h" -#include "ui/gfx/geometry/rect_f.h" -#include "ui/gfx/geometry/vector3d_f.h" - -namespace gfx { -class Transform; -} - -namespace cc { -struct GraphEdge; - -// Holds various useful properties derived from a layer's 3D outline. -struct CC_EXPORT LayerShape { - LayerShape(); - LayerShape(float width, float height, const gfx::Transform& draw_transform); - ~LayerShape(); - - float LayerZFromProjectedPoint(const gfx::PointF& p) const; - - gfx::Vector3dF layer_normal; - gfx::Point3F transform_origin; - gfx::QuadF projected_quad; - gfx::RectF projected_bounds; -}; - -struct GraphNode { - explicit GraphNode(LayerImpl* layer_impl); - ~GraphNode(); - - LayerImpl* layer; - LayerShape shape; - std::vector<GraphEdge*> incoming; - std::vector<GraphEdge*> outgoing; - float incoming_edge_weight; -}; - -struct GraphEdge { - GraphEdge(GraphNode* from_node, GraphNode* to_node, float weight) - : from(from_node), - to(to_node), - weight(weight) {} - - GraphNode* from; - GraphNode* to; - float weight; -}; - - - -class CC_EXPORT LayerSorter { - public: - LayerSorter(); - ~LayerSorter(); - - void Sort(LayerImplList::iterator first, LayerImplList::iterator last); - - enum ABCompareResult { A_BEFORE_B, B_BEFORE_A, NONE }; - - static ABCompareResult CheckOverlap(LayerShape* a, - LayerShape* b, - float z_threshold, - float* weight); - - private: - typedef std::vector<GraphNode> NodeList; - typedef std::vector<GraphEdge> EdgeList; - NodeList nodes_; - EdgeList edges_; - float z_range_; - - typedef base::hash_map<GraphEdge*, GraphEdge*> EdgeMap; - EdgeMap active_edges_; - - void CreateGraphNodes(LayerImplList::iterator first, - LayerImplList::iterator last); - void CreateGraphEdges(); - void RemoveEdgeFromList(GraphEdge* graph, std::vector<GraphEdge*>* list); - - DISALLOW_COPY_AND_ASSIGN(LayerSorter); -}; - -} // namespace cc -#endif // CC_TREES_LAYER_SORTER_H_
diff --git a/cc/trees/layer_sorter_unittest.cc b/cc/trees/layer_sorter_unittest.cc deleted file mode 100644 index 74d3cf5..0000000 --- a/cc/trees/layer_sorter_unittest.cc +++ /dev/null
@@ -1,329 +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/trees/layer_sorter.h" - -#include "cc/base/math_util.h" -#include "cc/layers/layer_impl.h" -#include "cc/test/fake_impl_proxy.h" -#include "cc/test/fake_layer_tree_host_impl.h" -#include "cc/test/test_shared_bitmap_manager.h" -#include "cc/trees/single_thread_proxy.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/transform.h" - -namespace cc { -namespace { - -// Note: In the following overlap tests, the "camera" is looking down the -// negative Z axis, meaning that layers with smaller z values (more negative) -// are further from the camera and therefore must be drawn before layers with -// higher z values. - -TEST(LayerSorterTest, BasicOverlap) { - LayerSorter::ABCompareResult overlap_result; - const float z_threshold = 0.1f; - float weight = 0.f; - - // Trivial test, with one layer directly obscuring the other. - gfx::Transform neg4_translate; - neg4_translate.Translate3d(0.0, 0.0, -4.0); - LayerShape front(2.f, 2.f, neg4_translate); - - gfx::Transform neg5_translate; - neg5_translate.Translate3d(0.0, 0.0, -5.0); - LayerShape back(2.f, 2.f, neg5_translate); - - overlap_result = - LayerSorter::CheckOverlap(&front, &back, z_threshold, &weight); - EXPECT_EQ(LayerSorter::B_BEFORE_A, overlap_result); - EXPECT_EQ(1.f, weight); - - overlap_result = - LayerSorter::CheckOverlap(&back, &front, z_threshold, &weight); - EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result); - EXPECT_EQ(1.f, weight); - - // One layer translated off to the right. No overlap should be detected. - gfx::Transform right_translate; - right_translate.Translate3d(10.0, 0.0, -5.0); - LayerShape back_right(2.f, 2.f, right_translate); - overlap_result = - LayerSorter::CheckOverlap(&front, &back_right, z_threshold, &weight); - EXPECT_EQ(LayerSorter::NONE, overlap_result); - - // When comparing a layer with itself, z difference is always 0. - overlap_result = - LayerSorter::CheckOverlap(&front, &front, z_threshold, &weight); - EXPECT_EQ(0.f, weight); -} - -TEST(LayerSorterTest, RightAngleOverlap) { - LayerSorter::ABCompareResult overlap_result; - const float z_threshold = 0.1f; - float weight = 0.f; - - gfx::Transform perspective_matrix; - perspective_matrix.ApplyPerspectiveDepth(1000.0); - - // Two layers forming a right angle with a perspective viewing transform. - gfx::Transform left_face_matrix; - left_face_matrix.Translate3d(-1.0, 0.0, -5.0); - left_face_matrix.RotateAboutYAxis(-90.0); - left_face_matrix.Translate(-1.0, -1.0); - LayerShape left_face(2.f, 2.f, perspective_matrix * left_face_matrix); - gfx::Transform front_face_matrix; - front_face_matrix.Translate3d(0.0, 0.0, -4.0); - front_face_matrix.Translate(-1.0, -1.0); - LayerShape front_face(2.f, 2.f, perspective_matrix * front_face_matrix); - - overlap_result = - LayerSorter::CheckOverlap(&front_face, &left_face, z_threshold, &weight); - EXPECT_EQ(LayerSorter::B_BEFORE_A, overlap_result); -} - -TEST(LayerSorterTest, IntersectingLayerOverlap) { - LayerSorter::ABCompareResult overlap_result; - const float z_threshold = 0.1f; - float weight = 0.f; - - gfx::Transform perspective_matrix; - perspective_matrix.ApplyPerspectiveDepth(1000.0); - - // Intersecting layers. An explicit order will be returned based on relative z - // values at the overlapping features but the weight returned should be zero. - gfx::Transform front_face_matrix; - front_face_matrix.Translate3d(0.0, 0.0, -4.0); - front_face_matrix.Translate(-1.0, -1.0); - LayerShape front_face(2.f, 2.f, perspective_matrix * front_face_matrix); - - gfx::Transform through_matrix; - through_matrix.Translate3d(0.0, 0.0, -4.0); - through_matrix.RotateAboutYAxis(45.0); - through_matrix.Translate(-1.0, -1.0); - LayerShape rotated_face(2.f, 2.f, perspective_matrix * through_matrix); - overlap_result = LayerSorter::CheckOverlap(&front_face, - &rotated_face, - z_threshold, - &weight); - EXPECT_NE(LayerSorter::NONE, overlap_result); - EXPECT_EQ(0.f, weight); -} - -TEST(LayerSorterTest, LayersAtAngleOverlap) { - LayerSorter::ABCompareResult overlap_result; - const float z_threshold = 0.1f; - float weight = 0.f; - - // Trickier test with layers at an angle. - // - // -x . . . . 0 . . . . +x - // -z / - // : /----B---- - // 0 C - // : ----A----/ - // +z / - // - // C is in front of A and behind B (not what you'd expect by comparing - // centers). A and B don't overlap, so they're incomparable. - - gfx::Transform transform_a; - transform_a.Translate3d(-6.0, 0.0, 1.0); - transform_a.Translate(-4.0, -10.0); - LayerShape layer_a(8.f, 20.f, transform_a); - - gfx::Transform transform_b; - transform_b.Translate3d(6.0, 0.0, -1.0); - transform_b.Translate(-4.0, -10.0); - LayerShape layer_b(8.f, 20.f, transform_b); - - gfx::Transform transform_c; - transform_c.RotateAboutYAxis(40.0); - transform_c.Translate(-4.0, -10.0); - LayerShape layer_c(8.f, 20.f, transform_c); - - overlap_result = - LayerSorter::CheckOverlap(&layer_a, &layer_c, z_threshold, &weight); - EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result); - overlap_result = - LayerSorter::CheckOverlap(&layer_c, &layer_b, z_threshold, &weight); - EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result); - overlap_result = - LayerSorter::CheckOverlap(&layer_a, &layer_b, z_threshold, &weight); - EXPECT_EQ(LayerSorter::NONE, overlap_result); -} - -TEST(LayerSorterTest, LayersUnderPathologicalPerspectiveTransform) { - LayerSorter::ABCompareResult overlap_result; - const float z_threshold = 0.1f; - float weight = 0.f; - - // On perspective projection, if w becomes negative, the re-projected point - // will be invalid and un-usable. Correct code needs to clip away portions of - // the geometry where w < 0. If the code uses the invalid value, it will think - // that a layer has different bounds than it really does, which can cause - // things to sort incorrectly. - - gfx::Transform perspective_matrix; - perspective_matrix.ApplyPerspectiveDepth(1); - - gfx::Transform transform_a; - transform_a.Translate3d(-15.0, 0.0, -2.0); - transform_a.Translate(-5.0, -5.0); - LayerShape layer_a(10.f, 10.f, perspective_matrix * transform_a); - - // With this sequence of transforms, when layer B is correctly clipped, it - // will be visible on the left half of the projection plane, in front of - // 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.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); - - // Sanity check that the test case actually covers the intended scenario, - // where part of layer B go behind the w = 0 plane. - gfx::QuadF test_quad = gfx::QuadF(gfx::RectF(-0.5f, -0.5f, 1.f, 1.f)); - bool clipped = false; - MathUtil::MapQuad(perspective_matrix * transform_b, test_quad, &clipped); - ASSERT_TRUE(clipped); - - overlap_result = - LayerSorter::CheckOverlap(&layer_a, &layer_b, z_threshold, &weight); - EXPECT_EQ(LayerSorter::A_BEFORE_B, overlap_result); -} - -TEST(LayerSorterTest, VerifyExistingOrderingPreservedWhenNoZDiff) { - // If there is no reason to re-sort the layers (i.e. no 3d z difference), then - // the existing ordering provided on input should be retained. This test - // covers the fix in https://bugs.webkit.org/show_bug.cgi?id=75046. Before - // this fix, ordering was accidentally reversed, causing bugs in z-index - // ordering on websites when preserves3D triggered the LayerSorter. - - // Input list of layers: [1, 2, 3, 4, 5]. - // Expected output: [3, 4, 1, 2, 5]. - // - 1, 2, and 5 do not have a 3d z difference, and therefore their - // relative ordering should be retained. - // - 3 and 4 do not have a 3d z difference, and therefore their relative - // ordering should be retained. - // - 3 and 4 should be re-sorted so they are in front of 1, 2, and 5. - - FakeImplProxy proxy; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); - - scoped_ptr<LayerImpl> layer1 = LayerImpl::Create(host_impl.active_tree(), 1); - scoped_ptr<LayerImpl> layer2 = LayerImpl::Create(host_impl.active_tree(), 2); - scoped_ptr<LayerImpl> layer3 = LayerImpl::Create(host_impl.active_tree(), 3); - scoped_ptr<LayerImpl> layer4 = LayerImpl::Create(host_impl.active_tree(), 4); - scoped_ptr<LayerImpl> layer5 = LayerImpl::Create(host_impl.active_tree(), 5); - - gfx::Transform BehindMatrix; - BehindMatrix.Translate3d(0.0, 0.0, 2.0); - gfx::Transform FrontMatrix; - FrontMatrix.Translate3d(0.0, 0.0, 1.0); - - layer1->SetBounds(gfx::Size(10, 10)); - layer1->SetContentBounds(gfx::Size(10, 10)); - layer1->draw_properties().target_space_transform = BehindMatrix; - layer1->SetDrawsContent(true); - - layer2->SetBounds(gfx::Size(20, 20)); - layer2->SetContentBounds(gfx::Size(20, 20)); - layer2->draw_properties().target_space_transform = BehindMatrix; - layer2->SetDrawsContent(true); - - layer3->SetBounds(gfx::Size(30, 30)); - layer3->SetContentBounds(gfx::Size(30, 30)); - layer3->draw_properties().target_space_transform = FrontMatrix; - layer3->SetDrawsContent(true); - - layer4->SetBounds(gfx::Size(40, 40)); - layer4->SetContentBounds(gfx::Size(40, 40)); - layer4->draw_properties().target_space_transform = FrontMatrix; - layer4->SetDrawsContent(true); - - layer5->SetBounds(gfx::Size(50, 50)); - layer5->SetContentBounds(gfx::Size(50, 50)); - layer5->draw_properties().target_space_transform = BehindMatrix; - layer5->SetDrawsContent(true); - - LayerImplList layer_list; - layer_list.push_back(layer1.get()); - layer_list.push_back(layer2.get()); - layer_list.push_back(layer3.get()); - layer_list.push_back(layer4.get()); - layer_list.push_back(layer5.get()); - - ASSERT_EQ(5u, layer_list.size()); - EXPECT_EQ(1, layer_list[0]->id()); - EXPECT_EQ(2, layer_list[1]->id()); - EXPECT_EQ(3, layer_list[2]->id()); - EXPECT_EQ(4, layer_list[3]->id()); - EXPECT_EQ(5, layer_list[4]->id()); - - LayerSorter layer_sorter; - layer_sorter.Sort(layer_list.begin(), layer_list.end()); - - ASSERT_EQ(5u, layer_list.size()); - EXPECT_EQ(3, layer_list[0]->id()); - EXPECT_EQ(4, layer_list[1]->id()); - EXPECT_EQ(1, layer_list[2]->id()); - EXPECT_EQ(2, layer_list[3]->id()); - EXPECT_EQ(5, layer_list[4]->id()); -} - -TEST(LayerSorterTest, VerifyConcidentLayerPrecisionLossResultsInDocumentOrder) { - FakeImplProxy proxy; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); - - scoped_ptr<LayerImpl> layer1 = LayerImpl::Create(host_impl.active_tree(), 1); - scoped_ptr<LayerImpl> layer2 = LayerImpl::Create(host_impl.active_tree(), 2); - - // Layer 1 should occur before layer 2 in paint. However, due to numeric - // issues in the sorter, it will put the layers in the wrong order - // in some situations. Here we test a patch that results in document - // order rather than calculated order when numeric percision is suspect - // in calculated order. - - gfx::Transform BehindMatrix; - BehindMatrix.Translate3d(0.f, 0.f, 0.999999f); - BehindMatrix.RotateAboutXAxis(38.5); - BehindMatrix.RotateAboutYAxis(77.0); - gfx::Transform FrontMatrix; - FrontMatrix.Translate3d(0, 0, 1.0); - FrontMatrix.RotateAboutXAxis(38.5); - FrontMatrix.RotateAboutYAxis(77.0); - - layer1->SetBounds(gfx::Size(10, 10)); - layer1->SetContentBounds(gfx::Size(10, 10)); - layer1->draw_properties().target_space_transform = BehindMatrix; - layer1->SetDrawsContent(true); - - layer2->SetBounds(gfx::Size(10, 10)); - layer2->SetContentBounds(gfx::Size(10, 10)); - layer2->draw_properties().target_space_transform = FrontMatrix; - layer2->SetDrawsContent(true); - - LayerImplList layer_list; - layer_list.push_back(layer1.get()); - layer_list.push_back(layer2.get()); - - ASSERT_EQ(2u, layer_list.size()); - EXPECT_EQ(1, layer_list[0]->id()); - EXPECT_EQ(2, layer_list[1]->id()); - - LayerSorter layer_sorter; - layer_sorter.Sort(layer_list.begin(), layer_list.end()); - - ASSERT_EQ(2u, layer_list.size()); - EXPECT_EQ(1, layer_list[0]->id()); - EXPECT_EQ(2, layer_list[1]->id()); -} - -} // namespace -} // namespace cc -
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index d893b33..2ac7ebe 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -544,34 +544,7 @@ void LayerTreeHost::SetAnimationEvents( scoped_ptr<AnimationEventsVector> events) { DCHECK(proxy_->IsMainThread()); - for (size_t event_index = 0; event_index < events->size(); ++event_index) { - int event_layer_id = (*events)[event_index].layer_id; - - // Use the map of all controllers, not just active ones, since non-active - // controllers may still receive events for impl-only animations. - const AnimationRegistrar::AnimationControllerMap& animation_controllers = - animation_registrar_->all_animation_controllers(); - auto iter = animation_controllers.find(event_layer_id); - if (iter != animation_controllers.end()) { - switch ((*events)[event_index].type) { - case AnimationEvent::STARTED: - (*iter).second->NotifyAnimationStarted((*events)[event_index]); - break; - - case AnimationEvent::FINISHED: - (*iter).second->NotifyAnimationFinished((*events)[event_index]); - break; - - case AnimationEvent::ABORTED: - (*iter).second->NotifyAnimationAborted((*events)[event_index]); - break; - - case AnimationEvent::PROPERTY_UPDATE: - (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]); - break; - } - } - } + animation_registrar_->SetAnimationEvents(events.Pass()); } void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) { @@ -1165,26 +1138,12 @@ animate)); } -void LayerTreeHost::AsValueInto(base::trace_event::TracedValue* state) const { - state->BeginDictionary("proxy"); - proxy_->AsValueInto(state); - state->EndDictionary(); -} - void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) { - if (!settings_.accelerated_animation_enabled || - animation_registrar_->active_animation_controllers().empty()) + if (!settings_.accelerated_animation_enabled) return; - TRACE_EVENT0("cc", "LayerTreeHost::AnimateLayers"); - - AnimationRegistrar::AnimationControllerMap active_controllers_copy = - animation_registrar_->active_animation_controllers(); - for (auto& it : active_controllers_copy) { - it.second->Animate(monotonic_time); - bool start_ready_animations = true; - it.second->UpdateState(start_ready_animations, NULL); - } + if (animation_registrar_->AnimateLayers(monotonic_time)) + animation_registrar_->UpdateAnimationState(true, NULL); } UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) {
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index e677f89..840a4fa 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -272,9 +272,6 @@ return animation_registrar_.get(); } - // Obtains a thorough dump of the LayerTreeHost as a value. - void AsValueInto(base::trace_event::TracedValue* value) const; - bool in_paint_layer_contents() const { return in_paint_layer_contents_; } // CreateUIResource creates a resource given a bitmap. The bitmap is
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index e468c07..064e91e 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -15,7 +15,6 @@ #include "cc/layers/render_surface.h" #include "cc/layers/render_surface_impl.h" #include "cc/trees/draw_property_utils.h" -#include "cc/trees/layer_sorter.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_impl.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -31,20 +30,6 @@ ScrollAndScaleSet::~ScrollAndScaleSet() {} -static void SortLayers(LayerList::iterator first, - LayerList::iterator end, - void* layer_sorter) { - NOTREACHED(); -} - -static void SortLayers(LayerImplList::iterator first, - LayerImplList::iterator end, - LayerSorter* layer_sorter) { - DCHECK(layer_sorter); - TRACE_EVENT0("cc", "LayerTreeHostCommon::SortLayers"); - layer_sorter->Sort(first, end); -} - template <typename LayerType> static gfx::Vector2dF GetEffectiveScrollDelta(LayerType* layer) { // Layer's scroll offset can have an integer part and fractional part. @@ -1128,6 +1113,8 @@ int current_render_surface_layer_list_id) { layer->draw_properties().last_drawn_render_surface_layer_list_id = current_render_surface_layer_list_id; + layer->draw_properties().layer_or_descendant_is_drawn = + !!current_render_surface_layer_list_id; } template <typename LayerTypePtr> @@ -1200,8 +1187,7 @@ data.layer_or_descendant_has_copy_request; layer_or_descendant_has_input_handler |= data.layer_or_descendant_has_input_handler; - num_unclipped_descendants += - data.num_unclipped_descendants; + num_unclipped_descendants += data.num_unclipped_descendants; } }; @@ -1233,6 +1219,7 @@ layer->draw_properties().sorted_for_recursion = false; layer->draw_properties().has_child_with_a_scroll_parent = false; + layer->draw_properties().layer_or_descendant_is_drawn = false; layer->draw_properties().visited = false; if (!HasInvertibleOrAnimatedTransform(layer)) { @@ -1279,7 +1266,6 @@ template <typename LayerType> struct SubtreeGlobals { - LayerSorter* layer_sorter; int max_texture_size; float device_scale_factor; float page_scale_factor; @@ -1814,8 +1800,6 @@ // layer's "screen space" and local content space. layer_draw_properties.screen_space_transform = data_from_ancestor.full_hierarchy_matrix; - if (layer->should_flatten_transform()) - layer_draw_properties.screen_space_transform.FlattenTo2d(); layer_draw_properties.screen_space_transform.PreconcatTransform (layer_draw_properties.target_space_transform); @@ -1934,6 +1918,10 @@ data_for_children.full_hierarchy_matrix.PreconcatTransform( render_surface->draw_transform()); + // A render surface inherently acts as a flattening point for the content of + // its descendants. + data_for_children.full_hierarchy_matrix.FlattenTo2d(); + if (layer->mask_layer()) { DrawProperties<LayerType>& mask_layer_draw_properties = layer->mask_layer()->draw_properties(); @@ -2212,6 +2200,8 @@ render_surface_layer_list->size() - child->draw_properties() .index_of_first_render_surface_layer_list_addition; + layer_draw_properties.layer_or_descendant_is_drawn |= + child->draw_properties().layer_or_descendant_is_drawn; } // Add the unsorted layer list contributions, if necessary. @@ -2365,17 +2355,6 @@ return; } - // If preserves-3d then sort all the descendants in 3D so that they can be - // drawn from back to front. If the preserves-3d property is also set on the - // parent then skip the sorting as the parent will sort all the descendants - // anyway. - if (globals.layer_sorter && descendants.size() && layer->Is3dSorted() && - !LayerIsInExisting3DRenderingContext(layer)) { - SortLayers(descendants.begin() + sorting_start_index, - descendants.end(), - globals.layer_sorter); - } - UpdateAccumulatedSurfaceState<LayerType>( layer, local_drawable_content_rect_of_subtree, accumulated_surface_state); @@ -2413,7 +2392,6 @@ scaled_device_transform.Scale(inputs.device_scale_factor, inputs.device_scale_factor); - globals->layer_sorter = NULL; globals->max_texture_size = inputs.max_texture_size; globals->device_scale_factor = inputs.device_scale_factor * device_transform_scale; @@ -2577,9 +2555,6 @@ DataForRecursion<LayerImpl> data_for_recursion; ProcessCalcDrawPropsInputs(*inputs, &globals, &data_for_recursion); - LayerSorter layer_sorter; - globals.layer_sorter = &layer_sorter; - PreCalculateMetaInformationRecursiveData recursive_data; PreCalculateMetaInformation(inputs->root_layer, &recursive_data); std::vector<AccumulatedSurfaceState<LayerImpl>> accumulated_surface_state;
diff --git a/cc/trees/layer_tree_host_common_perftest.cc b/cc/trees/layer_tree_host_common_perftest.cc index 73d5c1d..1732e55 100644 --- a/cc/trees/layer_tree_host_common_perftest.cc +++ b/cc/trees/layer_tree_host_common_perftest.cc
@@ -25,7 +25,6 @@ #include "cc/test/layer_tree_json_parser.h" #include "cc/test/layer_tree_test.h" #include "cc/test/paths.h" -#include "cc/trees/layer_sorter.h" #include "cc/trees/layer_tree_impl.h" #include "testing/perf/perf_test.h" @@ -162,55 +161,7 @@ } }; -class LayerSorterMainTest : public CalcDrawPropsImplTest { - public: - void RunSortLayers() { RunTest(false, false, false); } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { - LayerTreeImpl* active_tree = host_impl->active_tree(); - // First build the tree and then we'll start running tests on layersorter - // itself - bool can_render_to_separate_surface = true; - int max_texture_size = 8096; - DoCalcDrawPropertiesImpl(can_render_to_separate_surface, - max_texture_size, - active_tree, - host_impl); - - // Behaviour of this test is different from that of sorting in practice. - // In this case, all layers that exist in any 3D context are put into a list - // and are sorted as one big 3D context instead of several smaller ones. - BuildLayerImplList(active_tree->root_layer(), &base_list_); - timer_.Reset(); - do { - // Here we'll move the layers into a LayerImpl list of their own to be - // sorted so we don't have a sorted list for every run after the first - LayerImplList test_list = base_list_; - layer_sorter_.Sort(test_list.begin(), test_list.end()); - timer_.NextLap(); - } while (!timer_.HasTimeLimitExpired()); - - EndTest(); - } - - void BuildLayerImplList(LayerImpl* layer, LayerImplList* list) { - if (layer->Is3dSorted()) { - list->push_back(layer); - } - - for (size_t i = 0; i < layer->children().size(); i++) { - BuildLayerImplList(layer->children()[i], list); - } - } - - private: - LayerImplList base_list_; - LayerSorter layer_sorter_; -}; - -class BspTreePerfTest : public LayerSorterMainTest { +class BspTreePerfTest : public CalcDrawPropsImplTest { public: void RunSortLayers() { RunTest(false, false, false); } @@ -261,7 +212,18 @@ EndTest(); } + void BuildLayerImplList(LayerImpl* layer, LayerImplList* list) { + if (layer->Is3dSorted()) { + list->push_back(layer); + } + + for (size_t i = 0; i < layer->children().size(); i++) { + BuildLayerImplList(layer->children()[i], list); + } + } + private: + LayerImplList base_list_; int num_duplicates_; }; @@ -313,13 +275,13 @@ RunCalcDrawProps(); } -TEST_F(LayerSorterMainTest, LayerSorterCubes) { +TEST_F(BspTreePerfTest, LayerSorterCubes) { SetTestName("layer_sort_cubes"); ReadTestFile("layer_sort_cubes"); RunSortLayers(); } -TEST_F(LayerSorterMainTest, LayerSorterRubik) { +TEST_F(BspTreePerfTest, LayerSorterRubik) { SetTestName("layer_sort_rubik"); ReadTestFile("layer_sort_rubik"); // TODO(vollick): Remove verify_property_trees setting after
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 6234d87..d2c473e 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -1478,6 +1478,74 @@ } } +TEST_F(LayerTreeHostCommonTest, RenderSurfacesFlattenScreenSpaceTransform) { + // Render surfaces act as a flattening point for their subtree, so should + // always flatten the target-to-screen space transform seen by descendants. + + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<Layer> parent = Layer::Create(); + scoped_refptr<LayerWithForcedDrawsContent> child = + make_scoped_refptr(new LayerWithForcedDrawsContent()); + scoped_refptr<LayerWithForcedDrawsContent> grand_child = + make_scoped_refptr(new LayerWithForcedDrawsContent()); + + gfx::Transform rotation_about_y_axis; + rotation_about_y_axis.RotateAboutYAxis(30.0); + // Make |parent| have a render surface. + parent->SetOpacity(0.9f); + + const gfx::Transform identity_matrix; + SetLayerPropertiesForTesting(root.get(), identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false); + SetLayerPropertiesForTesting(parent.get(), rotation_about_y_axis, + gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10), + true, false); + SetLayerPropertiesForTesting(child.get(), identity_matrix, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false); + SetLayerPropertiesForTesting(grand_child.get(), identity_matrix, + gfx::Point3F(), gfx::PointF(), gfx::Size(10, 10), + true, false); + + root->AddChild(parent); + parent->AddChild(child); + child->AddChild(grand_child); + + grand_child->SetShouldFlattenTransform(false); + + scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); + host->SetRootLayer(root); + + // Only grand_child should preserve 3d. + EXPECT_TRUE(root->should_flatten_transform()); + EXPECT_TRUE(parent->should_flatten_transform()); + EXPECT_TRUE(child->should_flatten_transform()); + EXPECT_FALSE(grand_child->should_flatten_transform()); + + gfx::Transform expected_child_draw_transform = identity_matrix; + gfx::Transform expected_grand_child_draw_transform = identity_matrix; + + gfx::Transform flattened_rotation_about_y = rotation_about_y_axis; + flattened_rotation_about_y.FlattenTo2d(); + + ExecuteCalculateDrawProperties(root.get()); + + EXPECT_TRUE(parent->render_surface()); + EXPECT_FALSE(child->render_surface()); + EXPECT_FALSE(grand_child->render_surface()); + + EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, child->draw_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(identity_matrix, + grand_child->draw_transform()); + + // The screen-space transform inherited by |child| and |grand_child| should + // have been flattened at their render target. In particular, the fact that + // |grand_child| happens to preserve 3d shouldn't affect this flattening. + EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_y, + child->screen_space_transform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(flattened_rotation_about_y, + grand_child->screen_space_transform()); +} + TEST_F(LayerTreeHostCommonTest, ClipRectCullsRenderSurfaces) { // The entire subtree of layers that are outside the clip rect should be // culled away, and should not affect the render_surface_layer_list. @@ -2975,78 +3043,6 @@ EXPECT_FALSE(child->draw_properties().sorted_for_recursion); } -TEST_F(LayerTreeHostCommonTest, WillSortAtContextBoundary) { - // Creates a layer tree that looks as follows: - // * root (sorting-context-id1) - // * parent (sorting-context-id2) - // * child1 (sorting-context-id2) - // * child2 (sorting-context-id2) - // - // This test ensures that we sort at |parent| even though both it and root are - // set to be 3d sorted. - FakeImplProxy proxy; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); - - scoped_ptr<LayerImpl> root_ptr(LayerImpl::Create(host_impl.active_tree(), 1)); - LayerImpl* root = root_ptr.get(); - scoped_ptr<LayerImpl> parent_ptr( - LayerImpl::Create(host_impl.active_tree(), 2)); - LayerImpl* parent = parent_ptr.get(); - scoped_ptr<LayerImpl> child1_ptr( - LayerImpl::Create(host_impl.active_tree(), 3)); - LayerImpl* child1 = child1_ptr.get(); - scoped_ptr<LayerImpl> child2_ptr( - LayerImpl::Create(host_impl.active_tree(), 4)); - LayerImpl* child2 = child2_ptr.get(); - - gfx::Transform identity_matrix; - gfx::Transform below_matrix; - below_matrix.Translate3d(0.f, 0.f, -10.f); - gfx::Transform above_matrix; - above_matrix.Translate3d(0.f, 0.f, 10.f); - - SetLayerPropertiesForTesting(root, identity_matrix, gfx::Point3F(), - gfx::PointF(), gfx::Size(100, 100), true, true, - true); - SetLayerPropertiesForTesting(parent, identity_matrix, gfx::Point3F(), - gfx::PointF(), gfx::Size(50, 50), true, true, - true); - SetLayerPropertiesForTesting(child1, above_matrix, gfx::Point3F(), - gfx::PointF(), gfx::Size(50, 50), true, true, - false); - SetLayerPropertiesForTesting(child2, below_matrix, gfx::Point3F(), - gfx::PointF(), gfx::Size(50, 50), true, true, - false); - - root->Set3dSortingContextId(3); - root->SetDrawsContent(true); - parent->Set3dSortingContextId(7); - parent->SetDrawsContent(true); - child1->Set3dSortingContextId(7); - child1->SetDrawsContent(true); - child2->Set3dSortingContextId(7); - child2->SetDrawsContent(true); - - parent->AddChild(child1_ptr.Pass()); - parent->AddChild(child2_ptr.Pass()); - root->AddChild(parent_ptr.Pass()); - - LayerImplList render_surface_layer_list; - LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs( - root_ptr.get(), root->bounds(), &render_surface_layer_list); - inputs.can_adjust_raster_scales = true; - LayerTreeHostCommon::CalculateDrawProperties(&inputs); - - EXPECT_TRUE(root->render_surface()); - EXPECT_EQ(2u, render_surface_layer_list.size()); - - EXPECT_EQ(3u, parent->render_surface()->layer_list().size()); - EXPECT_EQ(child2->id(), parent->render_surface()->layer_list().at(0)->id()); - EXPECT_EQ(parent->id(), parent->render_surface()->layer_list().at(1)->id()); - EXPECT_EQ(child1->id(), parent->render_surface()->layer_list().at(2)->id()); -} - TEST_F(LayerTreeHostCommonTest, SingularNonAnimatingTransformDoesNotPreventClearingDrawProperties) { scoped_refptr<Layer> root = Layer::Create(); @@ -7592,110 +7588,6 @@ 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; - TestSharedBitmapManager shared_bitmap_manager; - FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager); - 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, gfx::Point3F(), - gfx::PointF(), gfx::Size(50, 50), true, false, - true); - SetLayerPropertiesForTesting(scroll_parent_border.get(), identity_transform, - gfx::Point3F(), gfx::PointF(), gfx::Size(40, 40), - true, false, false); - SetLayerPropertiesForTesting(scroll_parent_clip.get(), identity_transform, - gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30), - true, false, false); - SetLayerPropertiesForTesting(scroll_parent.get(), identity_transform, - gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), - true, false, false); - SetLayerPropertiesForTesting(scroll_child.get(), identity_transform, - gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), - true, false, false); - SetLayerPropertiesForTesting(top_content.get(), top_transform, gfx::Point3F(), - gfx::PointF(), gfx::Size(50, 50), false, true, - true); - SetLayerPropertiesForTesting(bottom_content.get(), bottom_transform, - gfx::Point3F(), gfx::PointF(), gfx::Size(50, 50), - false, true, true); - - scroll_child->SetShouldFlattenTransform(false); - scroll_child->Set3dSortingContextId(1); - - 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. @@ -8850,5 +8742,59 @@ grandchild->visible_rect_from_property_trees()); } +TEST_F(LayerTreeHostCommonTest, CombineClipsUsingContentTarget) { + // In the following layer tree, the layer |box|'s render target is |surface|. + // |surface| also creates a transform node. We want to combine clips for |box| + // in the space of its target (i.e., |surface|), not its target's target. This + // test ensures that happens. + + gfx::Transform rotate; + rotate.Rotate(5); + gfx::Transform identity; + + scoped_refptr<Layer> root = Layer::Create(); + SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(2500, 1500), true, + false); + + scoped_refptr<Layer> frame_clip = Layer::Create(); + SetLayerPropertiesForTesting(frame_clip.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(2500, 1500), true, + false); + frame_clip->SetMasksToBounds(true); + + scoped_refptr<Layer> rotated = Layer::Create(); + SetLayerPropertiesForTesting(rotated.get(), rotate, + gfx::Point3F(1250, 250, 0), gfx::PointF(), + gfx::Size(2500, 500), true, false); + + scoped_refptr<Layer> surface = Layer::Create(); + SetLayerPropertiesForTesting(surface.get(), rotate, gfx::Point3F(), + gfx::PointF(), gfx::Size(2500, 500), true, + false); + surface->SetOpacity(0.5); + + scoped_refptr<LayerWithForcedDrawsContent> container = + make_scoped_refptr(new LayerWithForcedDrawsContent()); + SetLayerPropertiesForTesting(container.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(300, 300), true, false); + + scoped_refptr<LayerWithForcedDrawsContent> box = + make_scoped_refptr(new LayerWithForcedDrawsContent()); + SetLayerPropertiesForTesting(box.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false); + + root->AddChild(frame_clip); + frame_clip->AddChild(rotated); + rotated->AddChild(surface); + surface->AddChild(container); + surface->AddChild(box); + + scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); + host->SetRootLayer(root); + + ExecuteCalculateDrawProperties(root.get()); +} + } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 2f4d9a9..f81a3b1 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -708,10 +708,11 @@ return DRAW_SUCCESS; } - TRACE_EVENT1("cc", - "LayerTreeHostImpl::CalculateRenderPasses", - "render_surface_layer_list.size()", - static_cast<uint64>(frame->render_surface_layer_list->size())); + TRACE_EVENT_BEGIN2( + "cc", "LayerTreeHostImpl::CalculateRenderPasses", + "render_surface_layer_list.size()", + static_cast<uint64>(frame->render_surface_layer_list->size()), + "RequiresHighResToDraw", RequiresHighResToDraw()); // Create the render passes in dependency order. for (int surface_index = frame->render_surface_layer_list->size() - 1; @@ -754,9 +755,6 @@ // due to an impl-animation, we drop the frame to avoid flashing due to the // texture suddenly appearing in the future. DrawResult draw_result = DRAW_SUCCESS; - // When we have a copy request for a layer, we need to draw no matter - // what, as the layer may disappear after this frame. - bool have_copy_request = false; int layers_drawn = 0; @@ -764,6 +762,8 @@ int num_missing_tiles = 0; int num_incomplete_tiles = 0; + bool have_copy_request = false; + bool have_missing_animated_tiles = false; auto end = LayerIterator<LayerImpl>::End(frame->render_surface_layer_list); for (auto it = @@ -848,18 +848,34 @@ it->screen_space_transform_is_animating() || it->draw_transform_is_animating(); if (layer_has_animating_transform) - draw_result = DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; - } - - if (append_quads_data.num_incomplete_tiles || - append_quads_data.num_missing_tiles) { - if (RequiresHighResToDraw()) - draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT; + have_missing_animated_tiles = true; } } - if (have_copy_request || - output_surface_->capabilities().draw_and_swap_full_viewport_every_frame) + if (have_missing_animated_tiles) + draw_result = DRAW_ABORTED_CHECKERBOARD_ANIMATIONS; + + // When we have a copy request for a layer, we need to draw even if there + // would be animating checkerboards, because failing under those conditions + // triggers a new main frame, which may cause the copy request layer to be + // destroyed. + // TODO(danakj): Leaking scheduler internals into LayerTreeHostImpl here. + if (have_copy_request) + draw_result = DRAW_SUCCESS; + + // When we require high res to draw, abort the draw (almost) always. This does + // not cause the scheduler to do a main frame, instead it will continue to try + // drawing until we finally complete, so the copy request will not be lost. + if (num_incomplete_tiles || num_missing_tiles) { + if (RequiresHighResToDraw()) + draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT; + } + + // When this capability is set we don't have control over the surface the + // compositor draws to, so even though the frame may not be complete, the + // previous frame has already been potentially lost, so an incomplete frame is + // better than nothing, so this takes highest precidence. + if (output_surface_->capabilities().draw_and_swap_full_viewport_every_frame) draw_result = DRAW_SUCCESS; #if DCHECK_IS_ON() @@ -910,6 +926,10 @@ frame->render_passes.size() == 1u) << frame->render_passes.size(); + TRACE_EVENT_END2("cc", "LayerTreeHostImpl::CalculateRenderPasses", + "draw_result", draw_result, "missing tiles", + num_missing_tiles); + return draw_result; } @@ -1055,7 +1075,7 @@ // This will cause NotifyTileStateChanged() to be called for any visible tiles // that completed, which will add damage to the frame for them so they appear // as part of the current frame being drawn. - if (settings().impl_side_painting) + if (tile_manager_) tile_manager_->UpdateVisibleTiles(global_tile_state_); frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList(); @@ -1528,7 +1548,7 @@ if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) { bool disable_picture_quad_image_filtering = - IsActivelyScrolling() || needs_animate_layers(); + IsActivelyScrolling() || animation_registrar_->needs_animate_layers(); scoped_ptr<SoftwareRenderer> temp_software_renderer = SoftwareRenderer::Create(this, &settings_.renderer_settings, @@ -1656,6 +1676,18 @@ if (!inner_container) return; + // TODO(bokan): This code is currently specific to top controls. It should be + // made general. crbug.com/464814. + if (!TopControlsHeight()) { + if (outer_container) + outer_container->SetBoundsDelta(gfx::Vector2dF()); + + inner_container->SetBoundsDelta(gfx::Vector2dF()); + active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(gfx::Vector2dF()); + + return; + } + ViewportAnchor anchor(InnerViewportScrollLayer(), OuterViewportScrollLayer()); @@ -1693,7 +1725,8 @@ void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() { // Only valid for the single-threaded non-scheduled/synchronous case // using the zero copy raster worker pool. - single_thread_synchronous_task_graph_runner_->RunUntilIdle(); + if (tile_manager_) + single_thread_synchronous_task_graph_runner_->RunUntilIdle(); } void LayerTreeHostImpl::DidLoseOutputSurface() { @@ -2057,6 +2090,11 @@ } } + // Synchronous single-threaded mode depends on tiles being ready to + // draw when raster is complete. Therefore, it must use one of zero + // copy, software raster, or GPU raster (in the branches above). + DCHECK(!IsSynchronousSingleThreaded()); + *resource_pool = ResourcePool::Create( resource_provider_.get(), GL_TEXTURE_2D); @@ -2119,7 +2157,7 @@ CreateAndSetRenderer(); - if (settings_.impl_side_painting) + if (settings_.impl_side_painting && settings_.raster_enabled) CreateAndSetTileManager(); RecreateTreeResources(); @@ -3112,52 +3150,35 @@ } void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) { - if (!settings_.accelerated_animation_enabled || - !needs_animate_layers() || - !active_tree_->root_layer()) + if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer()) return; - TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers"); - AnimationRegistrar::AnimationControllerMap controllers_copy = - animation_registrar_->active_animation_controllers(); - for (auto& it : controllers_copy) - it.second->Animate(monotonic_time); - - SetNeedsAnimate(); + if (animation_registrar_->AnimateLayers(monotonic_time)) + SetNeedsAnimate(); } void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) { - if (!settings_.accelerated_animation_enabled || !needs_animate_layers() || - !active_tree_->root_layer()) + if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer()) return; - TRACE_EVENT0("cc", "LayerTreeHostImpl::UpdateAnimationState"); scoped_ptr<AnimationEventsVector> events = - make_scoped_ptr(new AnimationEventsVector); - AnimationRegistrar::AnimationControllerMap active_controllers_copy = - animation_registrar_->active_animation_controllers(); - for (auto& it : active_controllers_copy) - it.second->UpdateState(start_ready_animations, events.get()); + animation_registrar_->CreateEvents(); + const bool has_active_animations = animation_registrar_->UpdateAnimationState( + start_ready_animations, events.get()); - if (!events->empty()) { + if (!events->empty()) client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass()); - } - SetNeedsAnimate(); + if (has_active_animations) + SetNeedsAnimate(); } void LayerTreeHostImpl::ActivateAnimations() { - if (!settings_.accelerated_animation_enabled || !needs_animate_layers() || - !active_tree_->root_layer()) + if (!settings_.accelerated_animation_enabled || !active_tree_->root_layer()) return; - TRACE_EVENT0("cc", "LayerTreeHostImpl::ActivateAnimations"); - AnimationRegistrar::AnimationControllerMap active_controllers_copy = - animation_registrar_->active_animation_controllers(); - for (auto& it : active_controllers_copy) - it.second->ActivateAnimations(); - - SetNeedsAnimate(); + if (animation_registrar_->ActivateAnimations()) + SetNeedsAnimate(); } std::string LayerTreeHostImpl::LayerTreeAsJson() const { @@ -3234,11 +3255,6 @@ } scoped_refptr<base::trace_event::ConvertableToTraceFormat> -LayerTreeHostImpl::AsValue() const { - return AsValueWithFrame(NULL); -} - -scoped_refptr<base::trace_event::ConvertableToTraceFormat> LayerTreeHostImpl::AsValueWithFrame(FrameData* frame) const { scoped_refptr<base::trace_event::TracedValue> state = new base::trace_event::TracedValue(); @@ -3246,11 +3262,6 @@ return state; } -void LayerTreeHostImpl::AsValueInto( - base::trace_event::TracedValue* value) const { - return AsValueWithFrameInto(NULL, value); -} - void LayerTreeHostImpl::AsValueWithFrameInto( FrameData* frame, base::trace_event::TracedValue* state) const { @@ -3299,14 +3310,6 @@ } } -scoped_refptr<base::trace_event::ConvertableToTraceFormat> -LayerTreeHostImpl::ActivationStateAsValue() const { - scoped_refptr<base::trace_event::TracedValue> state = - new base::trace_event::TracedValue(); - ActivationStateAsValueInto(state.get()); - return state; -} - void LayerTreeHostImpl::ActivationStateAsValueInto( base::trace_event::TracedValue* state) const { TracedValue::SetIDRef(this, state, "lthi");
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 73ed039..94012e0 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -380,10 +380,6 @@ scoped_ptr<ScrollAndScaleSet> ProcessScrollDeltas(); - bool needs_animate_layers() const { - return !animation_registrar_->active_animation_controllers().empty(); - } - void set_max_memory_needed_bytes(size_t bytes) { max_memory_needed_bytes_ = bytes; } @@ -454,14 +450,10 @@ return begin_impl_frame_interval_; } - void AsValueInto(base::trace_event::TracedValue* value) const; void AsValueWithFrameInto(FrameData* frame, base::trace_event::TracedValue* value) const; - scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const; scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValueWithFrame( FrameData* frame) const; - scoped_refptr<base::trace_event::ConvertableToTraceFormat> - ActivationStateAsValue() const; void ActivationStateAsValueInto(base::trace_event::TracedValue* value) const; bool page_scale_animation_active() const { return !!page_scale_animation_; } @@ -614,6 +606,7 @@ // |resource_provider_| and |tile_manager_| can be NULL, e.g. when using tile- // free rendering - see OutputSurface::ForcedDrawToSoftwareDevice(). + // |tile_manager_| can also be NULL when raster_enabled is false. scoped_ptr<ResourceProvider> resource_provider_; scoped_ptr<TileManager> tile_manager_; bool use_gpu_rasterization_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 7ffa683..4e3230b 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1558,192 +1558,160 @@ base::TimeTicks fake_current_physical_time_; }; -#define SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST() \ - gfx::Size viewport_size(10, 10); \ - gfx::Size content_size(100, 100); \ - \ - LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = \ - new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_, \ - shared_bitmap_manager_.get(), \ - &stats_instrumentation_); \ - host_impl_ = make_scoped_ptr(host_impl_override_time); \ - host_impl_->InitializeRenderer(CreateOutputSurface()); \ - host_impl_->SetViewportSize(viewport_size); \ - \ - scoped_ptr<LayerImpl> root = \ - LayerImpl::Create(host_impl_->active_tree(), 1); \ - root->SetBounds(viewport_size); \ - \ - scoped_ptr<LayerImpl> scroll = \ - LayerImpl::Create(host_impl_->active_tree(), 2); \ - scroll->SetScrollClipLayer(root->id()); \ - scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); \ - root->SetBounds(viewport_size); \ - scroll->SetBounds(content_size); \ - scroll->SetContentBounds(content_size); \ - scroll->SetIsContainerForFixedPositionLayers(true); \ - \ - scoped_ptr<LayerImpl> contents = \ - LayerImpl::Create(host_impl_->active_tree(), 3); \ - contents->SetDrawsContent(true); \ - contents->SetBounds(content_size); \ - contents->SetContentBounds(content_size); \ - \ - scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = \ - SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, \ - VERTICAL, 10, 0, false, true); \ - EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); \ - \ - scroll->AddChild(contents.Pass()); \ - root->AddChild(scroll.Pass()); \ - root->SetHasRenderSurface(true); \ - scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); \ - root->AddChild(scrollbar.Pass()); \ - \ - host_impl_->active_tree()->SetRootLayer(root.Pass()); \ - host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, \ - Layer::INVALID_ID); \ - host_impl_->active_tree()->DidBecomeActive(); \ - DrawFrame(); +class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest { + protected: + void SetupLayers(LayerTreeSettings settings) { + gfx::Size viewport_size(10, 10); + gfx::Size content_size(100, 100); -TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) { - LayerTreeSettings settings; - settings.scrollbar_animator = LayerTreeSettings::LINEAR_FADE; - settings.scrollbar_fade_delay_ms = 20; - settings.scrollbar_fade_duration_ms = 20; + LayerTreeHostImplOverridePhysicalTime* host_impl_override_time = + new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_, + shared_bitmap_manager_.get(), + &stats_instrumentation_); + host_impl_ = make_scoped_ptr(host_impl_override_time); + host_impl_->InitializeRenderer(CreateOutputSurface()); + host_impl_->SetViewportSize(viewport_size); - SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST(); + scoped_ptr<LayerImpl> root = + LayerImpl::Create(host_impl_->active_tree(), 1); + root->SetBounds(viewport_size); - base::TimeTicks fake_now = gfx::FrameTime::Now(); + scoped_ptr<LayerImpl> scroll = + LayerImpl::Create(host_impl_->active_tree(), 2); + scroll->SetScrollClipLayer(root->id()); + scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset()); + root->SetBounds(viewport_size); + scroll->SetBounds(content_size); + scroll->SetContentBounds(content_size); + scroll->SetIsContainerForFixedPositionLayers(true); - EXPECT_FALSE(did_request_animate_); - EXPECT_FALSE(did_request_redraw_); - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + scoped_ptr<LayerImpl> contents = + LayerImpl::Create(host_impl_->active_tree(), 3); + contents->SetDrawsContent(true); + contents->SetBounds(content_size); + contents->SetContentBounds(content_size); - // If no scroll happened during a scroll gesture, it should have no effect. - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); - host_impl_->ScrollEnd(); - EXPECT_FALSE(did_request_animate_); - EXPECT_FALSE(did_request_redraw_); - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar = + SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4, + VERTICAL, 10, 0, false, true); + EXPECT_FLOAT_EQ(0.f, scrollbar->opacity()); - // After a scroll, a fade animation should be scheduled about 20ms from now. - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5)); - EXPECT_FALSE(did_request_animate_); - EXPECT_TRUE(did_request_redraw_); - did_request_redraw_ = false; - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + scroll->AddChild(contents.Pass()); + root->AddChild(scroll.Pass()); + root->SetHasRenderSurface(true); + scrollbar->SetScrollLayerAndClipLayerByIds(2, 1); + root->AddChild(scrollbar.Pass()); - host_impl_->ScrollEnd(); - EXPECT_FALSE(did_request_animate_); - EXPECT_FALSE(did_request_redraw_); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); + host_impl_->active_tree()->SetRootLayer(root.Pass()); + host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2, + Layer::INVALID_ID); + host_impl_->active_tree()->DidBecomeActive(); + DrawFrame(); + } - fake_now += requested_animation_delay_; - requested_animation_delay_ = base::TimeDelta(); - animation_task_.Run(); - animation_task_ = base::Closure(); - EXPECT_TRUE(did_request_animate_); - did_request_animate_ = false; - EXPECT_FALSE(did_request_redraw_); + void RunTest(LayerTreeSettings::ScrollbarAnimator animator) { + LayerTreeSettings settings; + settings.scrollbar_animator = animator; + settings.scrollbar_fade_delay_ms = 20; + settings.scrollbar_fade_duration_ms = 20; - // After the fade begins, we should start getting redraws instead of a - // scheduled animation. - host_impl_->Animate(fake_now); - EXPECT_TRUE(did_request_animate_); - did_request_animate_ = false; - EXPECT_TRUE(did_request_redraw_); - did_request_redraw_ = false; - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + SetupLayers(settings); - // Setting the scroll offset outside a scroll should also cause the scrollbar - // to appear and to schedule a fade. - host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread( - gfx::ScrollOffset(5, 5)); - EXPECT_FALSE(did_request_animate_); - EXPECT_FALSE(did_request_redraw_); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), requested_animation_delay_); - EXPECT_FALSE(animation_task_.Equals(base::Closure())); - requested_animation_delay_ = base::TimeDelta(); - animation_task_ = base::Closure(); + base::TimeTicks fake_now = gfx::FrameTime::Now(); - // Unnecessarily Fade animation of solid color scrollbar is not triggered. - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); - EXPECT_FALSE(did_request_animate_); - EXPECT_TRUE(did_request_redraw_); - did_request_redraw_ = false; - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); - host_impl_->ScrollEnd(); - EXPECT_FALSE(did_request_animate_); - EXPECT_FALSE(did_request_redraw_); - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); + // If no scroll happened during a scroll gesture, it should have no effect. + host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); + host_impl_->ScrollEnd(); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + + // After a scroll, a scrollbar animation should be scheduled about 20ms from + // now. + host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5)); + EXPECT_FALSE(did_request_animate_); + EXPECT_TRUE(did_request_redraw_); + did_request_redraw_ = false; + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + + host_impl_->ScrollEnd(); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), + requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + + fake_now += requested_animation_delay_; + requested_animation_delay_ = base::TimeDelta(); + animation_task_.Run(); + animation_task_ = base::Closure(); + EXPECT_TRUE(did_request_animate_); + did_request_animate_ = false; + EXPECT_FALSE(did_request_redraw_); + + // After the scrollbar animation begins, we should start getting redraws. + host_impl_->Animate(fake_now); + EXPECT_TRUE(did_request_animate_); + did_request_animate_ = false; + EXPECT_TRUE(did_request_redraw_); + did_request_redraw_ = false; + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + + // Setting the scroll offset outside a scroll should also cause the + // scrollbar to appear and to schedule a scrollbar animation. + host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread( + gfx::ScrollOffset(5, 5)); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), + requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + requested_animation_delay_ = base::TimeDelta(); + animation_task_ = base::Closure(); + + // Scrollbar animation is not triggered unnecessarily. + host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); + EXPECT_FALSE(did_request_animate_); + EXPECT_TRUE(did_request_redraw_); + did_request_redraw_ = false; + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + + host_impl_->ScrollEnd(); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); + EXPECT_TRUE(animation_task_.Equals(base::Closure())); + + // Changing page scale triggers scrollbar animation. + host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); + host_impl_->SetPageScaleOnActiveTree(1.1f); + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_EQ(base::TimeDelta::FromMilliseconds(20), + requested_animation_delay_); + EXPECT_FALSE(animation_task_.Equals(base::Closure())); + requested_animation_delay_ = base::TimeDelta(); + animation_task_ = base::Closure(); + } +}; + +TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) { + RunTest(LayerTreeSettings::LINEAR_FADE); } -TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { - LayerTreeSettings settings; - settings.scrollbar_animator = LayerTreeSettings::LINEAR_FADE; - settings.scrollbar_fade_delay_ms = 20; - settings.scrollbar_fade_duration_ms = 20; - settings.use_pinch_zoom_scrollbars = true; - - SETUP_LAYERS_FOR_SCROLLBAR_ANIMATION_TEST(); - - base::TimeTicks fake_now = gfx::FrameTime::Now(); - - host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f); - - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_FALSE(did_request_animate_); - - // If no scroll happened during a scroll gesture, it should have no effect. - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); - host_impl_->ScrollEnd(); - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_FALSE(did_request_animate_); - EXPECT_TRUE(animation_task_.Equals(base::Closure())); - - // After a scroll, no fade animation should be scheduled. - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); - host_impl_->ScrollEnd(); - did_request_redraw_ = false; - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_FALSE(did_request_animate_); - requested_animation_delay_ = base::TimeDelta(); - - // We should not see any draw requests. - fake_now += base::TimeDelta::FromMilliseconds(25); - EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); - EXPECT_FALSE(did_request_animate_); - - // Make page scale > min so that subsequent scrolls will trigger fades. - host_impl_->SetPageScaleOnActiveTree(1.1f); - - // After a scroll, a fade animation should be scheduled about 20ms from now. - host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); - host_impl_->ScrollEnd(); - did_request_redraw_ = false; - EXPECT_LT(base::TimeDelta::FromMilliseconds(19), requested_animation_delay_); - EXPECT_FALSE(did_request_animate_); - requested_animation_delay_ = base::TimeDelta(); - animation_task_.Run(); - - // After the fade begins, we should start getting redraws instead of a - // scheduled animation. - fake_now += base::TimeDelta::FromMilliseconds(25); - host_impl_->Animate(fake_now); - EXPECT_TRUE(did_request_animate_); +TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) { + RunTest(LayerTreeSettings::THINNING); } void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( @@ -1960,6 +1928,16 @@ did_draw_called_ = false; } + static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {} + + void AddCopyRequest() { + ScopedPtrVector<CopyOutputRequest> requests; + requests.push_back( + CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult))); + SetHasRenderSurface(true); + PassCopyRequests(&requests); + } + protected: DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id) : LayerImpl(tree_impl, id), @@ -2189,60 +2167,219 @@ bool had_incomplete_tile_; }; -TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsOnDefault) { +struct PrepareToDrawSuccessTestCase { + struct State { + bool has_missing_tile = false; + bool has_incomplete_tile = false; + bool is_animating = false; + bool has_copy_request = false; + }; + bool high_res_required = false; + State layer_before; + State layer_between; + State layer_after; + DrawResult expected_result; + + explicit PrepareToDrawSuccessTestCase(DrawResult result) + : expected_result(result) {} +}; + +TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) { + std::vector<PrepareToDrawSuccessTestCase> cases; + + // 0. Default case. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + // 1. Animated layer first. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_before.is_animating = true; + // 2. Animated layer between. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_between.is_animating = true; + // 3. Animated layer last. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_after.is_animating = true; + // 4. Missing tile first. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_before.has_missing_tile = true; + // 5. Missing tile between. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_between.has_missing_tile = true; + // 6. Missing tile last. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_after.has_missing_tile = true; + // 7. Incomplete tile first. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_before.has_incomplete_tile = true; + // 8. Incomplete tile between. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_between.has_incomplete_tile = true; + // 9. Incomplete tile last. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_after.has_incomplete_tile = true; + // 10. Animation with missing tile. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS)); + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_between.is_animating = true; + // 11. Animation with missing tile and copy request after. Must succeed + // because the animation checkerboard means we'll get a new frame and the copy + // request's layer may be destroyed. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_between.is_animating = true; + cases.back().layer_after.has_copy_request = true; + // 12. Animation with missing tile and copy request before. Must succeed + // because the animation checkerboard means we'll get a new frame and the copy + // request's layer may be destroyed. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_between.is_animating = true; + cases.back().layer_before.has_copy_request = true; + // 13. Animation with incomplete tile. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_between.has_incomplete_tile = true; + cases.back().layer_between.is_animating = true; + + // 14. High res required. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().high_res_required = true; + // 15. High res required with incomplete tile. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); + cases.back().high_res_required = true; + cases.back().layer_between.has_incomplete_tile = true; + // 16. High res required with missing tile. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); + cases.back().high_res_required = true; + cases.back().layer_between.has_missing_tile = true; + + // 17. High res required is higher priority than animating missing tiles. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); + cases.back().high_res_required = true; + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_after.has_missing_tile = true; + cases.back().layer_after.is_animating = true; + // 18. High res required is higher priority than animating missing tiles. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); + cases.back().high_res_required = true; + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_before.has_missing_tile = true; + cases.back().layer_before.is_animating = true; + + // 19. High res required is higher priority than copy requests. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); + cases.back().high_res_required = true; + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_after.has_copy_request = true; + // 20. High res required is higher priority than copy requests. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); + cases.back().high_res_required = true; + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_before.has_copy_request = true; + // 21. High res required is higher priority than copy requests. + cases.push_back( + PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT)); + cases.back().high_res_required = true; + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_between.has_copy_request = true; + host_impl_->active_tree()->SetRootLayer( DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); root->SetHasRenderSurface(true); - bool tile_missing = false; - bool had_incomplete_tile = false; - bool is_animating = false; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 2, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); LayerTreeHostImpl::FrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); host_impl_->DidDrawAllLayers(frame); + host_impl_->SwapBuffers(frame); + + for (size_t i = 0; i < cases.size(); ++i) { + const auto& testcase = cases[i]; + std::vector<LayerImpl*> to_remove; + for (auto* child : root->children()) + to_remove.push_back(child); + for (auto* child : to_remove) + root->RemoveChild(child); + + std::ostringstream scope; + scope << "Test case: " << i; + SCOPED_TRACE(scope.str()); + + root->AddChild(MissingTextureAnimatingLayer::Create( + host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile, + testcase.layer_before.has_incomplete_tile, + testcase.layer_before.is_animating, host_impl_->resource_provider())); + DidDrawCheckLayer* before = + static_cast<DidDrawCheckLayer*>(root->children().back()); + if (testcase.layer_before.has_copy_request) + before->AddCopyRequest(); + + root->AddChild(MissingTextureAnimatingLayer::Create( + host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile, + testcase.layer_between.has_incomplete_tile, + testcase.layer_between.is_animating, host_impl_->resource_provider())); + DidDrawCheckLayer* between = + static_cast<DidDrawCheckLayer*>(root->children().back()); + if (testcase.layer_between.has_copy_request) + between->AddCopyRequest(); + + root->AddChild(MissingTextureAnimatingLayer::Create( + host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile, + testcase.layer_after.has_incomplete_tile, + testcase.layer_after.is_animating, host_impl_->resource_provider())); + DidDrawCheckLayer* after = + static_cast<DidDrawCheckLayer*>(root->children().back()); + if (testcase.layer_after.has_copy_request) + after->AddCopyRequest(); + + if (testcase.high_res_required) + host_impl_->SetRequiresHighResToDraw(); + + LayerTreeHostImpl::FrameData frame; + EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame)); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); + host_impl_->DidDrawAllLayers(frame); + host_impl_->SwapBuffers(frame); + } } -TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithAnimatedLayer) { +TEST_F(LayerTreeHostImplTest, + PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) { + CreateHostImpl(DefaultSettings(), + FakeOutputSurface::CreateAlwaysDrawAndSwap3d()); + EXPECT_TRUE(host_impl_->output_surface() + ->capabilities() + .draw_and_swap_full_viewport_every_frame); + + std::vector<PrepareToDrawSuccessTestCase> cases; + + // 0. Default case. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + // 1. Animation with missing tile. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().layer_between.has_missing_tile = true; + cases.back().layer_between.is_animating = true; + // 2. High res required with incomplete tile. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().high_res_required = true; + cases.back().layer_between.has_incomplete_tile = true; + // 3. High res required with missing tile. + cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS)); + cases.back().high_res_required = true; + cases.back().layer_between.has_missing_tile = true; + host_impl_->active_tree()->SetRootLayer( DidDrawCheckLayer::Create(host_impl_->active_tree(), 1)); DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); root->SetHasRenderSurface(true); - bool tile_missing = false; - bool had_incomplete_tile = false; - bool is_animating = true; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 2, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - - LayerTreeHostImpl::FrameData frame; - - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame); -} - -TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithMissingTiles) { - host_impl_->active_tree()->SetRootLayer( - DidDrawCheckLayer::Create(host_impl_->active_tree(), 3)); - DidDrawCheckLayer* root = - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); - root->SetHasRenderSurface(true); LayerTreeHostImpl::FrameData frame; EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); @@ -2250,204 +2387,54 @@ host_impl_->DidDrawAllLayers(frame); host_impl_->SwapBuffers(frame); - bool tile_missing = true; - bool had_incomplete_tile = false; - bool is_animating = false; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 4, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - LayerTreeHostImpl::FrameData frame2; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2)); - host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame2); -} + for (size_t i = 0; i < cases.size(); ++i) { + const auto& testcase = cases[i]; + std::vector<LayerImpl*> to_remove; + for (auto* child : root->children()) + to_remove.push_back(child); + for (auto* child : to_remove) + root->RemoveChild(child); -TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWithIncompleteTile) { - host_impl_->active_tree()->SetRootLayer( - DidDrawCheckLayer::Create(host_impl_->active_tree(), 3)); - DidDrawCheckLayer* root = - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); - root->SetHasRenderSurface(true); + std::ostringstream scope; + scope << "Test case: " << i; + SCOPED_TRACE(scope.str()); - LayerTreeHostImpl::FrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame); - host_impl_->SwapBuffers(frame); + root->AddChild(MissingTextureAnimatingLayer::Create( + host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile, + testcase.layer_before.has_incomplete_tile, + testcase.layer_before.is_animating, host_impl_->resource_provider())); + DidDrawCheckLayer* before = + static_cast<DidDrawCheckLayer*>(root->children().back()); + if (testcase.layer_before.has_copy_request) + before->AddCopyRequest(); - bool tile_missing = false; - bool had_incomplete_tile = true; - bool is_animating = false; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 4, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - LayerTreeHostImpl::FrameData frame2; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2)); - host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame2); -} + root->AddChild(MissingTextureAnimatingLayer::Create( + host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile, + testcase.layer_between.has_incomplete_tile, + testcase.layer_between.is_animating, host_impl_->resource_provider())); + DidDrawCheckLayer* between = + static_cast<DidDrawCheckLayer*>(root->children().back()); + if (testcase.layer_between.has_copy_request) + between->AddCopyRequest(); -TEST_F(LayerTreeHostImplTest, - PrepareToDrawFailsWithAnimationAndMissingTilesUsesCheckerboard) { - host_impl_->active_tree()->SetRootLayer( - DidDrawCheckLayer::Create(host_impl_->active_tree(), 5)); - DidDrawCheckLayer* root = - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); - root->SetHasRenderSurface(true); + root->AddChild(MissingTextureAnimatingLayer::Create( + host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile, + testcase.layer_after.has_incomplete_tile, + testcase.layer_after.is_animating, host_impl_->resource_provider())); + DidDrawCheckLayer* after = + static_cast<DidDrawCheckLayer*>(root->children().back()); + if (testcase.layer_after.has_copy_request) + after->AddCopyRequest(); - LayerTreeHostImpl::FrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame); - host_impl_->SwapBuffers(frame); + if (testcase.high_res_required) + host_impl_->SetRequiresHighResToDraw(); - bool tile_missing = true; - bool had_incomplete_tile = false; - bool is_animating = true; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 6, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - LayerTreeHostImpl::FrameData frame2; - EXPECT_EQ(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS, - host_impl_->PrepareToDraw(&frame2)); - host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame2); -} - -TEST_F(LayerTreeHostImplTest, - PrepareToDrawSucceedsWithAnimationAndIncompleteTiles) { - host_impl_->active_tree()->SetRootLayer( - DidDrawCheckLayer::Create(host_impl_->active_tree(), 5)); - DidDrawCheckLayer* root = - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); - root->SetHasRenderSurface(true); - - LayerTreeHostImpl::FrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame); - host_impl_->SwapBuffers(frame); - - bool tile_missing = false; - bool had_incomplete_tile = true; - bool is_animating = true; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 6, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - LayerTreeHostImpl::FrameData frame2; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2)); - host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame2); -} - -TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsWhenHighResRequired) { - host_impl_->active_tree()->SetRootLayer( - DidDrawCheckLayer::Create(host_impl_->active_tree(), 7)); - DidDrawCheckLayer* root = - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); - root->SetHasRenderSurface(true); - - LayerTreeHostImpl::FrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame); - host_impl_->SwapBuffers(frame); - - bool tile_missing = false; - bool had_incomplete_tile = false; - bool is_animating = false; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 8, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - host_impl_->SetRequiresHighResToDraw(); - LayerTreeHostImpl::FrameData frame2; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame2)); - host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame2); -} - -TEST_F(LayerTreeHostImplTest, - PrepareToDrawFailsWhenHighResRequiredAndIncompleteTiles) { - host_impl_->active_tree()->SetRootLayer( - DidDrawCheckLayer::Create(host_impl_->active_tree(), 7)); - DidDrawCheckLayer* root = - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); - root->SetHasRenderSurface(true); - - LayerTreeHostImpl::FrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame); - host_impl_->SwapBuffers(frame); - - bool tile_missing = false; - bool had_incomplete_tile = true; - bool is_animating = false; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 8, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - host_impl_->SetRequiresHighResToDraw(); - LayerTreeHostImpl::FrameData frame2; - EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT, - host_impl_->PrepareToDraw(&frame2)); - host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame2); -} - -TEST_F(LayerTreeHostImplTest, - PrepareToDrawFailsWhenHighResRequiredAndMissingTile) { - host_impl_->active_tree()->SetRootLayer( - DidDrawCheckLayer::Create(host_impl_->active_tree(), 7)); - DidDrawCheckLayer* root = - static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer()); - root->SetHasRenderSurface(true); - - LayerTreeHostImpl::FrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame); - host_impl_->SwapBuffers(frame); - - bool tile_missing = true; - bool had_incomplete_tile = false; - bool is_animating = false; - root->AddChild( - MissingTextureAnimatingLayer::Create(host_impl_->active_tree(), - 8, - tile_missing, - had_incomplete_tile, - is_animating, - host_impl_->resource_provider())); - host_impl_->SetRequiresHighResToDraw(); - LayerTreeHostImpl::FrameData frame2; - EXPECT_EQ(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT, - host_impl_->PrepareToDraw(&frame2)); - host_impl_->DrawLayers(&frame2, gfx::FrameTime::Now()); - host_impl_->DidDrawAllLayers(frame2); + LayerTreeHostImpl::FrameData frame; + EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame)); + host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); + host_impl_->DidDrawAllLayers(frame); + host_impl_->SwapBuffers(frame); + } } TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) { @@ -6530,9 +6517,10 @@ EXPECT_EQ(1, software_device->frames_began_); EXPECT_EQ(1, software_device->frames_ended_); - // Call other API methods that are likely to hit NULL pointer in this mode. - EXPECT_TRUE(host_impl_->AsValue().get()); - EXPECT_TRUE(host_impl_->ActivationStateAsValue().get()); + // Call another API method that is likely to hit nullptr in this mode. + scoped_refptr<base::trace_event::TracedValue> state = + make_scoped_refptr(new base::trace_event::TracedValue()); + host_impl_->ActivationStateAsValueInto(state.get()); } TEST_F(LayerTreeHostImplTest, @@ -7117,7 +7105,7 @@ host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); } -TEST_F(LayerTreeHostImplTest, ScrollInvisibleScroller) { +TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) { gfx::Size content_size(100, 100); SetupScrollAndContentsLayers(content_size); @@ -7141,13 +7129,50 @@ // any layer that is a drawn RSLL member, then we can ignore the hit. // // Why SCROLL_STARTED? In this case, it's because we've bubbled out and - // started overscrolling the inner viewport. + // started scrolling the inner viewport. EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id()); } +TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) { + gfx::Size content_size(100, 100); + SetupScrollAndContentsLayers(content_size); + + LayerImpl* root = host_impl_->active_tree()->LayerById(1); + LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2); + + scoped_ptr<LayerImpl> invisible_scroll_layer = + CreateScrollableLayer(7, content_size, root); + invisible_scroll_layer->SetDrawsContent(false); + + scoped_ptr<LayerImpl> child_layer = + LayerImpl::Create(host_impl_->active_tree(), 8); + child_layer->SetDrawsContent(false); + + scoped_ptr<LayerImpl> grand_child_layer = + LayerImpl::Create(host_impl_->active_tree(), 9); + grand_child_layer->SetDrawsContent(true); + grand_child_layer->SetBounds(content_size); + grand_child_layer->SetContentBounds(content_size); + // Move the grand child so it's not hit by our test point. + grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f)); + + child_layer->AddChild(grand_child_layer.Pass()); + invisible_scroll_layer->AddChild(child_layer.Pass()); + root_scroll_layer->AddChild(invisible_scroll_layer.Pass()); + + DrawFrame(); + + // We should have scrolled |invisible_scroll_layer| as it was hit and it has + // a descendant which is a drawn RSLL member. + EXPECT_EQ(InputHandler::SCROLL_STARTED, + host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); + + EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id()); +} + TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) { // This test case is very similar to the one above with one key difference: // the invisible scroller has a scroll child that is indeed draw contents. @@ -7193,12 +7218,9 @@ DrawFrame(); - // We should not have scrolled |child_scroll| even though we technically "hit" - // it. The reason for this is that if the scrolling the scroll would not move - // any layer that is a drawn RSLL member, then we can ignore the hit. - // - // Why SCROLL_STARTED? In this case, it's because we've bubbled out and - // started overscrolling the inner viewport. + // We should have scrolled |child_scroll| even though it is invisible. + // The reason for this is that if the scrolling the scroll would move a layer + // that is a drawn RSLL member, then we should accept this hit. EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL)); @@ -7495,7 +7517,8 @@ float offset = top_controls_height_ - residue; EXPECT_TRUE( host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); - EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-offset, + host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF().ToString(), scroll_layer->CurrentScrollOffset().ToString()); @@ -7554,7 +7577,8 @@ float offset = top_controls_height_ - residue; EXPECT_TRUE( host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); - EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-offset, + host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF().ToString(), scroll_layer->CurrentScrollOffset().ToString()); @@ -7624,7 +7648,8 @@ float offset = top_controls_height_ - residue; EXPECT_TRUE( host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); - EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-offset, + host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), scroll_layer->CurrentScrollOffset().ToString()); @@ -7687,7 +7712,8 @@ float offset = top_controls_height_ - residue; EXPECT_TRUE( host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); - EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); + EXPECT_FLOAT_EQ(-offset, + host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), scroll_layer->CurrentScrollOffset().ToString());
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index 76acaa8..dd3cf73 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -97,8 +97,8 @@ } TEST_F(LayerTreeHostFiltersPixelTest, BackgroundFilterBlurOffAxis) { - scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( - gfx::Rect(200, 200), SK_ColorWHITE); + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorTRANSPARENT); // This verifies that the perspective of the clear layer (with black border) // does not influence the blending of the green box behind it. Also verifies
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc index 7b0e53b..b9491bb 100644 --- a/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -12,6 +12,9 @@ #if !defined(OS_ANDROID) +// TODO(enne): these time out on Windows. http://crbug.com/435632 +#if !defined(OS_WIN) + namespace cc { namespace { @@ -57,9 +60,6 @@ gfx::Size bounds_; }; -// TODO(enne): these time out on Windows. http://crbug.com/435632 -#if !defined(OS_WIN) - TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayer) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer( gfx::Rect(200, 200), SK_ColorWHITE); @@ -280,8 +280,6 @@ "mask_of_replica_of_clipped_layer.png"))); } -#endif // !defined(OS_WIN) - class CheckerContentLayerClient : public ContentLayerClient { public: CheckerContentLayerClient(const gfx::Size& bounds, @@ -397,8 +395,8 @@ float percentage_pixels_large_error = 2.5f; // 2.5%, ~1600px / (256*256) float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 60.0f; - int large_error_allowed = 100; + float average_error_allowed_in_bad_pixels = 100.0f; + int large_error_allowed = 256; int small_error_allowed = 0; pixel_comparator_.reset(new FuzzyPixelComparator( true, // discard_alpha @@ -467,4 +465,5 @@ } // namespace } // namespace cc -#endif // OS_ANDROID +#endif // !defined(OS_WIN) +#endif // !defined(OS_ANDROID)
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 1be61a5..2ec6e66 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2099,6 +2099,7 @@ proxy->SetMaxPartialTextureUpdates(5); LayerTreeSettings settings; + settings.impl_side_painting = false; settings.max_partial_texture_updates = 10; LayerTreeHostWithProxy host(&client, settings, proxy.Pass()); @@ -2116,6 +2117,7 @@ proxy->SetMaxPartialTextureUpdates(5); LayerTreeSettings settings; + settings.impl_side_painting = false; settings.max_partial_texture_updates = 10; LayerTreeHostWithProxy host(&client, settings, proxy.Pass()); @@ -2133,6 +2135,7 @@ proxy->SetMaxPartialTextureUpdates(20); LayerTreeSettings settings; + settings.impl_side_painting = false; settings.max_partial_texture_updates = 10; LayerTreeHostWithProxy host(&client, settings, proxy.Pass()); @@ -2147,6 +2150,7 @@ LayerTreeSettings settings; settings.max_partial_texture_updates = 4; settings.single_thread_proxy_scheduler = false; + settings.impl_side_painting = false; scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); @@ -2170,6 +2174,7 @@ LayerTreeSettings settings; settings.max_partial_texture_updates = 4; settings.single_thread_proxy_scheduler = false; + settings.impl_side_painting = false; scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); @@ -2193,6 +2198,7 @@ LayerTreeSettings settings; settings.max_partial_texture_updates = 4; settings.single_thread_proxy_scheduler = false; + settings.impl_side_painting = false; scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager()); @@ -2217,6 +2223,7 @@ LayerTreeSettings settings; settings.max_partial_texture_updates = 4; settings.single_thread_proxy_scheduler = false; + settings.impl_side_painting = false; scoped_ptr<SharedBitmapManager> shared_bitmap_manager( new TestSharedBitmapManager());
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index c1da07e..e9b877d 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -196,7 +196,7 @@ void AnimateLayers(LayerTreeHostImpl* host_impl, base::TimeTicks monotonic_time) override { bool have_animations = !host_impl->animation_registrar() - ->active_animation_controllers() + ->active_animation_controllers_for_testing() .empty(); if (!started_animating_ && have_animations) { started_animating_ = true; @@ -1243,7 +1243,8 @@ // start times. num_swap_buffers_++; AnimationRegistrar::AnimationControllerMap controllers_copy = - host_impl->animation_registrar()->active_animation_controllers(); + host_impl->animation_registrar() + ->active_animation_controllers_for_testing(); if (controllers_copy.size() == 2u) { EndTest(); EXPECT_GE(num_swap_buffers_, 3);
diff --git a/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/cc/trees/layer_tree_host_unittest_no_message_loop.cc index 06b3674..622143d 100644 --- a/cc/trees/layer_tree_host_unittest_no_message_loop.cc +++ b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
@@ -104,6 +104,7 @@ LayerTreeSettings settings; settings.single_thread_proxy_scheduler = false; settings.verify_property_trees = true; + settings.raster_enabled = false; layer_tree_host_ = LayerTreeHost::CreateSingleThreaded( this, this, nullptr, nullptr, settings, nullptr, nullptr); layer_tree_host_->SetViewportSize(size_);
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 5114fdc..a27630e 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -1430,15 +1430,16 @@ static bool ScrollsAnyDrawnRenderSurfaceLayerListMember(LayerImpl* layer) { if (!layer->scrollable()) return false; - if (layer->IsDrawnRenderSurfaceLayerListMember()) + if (layer->draw_properties().layer_or_descendant_is_drawn) return true; + if (!layer->scroll_children()) return false; for (std::set<LayerImpl*>::const_iterator it = layer->scroll_children()->begin(); it != layer->scroll_children()->end(); ++it) { - if ((*it)->IsDrawnRenderSurfaceLayerListMember()) + if ((*it)->draw_properties().layer_or_descendant_is_drawn) return true; } return false;
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc index 67f98e6..06df3c2 100644 --- a/cc/trees/layer_tree_impl_unittest.cc +++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -920,14 +920,6 @@ ASSERT_TRUE(grand_child1); ASSERT_EQ(1u, RenderSurfaceLayerList().size()); - RenderSurfaceImpl* root_render_surface = - host_impl().active_tree()->root_layer()->render_surface(); - ASSERT_EQ(4u, root_render_surface->layer_list().size()); - ASSERT_EQ(3, root_render_surface->layer_list().at(0)->id()); - ASSERT_EQ(1, root_render_surface->layer_list().at(1)->id()); - ASSERT_EQ(2, root_render_surface->layer_list().at(2)->id()); - ASSERT_EQ(4, root_render_surface->layer_list().at(3)->id()); - // Nothing overlaps the root_layer at (1, 1), so hit testing there should find // the root layer. gfx::Point test_point = gfx::Point(1, 1);
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index 0088e91..213ad28 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc
@@ -15,6 +15,7 @@ LayerTreeSettings::LayerTreeSettings() : impl_side_painting(false), + raster_enabled(true), throttle_frame_production(true), single_thread_proxy_scheduler(true), use_external_begin_frame_source(false),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h index ce8d856..373f704 100644 --- a/cc/trees/layer_tree_settings.h +++ b/cc/trees/layer_tree_settings.h
@@ -21,6 +21,7 @@ RendererSettings renderer_settings; bool impl_side_painting; + bool raster_enabled; bool throttle_frame_production; bool single_thread_proxy_scheduler; bool use_external_begin_frame_source;
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc index 388eb6e..0f0ce15 100644 --- a/cc/trees/occlusion_tracker.cc +++ b/cc/trees/occlusion_tracker.cc
@@ -155,7 +155,7 @@ return layer->Is3dSorted(); } static inline bool LayerIsInUnsorted3dRenderingContext(const LayerImpl* layer) { - return false; + return layer->Is3dSorted(); } template <typename LayerType>
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc index e3639ad..f3f2185 100644 --- a/cc/trees/occlusion_tracker_unittest.cc +++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -1540,56 +1540,6 @@ } }; -// This test requires accumulating occlusion of 3d layers, which are skipped by -// the occlusion tracker on the main thread. So this test should run on the impl -// thread. -IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude); - -template <class Types> -class OcclusionTrackerTestLargePixelsOccludeInsideClipRect - : public OcclusionTrackerTest<Types> { - protected: - explicit OcclusionTrackerTestLargePixelsOccludeInsideClipRect( - bool opaque_layers) - : OcclusionTrackerTest<Types>(opaque_layers) {} - void RunMyTest() override { - gfx::Transform transform; - transform.Translate(50.0, 50.0); - transform.ApplyPerspectiveDepth(100.0); - transform.Translate3d(0.0, 0.0, 99.0); - transform.Translate(-50.0, -50.0); - - typename Types::ContentLayerType* parent = this->CreateRoot( - this->identity_matrix, gfx::PointF(), gfx::Size(100, 100)); - parent->SetMasksToBounds(true); - typename Types::ContentLayerType* layer = this->CreateDrawingLayer( - parent, transform, gfx::PointF(), gfx::Size(100, 100), true); - parent->SetShouldFlattenTransform(false); - parent->Set3dSortingContextId(1); - layer->SetShouldFlattenTransform(false); - layer->Set3dSortingContextId(1); - this->CalcDrawEtc(parent); - - TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion( - gfx::Rect(0, 0, 1000, 1000)); - - // This is very close to the camera, so pixels in its visible_content_rect() - // 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); - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - occlusion.occlusion_from_inside_target().ToString()); - EXPECT_EQ(gfx::Rect().ToString(), - occlusion.occlusion_from_outside_target().ToString()); - } -}; - -// This test requires accumulating occlusion of 3d layers, which are skipped by -// the occlusion tracker on the main thread. So this test should run on the impl -// thread. -IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect); - template <class Types> class OcclusionTrackerTestAnimationOpacity1OnMainThread : public OcclusionTrackerTest<Types> {
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 95e4366..8e8ef50 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -43,7 +43,8 @@ ancestors_are_invertible(true), is_animated(false), to_screen_is_animated(false), - flattens(false), + flattens_inherited_transform(false), + flattens_local_transform(false), scrolls(false), needs_sublayer_scale(false), layer_scale_factor(1.0f) { @@ -190,7 +191,8 @@ node->data.to_screen = node->data.to_parent; node->data.ancestors_are_invertible = true; node->data.to_screen_is_animated = false; - } else if (parent_node->data.flattens) { + } else if (parent_node->data.flattens_local_transform || + node->data.flattens_inherited_transform) { // Flattening is tricky. Once a layer is drawn into its render target, it // cannot escape, so we only need to consider transforms between the layer // and its target when flattening (i.e., its draw transform). To compute the
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 404f498..cb00e8a 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -69,7 +69,13 @@ bool is_animated; bool to_screen_is_animated; - bool flattens; + // We don't necessarily create a transform node to apply flattening. If we've + // skipped flattening for an ancestor, we must flatten the transform we + // inherit, but we don't necessarily need to flatten our local transform. We + // must therefore use two values to describe the flattening required for the + // local and inherited transforms. + bool flattens_inherited_transform; + bool flattens_local_transform; bool scrolls; bool needs_sublayer_scale;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 6f3f792..8352ab8 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -33,6 +33,7 @@ float page_scale_factor; float device_scale_factor; bool in_subtree_of_page_scale_application_layer; + bool should_flatten; const gfx::Transform* device_transform; }; @@ -124,13 +125,9 @@ const bool has_surface = !!layer->render_surface(); - const bool flattening_change = layer->parent() && - layer->should_flatten_transform() && - !layer->parent()->should_flatten_transform(); - bool requires_node = is_root || is_scrollable || has_significant_transform || has_animated_transform || has_surface || - is_page_scale_application_layer || flattening_change; + is_page_scale_application_layer; Layer* transform_parent = GetTransformParent(data_from_ancestor, layer); @@ -172,6 +169,7 @@ data_for_children->transform_tree_parent = layer; if (!requires_node) { + data_for_children->should_flatten |= layer->should_flatten_transform(); gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() + layer->transform().To2dTranslation(); layer->set_offset_to_transform_parent(parent_offset + local_offset); @@ -189,7 +187,9 @@ layer->set_transform_tree_index(node->id); node->data.scrolls = is_scrollable; - node->data.flattens = layer->should_flatten_transform(); + node->data.flattens_inherited_transform = data_for_children->should_flatten; + node->data.flattens_local_transform = layer->should_flatten_transform(); + data_for_children->should_flatten = false; node->data.target_id = data_from_ancestor.render_target->transform_tree_index(); node->data.content_target_id = @@ -316,6 +316,7 @@ data_for_recursion.page_scale_factor = page_scale_factor; data_for_recursion.device_scale_factor = device_scale_factor; data_for_recursion.in_subtree_of_page_scale_application_layer = false; + data_for_recursion.should_flatten = false; data_for_recursion.device_transform = &device_transform; ClipNode root_clip;
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h index 539effe..945e547 100644 --- a/cc/trees/proxy.h +++ b/cc/trees/proxy.h
@@ -80,9 +80,8 @@ virtual void NotifyInputThrottledUntilCommit() = 0; - // Defers commits until it is reset. It is only supported when in threaded - // mode. It's an error to make a sync call like CompositeAndReadback while - // commits are deferred. + // Defers commits until it is reset. It is only supported when using a + // scheduler. virtual void SetDeferCommits(bool defer_commits) = 0; virtual void MainThreadHasStoppedFlinging() = 0; @@ -103,8 +102,6 @@ virtual bool SupportsImplScrolling() const = 0; - virtual void AsValueInto(base::trace_event::TracedValue* value) const = 0; - virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0; virtual void SetChildrenNeedBeginFrames(bool children_need_begin_frames) = 0;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 401a4b8..81c70f0 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -549,18 +549,6 @@ } } -void SingleThreadProxy::AsValueInto( - base::trace_event::TracedValue* state) const { - // The following line casts away const modifiers because it is just - // setting debug state. We still want the AsValue() function and its - // call chain to be const throughout. - DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this)); - - state->BeginDictionary("layer_tree_host_impl"); - layer_tree_host_impl_->AsValueInto(state); - state->EndDictionary(); -} - void SingleThreadProxy::ForceSerializeOnSwapBuffers() { { DebugScopedSetImplThread impl(this);
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index 2612a4d..5bc6d3d 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h
@@ -59,7 +59,6 @@ size_t MaxPartialTextureUpdates() const override; void ForceSerializeOnSwapBuffers() override; bool SupportsImplScrolling() const override; - void AsValueInto(base::trace_event::TracedValue* state) const override; bool MainFrameWillHappenForTesting() override; void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index 8c766f2..7452520 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc
@@ -1252,31 +1252,6 @@ ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {} -void ThreadProxy::AsValueInto(base::trace_event::TracedValue* state) const { - CompletionEvent completion; - { - DebugScopedSetMainThreadBlocked main_thread_blocked( - const_cast<ThreadProxy*>(this)); - scoped_refptr<base::trace_event::TracedValue> state_refptr(state); - Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::AsValueOnImplThread, - impl_thread_weak_ptr_, - &completion, - state_refptr)); - completion.Wait(); - } -} - -void ThreadProxy::AsValueOnImplThread( - CompletionEvent* completion, - base::trace_event::TracedValue* state) const { - state->BeginDictionary("layer_tree_host_impl"); - impl().layer_tree_host_impl->AsValueInto(state); - state->EndDictionary(); - completion->Signal(); -} - bool ThreadProxy::MainFrameWillHappenForTesting() { DCHECK(IsMainThread()); CompletionEvent completion;
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index c2dd348..927caab 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h
@@ -175,7 +175,6 @@ void ForceSerializeOnSwapBuffers() override; bool SupportsImplScrolling() const override; void SetDebugState(const LayerTreeDebugState& debug_state) override; - void AsValueInto(base::trace_event::TracedValue* value) const override; bool MainFrameWillHappenForTesting() override; void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override; @@ -279,8 +278,6 @@ void ForceSerializeOnSwapBuffersOnImplThread(CompletionEvent* completion); void MainFrameWillHappenOnImplThreadForTesting(CompletionEvent* completion, bool* main_frame_will_happen); - void AsValueOnImplThread(CompletionEvent* completion, - base::trace_event::TracedValue* state) const; void SetSwapUsedIncompleteTileOnImplThread(bool used_incomplete_tile); void MainThreadHasStoppedFlingingOnImplThread(); void SetInputThrottledUntilCommitOnImplThread(bool is_throttled);
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index 6f011f7..502bc0a 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -33,6 +33,7 @@ # gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings => //gpu/skia_bindings import("//testing/test.gni") +import("//build/config/ui.gni") component("gpu") { public_deps = [ @@ -183,6 +184,7 @@ "command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc", "command_buffer/service/gles2_cmd_decoder_unittest_base.cc", "command_buffer/service/gles2_cmd_decoder_unittest_base.h", + "command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc", "command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc", "command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc", "command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc", @@ -259,6 +261,7 @@ "//base", "//base/test:test_support", "//gpu/command_buffer/service", + "//testing/gmock", "//testing/gtest", "//testing/perf", "//ui/gfx/geometry", @@ -280,3 +283,25 @@ "//third_party/angle:translator_static", ] } + +if (is_linux && !is_chromeos && target_cpu != "arm" && use_x11) { + executable("compositor_model_bench") { + sources = [ + "tools/compositor_model_bench/compositor_model_bench.cc", + "tools/compositor_model_bench/forward_render_model.cc", + "tools/compositor_model_bench/render_model_utils.cc", + "tools/compositor_model_bench/render_models.cc", + "tools/compositor_model_bench/render_tree.cc", + "tools/compositor_model_bench/shaders.cc", + ] + + libs = [ "GL" ] + + configs += [ "//build/config/linux:x11" ] + + deps = [ + "//base", + "//ui/gl", + ] + } +}
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index 60404dc..c425c52 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -69,6 +69,7 @@ #define glDisableVertexAttribArray GLES2_GET_FUN(DisableVertexAttribArray) #define glDrawArrays GLES2_GET_FUN(DrawArrays) #define glDrawElements GLES2_GET_FUN(DrawElements) +#define glDrawRangeElements GLES2_GET_FUN(DrawRangeElements) #define glEnable GLES2_GET_FUN(Enable) #define glEnableVertexAttribArray GLES2_GET_FUN(EnableVertexAttribArray) #define glFenceSync GLES2_GET_FUN(FenceSync) @@ -256,6 +257,8 @@ #define glUnmapBufferCHROMIUM GLES2_GET_FUN(UnmapBufferCHROMIUM) #define glMapBufferSubDataCHROMIUM GLES2_GET_FUN(MapBufferSubDataCHROMIUM) #define glUnmapBufferSubDataCHROMIUM GLES2_GET_FUN(UnmapBufferSubDataCHROMIUM) +#define glMapBufferRange GLES2_GET_FUN(MapBufferRange) +#define glUnmapBuffer GLES2_GET_FUN(UnmapBuffer) #define glMapTexSubImage2DCHROMIUM GLES2_GET_FUN(MapTexSubImage2DCHROMIUM) #define glUnmapTexSubImage2DCHROMIUM GLES2_GET_FUN(UnmapTexSubImage2DCHROMIUM) #define glResizeCHROMIUM GLES2_GET_FUN(ResizeCHROMIUM)
diff --git a/gpu/blink/webgraphicscontext3d_impl.cc b/gpu/blink/webgraphicscontext3d_impl.cc index 581e102..e469532 100644 --- a/gpu/blink/webgraphicscontext3d_impl.cc +++ b/gpu/blink/webgraphicscontext3d_impl.cc
@@ -19,6 +19,21 @@ #endif #include "third_party/khronos/GLES2/gl2ext.h" +using blink::WGC3Dbitfield; +using blink::WGC3Dboolean; +using blink::WGC3Dbyte; +using blink::WGC3Dchar; +using blink::WGC3Dclampf; +using blink::WGC3Denum; +using blink::WGC3Dfloat; +using blink::WGC3Dint; +using blink::WGC3Dintptr; +using blink::WGC3Dsizei; +using blink::WGC3Dsizeiptr; +using blink::WGC3Duint64; +using blink::WGC3Duint; +using blink::WebGLId; + namespace gpu_blink { namespace { @@ -361,11 +376,12 @@ program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); if (max_name_length < 0) return false; - scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); - if (!name) { - synthesizeGLError(GL_OUT_OF_MEMORY); + if (max_name_length == 0) { + // No active attributes exist. + synthesizeGLError(GL_INVALID_VALUE); return false; } + scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); GLsizei length = 0; GLint size = -1; GLenum type = 0; @@ -387,11 +403,12 @@ program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); if (max_name_length < 0) return false; - scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); - if (!name) { - synthesizeGLError(GL_OUT_OF_MEMORY); + if (max_name_length == 0) { + // No active uniforms exist. + synthesizeGLError(GL_INVALID_VALUE); return false; } + scoped_ptr<GLchar[]> name(new GLchar[max_name_length]); GLsizei length = 0; GLint size = -1; GLenum type = 0;
diff --git a/gpu/blink/webgraphicscontext3d_impl.h b/gpu/blink/webgraphicscontext3d_impl.h index a0d1461..a232d06 100644 --- a/gpu/blink/webgraphicscontext3d_impl.h +++ b/gpu/blink/webgraphicscontext3d_impl.h
@@ -23,22 +23,6 @@ } } -using blink::WebGLId; - -using blink::WGC3Dbyte; -using blink::WGC3Dchar; -using blink::WGC3Denum; -using blink::WGC3Dboolean; -using blink::WGC3Dbitfield; -using blink::WGC3Dint; -using blink::WGC3Dsizei; -using blink::WGC3Duint; -using blink::WGC3Dfloat; -using blink::WGC3Dclampf; -using blink::WGC3Dintptr; -using blink::WGC3Dsizeiptr; -using blink::WGC3Duint64; - namespace gpu_blink { class WebGraphicsContext3DErrorMessageCallback; @@ -56,7 +40,8 @@ virtual unsigned int insertSyncPoint(); virtual void waitSyncPoint(unsigned int sync_point); - virtual void loseContextCHROMIUM(WGC3Denum current, WGC3Denum other); + virtual void loseContextCHROMIUM(blink::WGC3Denum current, + blink::WGC3Denum other); virtual void reshapeWithScaleFactor( int width, int height, float scale_factor); @@ -64,368 +49,442 @@ virtual void prepareTexture(); virtual void postSubBufferCHROMIUM(int x, int y, int width, int height); - virtual void activeTexture(WGC3Denum texture); - virtual void attachShader(WebGLId program, WebGLId shader); - virtual void bindAttribLocation(WebGLId program, WGC3Duint index, - const WGC3Dchar* name); - virtual void bindBuffer(WGC3Denum target, WebGLId buffer); - virtual void bindFramebuffer(WGC3Denum target, WebGLId framebuffer); - virtual void bindRenderbuffer(WGC3Denum target, WebGLId renderbuffer); - virtual void bindTexture(WGC3Denum target, WebGLId texture); - virtual void blendColor(WGC3Dclampf red, WGC3Dclampf green, - WGC3Dclampf blue, WGC3Dclampf alpha); - virtual void blendEquation(WGC3Denum mode); - virtual void blendEquationSeparate(WGC3Denum modeRGB, - WGC3Denum modeAlpha); - virtual void blendFunc(WGC3Denum sfactor, WGC3Denum dfactor); - virtual void blendFuncSeparate(WGC3Denum srcRGB, - WGC3Denum dstRGB, - WGC3Denum srcAlpha, - WGC3Denum dstAlpha); + virtual void activeTexture(blink::WGC3Denum texture); + virtual void attachShader(blink::WebGLId program, blink::WebGLId shader); + virtual void bindAttribLocation(blink::WebGLId program, + blink::WGC3Duint index, + const blink::WGC3Dchar* name); + virtual void bindBuffer(blink::WGC3Denum target, blink::WebGLId buffer); + virtual void bindFramebuffer(blink::WGC3Denum target, + blink::WebGLId framebuffer); + virtual void bindRenderbuffer(blink::WGC3Denum target, + blink::WebGLId renderbuffer); + virtual void bindTexture(blink::WGC3Denum target, blink::WebGLId texture); + virtual void blendColor(blink::WGC3Dclampf red, + blink::WGC3Dclampf green, + blink::WGC3Dclampf blue, + blink::WGC3Dclampf alpha); + virtual void blendEquation(blink::WGC3Denum mode); + virtual void blendEquationSeparate(blink::WGC3Denum modeRGB, + blink::WGC3Denum modeAlpha); + virtual void blendFunc(blink::WGC3Denum sfactor, blink::WGC3Denum dfactor); + virtual void blendFuncSeparate(blink::WGC3Denum srcRGB, + blink::WGC3Denum dstRGB, + blink::WGC3Denum srcAlpha, + blink::WGC3Denum dstAlpha); - virtual void bufferData(WGC3Denum target, WGC3Dsizeiptr size, - const void* data, WGC3Denum usage); - virtual void bufferSubData(WGC3Denum target, WGC3Dintptr offset, - WGC3Dsizeiptr size, const void* data); + virtual void bufferData(blink::WGC3Denum target, + blink::WGC3Dsizeiptr size, + const void* data, + blink::WGC3Denum usage); + virtual void bufferSubData(blink::WGC3Denum target, + blink::WGC3Dintptr offset, + blink::WGC3Dsizeiptr size, + const void* data); - virtual WGC3Denum checkFramebufferStatus(WGC3Denum target); - virtual void clear(WGC3Dbitfield mask); - virtual void clearColor(WGC3Dclampf red, WGC3Dclampf green, - WGC3Dclampf blue, WGC3Dclampf alpha); - virtual void clearDepth(WGC3Dclampf depth); - virtual void clearStencil(WGC3Dint s); - virtual void colorMask(WGC3Dboolean red, WGC3Dboolean green, - WGC3Dboolean blue, WGC3Dboolean alpha); - virtual void compileShader(WebGLId shader); + virtual blink::WGC3Denum checkFramebufferStatus(blink::WGC3Denum target); + virtual void clear(blink::WGC3Dbitfield mask); + virtual void clearColor(blink::WGC3Dclampf red, + blink::WGC3Dclampf green, + blink::WGC3Dclampf blue, + blink::WGC3Dclampf alpha); + virtual void clearDepth(blink::WGC3Dclampf depth); + virtual void clearStencil(blink::WGC3Dint s); + virtual void colorMask(blink::WGC3Dboolean red, + blink::WGC3Dboolean green, + blink::WGC3Dboolean blue, + blink::WGC3Dboolean alpha); + virtual void compileShader(blink::WebGLId shader); - virtual void compressedTexImage2D(WGC3Denum target, - WGC3Dint level, - WGC3Denum internalformat, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Dint border, - WGC3Dsizei imageSize, + virtual void compressedTexImage2D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Denum internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dint border, + blink::WGC3Dsizei imageSize, const void* data); - virtual void compressedTexSubImage2D(WGC3Denum target, - WGC3Dint level, - WGC3Dint xoffset, - WGC3Dint yoffset, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Denum format, - WGC3Dsizei imageSize, + virtual void compressedTexSubImage2D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Denum format, + blink::WGC3Dsizei imageSize, const void* data); - virtual void copyTexImage2D(WGC3Denum target, - WGC3Dint level, - WGC3Denum internalformat, - WGC3Dint x, - WGC3Dint y, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Dint border); - virtual void copyTexSubImage2D(WGC3Denum target, - WGC3Dint level, - WGC3Dint xoffset, - WGC3Dint yoffset, - WGC3Dint x, - WGC3Dint y, - WGC3Dsizei width, - WGC3Dsizei height); - virtual void cullFace(WGC3Denum mode); - virtual void depthFunc(WGC3Denum func); - virtual void depthMask(WGC3Dboolean flag); - virtual void depthRange(WGC3Dclampf zNear, WGC3Dclampf zFar); - virtual void detachShader(WebGLId program, WebGLId shader); - virtual void disable(WGC3Denum cap); - virtual void disableVertexAttribArray(WGC3Duint index); - virtual void drawArrays(WGC3Denum mode, WGC3Dint first, WGC3Dsizei count); - virtual void drawElements(WGC3Denum mode, - WGC3Dsizei count, - WGC3Denum type, - WGC3Dintptr offset); + virtual void copyTexImage2D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Denum internalformat, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dint border); + virtual void copyTexSubImage2D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); + virtual void cullFace(blink::WGC3Denum mode); + virtual void depthFunc(blink::WGC3Denum func); + virtual void depthMask(blink::WGC3Dboolean flag); + virtual void depthRange(blink::WGC3Dclampf zNear, blink::WGC3Dclampf zFar); + virtual void detachShader(blink::WebGLId program, blink::WebGLId shader); + virtual void disable(blink::WGC3Denum cap); + virtual void disableVertexAttribArray(blink::WGC3Duint index); + virtual void drawArrays(blink::WGC3Denum mode, + blink::WGC3Dint first, + blink::WGC3Dsizei count); + virtual void drawElements(blink::WGC3Denum mode, + blink::WGC3Dsizei count, + blink::WGC3Denum type, + blink::WGC3Dintptr offset); - virtual void enable(WGC3Denum cap); - virtual void enableVertexAttribArray(WGC3Duint index); + virtual void enable(blink::WGC3Denum cap); + virtual void enableVertexAttribArray(blink::WGC3Duint index); virtual void finish(); virtual void flush(); - virtual void framebufferRenderbuffer(WGC3Denum target, - WGC3Denum attachment, - WGC3Denum renderbuffertarget, - WebGLId renderbuffer); - virtual void framebufferTexture2D(WGC3Denum target, - WGC3Denum attachment, - WGC3Denum textarget, - WebGLId texture, - WGC3Dint level); - virtual void frontFace(WGC3Denum mode); - virtual void generateMipmap(WGC3Denum target); + virtual void framebufferRenderbuffer(blink::WGC3Denum target, + blink::WGC3Denum attachment, + blink::WGC3Denum renderbuffertarget, + blink::WebGLId renderbuffer); + virtual void framebufferTexture2D(blink::WGC3Denum target, + blink::WGC3Denum attachment, + blink::WGC3Denum textarget, + blink::WebGLId texture, + blink::WGC3Dint level); + virtual void frontFace(blink::WGC3Denum mode); + virtual void generateMipmap(blink::WGC3Denum target); - virtual bool getActiveAttrib(WebGLId program, - WGC3Duint index, + virtual bool getActiveAttrib(blink::WebGLId program, + blink::WGC3Duint index, ActiveInfo&); - virtual bool getActiveUniform(WebGLId program, - WGC3Duint index, + virtual bool getActiveUniform(blink::WebGLId program, + blink::WGC3Duint index, ActiveInfo&); - virtual void getAttachedShaders(WebGLId program, - WGC3Dsizei maxCount, - WGC3Dsizei* count, - WebGLId* shaders); + virtual void getAttachedShaders(blink::WebGLId program, + blink::WGC3Dsizei maxCount, + blink::WGC3Dsizei* count, + blink::WebGLId* shaders); - virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name); + virtual blink::WGC3Dint getAttribLocation(blink::WebGLId program, + const blink::WGC3Dchar* name); - virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value); + virtual void getBooleanv(blink::WGC3Denum pname, blink::WGC3Dboolean* value); - virtual void getBufferParameteriv(WGC3Denum target, - WGC3Denum pname, - WGC3Dint* value); + virtual void getBufferParameteriv(blink::WGC3Denum target, + blink::WGC3Denum pname, + blink::WGC3Dint* value); - virtual WGC3Denum getError(); + virtual blink::WGC3Denum getError(); - virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value); + virtual void getFloatv(blink::WGC3Denum pname, blink::WGC3Dfloat* value); - virtual void getFramebufferAttachmentParameteriv(WGC3Denum target, - WGC3Denum attachment, - WGC3Denum pname, - WGC3Dint* value); + virtual void getFramebufferAttachmentParameteriv(blink::WGC3Denum target, + blink::WGC3Denum attachment, + blink::WGC3Denum pname, + blink::WGC3Dint* value); - virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value); + virtual void getIntegerv(blink::WGC3Denum pname, blink::WGC3Dint* value); - virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value); + virtual void getProgramiv(blink::WebGLId program, + blink::WGC3Denum pname, + blink::WGC3Dint* value); - virtual blink::WebString getProgramInfoLog(WebGLId program); + virtual blink::WebString getProgramInfoLog(blink::WebGLId program); - virtual void getRenderbufferParameteriv(WGC3Denum target, - WGC3Denum pname, - WGC3Dint* value); + virtual void getRenderbufferParameteriv(blink::WGC3Denum target, + blink::WGC3Denum pname, + blink::WGC3Dint* value); - virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value); + virtual void getShaderiv(blink::WebGLId shader, + blink::WGC3Denum pname, + blink::WGC3Dint* value); - virtual blink::WebString getShaderInfoLog(WebGLId shader); + virtual blink::WebString getShaderInfoLog(blink::WebGLId shader); - virtual void getShaderPrecisionFormat(WGC3Denum shadertype, - WGC3Denum precisiontype, - WGC3Dint* range, - WGC3Dint* precision); + virtual void getShaderPrecisionFormat(blink::WGC3Denum shadertype, + blink::WGC3Denum precisiontype, + blink::WGC3Dint* range, + blink::WGC3Dint* precision); - virtual blink::WebString getShaderSource(WebGLId shader); - virtual blink::WebString getString(WGC3Denum name); + virtual blink::WebString getShaderSource(blink::WebGLId shader); + virtual blink::WebString getString(blink::WGC3Denum name); - virtual void getTexParameterfv(WGC3Denum target, - WGC3Denum pname, - WGC3Dfloat* value); - virtual void getTexParameteriv(WGC3Denum target, - WGC3Denum pname, - WGC3Dint* value); + virtual void getTexParameterfv(blink::WGC3Denum target, + blink::WGC3Denum pname, + blink::WGC3Dfloat* value); + virtual void getTexParameteriv(blink::WGC3Denum target, + blink::WGC3Denum pname, + blink::WGC3Dint* value); - virtual void getUniformfv(WebGLId program, - WGC3Dint location, - WGC3Dfloat* value); - virtual void getUniformiv(WebGLId program, - WGC3Dint location, - WGC3Dint* value); + virtual void getUniformfv(blink::WebGLId program, + blink::WGC3Dint location, + blink::WGC3Dfloat* value); + virtual void getUniformiv(blink::WebGLId program, + blink::WGC3Dint location, + blink::WGC3Dint* value); - virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name); + virtual blink::WGC3Dint getUniformLocation(blink::WebGLId program, + const blink::WGC3Dchar* name); - virtual void getVertexAttribfv(WGC3Duint index, WGC3Denum pname, - WGC3Dfloat* value); - virtual void getVertexAttribiv(WGC3Duint index, WGC3Denum pname, - WGC3Dint* value); + virtual void getVertexAttribfv(blink::WGC3Duint index, + blink::WGC3Denum pname, + blink::WGC3Dfloat* value); + virtual void getVertexAttribiv(blink::WGC3Duint index, + blink::WGC3Denum pname, + blink::WGC3Dint* value); - virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index, WGC3Denum pname); + virtual blink::WGC3Dsizeiptr getVertexAttribOffset(blink::WGC3Duint index, + blink::WGC3Denum pname); - virtual void hint(WGC3Denum target, WGC3Denum mode); - virtual WGC3Dboolean isBuffer(WebGLId buffer); - virtual WGC3Dboolean isEnabled(WGC3Denum cap); - virtual WGC3Dboolean isFramebuffer(WebGLId framebuffer); - virtual WGC3Dboolean isProgram(WebGLId program); - virtual WGC3Dboolean isRenderbuffer(WebGLId renderbuffer); - virtual WGC3Dboolean isShader(WebGLId shader); - virtual WGC3Dboolean isTexture(WebGLId texture); - virtual void lineWidth(WGC3Dfloat); - virtual void linkProgram(WebGLId program); - virtual void pixelStorei(WGC3Denum pname, WGC3Dint param); - virtual void polygonOffset(WGC3Dfloat factor, WGC3Dfloat units); + virtual void hint(blink::WGC3Denum target, blink::WGC3Denum mode); + virtual blink::WGC3Dboolean isBuffer(blink::WebGLId buffer); + virtual blink::WGC3Dboolean isEnabled(blink::WGC3Denum cap); + virtual blink::WGC3Dboolean isFramebuffer(blink::WebGLId framebuffer); + virtual blink::WGC3Dboolean isProgram(blink::WebGLId program); + virtual blink::WGC3Dboolean isRenderbuffer(blink::WebGLId renderbuffer); + virtual blink::WGC3Dboolean isShader(blink::WebGLId shader); + virtual blink::WGC3Dboolean isTexture(blink::WebGLId texture); + virtual void lineWidth(blink::WGC3Dfloat); + virtual void linkProgram(blink::WebGLId program); + virtual void pixelStorei(blink::WGC3Denum pname, blink::WGC3Dint param); + virtual void polygonOffset(blink::WGC3Dfloat factor, blink::WGC3Dfloat units); - virtual void readPixels(WGC3Dint x, - WGC3Dint y, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Denum format, - WGC3Denum type, + virtual void readPixels(blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Denum format, + blink::WGC3Denum type, void* pixels); virtual void releaseShaderCompiler(); - virtual void renderbufferStorage(WGC3Denum target, - WGC3Denum internalformat, - WGC3Dsizei width, - WGC3Dsizei height); - virtual void sampleCoverage(WGC3Dfloat value, WGC3Dboolean invert); - virtual void scissor(WGC3Dint x, WGC3Dint y, - WGC3Dsizei width, WGC3Dsizei height); - virtual void shaderSource(WebGLId shader, const WGC3Dchar* string); - virtual void stencilFunc(WGC3Denum func, WGC3Dint ref, WGC3Duint mask); - virtual void stencilFuncSeparate(WGC3Denum face, - WGC3Denum func, - WGC3Dint ref, - WGC3Duint mask); - virtual void stencilMask(WGC3Duint mask); - virtual void stencilMaskSeparate(WGC3Denum face, WGC3Duint mask); - virtual void stencilOp(WGC3Denum fail, - WGC3Denum zfail, - WGC3Denum zpass); - virtual void stencilOpSeparate(WGC3Denum face, - WGC3Denum fail, - WGC3Denum zfail, - WGC3Denum zpass); + virtual void renderbufferStorage(blink::WGC3Denum target, + blink::WGC3Denum internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); + virtual void sampleCoverage(blink::WGC3Dfloat value, + blink::WGC3Dboolean invert); + virtual void scissor(blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); + virtual void shaderSource(blink::WebGLId shader, + const blink::WGC3Dchar* string); + virtual void stencilFunc(blink::WGC3Denum func, + blink::WGC3Dint ref, + blink::WGC3Duint mask); + virtual void stencilFuncSeparate(blink::WGC3Denum face, + blink::WGC3Denum func, + blink::WGC3Dint ref, + blink::WGC3Duint mask); + virtual void stencilMask(blink::WGC3Duint mask); + virtual void stencilMaskSeparate(blink::WGC3Denum face, + blink::WGC3Duint mask); + virtual void stencilOp(blink::WGC3Denum fail, + blink::WGC3Denum zfail, + blink::WGC3Denum zpass); + virtual void stencilOpSeparate(blink::WGC3Denum face, + blink::WGC3Denum fail, + blink::WGC3Denum zfail, + blink::WGC3Denum zpass); - virtual void texImage2D(WGC3Denum target, - WGC3Dint level, - WGC3Denum internalformat, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Dint border, - WGC3Denum format, - WGC3Denum type, + virtual void texImage2D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Denum internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dint border, + blink::WGC3Denum format, + blink::WGC3Denum type, const void* pixels); - virtual void texParameterf(WGC3Denum target, - WGC3Denum pname, - WGC3Dfloat param); - virtual void texParameteri(WGC3Denum target, - WGC3Denum pname, - WGC3Dint param); + virtual void texParameterf(blink::WGC3Denum target, + blink::WGC3Denum pname, + blink::WGC3Dfloat param); + virtual void texParameteri(blink::WGC3Denum target, + blink::WGC3Denum pname, + blink::WGC3Dint param); - virtual void texSubImage2D(WGC3Denum target, - WGC3Dint level, - WGC3Dint xoffset, - WGC3Dint yoffset, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Denum format, - WGC3Denum type, + virtual void texSubImage2D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Denum format, + blink::WGC3Denum type, const void* pixels); - virtual void uniform1f(WGC3Dint location, WGC3Dfloat x); - virtual void uniform1fv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dfloat* v); - virtual void uniform1i(WGC3Dint location, WGC3Dint x); - virtual void uniform1iv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dint* v); - virtual void uniform2f(WGC3Dint location, WGC3Dfloat x, WGC3Dfloat y); - virtual void uniform2fv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dfloat* v); - virtual void uniform2i(WGC3Dint location, WGC3Dint x, WGC3Dint y); - virtual void uniform2iv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dint* v); - virtual void uniform3f(WGC3Dint location, - WGC3Dfloat x, WGC3Dfloat y, WGC3Dfloat z); - virtual void uniform3fv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dfloat* v); - virtual void uniform3i(WGC3Dint location, - WGC3Dint x, WGC3Dint y, WGC3Dint z); - virtual void uniform3iv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dint* v); - virtual void uniform4f(WGC3Dint location, - WGC3Dfloat x, WGC3Dfloat y, - WGC3Dfloat z, WGC3Dfloat w); - virtual void uniform4fv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dfloat* v); - virtual void uniform4i(WGC3Dint location, - WGC3Dint x, WGC3Dint y, WGC3Dint z, WGC3Dint w); - virtual void uniform4iv(WGC3Dint location, - WGC3Dsizei count, const WGC3Dint* v); - virtual void uniformMatrix2fv(WGC3Dint location, - WGC3Dsizei count, - WGC3Dboolean transpose, - const WGC3Dfloat* value); - virtual void uniformMatrix3fv(WGC3Dint location, - WGC3Dsizei count, - WGC3Dboolean transpose, - const WGC3Dfloat* value); - virtual void uniformMatrix4fv(WGC3Dint location, - WGC3Dsizei count, - WGC3Dboolean transpose, - const WGC3Dfloat* value); + virtual void uniform1f(blink::WGC3Dint location, blink::WGC3Dfloat x); + virtual void uniform1fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dfloat* v); + virtual void uniform1i(blink::WGC3Dint location, blink::WGC3Dint x); + virtual void uniform1iv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dint* v); + virtual void uniform2f(blink::WGC3Dint location, + blink::WGC3Dfloat x, + blink::WGC3Dfloat y); + virtual void uniform2fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dfloat* v); + virtual void uniform2i(blink::WGC3Dint location, + blink::WGC3Dint x, + blink::WGC3Dint y); + virtual void uniform2iv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dint* v); + virtual void uniform3f(blink::WGC3Dint location, + blink::WGC3Dfloat x, + blink::WGC3Dfloat y, + blink::WGC3Dfloat z); + virtual void uniform3fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dfloat* v); + virtual void uniform3i(blink::WGC3Dint location, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dint z); + virtual void uniform3iv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dint* v); + virtual void uniform4f(blink::WGC3Dint location, + blink::WGC3Dfloat x, + blink::WGC3Dfloat y, + blink::WGC3Dfloat z, + blink::WGC3Dfloat w); + virtual void uniform4fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dfloat* v); + virtual void uniform4i(blink::WGC3Dint location, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dint z, + blink::WGC3Dint w); + virtual void uniform4iv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Dint* v); + virtual void uniformMatrix2fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void uniformMatrix3fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void uniformMatrix4fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); - virtual void useProgram(WebGLId program); - virtual void validateProgram(WebGLId program); + virtual void useProgram(blink::WebGLId program); + virtual void validateProgram(blink::WebGLId program); - virtual void vertexAttrib1f(WGC3Duint index, WGC3Dfloat x); - virtual void vertexAttrib1fv(WGC3Duint index, const WGC3Dfloat* values); - virtual void vertexAttrib2f(WGC3Duint index, WGC3Dfloat x, WGC3Dfloat y); - virtual void vertexAttrib2fv(WGC3Duint index, const WGC3Dfloat* values); - virtual void vertexAttrib3f(WGC3Duint index, - WGC3Dfloat x, WGC3Dfloat y, WGC3Dfloat z); - virtual void vertexAttrib3fv(WGC3Duint index, const WGC3Dfloat* values); - virtual void vertexAttrib4f(WGC3Duint index, - WGC3Dfloat x, WGC3Dfloat y, - WGC3Dfloat z, WGC3Dfloat w); - virtual void vertexAttrib4fv(WGC3Duint index, const WGC3Dfloat* values); - virtual void vertexAttribPointer(WGC3Duint index, - WGC3Dint size, - WGC3Denum type, - WGC3Dboolean normalized, - WGC3Dsizei stride, - WGC3Dintptr offset); + virtual void vertexAttrib1f(blink::WGC3Duint index, blink::WGC3Dfloat x); + virtual void vertexAttrib1fv(blink::WGC3Duint index, + const blink::WGC3Dfloat* values); + virtual void vertexAttrib2f(blink::WGC3Duint index, + blink::WGC3Dfloat x, + blink::WGC3Dfloat y); + virtual void vertexAttrib2fv(blink::WGC3Duint index, + const blink::WGC3Dfloat* values); + virtual void vertexAttrib3f(blink::WGC3Duint index, + blink::WGC3Dfloat x, + blink::WGC3Dfloat y, + blink::WGC3Dfloat z); + virtual void vertexAttrib3fv(blink::WGC3Duint index, + const blink::WGC3Dfloat* values); + virtual void vertexAttrib4f(blink::WGC3Duint index, + blink::WGC3Dfloat x, + blink::WGC3Dfloat y, + blink::WGC3Dfloat z, + blink::WGC3Dfloat w); + virtual void vertexAttrib4fv(blink::WGC3Duint index, + const blink::WGC3Dfloat* values); + virtual void vertexAttribPointer(blink::WGC3Duint index, + blink::WGC3Dint size, + blink::WGC3Denum type, + blink::WGC3Dboolean normalized, + blink::WGC3Dsizei stride, + blink::WGC3Dintptr offset); - virtual void viewport(WGC3Dint x, WGC3Dint y, - WGC3Dsizei width, WGC3Dsizei height); + virtual void viewport(blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); - virtual WebGLId createBuffer(); - virtual WebGLId createFramebuffer(); - virtual WebGLId createRenderbuffer(); - virtual WebGLId createTexture(); + virtual blink::WebGLId createBuffer(); + virtual blink::WebGLId createFramebuffer(); + virtual blink::WebGLId createRenderbuffer(); + virtual blink::WebGLId createTexture(); - virtual void deleteBuffer(WebGLId); - virtual void deleteFramebuffer(WebGLId); - virtual void deleteRenderbuffer(WebGLId); - virtual void deleteTexture(WebGLId); + virtual void deleteBuffer(blink::WebGLId); + virtual void deleteFramebuffer(blink::WebGLId); + virtual void deleteRenderbuffer(blink::WebGLId); + virtual void deleteTexture(blink::WebGLId); - virtual WebGLId createProgram(); - virtual WebGLId createShader(WGC3Denum); + virtual blink::WebGLId createProgram(); + virtual blink::WebGLId createShader(blink::WGC3Denum); - virtual void deleteProgram(WebGLId); - virtual void deleteShader(WebGLId); + virtual void deleteProgram(blink::WebGLId); + virtual void deleteShader(blink::WebGLId); - virtual void synthesizeGLError(WGC3Denum); + virtual void synthesizeGLError(blink::WGC3Denum); - virtual void* mapBufferSubDataCHROMIUM( - WGC3Denum target, WGC3Dintptr offset, - WGC3Dsizeiptr size, WGC3Denum access); + virtual void* mapBufferSubDataCHROMIUM(blink::WGC3Denum target, + blink::WGC3Dintptr offset, + blink::WGC3Dsizeiptr size, + blink::WGC3Denum access); virtual void unmapBufferSubDataCHROMIUM(const void*); - virtual void* mapTexSubImage2DCHROMIUM( - WGC3Denum target, - WGC3Dint level, - WGC3Dint xoffset, - WGC3Dint yoffset, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Denum format, - WGC3Denum type, - WGC3Denum access); + virtual void* mapTexSubImage2DCHROMIUM(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Denum format, + blink::WGC3Denum type, + blink::WGC3Denum access); virtual void unmapTexSubImage2DCHROMIUM(const void*); virtual void setVisibilityCHROMIUM(bool visible); - virtual void discardFramebufferEXT(WGC3Denum target, - WGC3Dsizei numAttachments, - const WGC3Denum* attachments); - virtual void copyTextureToParentTextureCHROMIUM( - WebGLId texture, WebGLId parentTexture); + virtual void discardFramebufferEXT(blink::WGC3Denum target, + blink::WGC3Dsizei numAttachments, + const blink::WGC3Denum* attachments); + virtual void copyTextureToParentTextureCHROMIUM(blink::WebGLId texture, + blink::WebGLId parentTexture); virtual blink::WebString getRequestableExtensionsCHROMIUM(); virtual void requestExtensionCHROMIUM(const char*); - virtual void blitFramebufferCHROMIUM( - WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, - WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, - WGC3Dbitfield mask, WGC3Denum filter); + virtual void blitFramebufferCHROMIUM(blink::WGC3Dint srcX0, + blink::WGC3Dint srcY0, + blink::WGC3Dint srcX1, + blink::WGC3Dint srcY1, + blink::WGC3Dint dstX0, + blink::WGC3Dint dstY0, + blink::WGC3Dint dstX1, + blink::WGC3Dint dstY1, + blink::WGC3Dbitfield mask, + blink::WGC3Denum filter); virtual void renderbufferStorageMultisampleCHROMIUM( - WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, - WGC3Dsizei width, WGC3Dsizei height); + blink::WGC3Denum target, + blink::WGC3Dsizei samples, + blink::WGC3Denum internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); - virtual blink::WebString getTranslatedShaderSourceANGLE(WebGLId shader); + virtual blink::WebString getTranslatedShaderSourceANGLE( + blink::WebGLId shader); virtual void setContextLostCallback( WebGraphicsContext3D::WebGraphicsContextLostCallback* callback); @@ -433,291 +492,424 @@ virtual void setErrorMessageCallback( WebGraphicsContext3D::WebGraphicsErrorMessageCallback* callback); - virtual void texImageIOSurface2DCHROMIUM( - WGC3Denum target, WGC3Dint width, WGC3Dint height, - WGC3Duint ioSurfaceId, WGC3Duint plane); + virtual void texImageIOSurface2DCHROMIUM(blink::WGC3Denum target, + blink::WGC3Dint width, + blink::WGC3Dint height, + blink::WGC3Duint ioSurfaceId, + blink::WGC3Duint plane); - virtual void texStorage2DEXT( - WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat, - WGC3Dint width, WGC3Dint height); + virtual void texStorage2DEXT(blink::WGC3Denum target, + blink::WGC3Dint levels, + blink::WGC3Duint internalformat, + blink::WGC3Dint width, + blink::WGC3Dint height); - virtual WebGLId createQueryEXT(); - virtual void deleteQueryEXT(WebGLId query); - virtual WGC3Dboolean isQueryEXT(WGC3Duint query); - virtual void beginQueryEXT(WGC3Denum target, WebGLId query); - virtual void endQueryEXT(WGC3Denum target); - virtual void getQueryivEXT( - WGC3Denum target, WGC3Denum pname, WGC3Dint* params); - virtual void getQueryObjectuivEXT( - WebGLId query, WGC3Denum pname, WGC3Duint* params); + virtual blink::WebGLId createQueryEXT(); + virtual void deleteQueryEXT(blink::WebGLId query); + virtual blink::WGC3Dboolean isQueryEXT(blink::WGC3Duint query); + virtual void beginQueryEXT(blink::WGC3Denum target, blink::WebGLId query); + virtual void endQueryEXT(blink::WGC3Denum target); + virtual void getQueryivEXT(blink::WGC3Denum target, + blink::WGC3Denum pname, + blink::WGC3Dint* params); + virtual void getQueryObjectuivEXT(blink::WebGLId query, + blink::WGC3Denum pname, + blink::WGC3Duint* params); // TODO(dshwang): Remove |level| in Blink and then remove it. - void copyTextureCHROMIUM(WGC3Denum target, - WebGLId source_id, - WebGLId dest_id, - WGC3Dint level, - WGC3Denum internal_format, - WGC3Denum dest_type) override; + void copyTextureCHROMIUM(blink::WGC3Denum target, + blink::WebGLId source_id, + blink::WebGLId dest_id, + blink::WGC3Dint level, + blink::WGC3Denum internal_format, + blink::WGC3Denum dest_type) override; - void copySubTextureCHROMIUM(WGC3Denum target, - WebGLId source_id, - WebGLId dest_id, - WGC3Dint level, - WGC3Dint xoffset, - WGC3Dint yoffset) override; + void copySubTextureCHROMIUM(blink::WGC3Denum target, + blink::WebGLId source_id, + blink::WebGLId dest_id, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset) override; - virtual void copyTextureCHROMIUM(WGC3Denum target, - WebGLId source_id, - WebGLId dest_id, - WGC3Denum internal_format, - WGC3Denum dest_type); + virtual void copyTextureCHROMIUM(blink::WGC3Denum target, + blink::WebGLId source_id, + blink::WebGLId dest_id, + blink::WGC3Denum internal_format, + blink::WGC3Denum dest_type); - virtual void copySubTextureCHROMIUM(WGC3Denum target, - WebGLId sourceId, - WebGLId destId, - WGC3Dint xoffset, - WGC3Dint yoffset); + virtual void copySubTextureCHROMIUM(blink::WGC3Denum target, + blink::WebGLId sourceId, + blink::WebGLId destId, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset); - virtual void bindUniformLocationCHROMIUM(WebGLId program, WGC3Dint location, - const WGC3Dchar* uniform); + virtual void bindUniformLocationCHROMIUM(blink::WebGLId program, + blink::WGC3Dint location, + const blink::WGC3Dchar* uniform); virtual void shallowFlushCHROMIUM(); virtual void shallowFinishCHROMIUM(); - virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox); - virtual void produceTextureCHROMIUM(WGC3Denum target, - const WGC3Dbyte* mailbox); - virtual void produceTextureDirectCHROMIUM(WebGLId texture, WGC3Denum target, - const WGC3Dbyte* mailbox); - virtual void consumeTextureCHROMIUM(WGC3Denum target, - const WGC3Dbyte* mailbox); - virtual WebGLId createAndConsumeTextureCHROMIUM(WGC3Denum target, - const WGC3Dbyte* mailbox); + virtual void genMailboxCHROMIUM(blink::WGC3Dbyte* mailbox); + virtual void produceTextureCHROMIUM(blink::WGC3Denum target, + const blink::WGC3Dbyte* mailbox); + virtual void produceTextureDirectCHROMIUM(blink::WebGLId texture, + blink::WGC3Denum target, + const blink::WGC3Dbyte* mailbox); + virtual void consumeTextureCHROMIUM(blink::WGC3Denum target, + const blink::WGC3Dbyte* mailbox); + virtual blink::WebGLId createAndConsumeTextureCHROMIUM( + blink::WGC3Denum target, + const blink::WGC3Dbyte* mailbox); - virtual void genValuebuffersCHROMIUM(WGC3Dsizei count, WebGLId* ids); - virtual WebGLId createValuebufferCHROMIUM(); - virtual void deleteValuebuffersCHROMIUM(WGC3Dsizei count, WebGLId* ids); - virtual void deleteValuebufferCHROMIUM(WebGLId); - virtual void bindValuebufferCHROMIUM(WGC3Denum target, WebGLId valuebuffer); - virtual WGC3Dboolean isValuebufferCHROMIUM(WebGLId renderbuffer); - virtual void subscribeValueCHROMIUM(WGC3Denum target, WGC3Denum subscription); - virtual void populateSubscribedValuesCHROMIUM(WGC3Denum target); - virtual void uniformValuebufferCHROMIUM(WGC3Dint location, - WGC3Denum target, - WGC3Denum subscription); - virtual void traceBeginCHROMIUM(const WGC3Dchar* category_name, - const WGC3Dchar* trace_name); + virtual void genValuebuffersCHROMIUM(blink::WGC3Dsizei count, + blink::WebGLId* ids); + virtual blink::WebGLId createValuebufferCHROMIUM(); + virtual void deleteValuebuffersCHROMIUM(blink::WGC3Dsizei count, + blink::WebGLId* ids); + virtual void deleteValuebufferCHROMIUM(blink::WebGLId); + virtual void bindValuebufferCHROMIUM(blink::WGC3Denum target, + blink::WebGLId valuebuffer); + virtual blink::WGC3Dboolean isValuebufferCHROMIUM( + blink::WebGLId renderbuffer); + virtual void subscribeValueCHROMIUM(blink::WGC3Denum target, + blink::WGC3Denum subscription); + virtual void populateSubscribedValuesCHROMIUM(blink::WGC3Denum target); + virtual void uniformValuebufferCHROMIUM(blink::WGC3Dint location, + blink::WGC3Denum target, + blink::WGC3Denum subscription); + virtual void traceBeginCHROMIUM(const blink::WGC3Dchar* category_name, + const blink::WGC3Dchar* trace_name); virtual void traceEndCHROMIUM(); - virtual void insertEventMarkerEXT(const WGC3Dchar* marker); - virtual void pushGroupMarkerEXT(const WGC3Dchar* marker); + virtual void insertEventMarkerEXT(const blink::WGC3Dchar* marker); + virtual void pushGroupMarkerEXT(const blink::WGC3Dchar* marker); virtual void popGroupMarkerEXT(); // GL_OES_vertex_array_object - virtual WebGLId createVertexArrayOES(); - virtual void deleteVertexArrayOES(WebGLId array); - virtual WGC3Dboolean isVertexArrayOES(WebGLId array); - virtual void bindVertexArrayOES(WebGLId array); + virtual blink::WebGLId createVertexArrayOES(); + virtual void deleteVertexArrayOES(blink::WebGLId array); + virtual blink::WGC3Dboolean isVertexArrayOES(blink::WebGLId array); + virtual void bindVertexArrayOES(blink::WebGLId array); - virtual void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint image_id); - virtual void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint image_id); + virtual void bindTexImage2DCHROMIUM(blink::WGC3Denum target, + blink::WGC3Dint image_id); + virtual void releaseTexImage2DCHROMIUM(blink::WGC3Denum target, + blink::WGC3Dint image_id); - virtual void* mapBufferCHROMIUM(WGC3Denum target, WGC3Denum access); - virtual WGC3Dboolean unmapBufferCHROMIUM(WGC3Denum target); + virtual void* mapBufferCHROMIUM(blink::WGC3Denum target, + blink::WGC3Denum access); + virtual blink::WGC3Dboolean unmapBufferCHROMIUM(blink::WGC3Denum target); // Async pixel transfer functions. - virtual void asyncTexImage2DCHROMIUM( - WGC3Denum target, - WGC3Dint level, - WGC3Denum internalformat, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Dint border, - WGC3Denum format, - WGC3Denum type, - const void* pixels); - virtual void asyncTexSubImage2DCHROMIUM( - WGC3Denum target, - WGC3Dint level, - WGC3Dint xoffset, - WGC3Dint yoffset, - WGC3Dsizei width, - WGC3Dsizei height, - WGC3Denum format, - WGC3Denum type, - const void* pixels); - virtual void waitAsyncTexImage2DCHROMIUM(WGC3Denum target); + virtual void asyncTexImage2DCHROMIUM(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Denum internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dint border, + blink::WGC3Denum format, + blink::WGC3Denum type, + const void* pixels); + virtual void asyncTexSubImage2DCHROMIUM(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Denum format, + blink::WGC3Denum type, + const void* pixels); + virtual void waitAsyncTexImage2DCHROMIUM(blink::WGC3Denum target); // GL_EXT_draw_buffers - virtual void drawBuffersEXT( - WGC3Dsizei n, - const WGC3Denum* bufs); + virtual void drawBuffersEXT(blink::WGC3Dsizei n, + const blink::WGC3Denum* bufs); // GL_ANGLE_instanced_arrays - virtual void drawArraysInstancedANGLE(WGC3Denum mode, WGC3Dint first, - WGC3Dsizei count, WGC3Dsizei primcount); - virtual void drawElementsInstancedANGLE(WGC3Denum mode, WGC3Dsizei count, - WGC3Denum type, WGC3Dintptr offset, WGC3Dsizei primcount); - virtual void vertexAttribDivisorANGLE(WGC3Duint index, WGC3Duint divisor); + virtual void drawArraysInstancedANGLE(blink::WGC3Denum mode, + blink::WGC3Dint first, + blink::WGC3Dsizei count, + blink::WGC3Dsizei primcount); + virtual void drawElementsInstancedANGLE(blink::WGC3Denum mode, + blink::WGC3Dsizei count, + blink::WGC3Denum type, + blink::WGC3Dintptr offset, + blink::WGC3Dsizei primcount); + virtual void vertexAttribDivisorANGLE(blink::WGC3Duint index, + blink::WGC3Duint divisor); // GL_CHROMIUM_gpu_memory_buffer_image - virtual WGC3Duint createGpuMemoryBufferImageCHROMIUM(WGC3Dsizei width, - WGC3Dsizei height, - WGC3Denum internalformat, - WGC3Denum usage); - virtual void destroyImageCHROMIUM(WGC3Duint image_id); + virtual blink::WGC3Duint createGpuMemoryBufferImageCHROMIUM( + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Denum internalformat, + blink::WGC3Denum usage); + virtual void destroyImageCHROMIUM(blink::WGC3Duint image_id); // GL_EXT_multisampled_render_to_texture - virtual void framebufferTexture2DMultisampleEXT(WGC3Denum target, - WGC3Denum attachment, - WGC3Denum textarget, - WebGLId texture, - WGC3Dint level, - WGC3Dsizei samples); + virtual void framebufferTexture2DMultisampleEXT(blink::WGC3Denum target, + blink::WGC3Denum attachment, + blink::WGC3Denum textarget, + blink::WebGLId texture, + blink::WGC3Dint level, + blink::WGC3Dsizei samples); virtual void renderbufferStorageMultisampleEXT( - WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, - WGC3Dsizei width, WGC3Dsizei height); + blink::WGC3Denum target, + blink::WGC3Dsizei samples, + blink::WGC3Denum internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); // OpenGL ES 3.0 functions not represented by pre-existing extensions - virtual void beginTransformFeedback(WGC3Denum primitiveMode); - virtual void bindBufferBase(WGC3Denum target, WGC3Duint index, - WGC3Duint buffer); - virtual void bindBufferRange(WGC3Denum target, WGC3Duint index, - WGC3Duint buffer, WGC3Dintptr offset, WGC3Dsizeiptr size); - virtual void bindSampler(WGC3Duint unit, WebGLId sampler); - virtual void bindTransformFeedback(WGC3Denum target, - WebGLId transformfeedback); - virtual void clearBufferfi(WGC3Denum buffer, WGC3Dint drawbuffer, - WGC3Dfloat depth, WGC3Dint stencil); - virtual void clearBufferfv(WGC3Denum buffer, WGC3Dint drawbuffer, - const WGC3Dfloat *value); - virtual void clearBufferiv(WGC3Denum buffer, WGC3Dint drawbuffer, - const WGC3Dint *value); - virtual void clearBufferuiv(WGC3Denum buffer, WGC3Dint drawbuffer, - const WGC3Duint *value); - //virtual WGC3Denum clientWaitSync(WebGLId sync, WGC3Dbitfield flags, - // WGC3Duint64 timeout); - //virtual void compressedTexImage3D(WGC3Denum target, WGC3Dint level, - // WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, - // WGC3Dsizei depth, WGC3Dint border, WGC3Dsizei imageSize, - // const void *data); - //virtual void compressedTexSubImage3D(WGC3Denum target, WGC3Dint level, - // WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dsizei width, - // WGC3Dsizei height, WGC3Dsizei depth, WGC3Denum format, + virtual void beginTransformFeedback(blink::WGC3Denum primitiveMode); + virtual void bindBufferBase(blink::WGC3Denum target, + blink::WGC3Duint index, + blink::WGC3Duint buffer); + virtual void bindBufferRange(blink::WGC3Denum target, + blink::WGC3Duint index, + blink::WGC3Duint buffer, + blink::WGC3Dintptr offset, + blink::WGC3Dsizeiptr size); + virtual void bindSampler(blink::WGC3Duint unit, blink::WebGLId sampler); + virtual void bindTransformFeedback(blink::WGC3Denum target, + blink::WebGLId transformfeedback); + virtual void clearBufferfi(blink::WGC3Denum buffer, + blink::WGC3Dint drawbuffer, + blink::WGC3Dfloat depth, + blink::WGC3Dint stencil); + virtual void clearBufferfv(blink::WGC3Denum buffer, + blink::WGC3Dint drawbuffer, + const blink::WGC3Dfloat* value); + virtual void clearBufferiv(blink::WGC3Denum buffer, + blink::WGC3Dint drawbuffer, + const blink::WGC3Dint* value); + virtual void clearBufferuiv(blink::WGC3Denum buffer, + blink::WGC3Dint drawbuffer, + const blink::WGC3Duint* value); + // virtual blink::WGC3Denum clientWaitSync(blink::WebGLId sync, + // blink::WGC3Dbitfield flags, + // blink::WGC3Duint64 timeout); + // virtual void compressedTexImage3D(blink::WGC3Denum target, blink::WGC3Dint + // level, + // blink::WGC3Denum internalformat, blink::WGC3Dsizei width, + // WGC3Dsizei height, WGC3Dsizei depth, blink::WGC3Dint border, // WGC3Dsizei imageSize, const void *data); - virtual void copyBufferSubData(WGC3Denum readTarget, WGC3Denum writeTarget, - WGC3Dintptr readOffset, WGC3Dintptr writeOffset, WGC3Dsizeiptr size); - virtual void copyTexSubImage3D(WGC3Denum target, WGC3Dint level, - WGC3Dint xoffset, WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dint x, - WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height); - virtual WebGLId createSampler(); - virtual WebGLId createTransformFeedback(); - virtual void deleteSampler(WebGLId sampler); - //virtual void deleteSync(WebGLId sync); - virtual void deleteTransformFeedback(WebGLId transformfeedback); + // virtual void compressedTexSubImage3D(blink::WGC3Denum target, + // blink::WGC3Dint level, blink::WGC3Dint xoffset, blink::WGC3Dint yoffset, + // blink::WGC3Dint zoffset, + // blink::WGC3Dsizei width, blink::WGC3Dsizei height, + // blink::WGC3Dsizei depth, blink::WGC3Denum format, + // blink::WGC3Dsizei imageSize, const void *data); + virtual void copyBufferSubData(blink::WGC3Denum readTarget, + blink::WGC3Denum writeTarget, + blink::WGC3Dintptr readOffset, + blink::WGC3Dintptr writeOffset, + blink::WGC3Dsizeiptr size); + virtual void copyTexSubImage3D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dint zoffset, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); + virtual blink::WebGLId createSampler(); + virtual blink::WebGLId createTransformFeedback(); + virtual void deleteSampler(blink::WebGLId sampler); + // virtual void deleteSync(blink::WebGLId sync); + virtual void deleteTransformFeedback(blink::WebGLId transformfeedback); virtual void endTransformFeedback(void); - //virtual WebGLId fenceSync(WGC3Denum condition, WGC3Dbitfield flags); - virtual void framebufferTextureLayer(WGC3Denum target, WGC3Denum attachment, - WGC3Duint texture, WGC3Dint level, WGC3Dint layer); - virtual void getActiveUniformBlockName(WGC3Duint program, - WGC3Duint uniformBlockIndex, WGC3Dsizei bufSize, WGC3Dsizei *length, - WGC3Dchar *uniformBlockName); - virtual void getActiveUniformBlockiv(WGC3Duint program, - WGC3Duint uniformBlockIndex, WGC3Denum pname, WGC3Dint *params); - //virtual void getActiveUniformsiv(WGC3Duint program, WGC3Dsizei uniformCount, - // const WGC3Duint *uniformIndices, WGC3Denum pname, WGC3Dint *params); - virtual WGC3Dint getFragDataLocation(WGC3Duint program, - const WGC3Dchar *name); - virtual void getInternalformativ(WGC3Denum target, WGC3Denum internalformat, - WGC3Denum pname, WGC3Dsizei bufSize, WGC3Dint *params); - virtual void getSamplerParameterfv(WGC3Duint sampler, WGC3Denum pname, - WGC3Dfloat *params); - virtual void getSamplerParameteriv(WGC3Duint sampler, WGC3Denum pname, - WGC3Dint *params); - //virtual void getTransformFeedbackVarying(WGC3Duint program, WGC3Duint index, - // WGC3Dsizei bufSize, WGC3Dsizei *length, WGC3Dsizei *size, - // WGC3Denum *type, WGC3Dchar *name); - virtual WGC3Duint getUniformBlockIndex(WGC3Duint program, - const WGC3Dchar *uniformBlockName); - //virtual void getUniformIndices(WGC3Duint program, WGC3Dsizei uniformCount, - // const WGC3Dchar *const*uniformNames, WGC3Duint *uniformIndices); - //virtual void getUniformuiv(WGC3Duint program, WGC3Dint location, - // WGC3Duint *params); - //virtual void getVertexAttribIiv(WGC3Duint index, WGC3Denum pname, - // WGC3Dint *params); - //virtual void getVertexAttribIuiv(WGC3Duint index, WGC3Denum pname, - // WGC3Duint *params); - virtual void invalidateFramebuffer(WGC3Denum target, - WGC3Dsizei numAttachments, const WGC3Denum *attachments); - virtual void invalidateSubFramebuffer(WGC3Denum target, - WGC3Dsizei numAttachments, const WGC3Denum *attachments, WGC3Dint x, - WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height); - virtual WGC3Dboolean isSampler(WebGLId sampler); - //virtual WGC3Dboolean isSync(WebGLId sync); - virtual WGC3Dboolean isTransformFeedback(WGC3Duint id); + // virtual blink::WebGLId fenceSync(blink::WGC3Denum condition, + // blink::WGC3Dbitfield flags); + virtual void framebufferTextureLayer(blink::WGC3Denum target, + blink::WGC3Denum attachment, + blink::WGC3Duint texture, + blink::WGC3Dint level, + blink::WGC3Dint layer); + virtual void getActiveUniformBlockName(blink::WGC3Duint program, + blink::WGC3Duint uniformBlockIndex, + blink::WGC3Dsizei bufSize, + blink::WGC3Dsizei* length, + blink::WGC3Dchar* uniformBlockName); + virtual void getActiveUniformBlockiv(blink::WGC3Duint program, + blink::WGC3Duint uniformBlockIndex, + blink::WGC3Denum pname, + blink::WGC3Dint* params); + // virtual void getActiveUniformsiv(blink::WGC3Duint program, + // blink::WGC3Dsizei uniformCount, const blink::WGC3Duint *uniformIndices, + // blink::WGC3Denum pname, blink::WGC3Dint *params); + virtual blink::WGC3Dint getFragDataLocation(blink::WGC3Duint program, + const blink::WGC3Dchar* name); + virtual void getInternalformativ(blink::WGC3Denum target, + blink::WGC3Denum internalformat, + blink::WGC3Denum pname, + blink::WGC3Dsizei bufSize, + blink::WGC3Dint* params); + virtual void getSamplerParameterfv(blink::WGC3Duint sampler, + blink::WGC3Denum pname, + blink::WGC3Dfloat* params); + virtual void getSamplerParameteriv(blink::WGC3Duint sampler, + blink::WGC3Denum pname, + blink::WGC3Dint* params); + // virtual void getTransformFeedbackVarying(blink::WGC3Duint program, + // blink::WGC3Duint index, + // blink::WGC3Dsizei bufSize, blink::WGC3Dsizei *length, + // blink::WGC3Dsizei *size, blink::WGC3Denum *type, + // blink::WGC3Dchar *name); + virtual blink::WGC3Duint getUniformBlockIndex( + blink::WGC3Duint program, + const blink::WGC3Dchar* uniformBlockName); + // virtual void getUniformIndices(blink::WGC3Duint program, + // blink::WGC3Dsizei uniformCount, + // const blink::WGC3Dchar *const*uniformNames, + // blink::WGC3Duint *uniformIndices); + // virtual void getUniformuiv(blink::WGC3Duint program, blink::WGC3Dint + // location, + // blink::WGC3Duint *params); + // virtual void getVertexAttribIiv(blink::WGC3Duint index, blink::WGC3Denum + // pname, + // blink::WGC3Dint *params); + // virtual void getVertexAttribIuiv(blink::WGC3Duint index, blink::WGC3Denum + // pname, + // blink::WGC3Duint *params); + virtual void invalidateFramebuffer(blink::WGC3Denum target, + blink::WGC3Dsizei numAttachments, + const blink::WGC3Denum* attachments); + virtual void invalidateSubFramebuffer(blink::WGC3Denum target, + blink::WGC3Dsizei numAttachments, + const blink::WGC3Denum* attachments, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height); + virtual blink::WGC3Dboolean isSampler(blink::WebGLId sampler); + // virtual blink::WGC3Dboolean isSync(blink::WebGLId sync); + virtual blink::WGC3Dboolean isTransformFeedback(blink::WGC3Duint id); virtual void pauseTransformFeedback(void); - //virtual void programParameteri(WGC3Duint program, WGC3Denum pname, - // WGC3Dint value); - virtual void readBuffer(WGC3Denum src); + // virtual void programParameteri(blink::WGC3Duint program, blink::WGC3Denum + // pname, + // blink::WGC3Dint value); + virtual void readBuffer(blink::WGC3Denum src); virtual void resumeTransformFeedback(void); - virtual void samplerParameterf(WGC3Duint sampler, WGC3Denum pname, - WGC3Dfloat param); - virtual void samplerParameterfv(WGC3Duint sampler, WGC3Denum pname, - const WGC3Dfloat *param); - virtual void samplerParameteri(WGC3Duint sampler, WGC3Denum pname, - WGC3Dint param); - virtual void samplerParameteriv(WGC3Duint sampler, WGC3Denum pname, - const WGC3Dint *param); - virtual void texImage3D(WGC3Denum target, WGC3Dint level, - WGC3Dint internalformat, WGC3Dsizei width, WGC3Dsizei height, - WGC3Dsizei depth, WGC3Dint border, WGC3Denum format, WGC3Denum type, - const void *pixels); - virtual void texStorage3D(WGC3Denum target, WGC3Dsizei levels, - WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, - WGC3Dsizei depth); - virtual void texSubImage3D(WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, - WGC3Dint yoffset, WGC3Dint zoffset, WGC3Dsizei width, WGC3Dsizei height, - WGC3Dsizei depth, WGC3Denum format, WGC3Denum type, const void *pixels); - virtual void transformFeedbackVaryings(WGC3Duint program, WGC3Dsizei count, - const WGC3Dchar *const*varyings, WGC3Denum bufferMode); - virtual void uniform1ui(WGC3Dint location, WGC3Duint x); - virtual void uniform1uiv(WGC3Dint location, WGC3Dsizei count, - const WGC3Duint *value); - virtual void uniform2ui(WGC3Dint location, WGC3Duint x, WGC3Duint y); - virtual void uniform2uiv(WGC3Dint location, WGC3Dsizei count, - const WGC3Duint *value); - virtual void uniform3ui(WGC3Dint location, WGC3Duint x, WGC3Duint y, - WGC3Duint z); - virtual void uniform3uiv(WGC3Dint location, WGC3Dsizei count, - const WGC3Duint *value); - virtual void uniform4ui(WGC3Dint location, WGC3Duint x, WGC3Duint y, - WGC3Duint z, WGC3Duint w); - virtual void uniform4uiv(WGC3Dint location, WGC3Dsizei count, - const WGC3Duint *value); - virtual void uniformBlockBinding(WGC3Duint program, - WGC3Duint uniformBlockIndex, WGC3Duint uniformBlockBinding); - virtual void uniformMatrix2x3fv(WGC3Dint location, WGC3Dsizei count, - WGC3Dboolean transpose, const WGC3Dfloat* value); - virtual void uniformMatrix2x4fv(WGC3Dint location, WGC3Dsizei count, - WGC3Dboolean transpose, const WGC3Dfloat* value); - virtual void uniformMatrix3x2fv(WGC3Dint location, WGC3Dsizei count, - WGC3Dboolean transpose, const WGC3Dfloat* value); - virtual void uniformMatrix3x4fv(WGC3Dint location, WGC3Dsizei count, - WGC3Dboolean transpose, const WGC3Dfloat* value); - virtual void uniformMatrix4x2fv(WGC3Dint location, WGC3Dsizei count, - WGC3Dboolean transpose, const WGC3Dfloat* value); - virtual void uniformMatrix4x3fv(WGC3Dint location, WGC3Dsizei count, - WGC3Dboolean transpose, const WGC3Dfloat* value); - virtual void vertexAttribI4i(WGC3Duint index, WGC3Dint x, WGC3Dint y, - WGC3Dint z, WGC3Dint w); - virtual void vertexAttribI4iv(WGC3Duint index, const WGC3Dint *v); - virtual void vertexAttribI4ui(WGC3Duint index, WGC3Duint x, WGC3Duint y, - WGC3Duint z, WGC3Duint w); - virtual void vertexAttribI4uiv(WGC3Duint index, const WGC3Duint *v); - virtual void vertexAttribIPointer(WGC3Duint index, WGC3Dint size, - WGC3Denum type, WGC3Dsizei stride, WGC3Dintptr pointer); - //virtual void waitSync(WebGLId sync, WGC3Dbitfield flags, - // WGC3Duint64 timeout); + virtual void samplerParameterf(blink::WGC3Duint sampler, + blink::WGC3Denum pname, + blink::WGC3Dfloat param); + virtual void samplerParameterfv(blink::WGC3Duint sampler, + blink::WGC3Denum pname, + const blink::WGC3Dfloat* param); + virtual void samplerParameteri(blink::WGC3Duint sampler, + blink::WGC3Denum pname, + blink::WGC3Dint param); + virtual void samplerParameteriv(blink::WGC3Duint sampler, + blink::WGC3Denum pname, + const blink::WGC3Dint* param); + virtual void texImage3D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dsizei depth, + blink::WGC3Dint border, + blink::WGC3Denum format, + blink::WGC3Denum type, + const void* pixels); + virtual void texStorage3D(blink::WGC3Denum target, + blink::WGC3Dsizei levels, + blink::WGC3Denum internalformat, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dsizei depth); + virtual void texSubImage3D(blink::WGC3Denum target, + blink::WGC3Dint level, + blink::WGC3Dint xoffset, + blink::WGC3Dint yoffset, + blink::WGC3Dint zoffset, + blink::WGC3Dsizei width, + blink::WGC3Dsizei height, + blink::WGC3Dsizei depth, + blink::WGC3Denum format, + blink::WGC3Denum type, + const void* pixels); + virtual void transformFeedbackVaryings( + blink::WGC3Duint program, + blink::WGC3Dsizei count, + const blink::WGC3Dchar* const* varyings, + blink::WGC3Denum bufferMode); + virtual void uniform1ui(blink::WGC3Dint location, blink::WGC3Duint x); + virtual void uniform1uiv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Duint* value); + virtual void uniform2ui(blink::WGC3Dint location, + blink::WGC3Duint x, + blink::WGC3Duint y); + virtual void uniform2uiv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Duint* value); + virtual void uniform3ui(blink::WGC3Dint location, + blink::WGC3Duint x, + blink::WGC3Duint y, + blink::WGC3Duint z); + virtual void uniform3uiv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Duint* value); + virtual void uniform4ui(blink::WGC3Dint location, + blink::WGC3Duint x, + blink::WGC3Duint y, + blink::WGC3Duint z, + blink::WGC3Duint w); + virtual void uniform4uiv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + const blink::WGC3Duint* value); + virtual void uniformBlockBinding(blink::WGC3Duint program, + blink::WGC3Duint uniformBlockIndex, + blink::WGC3Duint uniformBlockBinding); + virtual void uniformMatrix2x3fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void uniformMatrix2x4fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void uniformMatrix3x2fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void uniformMatrix3x4fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void uniformMatrix4x2fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void uniformMatrix4x3fv(blink::WGC3Dint location, + blink::WGC3Dsizei count, + blink::WGC3Dboolean transpose, + const blink::WGC3Dfloat* value); + virtual void vertexAttribI4i(blink::WGC3Duint index, + blink::WGC3Dint x, + blink::WGC3Dint y, + blink::WGC3Dint z, + blink::WGC3Dint w); + virtual void vertexAttribI4iv(blink::WGC3Duint index, + const blink::WGC3Dint* v); + virtual void vertexAttribI4ui(blink::WGC3Duint index, + blink::WGC3Duint x, + blink::WGC3Duint y, + blink::WGC3Duint z, + blink::WGC3Duint w); + virtual void vertexAttribI4uiv(blink::WGC3Duint index, + const blink::WGC3Duint* v); + virtual void vertexAttribIPointer(blink::WGC3Duint index, + blink::WGC3Dint size, + blink::WGC3Denum type, + blink::WGC3Dsizei stride, + blink::WGC3Dintptr pointer); + // virtual void waitSync(blink::WebGLId sync, blink::WGC3Dbitfield flags, + // blink::WGC3Duint64 timeout); virtual GrGLInterface* createGrGLInterface(); @@ -748,7 +940,7 @@ bool initialize_failed_; WebGraphicsContext3D::WebGraphicsContextLostCallback* context_lost_callback_; - WGC3Denum context_lost_reason_; + blink::WGC3Denum context_lost_reason_; WebGraphicsContext3D::WebGraphicsErrorMessageCallback* error_message_callback_; @@ -756,7 +948,7 @@ client_error_message_callback_; // Errors raised by synthesizeGLError(). - std::vector<WGC3Denum> synthetic_errors_; + std::vector<blink::WGC3Denum> synthetic_errors_; ::gpu::gles2::GLES2Interface* gl_; bool lose_context_when_out_of_memory_;
diff --git a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc index ff83e5a..cc7871c 100644 --- a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -24,6 +24,7 @@ #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_implementation.h" +using blink::WGC3Denum; using gpu::gles2::GLES2Implementation; using gpu::GLInProcessContext;
diff --git a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h index 8aba802..32bcbbf 100644 --- a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h +++ b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h
@@ -63,7 +63,7 @@ // WebGraphicsContext3D methods virtual bool isContextLost(); - virtual WGC3Denum getGraphicsResetStatusARB(); + virtual blink::WGC3Denum getGraphicsResetStatusARB(); ::gpu::ContextSupport* GetContextSupport();
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 5e6d9d9..bf5b19e 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -544,6 +544,7 @@ # named types are used in 'cmd_buffer_functions.txt'. # type: The actual GL type of the named type. # valid: The list of values that are valid for both the client and the service. +# valid_es3: The list of values that are valid in OpenGL ES 3, but not ES 2. # invalid: Examples of invalid values for the type. At least these values # should be tested to be invalid. # is_complete: The list of valid values of type are final and will not be @@ -584,6 +585,14 @@ 'GL_ARRAY_BUFFER', 'GL_ELEMENT_ARRAY_BUFFER', ], + 'valid_es3': [ + 'GL_COPY_READ_BUFFER', + 'GL_COPY_WRITE_BUFFER', + 'GL_PIXEL_PACK_BUFFER', + 'GL_PIXEL_UNPACK_BUFFER', + 'GL_TRANSFORM_FEEDBACK_BUFFER', + 'GL_UNIFORM_BUFFER', + ], 'invalid': [ 'GL_RENDERBUFFER', ], @@ -598,6 +607,20 @@ 'GL_RENDERBUFFER', ], }, + 'MapBufferAccess': { + 'type': 'GLenum', + 'valid': [ + 'GL_MAP_READ_BIT', + 'GL_MAP_WRITE_BIT', + 'GL_MAP_INVALIDATE_RANGE_BIT', + 'GL_MAP_INVALIDATE_BUFFER_BIT', + 'GL_MAP_FLUSH_EXPLICIT_BIT', + 'GL_MAP_UNSYNCHRONIZED_BIT', + ], + 'invalid': [ + 'GL_SYNC_FLUSH_COMMANDS_BIT', + ], + }, 'Bufferiv': { 'type': 'GLenum', 'valid': [ @@ -1979,6 +2002,11 @@ 'defer_draws': True, 'trace_level': 2, }, + 'DrawRangeElements': { + 'type': 'Manual', + 'gen_cmd': 'False', + 'unsafe': True, + }, 'Enable': { 'decoder_func': 'DoEnable', 'impl_func': False, @@ -2494,6 +2522,16 @@ 'client_test': False, 'pepper_interface': 'ChromiumMapSub', }, + 'MapBufferRange': { + 'type': 'Custom', + 'data_transfer_methods': ['shm'], + 'cmd_args': 'GLenumBufferTarget target, GLintptrNotNegative offset, ' + 'GLsizeiptr size, GLbitfieldMapBufferAccess access, ' + 'uint32_t data_shm_id, uint32_t data_shm_offset, ' + 'uint32_t result_shm_id, uint32_t result_shm_offset', + 'unsafe': True, + 'result': ['uint32_t'], + }, 'PauseTransformFeedback': { 'unsafe': True, }, @@ -2879,6 +2917,10 @@ 'client_test': False, 'pepper_interface': 'ChromiumMapSub', }, + 'UnmapBuffer': { + 'type': 'Custom', + 'unsafe': True, + }, 'UnmapTexSubImage2DCHROMIUM': { 'gen_cmd': False, 'extension': True, @@ -7507,6 +7549,10 @@ self.invalid = info['invalid'] else: self.invalid = [] + if 'valid_es3' in info: + self.valid_es3 = info['valid_es3'] + else: + self.valid_es3 = [] def GetType(self): return self.info['type'] @@ -7517,6 +7563,9 @@ def GetValidValues(self): return self.valid + def GetValidValuesES3(self): + return self.valid_es3 + def IsConstant(self): if not 'is_complete' in self.info: return False @@ -9816,6 +9865,13 @@ file.Write(" %s,\n" % value) file.Write("};\n") file.Write("\n") + if named_type.GetValidValuesES3(): + file.Write("static const %s valid_%s_table_es3[] = {\n" % + (named_type.GetType(), ToUnderscore(name))) + for value in named_type.GetValidValuesES3(): + file.Write(" %s,\n" % value) + file.Write("};\n") + file.Write("\n") file.Write("Validators::Validators()") pre = ' : ' for count, name in enumerate(names): @@ -9834,6 +9890,18 @@ pre = ',\n ' file.Write(" {\n"); file.Write("}\n\n"); + + file.Write("void Validators::AddES3Values() {\n") + for name in names: + named_type = NamedType(_NAMED_TYPE_INFO[name]) + if named_type.GetValidValuesES3(): + code = """ %(name)s.AddValues( + valid_%(name)s_table_es3, arraysize(valid_%(name)s_table_es3)); +""" + file.Write(code % { + 'name': ToUnderscore(name), + }) + file.Write("}\n\n"); file.Close() self.generated_cpp_filenames.append(file.filename) @@ -9892,9 +9960,13 @@ if _NAMED_TYPE_INFO[enum]['type'] == 'GLenum': file.Write("std::string GLES2Util::GetString%s(uint32_t value) {\n" % enum) - if len(_NAMED_TYPE_INFO[enum]['valid']) > 0: + valid_list = _NAMED_TYPE_INFO[enum]['valid'] + if 'valid_es3' in _NAMED_TYPE_INFO[enum]: + valid_list = valid_list + _NAMED_TYPE_INFO[enum]['valid_es3'] + assert len(valid_list) == len(set(valid_list)) + if len(valid_list) > 0: file.Write(" static const EnumToString string_table[] = {\n") - for value in _NAMED_TYPE_INFO[enum]['valid']: + for value in valid_list: file.Write(' { %s, "%s" },\n' % (value, value)) file.Write(""" }; return GLES2Util::GetQualifiedEnumString(
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn index 7e47f24..23d5a8c 100644 --- a/gpu/command_buffer/client/BUILD.gn +++ b/gpu/command_buffer/client/BUILD.gn
@@ -197,3 +197,23 @@ "//gpu/command_buffer/common", ] } + +# GYP version: gpu/gpu.gyp:gles2_c_lib_nocheck +# Same as gles2_c_lib except with no parameter checking. Required for +# OpenGL ES 2.0 conformance tests. +component("gles2_c_lib_nocheck") { + sources = gles2_c_lib_source_files + + defines = [ + "GLES2_C_LIB_IMPLEMENTATION", + "GLES2_CONFORMANCE_TESTS=1", + ] + deps = [ + ":client", + ":gles2_implementation_no_check", + ":gles2_interface", + "//base", + "//base/third_party/dynamic_annotations", + "//gpu/command_buffer/common", + ] +}
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 7e0da4b..ff3dde1 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -259,6 +259,15 @@ const void* indices) { gles2::GetGLContext()->DrawElements(mode, count, type, indices); } +void GLES2DrawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void* indices) { + gles2::GetGLContext()->DrawRangeElements(mode, start, end, count, type, + indices); +} void GLES2Enable(GLenum cap) { gles2::GetGLContext()->Enable(cap); } @@ -1065,6 +1074,15 @@ void GLES2UnmapBufferSubDataCHROMIUM(const void* mem) { gles2::GetGLContext()->UnmapBufferSubDataCHROMIUM(mem); } +void* GLES2MapBufferRange(GLenum target, + GLintptr offset, + GLsizeiptr size, + GLbitfield access) { + return gles2::GetGLContext()->MapBufferRange(target, offset, size, access); +} +GLboolean GLES2UnmapBuffer(GLenum target) { + return gles2::GetGLContext()->UnmapBuffer(target); +} void* GLES2MapTexSubImage2DCHROMIUM(GLenum target, GLint level, GLint xoffset, @@ -1557,6 +1575,10 @@ reinterpret_cast<GLES2FunctionPointer>(glDrawElements), }, { + "glDrawRangeElements", + reinterpret_cast<GLES2FunctionPointer>(glDrawRangeElements), + }, + { "glEnable", reinterpret_cast<GLES2FunctionPointer>(glEnable), }, @@ -2293,6 +2315,14 @@ reinterpret_cast<GLES2FunctionPointer>(glUnmapBufferSubDataCHROMIUM), }, { + "glMapBufferRange", + reinterpret_cast<GLES2FunctionPointer>(glMapBufferRange), + }, + { + "glUnmapBuffer", + reinterpret_cast<GLES2FunctionPointer>(glUnmapBuffer), + }, + { "glMapTexSubImage2DCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(glMapTexSubImage2DCHROMIUM), },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index ad3eb58..bd40e41 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -2226,6 +2226,28 @@ } } +void MapBufferRange(GLenum target, + GLintptr offset, + GLsizeiptr size, + GLbitfield access, + uint32_t data_shm_id, + uint32_t data_shm_offset, + uint32_t result_shm_id, + uint32_t result_shm_offset) { + gles2::cmds::MapBufferRange* c = GetCmdSpace<gles2::cmds::MapBufferRange>(); + if (c) { + c->Init(target, offset, size, access, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + } +} + +void UnmapBuffer(GLenum target) { + gles2::cmds::UnmapBuffer* c = GetCmdSpace<gles2::cmds::UnmapBuffer>(); + if (c) { + c->Init(target); + } +} + void ResizeCHROMIUM(GLuint width, GLuint height, GLfloat scale_factor) { gles2::cmds::ResizeCHROMIUM* c = GetCmdSpace<gles2::cmds::ResizeCHROMIUM>(); if (c) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 5938524..fe59c2a 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -222,6 +222,10 @@ DeleteBuffers(arraysize(reserved_ids_), &reserved_ids_[0]); } + // Release remaining BufferRange mem; This is when a MapBufferRange() is + // called but not the UnmapBuffer() pair. + ClearMappedBufferRangeMap(); + // Release any per-context data in share group. share_group_->FreeContext(this); @@ -605,6 +609,11 @@ } bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) { + // TODO(zmo): For all the BINDING points, there is a possibility where + // resources are shared among multiple contexts, that the cached points + // are invalid. It is not a problem for now, but once we allow resource + // sharing in WebGL, we need to implement a mechanism to allow correct + // client side binding points tracking. crbug.com/465562. switch (pname) { case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = capabilities_.max_combined_texture_image_units; @@ -643,18 +652,12 @@ *params = capabilities_.num_shader_binary_formats; return true; case GL_ARRAY_BUFFER_BINDING: - if (share_group_->bind_generates_resource()) { - *params = bound_array_buffer_id_; - return true; - } - return false; + *params = bound_array_buffer_id_; + return true; case GL_ELEMENT_ARRAY_BUFFER_BINDING: - if (share_group_->bind_generates_resource()) { - *params = - vertex_array_object_manager_->bound_element_array_buffer(); - return true; - } - return false; + *params = + vertex_array_object_manager_->bound_element_array_buffer(); + return true; case GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM: *params = bound_pixel_pack_transfer_buffer_id_; return true; @@ -665,43 +668,27 @@ *params = active_texture_unit_ + GL_TEXTURE0; return true; case GL_TEXTURE_BINDING_2D: - if (share_group_->bind_generates_resource()) { - *params = texture_units_[active_texture_unit_].bound_texture_2d; - return true; - } - return false; + *params = texture_units_[active_texture_unit_].bound_texture_2d; + return true; case GL_TEXTURE_BINDING_CUBE_MAP: - if (share_group_->bind_generates_resource()) { - *params = texture_units_[active_texture_unit_].bound_texture_cube_map; - return true; - } - return false; + *params = texture_units_[active_texture_unit_].bound_texture_cube_map; + return true; case GL_TEXTURE_BINDING_EXTERNAL_OES: - if (share_group_->bind_generates_resource()) { - *params = - texture_units_[active_texture_unit_].bound_texture_external_oes; - return true; - } - return false; + *params = + texture_units_[active_texture_unit_].bound_texture_external_oes; + return true; case GL_FRAMEBUFFER_BINDING: - if (share_group_->bind_generates_resource()) { - *params = bound_framebuffer_; - return true; - } - return false; + *params = bound_framebuffer_; + return true; case GL_READ_FRAMEBUFFER_BINDING: - if (IsChromiumFramebufferMultisampleAvailable() && - share_group_->bind_generates_resource()) { + if (IsChromiumFramebufferMultisampleAvailable()) { *params = bound_read_framebuffer_; return true; } return false; case GL_RENDERBUFFER_BINDING: - if (share_group_->bind_generates_resource()) { - *params = bound_renderbuffer_; - return true; - } - return false; + *params = bound_renderbuffer_; + return true; case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = capabilities_.max_uniform_buffer_bindings; return true; @@ -711,6 +698,7 @@ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = capabilities_.uniform_buffer_offset_alignment; return true; + // TODO(zmo): Support ES3 pnames. default: return false; } @@ -828,23 +816,44 @@ << count << ", " << GLES2Util::GetStringIndexType(type) << ", " << static_cast<const void*>(indices) << ")"); + DrawElementsImpl(mode, count, type, indices, "glDrawRangeElements"); +} + +void GLES2Implementation::DrawRangeElements( + GLenum mode, GLuint start, GLuint end, + GLsizei count, GLenum type, const void* indices) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDrawRangeElements(" + << GLES2Util::GetStringDrawMode(mode) << ", " + << start << ", " << end << ", " << count << ", " + << GLES2Util::GetStringIndexType(type) << ", " + << static_cast<const void*>(indices) << ")"); + if (end < start) { + SetGLError(GL_INVALID_VALUE, "glDrawRangeElements", "end < start"); + return; + } + DrawElementsImpl(mode, count, type, indices, "glDrawRangeElements"); +} + +void GLES2Implementation::DrawElementsImpl( + GLenum mode, GLsizei count, GLenum type, const void* indices, + const char* func_name) { if (count < 0) { - SetGLError(GL_INVALID_VALUE, "glDrawElements", "count less than 0."); + SetGLError(GL_INVALID_VALUE, func_name, "count < 0"); return; } - if (count == 0) { - return; - } - if (vertex_array_object_manager_->bound_element_array_buffer() != 0 && - !ValidateOffset("glDrawElements", reinterpret_cast<GLintptr>(indices))) { - return; - } - GLuint offset = 0; bool simulated = false; - if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers( - "glDrawElements", this, helper_, count, type, 0, indices, - &offset, &simulated)) { - return; + GLuint offset = ToGLuint(indices); + if (count > 0) { + if (vertex_array_object_manager_->bound_element_array_buffer() != 0 && + !ValidateOffset(func_name, reinterpret_cast<GLintptr>(indices))) { + return; + } + if (!vertex_array_object_manager_->SetupSimulatedIndexAndClientSideBuffers( + func_name, this, helper_, count, type, 0, indices, + &offset, &simulated)) { + return; + } } helper_->DrawElements(mode, count, type, offset); RestoreElementAndArrayBuffers(simulated); @@ -1384,12 +1393,10 @@ return; } - if (size == 0) { - return; - } + RemoveMappedBufferRangeByTarget(target); // If there is no data just send BufferData - if (!data) { + if (size == 0 || !data) { helper_->BufferData(target, size, 0, 0, usage); return; } @@ -3291,6 +3298,8 @@ if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { bound_pixel_unpack_transfer_buffer_id_ = 0; } + + RemoveMappedBufferRangeById(buffers[ii]); } } @@ -3672,6 +3681,133 @@ CheckGLError(); } +GLuint GLES2Implementation::GetBoundBufferHelper(GLenum target) { + GLenum binding = GLES2Util::MapBufferTargetToBindingEnum(target); + GLint id = 0; + bool cached = GetHelper(binding, &id); + DCHECK(cached); + return static_cast<GLuint>(id); +} + +void GLES2Implementation::RemoveMappedBufferRangeByTarget(GLenum target) { + GLuint buffer = GetBoundBufferHelper(target); + RemoveMappedBufferRangeById(buffer); +} + +void GLES2Implementation::RemoveMappedBufferRangeById(GLuint buffer) { + if (buffer > 0) { + auto iter = mapped_buffer_range_map_.find(buffer); + if (iter != mapped_buffer_range_map_.end() && iter->second.shm_memory) { + mapped_memory_->FreePendingToken( + iter->second.shm_memory, helper_->InsertToken()); + mapped_buffer_range_map_.erase(iter); + } + } +} + +void GLES2Implementation::ClearMappedBufferRangeMap() { + for (auto& buffer_range : mapped_buffer_range_map_) { + if (buffer_range.second.shm_memory) { + mapped_memory_->FreePendingToken( + buffer_range.second.shm_memory, helper_->InsertToken()); + } + } + mapped_buffer_range_map_.clear(); +} + +void* GLES2Implementation::MapBufferRange( + GLenum target, GLintptr offset, GLsizeiptr size, GLbitfield access) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapBufferRange(" + << GLES2Util::GetStringEnum(target) << ", " << offset << ", " + << size << ", " << access << ")"); + if (!ValidateSize("glMapBufferRange", size) || + !ValidateOffset("glMapBufferRange", offset)) { + return nullptr; + } + + int32 shm_id; + unsigned int shm_offset; + void* mem = mapped_memory_->Alloc(size, &shm_id, &shm_offset); + if (!mem) { + SetGLError(GL_OUT_OF_MEMORY, "glMapBufferRange", "out of memory"); + return nullptr; + } + + typedef cmds::MapBufferRange::Result Result; + Result* result = GetResultAs<Result*>(); + *result = 0; + helper_->MapBufferRange(target, offset, size, access, shm_id, shm_offset, + GetResultShmId(), GetResultShmOffset()); + // TODO(zmo): For write only mode with MAP_INVALID_*_BIT, we should + // consider an early return without WaitForCmd(). crbug.com/465804. + WaitForCmd(); + if (*result) { + const GLbitfield kInvalidateBits = + GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_INVALIDATE_RANGE_BIT; + if ((access & kInvalidateBits) != 0) { + // We do not read back from the buffer, therefore, we set the client + // side memory to zero to avoid uninitialized data. + memset(mem, 0, size); + } + GLuint buffer = GetBoundBufferHelper(target); + DCHECK_NE(0u, buffer); + // glMapBufferRange fails on an already mapped buffer. + DCHECK(mapped_buffer_range_map_.find(buffer) == + mapped_buffer_range_map_.end()); + auto iter = mapped_buffer_range_map_.insert(std::make_pair( + buffer, + MappedBuffer(access, shm_id, mem, shm_offset, target, offset, size))); + DCHECK(iter.second); + } else { + mapped_memory_->Free(mem); + mem = nullptr; + } + + GPU_CLIENT_LOG(" returned " << mem); + CheckGLError(); + return mem; +} + +GLboolean GLES2Implementation::UnmapBuffer(GLenum target) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapBuffer(" + << GLES2Util::GetStringEnum(target) << ")"); + switch (target) { + case GL_ARRAY_BUFFER: + case GL_ELEMENT_ARRAY_BUFFER: + case GL_COPY_READ_BUFFER: + case GL_COPY_WRITE_BUFFER: + case GL_PIXEL_PACK_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_UNIFORM_BUFFER: + break; + default: + SetGLError(GL_INVALID_ENUM, "glUnmapBuffer", "invalid target"); + return GL_FALSE; + } + GLuint buffer = GetBoundBufferHelper(target); + if (buffer == 0) { + SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "no buffer bound"); + return GL_FALSE; + } + auto iter = mapped_buffer_range_map_.find(buffer); + if (iter == mapped_buffer_range_map_.end()) { + SetGLError(GL_INVALID_OPERATION, "glUnmapBuffer", "buffer is unmapped"); + return GL_FALSE; + } + + helper_->UnmapBuffer(target); + RemoveMappedBufferRangeById(buffer); + // TODO(zmo): There is a rare situation that data might be corrupted and + // GL_FALSE should be returned. We lose context on that sitatuon, so we + // don't have to WaitForCmd(). + GPU_CLIENT_LOG(" returned " << GL_TRUE); + CheckGLError(); + return GL_TRUE; +} + void* GLES2Implementation::MapTexSubImage2DCHROMIUM( GLenum target, GLint level,
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 1ffdf91..39b5870 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -560,6 +560,7 @@ // Helpers for query functions. bool GetHelper(GLenum pname, GLint* params); + GLuint GetBoundBufferHelper(GLenum target); bool GetBooleanvHelper(GLenum pname, GLboolean* params); bool GetBufferParameterivHelper(GLenum target, GLenum pname, GLint* params); bool GetFloatvHelper(GLenum pname, GLfloat* params); @@ -659,6 +660,13 @@ void FailGLError(GLenum /* error */) { } #endif + void RemoveMappedBufferRangeByTarget(GLenum target); + void RemoveMappedBufferRangeById(GLuint buffer); + void ClearMappedBufferRangeMap(); + + void DrawElementsImpl(GLenum mode, GLsizei count, GLenum type, + const void* indices, const char* func_name); + GLES2Util util_; GLES2CmdHelper* helper_; TransferBufferInterface* transfer_buffer_; @@ -767,6 +775,10 @@ typedef std::map<const void*, MappedBuffer> MappedBufferMap; MappedBufferMap mapped_buffers_; + // TODO(zmo): Consolidate |mapped_buffers_| and |mapped_buffer_range_map_|. + typedef base::hash_map<GLuint, MappedBuffer> MappedBufferRangeMap; + MappedBufferRangeMap mapped_buffer_range_map_; + typedef std::map<const void*, MappedTexture> MappedTextureMap; MappedTextureMap mapped_textures_;
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 8e032e4..24236bc 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -200,6 +200,13 @@ GLenum type, const void* indices) override; +void DrawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void* indices) override; + void Enable(GLenum cap) override; GLsync FenceSync(GLenum condition, GLbitfield flags) override; @@ -800,6 +807,13 @@ void UnmapBufferSubDataCHROMIUM(const void* mem) override; +void* MapBufferRange(GLenum target, + GLintptr offset, + GLsizeiptr size, + GLbitfield access) override; + +GLboolean UnmapBuffer(GLenum target) override; + void* MapTexSubImage2DCHROMIUM(GLenum target, GLint level, GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 3af9413..4fecbbc 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -2858,37 +2858,6 @@ reinterpret_cast<uint8*>(pixels.get()) + offset_to_last, mem2_2.ptr)); } -// Binds can not be cached with bind_generates_resource = false because -// our id might not be valid. More specifically if you bind on contextA then -// delete on contextB the resource is still bound on contextA but GetInterger -// won't return an id. -TEST_F(GLES2ImplementationStrictSharedTest, BindsNotCached) { - struct PNameValue { - GLenum pname; - GLint expected; - }; - const PNameValue pairs[] = {{GL_TEXTURE_BINDING_2D, 1, }, - {GL_TEXTURE_BINDING_CUBE_MAP, 2, }, - {GL_TEXTURE_BINDING_EXTERNAL_OES, 3, }, - {GL_FRAMEBUFFER_BINDING, 4, }, - {GL_RENDERBUFFER_BINDING, 5, }, - {GL_ARRAY_BUFFER_BINDING, 6, }, - {GL_ELEMENT_ARRAY_BUFFER_BINDING, 7, }, }; - size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]); - for (size_t ii = 0; ii < num_pairs; ++ii) { - const PNameValue& pv = pairs[ii]; - GLint v = -1; - ExpectedMemoryInfo result1 = - GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result)); - EXPECT_CALL(*command_buffer(), OnFlush()) - .WillOnce(SetMemory(result1.ptr, - SizedResultHelper<GLuint>(pv.expected))) - .RetiresOnSaturation(); - gl_->GetIntegerv(pv.pname, &v); - EXPECT_EQ(pv.expected, v); - } -} - // glGen* Ids must not be reused until glDelete* commands have been // flushed by glFlush. TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestBuffers) { @@ -3631,6 +3600,150 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferWrite) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result)); + + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result.ptr, uint32_t(1))) + .RetiresOnSaturation(); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT); + EXPECT_TRUE(mem != nullptr); + + EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER)); +} + +TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithInvalidateBit) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result)); + + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result.ptr, uint32_t(1))) + .RetiresOnSaturation(); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + GLsizeiptr kSize = 64; + void* mem = gl_->MapBufferRange( + GL_ARRAY_BUFFER, 10, kSize, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT); + EXPECT_TRUE(mem != nullptr); + std::vector<int8_t> zero(kSize); + memset(&zero[0], 0, kSize); + EXPECT_EQ(0, memcmp(mem, &zero[0], kSize)); +} + +TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithGLError) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result)); + + // Return a result of 0 to indicate an GL error. + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result.ptr, uint32_t(0))) + .RetiresOnSaturation(); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT); + EXPECT_TRUE(mem == nullptr); +} + +TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferRead) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result)); + + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result.ptr, uint32_t(1))) + .RetiresOnSaturation(); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_READ_BIT); + EXPECT_TRUE(mem != nullptr); + + EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER)); +} + +TEST_F(GLES2ImplementationTest, MapBufferRangeReadWithGLError) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result)); + + // Return a result of 0 to indicate an GL error. + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result.ptr, uint32_t(0))) + .RetiresOnSaturation(); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_READ_BIT); + EXPECT_TRUE(mem == nullptr); +} + +TEST_F(GLES2ImplementationTest, UnmapBufferFails) { + // No bound buffer. + EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER)); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + // Buffer is unmapped. + EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER)); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); +} + +TEST_F(GLES2ImplementationTest, BufferDataUnmapsDataStore) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result)); + + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result.ptr, uint32_t(1))) + .RetiresOnSaturation(); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT); + EXPECT_TRUE(mem != nullptr); + + std::vector<uint8_t> data(16); + // BufferData unmaps the data store. + gl_->BufferData(GL_ARRAY_BUFFER, 16, &data[0], GL_STREAM_DRAW); + + EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER)); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); +} + +TEST_F(GLES2ImplementationTest, DeleteBuffersUnmapsDataStore) { + ExpectedMemoryInfo result = + GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result)); + + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result.ptr, uint32_t(1))) + .RetiresOnSaturation(); + + const GLuint kBufferId = 123; + gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId); + + void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT); + EXPECT_TRUE(mem != nullptr); + + std::vector<uint8_t> data(16); + // DeleteBuffers unmaps the data store. + gl_->DeleteBuffers(1, &kBufferId); + + EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER)); + EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); +} + TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) { ContextInitOptions init_options; init_options.lose_context_when_out_of_memory = true;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 2d8480a..a0c908f 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -556,6 +556,7 @@ gl_->DrawArrays(GL_POINTS, 2, 3); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +// TODO(zmo): Implement unit test for DrawRangeElements TEST_F(GLES2ImplementationTest, EnableVertexAttribArray) { struct Cmds { @@ -2718,6 +2719,8 @@ EXPECT_TRUE(result); } // TODO(zmo): Implement unit test for EnableFeatureCHROMIUM +// TODO(zmo): Implement unit test for MapBufferRange +// TODO(zmo): Implement unit test for UnmapBuffer TEST_F(GLES2ImplementationTest, ResizeCHROMIUM) { struct Cmds {
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index f93ec07..3da9e22 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -148,6 +148,12 @@ GLsizei count, GLenum type, const void* indices) = 0; +virtual void DrawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void* indices) = 0; virtual void Enable(GLenum cap) = 0; virtual void EnableVertexAttribArray(GLuint index) = 0; virtual GLsync FenceSync(GLenum condition, GLbitfield flags) = 0; @@ -583,6 +589,11 @@ GLsizeiptr size, GLenum access) = 0; virtual void UnmapBufferSubDataCHROMIUM(const void* mem) = 0; +virtual void* MapBufferRange(GLenum target, + GLintptr offset, + GLsizeiptr size, + GLbitfield access) = 0; +virtual GLboolean UnmapBuffer(GLenum target) = 0; virtual void* MapTexSubImage2DCHROMIUM(GLenum target, GLint level, GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 0381b32..14ac101 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -145,6 +145,12 @@ GLsizei count, GLenum type, const void* indices) override; +void DrawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void* indices) override; void Enable(GLenum cap) override; void EnableVertexAttribArray(GLuint index) override; GLsync FenceSync(GLenum condition, GLbitfield flags) override; @@ -568,6 +574,11 @@ GLsizeiptr size, GLenum access) override; void UnmapBufferSubDataCHROMIUM(const void* mem) override; +void* MapBufferRange(GLenum target, + GLintptr offset, + GLsizeiptr size, + GLbitfield access) override; +GLboolean UnmapBuffer(GLenum target) override; void* MapTexSubImage2DCHROMIUM(GLenum target, GLint level, GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 0f2e5fd..7b9569d 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -226,6 +226,13 @@ GLenum /* type */, const void* /* indices */) { } +void GLES2InterfaceStub::DrawRangeElements(GLenum /* mode */, + GLuint /* start */, + GLuint /* end */, + GLsizei /* count */, + GLenum /* type */, + const void* /* indices */) { +} void GLES2InterfaceStub::Enable(GLenum /* cap */) { } void GLES2InterfaceStub::EnableVertexAttribArray(GLuint /* index */) { @@ -987,6 +994,15 @@ } void GLES2InterfaceStub::UnmapBufferSubDataCHROMIUM(const void* /* mem */) { } +void* GLES2InterfaceStub::MapBufferRange(GLenum /* target */, + GLintptr /* offset */, + GLsizeiptr /* size */, + GLbitfield /* access */) { + return 0; +} +GLboolean GLES2InterfaceStub::UnmapBuffer(GLenum /* target */) { + return 0; +} void* GLES2InterfaceStub::MapTexSubImage2DCHROMIUM(GLenum /* target */, GLint /* level */, GLint /* xoffset */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 8a9be79..1e5660e 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -145,6 +145,12 @@ GLsizei count, GLenum type, const void* indices) override; +void DrawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void* indices) override; void Enable(GLenum cap) override; void EnableVertexAttribArray(GLuint index) override; GLsync FenceSync(GLenum condition, GLbitfield flags) override; @@ -568,6 +574,11 @@ GLsizeiptr size, GLenum access) override; void UnmapBufferSubDataCHROMIUM(const void* mem) override; +void* MapBufferRange(GLenum target, + GLintptr offset, + GLsizeiptr size, + GLbitfield access) override; +GLboolean UnmapBuffer(GLenum target) override; void* MapTexSubImage2DCHROMIUM(GLenum target, GLint level, GLint xoffset,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index d1479b1..627c90e 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -390,6 +390,16 @@ gl_->DrawElements(mode, count, type, indices); } +void GLES2TraceImplementation::DrawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void* indices) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DrawRangeElements"); + gl_->DrawRangeElements(mode, start, end, count, type, indices); +} + void GLES2TraceImplementation::Enable(GLenum cap) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::Enable"); gl_->Enable(cap); @@ -1683,6 +1693,19 @@ gl_->UnmapBufferSubDataCHROMIUM(mem); } +void* GLES2TraceImplementation::MapBufferRange(GLenum target, + GLintptr offset, + GLsizeiptr size, + GLbitfield access) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::MapBufferRange"); + return gl_->MapBufferRange(target, offset, size, access); +} + +GLboolean GLES2TraceImplementation::UnmapBuffer(GLenum target) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UnmapBuffer"); + return gl_->UnmapBuffer(target); +} + void* GLES2TraceImplementation::MapTexSubImage2DCHROMIUM(GLenum target, GLint level, GLint xoffset,
diff --git a/gpu/command_buffer/client/share_group.cc b/gpu/command_buffer/client/share_group.cc index 6463200..f5c9bf1 100644 --- a/gpu/command_buffer/client/share_group.cc +++ b/gpu/command_buffer/client/share_group.cc
@@ -60,9 +60,7 @@ (gl_impl->*delete_fn)(n, ids); // We need to ensure that the delete call is evaluated on the service side // before any other contexts issue commands using these client ids. - // TODO(vmiura): Can remove this by virtualizing internal ids, however - // this code only affects PPAPI for now. - gl_impl->helper()->CommandBufferHelper::Flush(); + gl_impl->helper()->CommandBufferHelper::OrderingBarrier(); return true; }
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 140db2c..1dd35fd 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -60,6 +60,7 @@ GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); GL_APICALL void GL_APIENTRY glDrawArrays (GLenumDrawMode mode, GLint first, GLsizei count); GL_APICALL void GL_APIENTRY glDrawElements (GLenumDrawMode mode, GLsizei count, GLenumIndexType type, const void* indices); +GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenumDrawMode mode, GLuint start, GLuint end, GLsizei count, GLenumIndexType type, const void* indices); GL_APICALL void GL_APIENTRY glEnable (GLenumCapability cap); GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenumSyncCondition condition, GLbitfieldSyncFlags flags); @@ -246,6 +247,8 @@ GL_APICALL GLboolean GL_APIENTRY glUnmapBufferCHROMIUM (GLuint target); GL_APICALL void* GL_APIENTRY glMapBufferSubDataCHROMIUM (GLuint target, GLintptrNotNegative offset, GLsizeiptr size, GLenum access); GL_APICALL void GL_APIENTRY glUnmapBufferSubDataCHROMIUM (const void* mem); +GL_APICALL void* GL_APIENTRY glMapBufferRange (GLenumBufferTarget target, GLintptrNotNegative offset, GLsizeiptr size, GLbitfieldMapBufferAccess access); +GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenumBufferTarget target); GL_APICALL void* GL_APIENTRY glMapTexSubImage2DCHROMIUM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access); GL_APICALL void GL_APIENTRY glUnmapTexSubImage2DCHROMIUM (const void* mem); GL_APICALL void GL_APIENTRY glResizeCHROMIUM (GLuint width, GLuint height, GLfloat scale_factor);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index d3cb00a..a829dcb 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -10939,6 +10939,118 @@ static_assert(offsetof(EnableFeatureCHROMIUM, result_shm_offset) == 12, "offset of EnableFeatureCHROMIUM result_shm_offset should be 12"); +struct MapBufferRange { + typedef MapBufferRange ValueType; + static const CommandId kCmdId = kMapBufferRange; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + typedef uint32_t Result; + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLenum _target, + GLintptr _offset, + GLsizeiptr _size, + GLbitfield _access, + uint32_t _data_shm_id, + uint32_t _data_shm_offset, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + SetHeader(); + target = _target; + offset = _offset; + size = _size; + access = _access; + data_shm_id = _data_shm_id; + data_shm_offset = _data_shm_offset; + result_shm_id = _result_shm_id; + result_shm_offset = _result_shm_offset; + } + + void* Set(void* cmd, + GLenum _target, + GLintptr _offset, + GLsizeiptr _size, + GLbitfield _access, + uint32_t _data_shm_id, + uint32_t _data_shm_offset, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + static_cast<ValueType*>(cmd)->Init(_target, _offset, _size, _access, + _data_shm_id, _data_shm_offset, + _result_shm_id, _result_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + int32_t offset; + int32_t size; + uint32_t access; + uint32_t data_shm_id; + uint32_t data_shm_offset; + uint32_t result_shm_id; + uint32_t result_shm_offset; +}; + +static_assert(sizeof(MapBufferRange) == 36, + "size of MapBufferRange should be 36"); +static_assert(offsetof(MapBufferRange, header) == 0, + "offset of MapBufferRange header should be 0"); +static_assert(offsetof(MapBufferRange, target) == 4, + "offset of MapBufferRange target should be 4"); +static_assert(offsetof(MapBufferRange, offset) == 8, + "offset of MapBufferRange offset should be 8"); +static_assert(offsetof(MapBufferRange, size) == 12, + "offset of MapBufferRange size should be 12"); +static_assert(offsetof(MapBufferRange, access) == 16, + "offset of MapBufferRange access should be 16"); +static_assert(offsetof(MapBufferRange, data_shm_id) == 20, + "offset of MapBufferRange data_shm_id should be 20"); +static_assert(offsetof(MapBufferRange, data_shm_offset) == 24, + "offset of MapBufferRange data_shm_offset should be 24"); +static_assert(offsetof(MapBufferRange, result_shm_id) == 28, + "offset of MapBufferRange result_shm_id should be 28"); +static_assert(offsetof(MapBufferRange, result_shm_offset) == 32, + "offset of MapBufferRange result_shm_offset should be 32"); + +struct UnmapBuffer { + typedef UnmapBuffer ValueType; + static const CommandId kCmdId = kUnmapBuffer; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLenum _target) { + SetHeader(); + target = _target; + } + + void* Set(void* cmd, GLenum _target) { + static_cast<ValueType*>(cmd)->Init(_target); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t target; +}; + +static_assert(sizeof(UnmapBuffer) == 8, "size of UnmapBuffer should be 8"); +static_assert(offsetof(UnmapBuffer, header) == 0, + "offset of UnmapBuffer header should be 0"); +static_assert(offsetof(UnmapBuffer, target) == 4, + "offset of UnmapBuffer target should be 4"); + struct ResizeCHROMIUM { typedef ResizeCHROMIUM ValueType; static const CommandId kCmdId = kResizeCHROMIUM;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 3162276..d14f48d 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -3778,6 +3778,37 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, MapBufferRange) { + cmds::MapBufferRange& cmd = *GetBufferAs<cmds::MapBufferRange>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLintptr>(12), + static_cast<GLsizeiptr>(13), static_cast<GLbitfield>(14), + static_cast<uint32_t>(15), static_cast<uint32_t>(16), + static_cast<uint32_t>(17), static_cast<uint32_t>(18)); + EXPECT_EQ(static_cast<uint32_t>(cmds::MapBufferRange::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLintptr>(12), cmd.offset); + EXPECT_EQ(static_cast<GLsizeiptr>(13), cmd.size); + EXPECT_EQ(static_cast<GLbitfield>(14), cmd.access); + EXPECT_EQ(static_cast<uint32_t>(15), cmd.data_shm_id); + EXPECT_EQ(static_cast<uint32_t>(16), cmd.data_shm_offset); + EXPECT_EQ(static_cast<uint32_t>(17), cmd.result_shm_id); + EXPECT_EQ(static_cast<uint32_t>(18), cmd.result_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, UnmapBuffer) { + cmds::UnmapBuffer& cmd = *GetBufferAs<cmds::UnmapBuffer>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11)); + EXPECT_EQ(static_cast<uint32_t>(cmds::UnmapBuffer::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, ResizeCHROMIUM) { cmds::ResizeCHROMIUM& cmd = *GetBufferAs<cmds::ResizeCHROMIUM>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 1c739e8..ea62be1 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -243,53 +243,55 @@ OP(SwapBuffers) /* 484 */ \ OP(GetMaxValueInBufferCHROMIUM) /* 485 */ \ OP(EnableFeatureCHROMIUM) /* 486 */ \ - OP(ResizeCHROMIUM) /* 487 */ \ - OP(GetRequestableExtensionsCHROMIUM) /* 488 */ \ - OP(RequestExtensionCHROMIUM) /* 489 */ \ - OP(GetProgramInfoCHROMIUM) /* 490 */ \ - OP(GetUniformBlocksCHROMIUM) /* 491 */ \ - OP(GetTransformFeedbackVaryingsCHROMIUM) /* 492 */ \ - OP(GetUniformsES3CHROMIUM) /* 493 */ \ - OP(GetTranslatedShaderSourceANGLE) /* 494 */ \ - OP(PostSubBufferCHROMIUM) /* 495 */ \ - OP(TexImageIOSurface2DCHROMIUM) /* 496 */ \ - OP(CopyTextureCHROMIUM) /* 497 */ \ - OP(CopySubTextureCHROMIUM) /* 498 */ \ - OP(DrawArraysInstancedANGLE) /* 499 */ \ - OP(DrawElementsInstancedANGLE) /* 500 */ \ - OP(VertexAttribDivisorANGLE) /* 501 */ \ - OP(GenMailboxCHROMIUM) /* 502 */ \ - OP(ProduceTextureCHROMIUMImmediate) /* 503 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 504 */ \ - OP(ConsumeTextureCHROMIUMImmediate) /* 505 */ \ - OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 506 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 507 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 508 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 509 */ \ - OP(IsValuebufferCHROMIUM) /* 510 */ \ - OP(BindValuebufferCHROMIUM) /* 511 */ \ - OP(SubscribeValueCHROMIUM) /* 512 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 513 */ \ - OP(UniformValuebufferCHROMIUM) /* 514 */ \ - OP(BindTexImage2DCHROMIUM) /* 515 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 516 */ \ - OP(TraceBeginCHROMIUM) /* 517 */ \ - OP(TraceEndCHROMIUM) /* 518 */ \ - OP(AsyncTexSubImage2DCHROMIUM) /* 519 */ \ - OP(AsyncTexImage2DCHROMIUM) /* 520 */ \ - OP(WaitAsyncTexImage2DCHROMIUM) /* 521 */ \ - OP(WaitAllAsyncTexImage2DCHROMIUM) /* 522 */ \ - OP(DiscardFramebufferEXTImmediate) /* 523 */ \ - OP(LoseContextCHROMIUM) /* 524 */ \ - OP(InsertSyncPointCHROMIUM) /* 525 */ \ - OP(WaitSyncPointCHROMIUM) /* 526 */ \ - OP(DrawBuffersEXTImmediate) /* 527 */ \ - OP(DiscardBackbufferCHROMIUM) /* 528 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 529 */ \ - OP(SwapInterval) /* 530 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 531 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 532 */ \ - OP(BlendBarrierKHR) /* 533 */ + OP(MapBufferRange) /* 487 */ \ + OP(UnmapBuffer) /* 488 */ \ + OP(ResizeCHROMIUM) /* 489 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 490 */ \ + OP(RequestExtensionCHROMIUM) /* 491 */ \ + OP(GetProgramInfoCHROMIUM) /* 492 */ \ + OP(GetUniformBlocksCHROMIUM) /* 493 */ \ + OP(GetTransformFeedbackVaryingsCHROMIUM) /* 494 */ \ + OP(GetUniformsES3CHROMIUM) /* 495 */ \ + OP(GetTranslatedShaderSourceANGLE) /* 496 */ \ + OP(PostSubBufferCHROMIUM) /* 497 */ \ + OP(TexImageIOSurface2DCHROMIUM) /* 498 */ \ + OP(CopyTextureCHROMIUM) /* 499 */ \ + OP(CopySubTextureCHROMIUM) /* 500 */ \ + OP(DrawArraysInstancedANGLE) /* 501 */ \ + OP(DrawElementsInstancedANGLE) /* 502 */ \ + OP(VertexAttribDivisorANGLE) /* 503 */ \ + OP(GenMailboxCHROMIUM) /* 504 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 505 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 506 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 507 */ \ + OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 508 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 509 */ \ + OP(GenValuebuffersCHROMIUMImmediate) /* 510 */ \ + OP(DeleteValuebuffersCHROMIUMImmediate) /* 511 */ \ + OP(IsValuebufferCHROMIUM) /* 512 */ \ + OP(BindValuebufferCHROMIUM) /* 513 */ \ + OP(SubscribeValueCHROMIUM) /* 514 */ \ + OP(PopulateSubscribedValuesCHROMIUM) /* 515 */ \ + OP(UniformValuebufferCHROMIUM) /* 516 */ \ + OP(BindTexImage2DCHROMIUM) /* 517 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 518 */ \ + OP(TraceBeginCHROMIUM) /* 519 */ \ + OP(TraceEndCHROMIUM) /* 520 */ \ + OP(AsyncTexSubImage2DCHROMIUM) /* 521 */ \ + OP(AsyncTexImage2DCHROMIUM) /* 522 */ \ + OP(WaitAsyncTexImage2DCHROMIUM) /* 523 */ \ + OP(WaitAllAsyncTexImage2DCHROMIUM) /* 524 */ \ + OP(DiscardFramebufferEXTImmediate) /* 525 */ \ + OP(LoseContextCHROMIUM) /* 526 */ \ + OP(InsertSyncPointCHROMIUM) /* 527 */ \ + OP(WaitSyncPointCHROMIUM) /* 528 */ \ + OP(DrawBuffersEXTImmediate) /* 529 */ \ + OP(DiscardBackbufferCHROMIUM) /* 530 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 531 */ \ + OP(SwapInterval) /* 532 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 533 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 534 */ \ + OP(BlendBarrierKHR) /* 535 */ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index 0950b41..14d6a21 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -870,6 +870,31 @@ return (v64 << 32) | v32_0; } +// static +uint32_t GLES2Util::MapBufferTargetToBindingEnum(uint32_t target) { + switch (target) { + case GL_ARRAY_BUFFER: + return GL_ARRAY_BUFFER_BINDING; + case GL_COPY_READ_BUFFER: + return GL_COPY_READ_BUFFER_BINDING; + case GL_COPY_WRITE_BUFFER: + return GL_COPY_WRITE_BUFFER_BINDING; + case GL_ELEMENT_ARRAY_BUFFER: + return GL_ELEMENT_ARRAY_BUFFER_BINDING; + case GL_PIXEL_PACK_BUFFER: + return GL_PIXEL_PACK_BUFFER_BINDING; + case GL_PIXEL_UNPACK_BUFFER: + return GL_PIXEL_UNPACK_BUFFER_BINDING; + case GL_TRANSFORM_FEEDBACK_BUFFER: + return GL_TRANSFORM_FEEDBACK_BUFFER_BINDING; + case GL_UNIFORM_BUFFER: + return GL_UNIFORM_BUFFER_BINDING; + default: + return 0; + } +} + + namespace { // WebGraphicsContext3DCommandBufferImpl configuration attributes. Those in
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h index 9dd8f28..1661247 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.h +++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -191,6 +191,8 @@ uint64_t v64, uint32_t* v32_0, uint32_t* v32_1); static uint64_t MapTwoUint32ToUint64(uint32_t v32_0, uint32_t v32_1); + static uint32_t MapBufferTargetToBindingEnum(uint32_t target); + #include "../common/gles2_cmd_utils_autogen.h" private:
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h index 76419ce..cd5002d 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -41,6 +41,7 @@ static std::string GetStringImageUsage(uint32_t value); static std::string GetStringIndexType(uint32_t value); static std::string GetStringIndexedBufferTarget(uint32_t value); +static std::string GetStringMapBufferAccess(uint32_t value); static std::string GetStringMatrixMode(uint32_t value); static std::string GetStringPixelStore(uint32_t value); static std::string GetStringPixelType(uint32_t value);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 899a2f4..52511ed 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -4496,6 +4496,12 @@ static const EnumToString string_table[] = { {GL_ARRAY_BUFFER, "GL_ARRAY_BUFFER"}, {GL_ELEMENT_ARRAY_BUFFER, "GL_ELEMENT_ARRAY_BUFFER"}, + {GL_COPY_READ_BUFFER, "GL_COPY_READ_BUFFER"}, + {GL_COPY_WRITE_BUFFER, "GL_COPY_WRITE_BUFFER"}, + {GL_PIXEL_PACK_BUFFER, "GL_PIXEL_PACK_BUFFER"}, + {GL_PIXEL_UNPACK_BUFFER, "GL_PIXEL_UNPACK_BUFFER"}, + {GL_TRANSFORM_FEEDBACK_BUFFER, "GL_TRANSFORM_FEEDBACK_BUFFER"}, + {GL_UNIFORM_BUFFER, "GL_UNIFORM_BUFFER"}, }; return GLES2Util::GetQualifiedEnumString(string_table, arraysize(string_table), value); @@ -4839,6 +4845,19 @@ arraysize(string_table), value); } +std::string GLES2Util::GetStringMapBufferAccess(uint32_t value) { + static const EnumToString string_table[] = { + {GL_MAP_READ_BIT, "GL_MAP_READ_BIT"}, + {GL_MAP_WRITE_BIT, "GL_MAP_WRITE_BIT"}, + {GL_MAP_INVALIDATE_RANGE_BIT, "GL_MAP_INVALIDATE_RANGE_BIT"}, + {GL_MAP_INVALIDATE_BUFFER_BIT, "GL_MAP_INVALIDATE_BUFFER_BIT"}, + {GL_MAP_FLUSH_EXPLICIT_BIT, "GL_MAP_FLUSH_EXPLICIT_BIT"}, + {GL_MAP_UNSYNCHRONIZED_BIT, "GL_MAP_UNSYNCHRONIZED_BIT"}, + }; + return GLES2Util::GetQualifiedEnumString(string_table, + arraysize(string_table), value); +} + std::string GLES2Util::GetStringMatrixMode(uint32_t value) { static const EnumToString string_table[] = { {GL_PATH_PROJECTION_CHROMIUM, "GL_PATH_PROJECTION_CHROMIUM"},
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc index 1f64fd5..c2a0ba5 100644 --- a/gpu/command_buffer/service/buffer_manager.cc +++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -74,6 +74,27 @@ --buffer_count_; } +Buffer::MappedRange::MappedRange( + GLintptr offset, GLsizeiptr size, GLenum access, void* pointer, + scoped_refptr<gpu::Buffer> shm) + : offset(offset), + size(size), + access(access), + pointer(pointer), + shm(shm) { + DCHECK(pointer); + DCHECK(shm.get() && GetShmPointer()); +} + +Buffer::MappedRange::~MappedRange() { +} + +void* Buffer::MappedRange::GetShmPointer() const { + DCHECK(shm.get()); + return shm->GetDataAddress(static_cast<unsigned int>(offset), + static_cast<unsigned int>(size)); +} + Buffer::Buffer(BufferManager* manager, GLuint service_id) : manager_(manager), size_(0), @@ -119,6 +140,7 @@ memset(shadow_.get(), 0, size); } } + mapped_range_.reset(nullptr); } bool Buffer::CheckRange( @@ -397,12 +419,23 @@ // Since one BufferManager can be shared by multiple decoders, ContextState is // passed in each time and not just passed in during initialization. Buffer* BufferManager::GetBufferInfoForTarget( - ContextState* state, GLenum target) { - DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER); - if (target == GL_ARRAY_BUFFER) { - return state->bound_array_buffer.get(); - } else { - return state->vertex_attrib_manager->element_array_buffer(); + ContextState* state, GLenum target) const { + switch (target) { + case GL_ARRAY_BUFFER: + return state->bound_array_buffer.get(); + case GL_ELEMENT_ARRAY_BUFFER: + return state->vertex_attrib_manager->element_array_buffer(); + case GL_COPY_READ_BUFFER: + case GL_COPY_WRITE_BUFFER: + case GL_PIXEL_PACK_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_UNIFORM_BUFFER: + NOTIMPLEMENTED(); + return nullptr; + default: + NOTREACHED(); + return nullptr; } }
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h index 22a6e42..29bfaf4 100644 --- a/gpu/command_buffer/service/buffer_manager.h +++ b/gpu/command_buffer/service/buffer_manager.h
@@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "gpu/command_buffer/common/buffer.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "gpu/gpu_export.h" @@ -27,6 +28,19 @@ // Info about Buffers currently in the system. class GPU_EXPORT Buffer : public base::RefCounted<Buffer> { public: + struct MappedRange { + GLintptr offset; + GLsizeiptr size; + GLenum access; + void* pointer; // Pointer returned by driver. + scoped_refptr<gpu::Buffer> shm; // Client side mem. + + MappedRange(GLintptr offset, GLsizeiptr size, GLenum access, + void* pointer, scoped_refptr<gpu::Buffer> shm); + ~MappedRange(); + void* GetShmPointer() const; + }; + Buffer(BufferManager* manager, GLuint service_id); GLuint service_id() const { @@ -67,6 +81,19 @@ return is_client_side_array_; } + void SetMappedRange(GLintptr offset, GLsizeiptr size, GLenum access, + void* pointer, scoped_refptr<gpu::Buffer> shm) { + mapped_range_.reset(new MappedRange(offset, size, access, pointer, shm)); + } + + void RemoveMappedRange() { + mapped_range_.reset(nullptr); + } + + const MappedRange* GetMappedRange() const { + return mapped_range_.get(); + } + private: friend class BufferManager; friend class BufferManagerTestBase; @@ -163,6 +190,9 @@ // Usage of buffer. GLenum usage_; + // Data cached from last glMapBufferRange call. + scoped_ptr<MappedRange> mapped_range_; + // A map of ranges to the highest value in that range of a certain type. typedef std::map<Range, GLuint, Range::Less> RangeToMaxValueMap; RangeToMaxValueMap range_set_; @@ -232,15 +262,16 @@ // set to a non-zero size. bool UseNonZeroSizeForClientSideArrayBuffer(); + Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target) const; + private: friend class Buffer; friend class TestHelper; // Needs access to DoBufferData. friend class BufferManagerTestBase; // Needs access to DoBufferSubData. + void StartTracking(Buffer* buffer); void StopTracking(Buffer* buffer); - Buffer* GetBufferInfoForTarget(ContextState* state, GLenum target); - // Does a glBufferSubData and updates the approriate accounting. // Assumes the values have already been validated. void DoBufferSubData(
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 897afd3..2452954 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -1052,6 +1052,27 @@ #endif } +bool FeatureInfo::IsES3Capable() const { + if (gl_version_info_->IsAtLeastGLES(3, 0)) + return true; + // TODO(zmo): For Desktop GL, with anything lower than 4.2, we need to check + // the existence of a few extensions to have full WebGL 2 capabilities. + if (gl_version_info_->IsAtLeastGL(4, 2)) + return true; +#if defined(OS_MACOSX) + // TODO(zmo): For experimentation purpose on MacOSX with core profile, + // allow 3.2 or plus for now. + if (gl_version_info_->IsAtLeastGL(3, 2)) + return true; +#endif + return false; +} + +void FeatureInfo::EnableES3Validators() { + DCHECK(IsES3Capable()); + validators_.AddES3Values(); +} + void FeatureInfo::AddExtensionString(const char* s) { std::string str(s); size_t pos = extensions_.find(str);
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index 1a1870d..7816e79 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h
@@ -130,6 +130,9 @@ return *(gl_version_info_.get()); } + bool IsES3Capable() const; + void EnableES3Validators(); + private: friend class base::RefCounted<FeatureInfo>; friend class BufferManagerClientSideArraysTest;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index f76c085..3e568e3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2474,14 +2474,6 @@ set_log_commands(true); } - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableUnsafeES3APIs) && - attrib_parser.es3_context_required) { - // TODO(zmo): We need to implement capabilities check to ensure we can - // actually create ES3 contexts. - set_unsafe_es3_apis_enabled(true); - } - compile_shader_always_succeeds_ = base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kCompileShaderAlwaysSucceeds); @@ -2516,6 +2508,14 @@ } CHECK_GL_ERROR(); + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableUnsafeES3APIs) && + attrib_parser.es3_context_required && + feature_info_->IsES3Capable()) { + feature_info_->EnableES3Validators(); + set_unsafe_es3_apis_enabled(true); + } + disallowed_features_ = disallowed_features; state_.attrib_values.resize(group_->max_vertex_attribs()); @@ -3113,6 +3113,7 @@ for (GLsizei ii = 0; ii < n; ++ii) { Buffer* buffer = GetBuffer(client_ids[ii]); if (buffer && !buffer->IsDeleted()) { + buffer->RemoveMappedRange(); state_.vertex_attrib_manager->Unbind(buffer); if (state_.bound_array_buffer.get() == buffer) { state_.bound_array_buffer = NULL; @@ -12288,6 +12289,118 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleMapBufferRange( + uint32_t immediate_data_size, const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) { + return error::kUnknownCommand; + } + const gles2::cmds::MapBufferRange& c = + *static_cast<const gles2::cmds::MapBufferRange*>(cmd_data); + GLenum target = static_cast<GLenum>(c.target); + GLbitfield access = static_cast<GLbitfield>(c.access); + GLintptr offset = static_cast<GLintptr>(c.offset); + GLsizeiptr size = static_cast<GLsizeiptr>(c.size); + + typedef cmds::MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>( + c.result_shm_id, c.result_shm_offset, sizeof(*result)); + if (!result) { + return error::kOutOfBounds; + } + if (*result != 0) { + *result = 0; + return error::kInvalidArguments; + } + int8_t* mem = + GetSharedMemoryAs<int8_t*>(c.data_shm_id, c.data_shm_offset, size); + if (!mem) { + return error::kOutOfBounds; + } + + GLbitfield mask = GL_MAP_INVALIDATE_BUFFER_BIT; + if ((access & mask) == mask) { + // TODO(zmo): To be on the safe side, always map + // GL_MAP_INVALIDATE_BUFFER_BIT to GL_MAP_INVALIDATE_RANGE_BIT. + access = (access & ~GL_MAP_INVALIDATE_BUFFER_BIT); + access = (access | GL_MAP_INVALIDATE_RANGE_BIT); + } + // TODO(zmo): Always filter out GL_MAP_UNSYNCHRONIZED_BIT to get rid of + // undefined behaviors. + mask = GL_MAP_READ_BIT | GL_MAP_UNSYNCHRONIZED_BIT; + if ((access & mask) == mask) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "MapBufferRange", + "incompatible access bits"); + return error::kNoError; + } + access = (access & ~GL_MAP_UNSYNCHRONIZED_BIT); + if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT && + (access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) { + access = (access | GL_MAP_READ_BIT); + } + void* ptr = glMapBufferRange(target, offset, size, access); + if (ptr == nullptr) { + return error::kNoError; + } + Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target); + DCHECK(buffer); + buffer->SetMappedRange(offset, size, access, ptr, + GetSharedMemoryBuffer(c.data_shm_id)); + if ((access & GL_MAP_INVALIDATE_RANGE_BIT) == 0) { + memcpy(mem, ptr, size); + } + *result = 1; + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleUnmapBuffer( + uint32_t immediate_data_size, const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) { + return error::kUnknownCommand; + } + const gles2::cmds::UnmapBuffer& c = + *static_cast<const gles2::cmds::UnmapBuffer*>(cmd_data); + GLenum target = static_cast<GLenum>(c.target); + + Buffer* buffer = buffer_manager()->GetBufferInfoForTarget(&state_, target); + if (!buffer) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", "no buffer bound"); + return error::kNoError; + } + const Buffer::MappedRange* mapped_range = buffer->GetMappedRange(); + if (!mapped_range) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "UnmapBuffer", + "buffer is unmapped"); + return error::kNoError; + } + if ((mapped_range->access & GL_MAP_WRITE_BIT) == 0 || + (mapped_range->access & GL_MAP_FLUSH_EXPLICIT_BIT) == + GL_MAP_FLUSH_EXPLICIT_BIT) { + // If we don't need to write back, or explict flush is required, no copying + // back is needed. + } else { + void* mem = mapped_range->GetShmPointer(); + if (!mem) { + return error::kOutOfBounds; + } + DCHECK(mapped_range->pointer); + memcpy(mapped_range->pointer, mem, mapped_range->size); + } + buffer->RemoveMappedRange(); + GLboolean rt = glUnmapBuffer(target); + if (rt == GL_FALSE) { + // At this point, we have already done the necessary validation, so + // GL_FALSE indicates data corruption. + // TODO(zmo): We could redo the map / copy data / unmap to recover, but + // the second unmap could still return GL_FALSE. For now, we simply lose + // the contexts in the share group. + LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE"; + group_->LoseContexts(GL_INNOCENT_CONTEXT_RESET_ARB); + reset_status_ = GL_GUILTY_CONTEXT_RESET_ARB; + return error::kLostContext; + } + return error::kNoError; +} + void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer( TextureRef* texture_ref) { Texture* texture = texture_ref->texture();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index 29a55ba..2e153b4 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -218,6 +218,10 @@ // TODO(gman): GetMaxValueInBufferCHROMIUM // TODO(gman): EnableFeatureCHROMIUM +// TODO(gman): MapBufferRange + +// TODO(gman): UnmapBuffer + // TODO(gman): ResizeCHROMIUM // TODO(gman): GetRequestableExtensionsCHROMIUM
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc new file mode 100644 index 0000000..389c78f --- /dev/null +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
@@ -0,0 +1,471 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::Return; +using ::testing::SetArgPointee; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +namespace { + +} // namespace anonymous + +TEST_P(GLES2DecoderTest, MapBufferRangeUnmapBufferReadSucceeds) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_READ_BIT; + + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + // uint32_t is Result for both MapBufferRange and UnmapBuffer commands. + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t); + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + std::vector<int8_t> data(kSize); + for (GLsizeiptr ii = 0; ii < kSize; ++ii) { + data[ii] = static_cast<int8_t>(ii % 255); + } + + { // MapBufferRange + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kAccess)) + .WillOnce(Return(&data[0])) + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + decoder_->set_unsafe_es3_apis_enabled(false); + *result = 0; + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); + EXPECT_EQ(0u, *result); + decoder_->set_unsafe_es3_apis_enabled(true); + *result = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + int8_t* mem = reinterpret_cast<int8_t*>(&result[1]); + EXPECT_EQ(0, memcmp(&data[0], mem, kSize)); + EXPECT_EQ(1u, *result); + } + + { // UnmapBuffer + EXPECT_CALL(*gl_, UnmapBuffer(kTarget)) + .WillOnce(Return(GL_TRUE)) + .RetiresOnSaturation(); + + UnmapBuffer cmd; + cmd.Init(kTarget); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, MapBufferRangeUnmapBufferWriteSucceeds) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_WRITE_BIT; + const GLbitfield kMappedAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT; + + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + // uint32_t is Result for both MapBufferRange and UnmapBuffer commands. + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t); + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + std::vector<int8_t> data(kSize); + for (GLsizeiptr ii = 0; ii < kSize; ++ii) { + data[ii] = static_cast<int8_t>(ii % 255); + } + + { // MapBufferRange succeeds + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kMappedAccess)) + .WillOnce(Return(&data[0])) + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + decoder_->set_unsafe_es3_apis_enabled(false); + *result = 0; + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); + EXPECT_EQ(0u, *result); + decoder_->set_unsafe_es3_apis_enabled(true); + *result = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + int8_t* mem = reinterpret_cast<int8_t*>(&result[1]); + EXPECT_EQ(0, memcmp(&data[0], mem, kSize)); + EXPECT_EQ(1u, *result); + } + + { // UnmapBuffer succeeds + EXPECT_CALL(*gl_, UnmapBuffer(kTarget)) + .WillOnce(Return(GL_TRUE)) + .RetiresOnSaturation(); + + UnmapBuffer cmd; + cmd.Init(kTarget); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } + + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest, MapBufferRangeNotInitFails) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_READ_BIT; + std::vector<int8_t> data(kSize); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = 1; // Any value other than 0. + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result); + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, MapBufferRangeWriteInvalidateRangeSucceeds) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + // With MAP_INVALIDATE_RANGE_BIT, no need to append MAP_READ_BIT. + const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT; + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + std::vector<int8_t> data(kSize); + for (GLsizeiptr ii = 0; ii < kSize; ++ii) { + data[ii] = static_cast<int8_t>(ii % 255); + } + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kAccess)) + .WillOnce(Return(&data[0])) + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = 0; + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result); + + int8_t* mem = reinterpret_cast<int8_t*>(&result[1]); + memset(mem, 72, kSize); // Init to a random value other than 0. + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, MapBufferRangeWriteInvalidateBufferSucceeds) { + // Test INVALIDATE_BUFFER_BIT is mapped to INVALIDATE_RANGE_BIT. + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT; + // With MAP_INVALIDATE_BUFFER_BIT, no need to append MAP_READ_BIT. + const GLbitfield kFilteredAccess = + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT; + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + std::vector<int8_t> data(kSize); + for (GLsizeiptr ii = 0; ii < kSize; ++ii) { + data[ii] = static_cast<int8_t>(ii % 255); + } + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess)) + .WillOnce(Return(&data[0])) + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = 0; + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result); + + int8_t* mem = reinterpret_cast<int8_t*>(&result[1]); + memset(mem, 72, kSize); // Init to a random value other than 0. + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, MapBufferRangeWriteUnsynchronizedBit) { + // Test UNSYNCHRONIZED_BIT is filtered out. + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT; + const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT; + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + std::vector<int8_t> data(kSize); + for (GLsizeiptr ii = 0; ii < kSize; ++ii) { + data[ii] = static_cast<int8_t>(ii % 255); + } + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess)) + .WillOnce(Return(&data[0])) + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = 0; + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result); + + int8_t* mem = reinterpret_cast<int8_t*>(&result[1]); + memset(mem, 72, kSize); // Init to a random value other than 0. + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(0, memcmp(&data[0], mem, kSize)); +} + +TEST_P(GLES2DecoderTest, MapBufferRangeWithError) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_READ_BIT; + std::vector<int8_t> data(kSize); + for (GLsizeiptr ii = 0; ii < kSize; ++ii) { + data[ii] = static_cast<int8_t>(ii % 255); + } + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kAccess)) + .WillOnce(Return(nullptr)) // Return nullptr to indicate a GL error. + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = 0; + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result); + + int8_t* mem = reinterpret_cast<int8_t*>(&result[1]); + memset(mem, 72, kSize); // Init to a random value other than 0. + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + memset(&data[0], 72, kSize); + // Mem is untouched. + EXPECT_EQ(0, memcmp(&data[0], mem, kSize)); + EXPECT_EQ(0u, *result); +} + +TEST_P(GLES2DecoderTest, MapBufferRangeBadSharedMemoryFails) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_READ_BIT; + std::vector<int8_t> data(kSize); + for (GLsizeiptr ii = 0; ii < kSize; ++ii) { + data[ii] = static_cast<int8_t>(ii % 255); + } + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = 0; + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result); + + decoder_->set_unsafe_es3_apis_enabled(true); + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, + kInvalidSharedMemoryId, data_shm_offset, + result_shm_id, result_shm_offset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(kTarget, kOffset, kSize, kAccess, + data_shm_id, data_shm_offset, + kInvalidSharedMemoryId, result_shm_offset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(kTarget, kOffset, kSize, kAccess, + data_shm_id, kInvalidSharedMemoryOffset, + result_shm_id, result_shm_offset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(kTarget, kOffset, kSize, kAccess, + data_shm_id, data_shm_offset, + result_shm_id, kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest, UnmapBufferWriteNotMappedFails) { + const GLenum kTarget = GL_ARRAY_BUFFER; + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + UnmapBuffer cmd; + cmd.Init(kTarget); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, UnmapBufferWriteNoBoundBufferFails) { + const GLenum kTarget = GL_ARRAY_BUFFER; + + UnmapBuffer cmd; + cmd.Init(kTarget); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); +} + +TEST_P(GLES2DecoderTest, BufferDataDestroysDataStore) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_WRITE_BIT; + const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT; + + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + // uint32_t is Result for both MapBufferRange and UnmapBuffer commands. + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t); + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + std::vector<int8_t> data(kSize); + + decoder_->set_unsafe_es3_apis_enabled(true); + + { // MapBufferRange succeeds + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess)) + .WillOnce(Return(&data[0])) + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + *result = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1u, *result); + } + + { // BufferData unmaps the data store. + DoBufferData(kTarget, kSize * 2); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + { // UnmapBuffer fails. + UnmapBuffer cmd; + cmd.Init(kTarget); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + } +} + +TEST_P(GLES2DecoderTest, DeleteBuffersDestroysDataStore) { + const GLenum kTarget = GL_ARRAY_BUFFER; + const GLintptr kOffset = 10; + const GLsizeiptr kSize = 64; + const GLbitfield kAccess = GL_MAP_WRITE_BIT; + const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT; + + uint32_t result_shm_id = kSharedMemoryId; + uint32_t result_shm_offset = kSharedMemoryOffset; + uint32_t data_shm_id = kSharedMemoryId; + // uint32_t is Result for both MapBufferRange and UnmapBuffer commands. + uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t); + + DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId); + + std::vector<int8_t> data(kSize); + + decoder_->set_unsafe_es3_apis_enabled(true); + + { // MapBufferRange succeeds + EXPECT_CALL(*gl_, + MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess)) + .WillOnce(Return(&data[0])) + .RetiresOnSaturation(); + + typedef MapBufferRange::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + + MapBufferRange cmd; + cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset, + result_shm_id, result_shm_offset); + *result = 0; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(1u, *result); + } + + { // DeleteBuffers unmaps the data store. + DoDeleteBuffer(client_buffer_id_, kServiceBufferId); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + } + + { // UnmapBuffer fails. + UnmapBuffer cmd; + cmd.Init(kTarget); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); + } +} + +} // namespace gles2 +} // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_validation.h b/gpu/command_buffer/service/gles2_cmd_validation.h index 22ee2da..8ca9861 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation.h +++ b/gpu/command_buffer/service/gles2_cmd_validation.h
@@ -22,9 +22,7 @@ ValueValidator() {} ValueValidator(const T* valid_values, int num_values) { - for (int ii = 0; ii < num_values; ++ii) { - AddValue(valid_values[ii]); - } + AddValues(valid_values, num_values); } void AddValue(const T value) { @@ -33,6 +31,12 @@ } } + void AddValues(const T* valid_values, int num_values) { + for (int ii = 0; ii < num_values; ++ii) { + AddValue(valid_values[ii]); + } + } + bool IsValid(const T value) const { return std::find(valid_values_.begin(), valid_values_.end(), value) != valid_values_.end(); @@ -48,6 +52,9 @@ struct Validators { Validators(); + + void AddES3Values(); + #include "gpu/command_buffer/service/gles2_cmd_validation_autogen.h" };
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index 953c0f9..2a8684a 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -41,6 +41,7 @@ ValueValidator<GLenum> image_usage; ValueValidator<GLenum> index_type; ValueValidator<GLenum> indexed_buffer_target; +ValueValidator<GLenum> map_buffer_access; ValueValidator<GLenum> matrix_mode; ValueValidator<GLenum> pixel_store; ValueValidator<GLint> pixel_store_alignment;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 5512be9..2f83240 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -43,6 +43,15 @@ GL_ELEMENT_ARRAY_BUFFER, }; +static const GLenum valid_buffer_target_table_es3[] = { + GL_COPY_READ_BUFFER, + GL_COPY_WRITE_BUFFER, + GL_PIXEL_PACK_BUFFER, + GL_PIXEL_UNPACK_BUFFER, + GL_TRANSFORM_FEEDBACK_BUFFER, + GL_UNIFORM_BUFFER, +}; + static const GLenum valid_buffer_usage_table[] = { GL_STREAM_DRAW, GL_STATIC_DRAW, @@ -280,6 +289,15 @@ GL_UNIFORM_BUFFER, }; +static const GLenum valid_map_buffer_access_table[] = { + GL_MAP_READ_BIT, + GL_MAP_WRITE_BIT, + GL_MAP_INVALIDATE_RANGE_BIT, + GL_MAP_INVALIDATE_BUFFER_BIT, + GL_MAP_FLUSH_EXPLICIT_BIT, + GL_MAP_UNSYNCHRONIZED_BIT, +}; + static const GLenum valid_matrix_mode_table[] = { GL_PATH_PROJECTION_CHROMIUM, GL_PATH_MODELVIEW_CHROMIUM, @@ -661,6 +679,8 @@ index_type(valid_index_type_table, arraysize(valid_index_type_table)), indexed_buffer_target(valid_indexed_buffer_target_table, arraysize(valid_indexed_buffer_target_table)), + map_buffer_access(valid_map_buffer_access_table, + arraysize(valid_map_buffer_access_table)), matrix_mode(valid_matrix_mode_table, arraysize(valid_matrix_mode_table)), pixel_store(valid_pixel_store_table, arraysize(valid_pixel_store_table)), pixel_store_alignment(valid_pixel_store_alignment_table, @@ -751,4 +771,9 @@ arraysize(valid_vertex_pointer_table)) { } +void Validators::AddES3Values() { + buffer_target.AddValues(valid_buffer_target_table_es3, + arraysize(valid_buffer_target_table_es3)); +} + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_IMPLEMENTATION_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gpu_tracer.cc b/gpu/command_buffer/service/gpu_tracer.cc index 2fbf46c..d00deb0 100644 --- a/gpu/command_buffer/service/gpu_tracer.cc +++ b/gpu/command_buffer/service/gpu_tracer.cc
@@ -90,7 +90,8 @@ name_(name), outputter_(outputter), enabled_(enabled) { - if (gpu_timing_client->IsAvailable()) { + if (gpu_timing_client->IsAvailable() && + gpu_timing_client->IsTimerOffsetAvailable()) { gpu_timer_ = gpu_timing_client->CreateGPUTimer(); } }
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc index 946d8ae..48a4db9 100644 --- a/gpu/command_buffer/service/gpu_tracer_unittest.cc +++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -198,7 +198,10 @@ g_fakeCPUTime = 0; const char* gl_version = "3.2"; const char* extensions = ""; - if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) { + if (GetTimerType() == gfx::GPUTiming::kTimerTypeEXT) { + gl_version = "opengl 2.1"; + extensions = "GL_EXT_timer_query"; + } else if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) { gl_version = "opengl es 3.0"; extensions = "GL_EXT_disjoint_timer_query"; } else if (GetTimerType() == gfx::GPUTiming::kTimerTypeARB) { @@ -231,7 +234,8 @@ } void ExpectTraceQueryMocks() { - if (GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid) { + if (gpu_timing_client_->IsAvailable() && + gpu_timing_client_->IsTimerOffsetAvailable()) { // Delegate query APIs used by GPUTrace to a GlFakeQueries EXPECT_CALL(*gl_, GenQueriesARB(2, NotNull())).Times(AtLeast(1)) .WillRepeatedly( @@ -293,7 +297,8 @@ const std::string& name, int64 expect_start_time, int64 expect_end_time) { ExpectOutputterBeginMocks(outputter, category, name); - bool valid_timer = GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid; + bool valid_timer = gpu_timing_client_->IsAvailable() && + gpu_timing_client_->IsTimerOffsetAvailable(); ExpectOutputterEndMocks(outputter, category, name, expect_start_time, expect_end_time, valid_timer); } @@ -478,7 +483,8 @@ std::string source_category = category_name + num_char; std::string source_trace_name = trace_name + num_char; - bool valid_timer = GetTimerType() != gfx::GPUTiming::kTimerTypeInvalid; + bool valid_timer = gpu_timing_client_->IsAvailable() && + gpu_timing_client_->IsTimerOffsetAvailable(); ExpectOutputterEndMocks(outputter_ref_.get(), source_category, source_trace_name, expect_start_time + i, expect_end_time + i, valid_timer); @@ -565,6 +571,11 @@ : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeInvalid) {} }; +class GpuEXTTimerTracerTest : public BaseGpuTracerTest { + public: + GpuEXTTimerTracerTest() : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeEXT) {} +}; + class GpuARBTimerTracerTest : public BaseGpuTracerTest { public: GpuARBTimerTracerTest() @@ -581,6 +592,10 @@ DoBasicTracerTest(); } +TEST_F(GpuEXTTimerTracerTest, EXTTimerBasicTracerTest) { + DoBasicTracerTest(); +} + TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerTest) { DoBasicTracerTest(); } @@ -593,6 +608,10 @@ DoTracerMarkersTest(); } +TEST_F(GpuEXTTimerTracerTest, EXTTimerTracerMarkersTest) { + DoTracerMarkersTest(); +} + TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerMarkersTest) { DoTracerMarkersTest(); }
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc index fa07180..55754b7 100644 --- a/gpu/command_buffer/service/shader_manager.cc +++ b/gpu/command_buffer/service/shader_manager.cc
@@ -27,6 +27,7 @@ Shader::Shader(GLuint service_id, GLenum shader_type) : use_count_(0), shader_state_(kShaderStateWaiting), + marked_for_deletion_(false), service_id_(service_id), shader_type_(shader_type), source_type_(kANGLE), @@ -36,6 +37,12 @@ Shader::~Shader() { } +void Shader::Destroy() { + if (service_id_) { + DeleteServiceID(); + } +} + void Shader::RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator, TranslatedShaderSourceType type) { shader_state_ = kShaderStateCompileRequested; @@ -105,6 +112,8 @@ // We cannot reach here if we are using the shader translator. // All invalid shaders must be rejected by the translator. // All translated shaders must compile. + std::string translator_log = log_info_; + GLint max_len = 0; glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len); log_info_.resize(max_len); @@ -115,9 +124,11 @@ DCHECK(len == 0 || log_info_[len] == '\0'); log_info_.resize(len); } + LOG_IF(ERROR, translator) << "Shader translator allowed/produced an invalid shader " << "unless the driver is buggy:" + << "\n--Log from shader translator--\n" << translator_log << "\n--original-shader--\n" << last_compiled_source_ << "\n--translated-shader--\n" << source_for_driver << "\n--info-log--\n" << log_info_; @@ -131,13 +142,22 @@ void Shader::DecUseCount() { --use_count_; DCHECK_GE(use_count_, 0); + if (service_id_ && use_count_ == 0 && marked_for_deletion_) { + DeleteServiceID(); + } } -void Shader::Delete() { - if (use_count_ > 0) { - // If attached, compile the shader before we delete it. - DoCompile(); +void Shader::MarkForDeletion() { + DCHECK(!marked_for_deletion_); + DCHECK_NE(service_id_, 0u); + + marked_for_deletion_ = true; + if (use_count_ == 0) { + DeleteServiceID(); } +} + +void Shader::DeleteServiceID() { DCHECK_NE(service_id_, 0u); glDeleteShader(service_id_); service_id_ = 0; @@ -189,9 +209,7 @@ while (!shaders_.empty()) { if (have_context) { Shader* shader = shaders_.begin()->second.get(); - if (!shader->IsDeleted()) { - shader->Delete(); - } + shader->Destroy(); } shaders_.erase(shaders_.begin()); } @@ -254,7 +272,7 @@ void ShaderManager::Delete(Shader* shader) { DCHECK(shader); DCHECK(IsOwned(shader)); - shader->Delete(); + shader->MarkForDeletion(); RemoveShader(shader); }
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h index 2fbe0dc..0c48b99 100644 --- a/gpu/command_buffer/service/shader_manager.h +++ b/gpu/command_buffer/service/shader_manager.h
@@ -45,7 +45,7 @@ } GLuint service_id() const { - return service_id_; + return marked_for_deletion_ ? 0 : service_id_; } GLenum shader_type() const { @@ -97,7 +97,7 @@ } bool IsDeleted() const { - return service_id_ == 0; + return marked_for_deletion_; } bool InUse() const { @@ -145,15 +145,23 @@ Shader(GLuint service_id, GLenum shader_type); ~Shader(); + // Must be called only if we currently own the context. Forces the deletion + // of the underlying shader service id. + void Destroy(); + void IncUseCount(); void DecUseCount(); - void Delete(); + void MarkForDeletion(); + void DeleteServiceID(); int use_count_; // The current state of the shader. ShaderState shader_state_; + // The shader has been marked for deletion. + bool marked_for_deletion_; + // The shader this Shader is tracking. GLuint service_id_;
diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc index 88f4715..3103e88 100644 --- a/gpu/command_buffer/service/shader_manager_unittest.cc +++ b/gpu/command_buffer/service/shader_manager_unittest.cc
@@ -82,16 +82,19 @@ ASSERT_TRUE(shader1.get()); ASSERT_TRUE(shader2.get()); manager_.UseShader(shader1.get()); - EXPECT_CALL(*gl_, DeleteShader(kService1Id)) - .Times(1) - .RetiresOnSaturation(); manager_.Delete(shader1.get()); + EXPECT_CALL(*gl_, DeleteShader(kService2Id)) .Times(1) .RetiresOnSaturation(); manager_.Delete(shader2.get()); EXPECT_TRUE(manager_.IsOwned(shader1.get())); EXPECT_FALSE(manager_.IsOwned(shader2.get())); + + EXPECT_CALL(*gl_, DeleteShader(kService1Id)) + .Times(1) + .RetiresOnSaturation(); + manager_.UnuseShader(shader1.get()); } TEST_F(ShaderManagerTest, DoCompile) {
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc index f4a382c..c95ef9f 100644 --- a/gpu/config/gpu_control_list.cc +++ b/gpu/config/gpu_control_list.cc
@@ -1010,7 +1010,9 @@ GLType gl_type = kGLTypeNone; if (segments.size() > 2 && segments[0] == "OpenGL" && segments[1] == "ES") { - number = segments[2]; + bool full_match = RE2::FullMatch(segments[2], "([\\d.]+).*", &number); + DCHECK(full_match); + gl_type = kGLTypeGLES; if (segments.size() > 3 && StartsWithASCII(segments[3], "(ANGLE", false)) {
diff --git a/gpu/config/gpu_control_list_entry_unittest.cc b/gpu/config/gpu_control_list_entry_unittest.cc index 4a26918..5587446 100644 --- a/gpu/config/gpu_control_list_entry_unittest.cc +++ b/gpu/config/gpu_control_list_entry_unittest.cc
@@ -398,6 +398,9 @@ gpu_info.gl_version = "OpenGL ES 3.0 V@66.0 AU@ (CL@)"; EXPECT_TRUE(entry->Contains(GpuControlList::kOsAndroid, "4.4.2", gpu_info)); + gpu_info.gl_version = "OpenGL ES 3.0V@66.0 AU@ (CL@)"; + EXPECT_TRUE(entry->Contains(GpuControlList::kOsAndroid, "4.4.2", gpu_info)); + gpu_info.gl_version = "OpenGL ES 3.1 V@66.0 AU@ (CL@)"; EXPECT_FALSE(entry->Contains(GpuControlList::kOsAndroid, "4.4.2", gpu_info));
diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc index 437c5d9..95d828d 100644 --- a/gpu/config/software_rendering_list_json.cc +++ b/gpu/config/software_rendering_list_json.cc
@@ -18,7 +18,7 @@ { "name": "software rendering list", // Please update the version number whenever you change this file. - "version": "9.18", + "version": "9.19", "entries": [ { "id": 1, @@ -1054,15 +1054,6 @@ "type": "android", "version": { "op": ">=", - "value": "4.4.99" - } - } - }, - { - "os": { - "type": "android", - "version": { - "op": ">=", "value": "4.4" } },
diff --git a/gpu/gles2_conform_support/egl/BUILD.gn b/gpu/gles2_conform_support/egl/BUILD.gn new file mode 100644 index 0000000..0216522 --- /dev/null +++ b/gpu/gles2_conform_support/egl/BUILD.gn
@@ -0,0 +1,36 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# GYP version: gpu/gles2_conform_support/gles_conform_support.gyp:egl_native +source_set("egl") { + output_name = "egl_native" + sources = [ + "config.cc", + "config.h", + "display.cc", + "display.h", + "egl.cc", + "surface.cc", + "surface.h", + ] + + configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + + defines = [ + "EGLAPI=", + "EGLAPIENTRY=", + ] + + deps = [ + "//base", + "//gpu/command_buffer/client:gles2_c_lib", + "//gpu/command_buffer/client:gles2_implementation_no_check", + "//gpu/command_buffer/service", + "//gpu", + "//ui/base", + "//ui/gfx", + "//ui/gfx/geometry", + "//ui/gl", + ] +}
diff --git a/gpu/gles2_conform_support/gles2_conform_support.gyp b/gpu/gles2_conform_support/gles2_conform_support.gyp index 6bf8510..05aa9ac 100644 --- a/gpu/gles2_conform_support/gles2_conform_support.gyp +++ b/gpu/gles2_conform_support/gles2_conform_support.gyp
@@ -30,6 +30,7 @@ }, 'targets': [ { + # GN version: //gpu/gles2_conform_support/egl 'target_name': 'egl_native', 'type': 'static_library', 'dependencies': [ @@ -60,6 +61,7 @@ 'msvs_disabled_warnings': [ 4267, ], }, { + # GN version: //gpu/gles2_conform_support/native 'target_name': 'egl_main_native', 'type': 'static_library', 'dependencies': [ @@ -77,6 +79,7 @@ ], }, { + # GN version: //gpu/gles2_conform_support/native:windowless 'target_name': 'egl_main_windowless', 'type': 'static_library', 'dependencies': [
diff --git a/gpu/gles2_conform_support/native/BUILD.gn b/gpu/gles2_conform_support/native/BUILD.gn new file mode 100644 index 0000000..aeaa6d2 --- /dev/null +++ b/gpu/gles2_conform_support/native/BUILD.gn
@@ -0,0 +1,62 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# GYP version: gpu/gles2_conform_support/gles2_conform_support.gyp:egl_main_native +source_set("native") { + output_name = "egl_main_native" + sources = [ + "egl_native.cc", + "main.cc", + ] + defines = [ + "GLES2_CONFORM_SUPPORT_ONLY", + "GTF_GLES20", + "EGLAPI=", + "EGLAPIENTRY=", + ] + deps = [ + "//base", + "//gpu/gles2_conform_support/egl", + "//ui/gl", + ] + if (is_linux) { + sources += [ + "egl_native_aura.cc", + "egl_native_x11.cc", + ] + } + if (is_win) { + sources += [ "egl_native_win.cc" ] + } +} + +# GYP version: gpu/gles2_conform_support/gles2_conform_support.gyp:egl_main_windowless +source_set("windowless") { + output_name = "egl_main_windowless" + sources = [ + "egl_native.cc", + "egl_native_windowless.cc", + "main.cc", + ] + defines = [ + "GLES2_CONFORM_SUPPORT_ONLY", + "GTF_GLES20", + "EGLAPI=", + "EGLAPIENTRY=", + ] + deps = [ + "//base", + "//gpu/gles2_conform_support/egl", + "//ui/gl", + ] + if (is_linux) { + sources += [ + "egl_native_aura.cc", + "egl_native_x11.cc", + ] + } + if (is_win) { + sources += [ "egl_native_win.cc" ] + } +}
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 2bb7465..0e31fb0 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp
@@ -103,6 +103,7 @@ 'msvs_disabled_warnings': [4267, ], }, { + # GN version: //gpu/command_buffer/client:gles2_c_lib_nocheck # Same as gles2_c_lib except with no parameter checking. Required for # OpenGL ES 2.0 conformance tests. 'target_name': 'gles2_c_lib_nocheck', @@ -220,6 +221,7 @@ 'command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_base.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_base.h', + 'command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc', @@ -287,6 +289,7 @@ 'dependencies': [ '../base/base.gyp:base', '../base/base.gyp:test_support_base', + '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', '../testing/perf/perf_test.gyp:perf_test', '../ui/gfx/gfx.gyp:gfx_geometry',
diff --git a/gpu/gpu_unittests.isolate b/gpu/gpu_unittests.isolate index a718aac..7ad1b79 100644 --- a/gpu/gpu_unittests.isolate +++ b/gpu/gpu_unittests.isolate
@@ -3,15 +3,20 @@ # found in the LICENSE file. { 'conditions': [ - ['OS=="linux" or OS=="mac" or OS=="win"', { + ['use_x11==0', { 'variables': { - 'files': [ + 'command': [ '../testing/test_env.py', '<(PRODUCT_DIR)/gpu_unittests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--msan=<(msan)', + '--tsan=<(tsan)', ], }, }], - ['OS=="linux"', { + ['use_x11==1', { 'variables': { 'command': [ '../testing/xvfb.py', @@ -29,29 +34,11 @@ ], }, }], - ['OS=="mac"', { + ['OS=="linux" or OS=="mac" or OS=="win"', { 'variables': { - 'command': [ + 'files': [ '../testing/test_env.py', - '<(PRODUCT_DIR)/gpu_unittests', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--msan=<(msan)', - '--tsan=<(tsan)', - ], - }, - }], - ['OS=="win"', { - 'variables': { - 'command': [ - '../testing/test_env.py', - '<(PRODUCT_DIR)/gpu_unittests.exe', - '--brave-new-test-launcher', - '--test-launcher-bot-mode', - '--asan=<(asan)', - '--msan=<(msan)', - '--tsan=<(tsan)', + '<(PRODUCT_DIR)/gpu_unittests<(EXECUTABLE_SUFFIX)', ], }, }], @@ -72,5 +59,6 @@ ], 'includes': [ '../base/base.isolate', + '../third_party/angle/angle.isolate', ], }
diff --git a/gpu/perftests/texture_upload_perftest.cc b/gpu/perftests/texture_upload_perftest.cc index 5f76746..e36fb1b 100644 --- a/gpu/perftests/texture_upload_perftest.cc +++ b/gpu/perftests/texture_upload_perftest.cc
@@ -11,11 +11,14 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "gpu/perftests/measurements.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/vector2d_f.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" +#include "ui/gl/gl_enums.h" #include "ui/gl/gl_surface.h" #include "ui/gl/gpu_timing.h" #include "ui/gl/scoped_make_current.h" @@ -31,11 +34,13 @@ // clang-format off const char kVertexShader[] = SHADER( + uniform vec2 translation = vec2(0.0, 0.0); attribute vec2 a_position; attribute vec2 a_texCoord; varying vec2 v_texCoord; void main() { - gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); + gl_Position = vec4( + translation.x + a_position.x, translation.y + a_position.y, 0.0, 1.0); v_texCoord = a_texCoord; } ); @@ -77,20 +82,57 @@ } void GenerateTextureData(const gfx::Size& size, + int bytes_per_pixel, const int seed, std::vector<uint8>* const pixels) { - pixels->resize(size.GetArea() * 4); - for (int y = 0; y < size.height(); ++y) { - for (int x = 0; x < size.width(); ++x) { - const size_t offset = (y * size.width() + x) * 4; - pixels->at(offset) = (y + seed) % 64; - pixels->at(offset + 1) = (x + seed) % 128; - pixels->at(offset + 2) = (y + x + seed) % 256; - pixels->at(offset + 3) = 255; + int bytes = size.GetArea() * bytes_per_pixel; + pixels->resize(bytes); + for (int i = 0; i < bytes; ++i) { + int channel = i % bytes_per_pixel; + if (channel == 3) { // Alpha channel. + pixels->at(i) = 255; + } else { + pixels->at(i) = (i + (seed << 2)) % (32 << channel); } } } +// Compare a buffer containing pixels in a specified format to GL_RGBA buffer +// where the former buffer have been uploaded as a texture and drawn on the +// RGBA buffer. +bool CompareBufferToRGBABuffer(GLenum format, + const std::vector<uint8>& pixels, + const std::vector<uint8>& pixels_rgba) { + for (size_t i = 0; i < pixels.size(); i += 4) { + switch (format) { + case GL_RED_EXT: // (R_t, 0, 0, 1) + if (pixels_rgba[i] != pixels[i / 4] || pixels_rgba[i + 1] != 0 || + pixels_rgba[i + 2] != 0 || pixels_rgba[i + 3] != 255) { + return false; + } + break; + case GL_LUMINANCE: // (L_t, L_t, L_t, 1) + if (pixels_rgba[i] != pixels[i / 4] || + pixels_rgba[i + 1] != pixels[i / 4] || + pixels_rgba[i + 2] != pixels[i / 4] || pixels_rgba[i + 3] != 255) { + return false; + } + break; + case GL_RGBA: // (R_t, G_t, B_t, A_t) + if (pixels_rgba[i] != pixels[i] || + pixels_rgba[i + 1] != pixels[i + 1] || + pixels_rgba[i + 2] != pixels[i + 2] || + pixels_rgba[i + 3] != pixels[i + 3]) { + return false; + } + break; + default: + NOTREACHED(); + } + } + return true; +} + // PerfTest to check costs of texture upload at different stages // on different platforms. class TextureUploadPerfTest : public testing::Test { @@ -99,8 +141,9 @@ // Overridden from testing::Test void SetUp() override { + static bool gl_initialized = gfx::GLSurface::InitializeOneOff(); + DCHECK(gl_initialized); // Initialize an offscreen surface and a gl context. - gfx::GLSurface::InitializeOneOff(); surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(4, 4)); gl_context_ = gfx::GLContext::CreateGLContext(NULL, // share_group surface_.get(), @@ -146,15 +189,28 @@ glBindAttribLocation(program_object_, 1, "a_texCoord"); glLinkProgram(program_object_); + translation_location_ = + glGetUniformLocation(program_object_, "translation"); + DCHECK_NE(-1, translation_location_); + GLint linked = -1; glGetProgramiv(program_object_, GL_LINK_STATUS, &linked); CHECK_NE(0, linked); + glUseProgram(program_object_); + glUniform1i(sampler_location_, 0); sampler_location_ = glGetUniformLocation(program_object_, "a_texture"); CHECK_NE(-1, sampler_location_); glGenBuffersARB(1, &vertex_buffer_); CHECK_NE(0u, vertex_buffer_); + DCHECK_NE(0u, vertex_buffer_); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, + reinterpret_cast<void*>(sizeof(GLfloat) * 2)); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); CheckNoGlError(); } @@ -176,7 +232,6 @@ -1.f, top, 0.f, 1.f, right, top, 1.f, 1.f}; // clang-format on - glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); CheckNoGlError(); } @@ -199,41 +254,39 @@ } protected: - // Upload and draw on the offscren surface. - // Return a list of pair. Each pair describe a gl operation and the wall - // time elapsed in milliseconds. - std::vector<Measurement> UploadAndDraw(const gfx::Size& size, - const std::vector<uint8>& pixels, - const GLenum format, - const GLenum type) { - MeasurementTimers total_timers(gpu_timing_client_.get()); + GLuint CreateGLTexture() { GLuint texture_id = 0; - - MeasurementTimers tex_timers(gpu_timing_client_.get()); glActiveTexture(GL_TEXTURE0); glGenTextures(1, &texture_id); glBindTexture(GL_TEXTURE_2D, texture_id); + return texture_id; + } + void UploadTexture(GLuint texture_id, + const gfx::Size& size, + const std::vector<uint8>& pixels, + GLenum format) { glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, - format, type, &pixels[0]); + format, GL_UNSIGNED_BYTE, &pixels[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CheckNoGlError(); + } + + // Upload and draw on the offscren surface. + // Return a list of pair. Each pair describe a gl operation and the wall + // time elapsed in milliseconds. + std::vector<Measurement> UploadAndDraw(const gfx::Size& size, + const std::vector<uint8>& pixels, + const GLenum format) { + GLuint texture_id = CreateGLTexture(); + MeasurementTimers tex_timers(gpu_timing_client_.get()); + UploadTexture(texture_id, size, pixels, format); tex_timers.Record(); MeasurementTimers draw_timers(gpu_timing_client_.get()); - glUseProgram(program_object_); - glUniform1i(sampler_location_, 0); - - DCHECK_NE(0u, vertex_buffer_); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, - reinterpret_cast<void*>(sizeof(GLfloat) * 2)); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); draw_timers.Record(); @@ -242,26 +295,21 @@ glFinish(); CheckNoGlError(); finish_timers.Record(); - total_timers.Record(); glDeleteTextures(1, &texture_id); std::vector<uint8> pixels_rendered(size.GetArea() * 4); - glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, type, + glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels_rendered[0]); CheckNoGlError(); - - // TODO(dcastagna): don't assume the format of the texture and do - // the appropriate format conversion. - EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format); - EXPECT_EQ(pixels, pixels_rendered); + EXPECT_TRUE(CompareBufferToRGBABuffer(format, pixels, pixels_rendered)) + << "Format is: " << gfx::GLEnums::GetStringEnum(format); std::vector<Measurement> measurements; bool gpu_timer_errors = gpu_timing_client_->IsAvailable() && gpu_timing_client_->CheckAndResetTimerErrors(); if (!gpu_timer_errors) { - measurements.push_back(total_timers.GetAsMeasurement("total")); measurements.push_back(tex_timers.GetAsMeasurement("teximage2d")); measurements.push_back(draw_timers.GetAsMeasurement("drawarrays")); measurements.push_back(finish_timers.GetAsMeasurement("finish")); @@ -269,14 +317,16 @@ return measurements; } - void RunUploadAndDrawMultipleTimes(const gfx::Size& size) { + void RunUploadAndDrawMultipleTimes(const gfx::Size& size, + const GLenum format) { std::vector<uint8> pixels; base::SmallMap<std::map<std::string, Measurement>> aggregates; // indexed by name int successful_runs = 0; + ASSERT_THAT(format, testing::AnyOf(GL_RGBA, GL_LUMINANCE, GL_RED_EXT)); for (int i = 0; i < kUploadPerfWarmupRuns + kUploadPerfTestRuns; ++i) { - GenerateTextureData(size, i + 1, &pixels); - auto run = UploadAndDraw(size, pixels, GL_RGBA, GL_UNSIGNED_BYTE); + GenerateTextureData(size, format == GL_RGBA ? 4 : 1, i + 1, &pixels); + auto run = UploadAndDraw(size, pixels, format); if (i < kUploadPerfWarmupRuns || !run.size()) { continue; } @@ -287,13 +337,15 @@ aggregate.Increment(measurement); } } + std::string suffix = base::StringPrintf( + "_%d_%s", size.width(), gfx::GLEnums::GetStringEnum(format).c_str()); if (successful_runs) { for (const auto& entry : aggregates) { const auto m = entry.second.Divide(successful_runs); - m.PrintResult(base::StringPrintf("_%d", size.width())); + m.PrintResult(suffix); } } - perf_test::PrintResult("sample_runs", "", "", + perf_test::PrintResult("sample_runs", suffix, "", static_cast<size_t>(successful_runs), "laps", true); } @@ -308,6 +360,7 @@ GLuint fragment_shader_ = 0; GLuint program_object_ = 0; GLint sampler_location_ = -1; + GLint translation_location_ = -1; GLuint vertex_buffer_ = 0; }; @@ -315,18 +368,95 @@ // and prints out aggregated measurements for all the runs. TEST_F(TextureUploadPerfTest, glTexImage2d) { int sizes[] = {128, 256, 512, 1024}; + std::vector<GLenum> formats; + formats.push_back(GL_RGBA); + // Used by default for ResourceProvider::yuv_resource_format_. + formats.push_back(GL_LUMINANCE); + + ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); + bool has_texture_rg = gl_context_->HasExtension("GL_EXT_texture_rg") || + gl_context_->HasExtension("GL_ARB_texture_rg"); + + if (has_texture_rg) { + // Used as ResourceProvider::yuv_resource_format_ if + // {ARB,EXT}_texture_rg is available. + formats.push_back(GL_RED_EXT); + } for (int side : sizes) { ASSERT_GE(fbo_size_.width(), side); ASSERT_GE(fbo_size_.height(), side); - gfx::Size size(side, side); - ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); GenerateVertexBuffer(size); + for (GLenum format : formats) { + RunUploadAndDrawMultipleTimes(size, format); + } + } +} - DCHECK_NE(0u, framebuffer_object_); - glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_object_); +// Perf test to check if the driver is doing texture renaming. +// This test creates one GL texture_id and four different images. For +// every image it uploads it using texture_id and it draws multiple +// times. The cpu/wall time and the gpu time for all the uploads and +// draws, but before glFinish, is computed and is printed out at the end as +// "upload_and_draw". If the gpu time is >> than the cpu/wall time we expect the +// driver to do texture renaming: this means that while the gpu is drawing using +// texture_id it didn't block cpu side the texture upload using the same +// texture_id. +TEST_F(TextureUploadPerfTest, renaming) { + gfx::Size texture_size(fbo_size_.width() / 2, fbo_size_.height() / 2); - RunUploadAndDrawMultipleTimes(size); + std::vector<uint8> pixels[4]; + for (int i = 0; i < 4; ++i) { + GenerateTextureData(texture_size, 4, i + 1, &pixels[i]); + } + + ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get()); + GenerateVertexBuffer(texture_size); + + gfx::Vector2dF positions[] = {gfx::Vector2dF(0.f, 0.f), + gfx::Vector2dF(1.f, 0.f), + gfx::Vector2dF(0.f, 1.f), + gfx::Vector2dF(1.f, 1.f)}; + GLuint texture_id = CreateGLTexture(); + + MeasurementTimers upload_and_draw_timers(gpu_timing_client_.get()); + + for (int i = 0; i < 4; ++i) { + UploadTexture(texture_id, texture_size, pixels[i % 4], GL_RGBA); + DCHECK_NE(-1, translation_location_); + glUniform2f(translation_location_, positions[i % 4].x(), + positions[i % 4].y()); + // Draw the same quad multiple times to make sure that the time spent on the + // gpu is more than the cpu time. + for (int draw = 0; draw < 128; ++draw) { + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } + + upload_and_draw_timers.Record(); + MeasurementTimers finish_timers(gpu_timing_client_.get()); + glFinish(); + CheckNoGlError(); + finish_timers.Record(); + + glDeleteTextures(1, &texture_id); + + for (int i = 0; i < 4; ++i) { + std::vector<uint8> pixels_rendered(texture_size.GetArea() * 4); + glReadPixels(texture_size.width() * positions[i].x(), + texture_size.height() * positions[i].y(), texture_size.width(), + texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, + &pixels_rendered[0]); + CheckNoGlError(); + ASSERT_EQ(pixels[i].size(), pixels_rendered.size()); + EXPECT_EQ(pixels[i], pixels_rendered); + } + + bool gpu_timer_errors = gpu_timing_client_->IsAvailable() && + gpu_timing_client_->CheckAndResetTimerErrors(); + if (!gpu_timer_errors) { + upload_and_draw_timers.GetAsMeasurement("upload_and_draw").PrintResult(""); + finish_timers.GetAsMeasurement("finish").PrintResult(""); } }
diff --git a/gpu/tools/tools.gyp b/gpu/tools/tools.gyp index 73ef754..4ea41b7 100644 --- a/gpu/tools/tools.gyp +++ b/gpu/tools/tools.gyp
@@ -12,6 +12,7 @@ ['OS == "linux" and target_arch != "arm" and use_x11==1', { 'targets': [ { + # GN: //gpu:compositor_model_bench 'target_name': 'compositor_model_bench', 'type': 'executable', 'dependencies': [
diff --git a/mojo/tools/roll/build_v8.patch b/mojo/tools/roll/build_v8.patch index 5f37307..7de0f0a 100644 --- a/mojo/tools/roll/build_v8.patch +++ b/mojo/tools/roll/build_v8.patch
@@ -1,10 +1,10 @@ diff --git a/build/module_args/v8.gni b/build/module_args/v8.gni -index e4bbf46..d42babd 100644 +index df6a4a3..05b673b 100644 --- a/build/module_args/v8.gni +++ b/build/module_args/v8.gni -@@ -6,5 +6,7 @@ if (is_android) { - import("//build/config/android/config.gni") - } +@@ -9,5 +9,7 @@ if (is_android) { + # TODO(sky): nuke this. Temporary while sorting out http://crbug.com/465456. + enable_correct_v8_arch = false -v8_use_external_startup_data = - !((is_android && is_android_webview_build) || is_chromeos || is_win)
diff --git a/mojo/tools/roll/cc_strip_video.patch b/mojo/tools/roll/cc_strip_video.patch index a992d5d..ebc7495 100644 --- a/mojo/tools/roll/cc_strip_video.patch +++ b/mojo/tools/roll/cc_strip_video.patch
@@ -1,5 +1,5 @@ diff --git a/cc/BUILD.gn b/cc/BUILD.gn -index 9c4752d..e217b12 100644 +index 0411b45..4ee07db 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -222,13 +222,6 @@ component("cc") { @@ -16,7 +16,7 @@ "output/begin_frame_args.cc", "output/begin_frame_args.h", "output/bsp_tree.cc", -@@ -480,8 +473,6 @@ component("cc") { +@@ -486,8 +479,6 @@ component("cc") { "resources/ui_resource_client.h", "resources/ui_resource_request.cc", "resources/ui_resource_request.h", @@ -25,7 +25,7 @@ "resources/zero_copy_tile_task_worker_pool.cc", "resources/zero_copy_tile_task_worker_pool.h", "scheduler/begin_frame_source.cc", -@@ -623,8 +614,6 @@ source_set("test_support") { +@@ -628,8 +619,6 @@ source_set("test_support") { "test/fake_tile_manager_client.h", "test/fake_ui_resource_layer_tree_host_impl.cc", "test/fake_ui_resource_layer_tree_host_impl.h", @@ -34,7 +34,7 @@ "test/geometry_test_utils.cc", "test/geometry_test_utils.h", "test/impl_side_painting_settings.h", -@@ -782,7 +771,6 @@ test("cc_unittests") { +@@ -787,7 +776,6 @@ test("cc_unittests") { "layers/tiled_layer_unittest.cc", "layers/ui_resource_layer_impl_unittest.cc", "layers/ui_resource_layer_unittest.cc", @@ -42,7 +42,7 @@ "output/begin_frame_args_unittest.cc", "output/delegating_renderer_unittest.cc", "output/filter_operations_unittest.cc", -@@ -843,7 +831,6 @@ test("cc_unittests") { +@@ -848,7 +836,6 @@ test("cc_unittests") { "trees/layer_tree_host_unittest_picture.cc", "trees/layer_tree_host_unittest_proxy.cc", "trees/layer_tree_host_unittest_scroll.cc", @@ -242,11 +242,11 @@ - -} // namespace cc diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc -index 2016447..578faa9 100644 +index 613ea4b..3813e1d 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc -@@ -13,7 +13,6 @@ - #include "base/logging.h" +@@ -18,7 +18,6 @@ + #include "build/build_config.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" -#include "cc/layers/video_layer_impl.h" @@ -254,7 +254,7 @@ #include "cc/output/compositor_frame_metadata.h" #include "cc/output/context_provider.h" diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc -index b30b0a5..81ad842 100644 +index 295fc84..ebda8d6 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -12,7 +12,6 @@ @@ -265,86 +265,12 @@ #include "third_party/skia/include/core/SkColorPriv.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkMatrix.h" -@@ -388,453 +387,6 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) { +@@ -902,243 +901,6 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) { FuzzyPixelOffByOneComparator(true))); } - + -class VideoGLRendererPixelTest : public GLRendererPixelTest { - protected: -- void CreateTestYUVVideoDrawQuad_Striped(const SharedQuadState* shared_state, -- media::VideoFrame::Format format, -- bool is_transparent, -- const gfx::RectF& tex_coord_rect, -- RenderPass* render_pass) { -- const gfx::Rect rect(this->device_viewport_size_); -- -- scoped_refptr<media::VideoFrame> video_frame = -- media::VideoFrame::CreateFrame( -- format, rect.size(), rect, rect.size(), base::TimeDelta()); -- -- // YUV values representing a striped pattern, for validating texture -- // coordinates for sampling. -- uint8_t y_value = 0; -- uint8_t u_value = 0; -- uint8_t v_value = 0; -- for (int i = 0; i < video_frame->rows(media::VideoFrame::kYPlane); ++i) { -- uint8_t* y_row = video_frame->data(media::VideoFrame::kYPlane) + -- video_frame->stride(media::VideoFrame::kYPlane) * i; -- for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kYPlane); -- ++j) { -- y_row[j] = (y_value += 1); -- } -- } -- for (int i = 0; i < video_frame->rows(media::VideoFrame::kUPlane); ++i) { -- uint8_t* u_row = video_frame->data(media::VideoFrame::kUPlane) + -- video_frame->stride(media::VideoFrame::kUPlane) * i; -- uint8_t* v_row = video_frame->data(media::VideoFrame::kVPlane) + -- video_frame->stride(media::VideoFrame::kVPlane) * i; -- for (int j = 0; j < video_frame->row_bytes(media::VideoFrame::kUPlane); -- ++j) { -- u_row[j] = (u_value += 3); -- v_row[j] = (v_value += 5); -- } -- } -- uint8 alpha_value = is_transparent ? 0 : 128; -- CreateTestYUVVideoDrawQuad_FromVideoFrame( -- shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); -- } -- -- void CreateTestYUVVideoDrawQuad_Solid(const SharedQuadState* shared_state, -- media::VideoFrame::Format format, -- bool is_transparent, -- const gfx::RectF& tex_coord_rect, -- uint8 y, -- uint8 u, -- uint8 v, -- RenderPass* render_pass) { -- const gfx::Rect rect(this->device_viewport_size_); -- -- scoped_refptr<media::VideoFrame> video_frame = -- media::VideoFrame::CreateFrame( -- format, rect.size(), rect, rect.size(), base::TimeDelta()); -- -- // YUV values of a solid, constant, color. Useful for testing that color -- // space/color range are being handled properly. -- memset(video_frame->data(media::VideoFrame::kYPlane), -- y, -- video_frame->stride(media::VideoFrame::kYPlane) * -- video_frame->rows(media::VideoFrame::kYPlane)); -- memset(video_frame->data(media::VideoFrame::kUPlane), -- u, -- video_frame->stride(media::VideoFrame::kUPlane) * -- video_frame->rows(media::VideoFrame::kUPlane)); -- memset(video_frame->data(media::VideoFrame::kVPlane), -- v, -- video_frame->stride(media::VideoFrame::kVPlane) * -- video_frame->rows(media::VideoFrame::kVPlane)); -- -- uint8 alpha_value = is_transparent ? 0 : 128; -- CreateTestYUVVideoDrawQuad_FromVideoFrame( -- shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); -- } -- - void CreateEdgeBleedPass(media::VideoFrame::Format format, - RenderPassList* pass_list) { - gfx::Rect rect(200, 200); @@ -373,139 +299,19 @@ - // green sub-rectangle that should be the only thing displayed in - // the final image. Bleeding will appear on all four sides of the video - // if the tex coords are not clamped. -- CreateTestYUVVideoDrawQuad_TwoColor(shared_state, format, false, -- tex_coord_rect, background_size, 0, 0, -- 0, green_rect, 149, 43, 21, pass.get()); +- CreateTestYUVVideoDrawQuad_TwoColor( +- shared_state, format, false, tex_coord_rect, background_size, 0, 0, 0, +- green_rect, 149, 43, 21, pass.get(), video_resource_updater_.get(), +- resource_provider_.get()); - pass_list->push_back(pass.Pass()); - } - -- // Creates a video frame of size background_size filled with yuv_background, -- // and then draws a foreground rectangle in a different color on top of -- // that. The foreground rectangle must have coordinates that are divisible -- // by 2 because YUV is a block format. -- void CreateTestYUVVideoDrawQuad_TwoColor(const SharedQuadState* shared_state, -- media::VideoFrame::Format format, -- bool is_transparent, -- const gfx::RectF& tex_coord_rect, -- const gfx::Size& background_size, -- uint8 y_background, -- uint8 u_background, -- uint8 v_background, -- const gfx::Rect& foreground_rect, -- uint8 y_foreground, -- uint8 u_foreground, -- uint8 v_foreground, -- RenderPass* render_pass) { -- const gfx::Rect rect(background_size); -- -- scoped_refptr<media::VideoFrame> video_frame = -- media::VideoFrame::CreateFrame(format, background_size, foreground_rect, -- foreground_rect.size(), -- base::TimeDelta()); -- -- int planes[] = {media::VideoFrame::kYPlane, -- media::VideoFrame::kUPlane, -- media::VideoFrame::kVPlane}; -- uint8 yuv_background[] = {y_background, u_background, v_background}; -- uint8 yuv_foreground[] = {y_foreground, u_foreground, v_foreground}; -- int sample_size[] = {1, 2, 2}; -- -- for (int i = 0; i < 3; ++i) { -- memset(video_frame->data(planes[i]), yuv_background[i], -- video_frame->stride(planes[i]) * video_frame->rows(planes[i])); -- } -- -- for (int i = 0; i < 3; ++i) { -- // Since yuv encoding uses block encoding, widths have to be divisible -- // by the sample size in order for this function to behave properly. -- DCHECK_EQ(foreground_rect.x() % sample_size[i], 0); -- DCHECK_EQ(foreground_rect.y() % sample_size[i], 0); -- DCHECK_EQ(foreground_rect.width() % sample_size[i], 0); -- DCHECK_EQ(foreground_rect.height() % sample_size[i], 0); -- -- gfx::Rect sample_rect(foreground_rect.x() / sample_size[i], -- foreground_rect.y() / sample_size[i], -- foreground_rect.width() / sample_size[i], -- foreground_rect.height() / sample_size[i]); -- for (int y = sample_rect.y(); y < sample_rect.bottom(); ++y) { -- for (int x = sample_rect.x(); x < sample_rect.right(); ++x) { -- size_t offset = y * video_frame->stride(planes[i]) + x; -- video_frame->data(planes[i])[offset] = yuv_foreground[i]; -- } -- } -- } -- -- uint8 alpha_value = 255; -- CreateTestYUVVideoDrawQuad_FromVideoFrame( -- shared_state, video_frame, alpha_value, tex_coord_rect, render_pass); -- } -- -- void CreateTestYUVVideoDrawQuad_FromVideoFrame( -- const SharedQuadState* shared_state, -- scoped_refptr<media::VideoFrame> video_frame, -- uint8 alpha_value, -- const gfx::RectF& tex_coord_rect, -- RenderPass* render_pass) { -- const bool with_alpha = (video_frame->format() == media::VideoFrame::YV12A); -- const YUVVideoDrawQuad::ColorSpace color_space = -- (video_frame->format() == media::VideoFrame::YV12J -- ? YUVVideoDrawQuad::JPEG -- : YUVVideoDrawQuad::REC_601); -- const gfx::Rect rect(shared_state->content_bounds); -- const gfx::Rect opaque_rect(0, 0, 0, 0); -- -- if (with_alpha) -- memset(video_frame->data(media::VideoFrame::kAPlane), alpha_value, -- video_frame->stride(media::VideoFrame::kAPlane) * -- video_frame->rows(media::VideoFrame::kAPlane)); -- -- VideoFrameExternalResources resources = -- video_resource_updater_->CreateExternalResourcesFromVideoFrame( -- video_frame); -- -- EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); -- EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()), -- resources.mailboxes.size()); -- EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()), -- resources.release_callbacks.size()); -- -- ResourceProvider::ResourceId y_resource = -- resource_provider_->CreateResourceFromTextureMailbox( -- resources.mailboxes[media::VideoFrame::kYPlane], -- SingleReleaseCallbackImpl::Create( -- resources.release_callbacks[media::VideoFrame::kYPlane])); -- ResourceProvider::ResourceId u_resource = -- resource_provider_->CreateResourceFromTextureMailbox( -- resources.mailboxes[media::VideoFrame::kUPlane], -- SingleReleaseCallbackImpl::Create( -- resources.release_callbacks[media::VideoFrame::kUPlane])); -- ResourceProvider::ResourceId v_resource = -- resource_provider_->CreateResourceFromTextureMailbox( -- resources.mailboxes[media::VideoFrame::kVPlane], -- SingleReleaseCallbackImpl::Create( -- resources.release_callbacks[media::VideoFrame::kVPlane])); -- ResourceProvider::ResourceId a_resource = 0; -- if (with_alpha) { -- a_resource = resource_provider_->CreateResourceFromTextureMailbox( -- resources.mailboxes[media::VideoFrame::kAPlane], -- SingleReleaseCallbackImpl::Create( -- resources.release_callbacks[media::VideoFrame::kAPlane])); -- } -- -- YUVVideoDrawQuad* yuv_quad = -- render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>(); -- yuv_quad->SetNew(shared_state, rect, opaque_rect, rect, tex_coord_rect, -- video_frame->coded_size(), y_resource, u_resource, -- v_resource, a_resource, color_space); -- } -- - void SetUp() override { - GLRendererPixelTest::SetUp(); - video_resource_updater_.reset(new VideoResourceUpdater( - output_surface_->context_provider(), resource_provider_.get())); - } - -- private: - scoped_ptr<VideoResourceUpdater> video_resource_updater_; -}; - @@ -518,11 +324,10 @@ - SharedQuadState* shared_state = - CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - -- CreateTestYUVVideoDrawQuad_Striped(shared_state, -- media::VideoFrame::YV12, -- false, -- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), -- pass.get()); +- CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12, +- false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), +- pass.get(), video_resource_updater_.get(), +- rect, resource_provider_.get()); - - RenderPassList pass_list; - pass_list.push_back(pass.Pass()); @@ -543,11 +348,10 @@ - CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - - // Intentionally sets frame format to I420 for testing coverage. -- CreateTestYUVVideoDrawQuad_Striped(shared_state, -- media::VideoFrame::I420, -- false, -- gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f), -- pass.get()); +- CreateTestYUVVideoDrawQuad_Striped( +- shared_state, media::VideoFrame::I420, false, +- gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f), pass.get(), +- video_resource_updater_.get(), rect, resource_provider_.get()); - - RenderPassList pass_list; - pass_list.push_back(pass.Pass()); @@ -568,14 +372,10 @@ - CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - - // In MPEG color range YUV values of (15,128,128) should produce black. -- CreateTestYUVVideoDrawQuad_Solid(shared_state, -- media::VideoFrame::YV12, -- false, -- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), -- 15, -- 128, -- 128, -- pass.get()); +- CreateTestYUVVideoDrawQuad_Solid( +- shared_state, media::VideoFrame::YV12, false, +- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(), +- video_resource_updater_.get(), rect, resource_provider_.get()); - - RenderPassList pass_list; - pass_list.push_back(pass.Pass()); @@ -597,14 +397,10 @@ - CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - - // YUV of (149,43,21) should be green (0,255,0) in RGB. -- CreateTestYUVVideoDrawQuad_Solid(shared_state, -- media::VideoFrame::YV12J, -- false, -- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), -- 149, -- 43, -- 21, -- pass.get()); +- CreateTestYUVVideoDrawQuad_Solid( +- shared_state, media::VideoFrame::YV12J, false, +- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(), +- video_resource_updater_.get(), rect, resource_provider_.get()); - - RenderPassList pass_list; - pass_list.push_back(pass.Pass()); @@ -642,14 +438,10 @@ - CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - - // Dark grey in JPEG color range (in MPEG, this is black). -- CreateTestYUVVideoDrawQuad_Solid(shared_state, -- media::VideoFrame::YV12J, -- false, -- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), -- 15, -- 128, -- 128, -- pass.get()); +- CreateTestYUVVideoDrawQuad_Solid( +- shared_state, media::VideoFrame::YV12J, false, +- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(), +- video_resource_updater_.get(), rect, resource_provider_.get()); - - RenderPassList pass_list; - pass_list.push_back(pass.Pass()); @@ -669,11 +461,10 @@ - SharedQuadState* shared_state = - CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - -- CreateTestYUVVideoDrawQuad_Striped(shared_state, -- media::VideoFrame::YV12A, -- false, -- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), -- pass.get()); +- CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A, +- false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), +- pass.get(), video_resource_updater_.get(), +- rect, resource_provider_.get()); - - SolidColorDrawQuad* color_quad = - pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -697,11 +488,10 @@ - SharedQuadState* shared_state = - CreateTestSharedQuadState(gfx::Transform(), rect, pass.get()); - -- CreateTestYUVVideoDrawQuad_Striped(shared_state, -- media::VideoFrame::YV12A, -- true, -- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), -- pass.get()); +- CreateTestYUVVideoDrawQuad_Striped(shared_state, media::VideoFrame::YV12A, +- true, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), +- pass.get(), video_resource_updater_.get(), +- rect, resource_provider_.get()); - - SolidColorDrawQuad* color_quad = - pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); @@ -718,7 +508,7 @@ - TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) { gfx::Rect viewport_rect(this->device_viewport_size_); - + diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h index 358929e..15bce98 100644 --- a/cc/quads/yuv_video_draw_quad.h @@ -729,22 +519,22 @@ #include "cc/base/cc_export.h" -#include "cc/layers/video_layer_impl.h" #include "cc/quads/draw_quad.h" - + namespace cc { diff --git a/cc/resources/drawing_display_item.cc b/cc/resources/drawing_display_item.cc index 648f9de..6dffad9 100644 --- a/cc/resources/drawing_display_item.cc +++ b/cc/resources/drawing_display_item.cc @@ -6,6 +6,7 @@ - + #include <string> - + +#include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event_argument.h" #include "cc/debug/picture_debug_util.h" diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc -index 4b2bc75..7ffa683 100644 +index 4289a99..4e3230b 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -27,7 +27,6 @@ @@ -776,7 +566,7 @@ using ::testing::AtLeast; using ::testing::_; -using media::VideoFrame; - + namespace cc { namespace { @@ -96,7 +92,6 @@ class LayerTreeHostImplTest : public testing::Test, @@ -785,12 +575,12 @@ current_priority_cutoff_value_(0) { - media::InitializeMediaLibraryForTesting(); } - + LayerTreeSettings DefaultSettings() { -@@ -5486,18 +5481,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { +@@ -5473,18 +5468,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { root_layer->SetBounds(gfx::Size(10, 10)); root_layer->SetHasRenderSurface(true); - + - scoped_refptr<VideoFrame> softwareFrame = - media::VideoFrame::CreateColorFrame( - gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta()); @@ -806,10 +596,10 @@ scoped_ptr<IOSurfaceLayerImpl> io_surface_layer = IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5); io_surface_layer->SetBounds(gfx::Size(10, 10)); -@@ -6578,16 +6561,6 @@ TEST_F(LayerTreeHostImplTest, +@@ -6566,16 +6549,6 @@ TEST_F(LayerTreeHostImplTest, scoped_ptr<SolidColorLayerImpl> root_layer = SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); - + - // VideoLayerImpl will not be drawn. - FakeVideoFrameProvider provider; - scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create( @@ -824,7 +614,7 @@ EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); host_impl_->DrawLayers(&frame, gfx::FrameTime::Now()); diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc -index c52132e..1be61a5 100644 +index 68a1f58..2ec6e66 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -18,7 +18,6 @@ @@ -843,10 +633,10 @@ #include "cc/test/geometry_test_utils.h" #include "cc/test/impl_side_painting_settings.h" #include "cc/test/layer_tree_test.h" -@@ -4163,28 +4161,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest { +@@ -4170,28 +4168,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest { int num_draws_; }; - + -// VideoLayer must support being invalidated and then passing that along -// to the compositor thread, even though no resources are updated in -// response to that invalidation. @@ -900,7 +690,7 @@ -#include "media/base/media.h" - -using media::VideoFrame; - + namespace cc { namespace { @@ -66,7 +60,6 @@ class LayerTreeHostContextTest : public LayerTreeTest { @@ -909,12 +699,12 @@ async_output_surface_creation_(false) { - media::InitializeMediaLibraryForTesting(); } - + void LoseContext() { @@ -1055,41 +1048,6 @@ class LayerTreeHostContextTestDontUseLostResources layer_with_mask->SetMaskLayer(mask.get()); root->AddChild(layer_with_mask); - + - scoped_refptr<VideoLayer> video_color = - VideoLayer::Create(&color_frame_provider_, media::VIDEO_ROTATION_0); - video_color->SetBounds(gfx::Size(10, 10)); @@ -954,7 +744,7 @@ // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335 scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create(); @@ -1119,14 +1077,6 @@ class LayerTreeHostContextTestDontUseLostResources - + void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { LayerTreeHostContextTest::CommitCompleteOnThread(host_impl); - @@ -966,7 +756,7 @@ - scaled_hw_frame_provider_.set_frame(NULL); - } } - + DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, @@ -1175,14 +1125,6 @@ class LayerTreeHostContextTestDontUseLostResources scoped_refptr<DelegatedFrameResourceCollection> @@ -981,5 +771,5 @@ - FakeVideoFrameProvider hw_frame_provider_; - FakeVideoFrameProvider scaled_hw_frame_provider_; }; - + SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
diff --git a/mojo/tools/roll/skia_build.patch b/mojo/tools/roll/skia_build.patch index a252691..5340f2d 100644 --- a/mojo/tools/roll/skia_build.patch +++ b/mojo/tools/roll/skia_build.patch
@@ -1,8 +1,8 @@ diff --git a/skia/BUILD.gn b/skia/BUILD.gn -index c793e0b..85ccce7 100644 +index 248bc1c..2357a7f 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn -@@ -12,18 +12,6 @@ if (cpu_arch == "arm") { +@@ -12,18 +12,6 @@ if (current_cpu == "arm") { skia_support_gpu = !is_ios skia_support_pdf = !is_ios && (enable_basic_printing || enable_print_preview) @@ -21,8 +21,8 @@ # The list of Skia defines that are to be set for chromium. gypi_skia_defines = exec_script("//build/gypi_to_gn.py", -@@ -133,8 +121,7 @@ config("skia_config") { - "//third_party/skia/src/core", +@@ -130,8 +118,7 @@ config("skia_config") { + "//third_party/skia/include/utils", ] - defines = gypi_blink_skia_defines.blink_skia_defines
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index ccb186a..3b340bd 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn
@@ -168,6 +168,8 @@ "bpf_dsl/syscall_set.cc", "bpf_dsl/syscall_set.h", "bpf_dsl/trap_registry.h", + "bpf_dsl/verifier.cc", + "bpf_dsl/verifier.h", "seccomp-bpf/die.cc", "seccomp-bpf/die.h", "seccomp-bpf/errorcode.cc", @@ -178,8 +180,6 @@ "seccomp-bpf/syscall.h", "seccomp-bpf/trap.cc", "seccomp-bpf/trap.h", - "seccomp-bpf/verifier.cc", - "seccomp-bpf/verifier.h", ] defines = [ "SANDBOX_IMPLEMENTATION" ]
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc index cffadc5..dba421f 100644 --- a/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc +++ b/sandbox/linux/bpf_dsl/bpf_dsl_unittest.cc
@@ -12,55 +12,132 @@ #include <sys/utsname.h> #include <unistd.h> +#include <map> +#include <utility> + #include "base/files/scoped_file.h" #include "base/macros.h" #include "build/build_config.h" #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" +#include "sandbox/linux/bpf_dsl/codegen.h" #include "sandbox/linux/bpf_dsl/policy.h" -#include "sandbox/linux/seccomp-bpf/bpf_tests.h" +#include "sandbox/linux/bpf_dsl/policy_compiler.h" +#include "sandbox/linux/bpf_dsl/seccomp_macros.h" +#include "sandbox/linux/bpf_dsl/trap_registry.h" +#include "sandbox/linux/bpf_dsl/verifier.h" #include "sandbox/linux/seccomp-bpf/errorcode.h" -#include "sandbox/linux/seccomp-bpf/syscall.h" #include "testing/gtest/include/gtest/gtest.h" #define CASES SANDBOX_BPF_DSL_CASES -// Helper macro to assert that invoking system call |sys| directly via -// Syscall::Call with arguments |...| returns |res|. -// Errors can be asserted by specifying a value like "-EINVAL". -#define ASSERT_SYSCALL_RESULT(res, sys, ...) \ - BPF_ASSERT_EQ(res, Stubs::sys(__VA_ARGS__)) - namespace sandbox { namespace bpf_dsl { namespace { -// Type safe stubs for tested system calls. -class Stubs { +// Helper function to construct fake arch_seccomp_data objects. +struct arch_seccomp_data FakeSyscall(int nr, + uint64_t p0 = 0, + uint64_t p1 = 0, + uint64_t p2 = 0, + uint64_t p3 = 0, + uint64_t p4 = 0, + uint64_t p5 = 0) { + // Made up program counter for syscall address. + const uint64_t kFakePC = 0x543210; + + struct arch_seccomp_data data = { + nr, + SECCOMP_ARCH, + kFakePC, + { + p0, p1, p2, p3, p4, p5, + }, + }; + + return data; +} + +class FakeTrapRegistry : public TrapRegistry { public: - static int getpgid(pid_t pid) { return Syscall::Call(__NR_getpgid, pid); } - static int setuid(uid_t uid) { return Syscall::Call(__NR_setuid, uid); } - static int setgid(gid_t gid) { return Syscall::Call(__NR_setgid, gid); } - static int setpgid(pid_t pid, pid_t pgid) { - return Syscall::Call(__NR_setpgid, pid, pgid); + FakeTrapRegistry() : map_() {} + virtual ~FakeTrapRegistry() {} + + uint16_t Add(TrapFnc fnc, const void* aux, bool safe) override { + EXPECT_TRUE(safe); + + const uint16_t next_id = map_.size() + 1; + return map_.insert(std::make_pair(Key(fnc, aux), next_id)).first->second; } - static int fcntl(int fd, int cmd, unsigned long arg = 0) { - return Syscall::Call(__NR_fcntl, fd, cmd, arg); + bool EnableUnsafeTraps() override { + ADD_FAILURE() << "Unimplemented"; + return false; } - static int uname(struct utsname* buf) { - return Syscall::Call(__NR_uname, buf); + private: + using Key = std::pair<TrapFnc, const void*>; + + std::map<Key, uint16_t> map_; + + DISALLOW_COPY_AND_ASSIGN(FakeTrapRegistry); +}; + +intptr_t FakeTrapFuncOne(const arch_seccomp_data& data, void* aux) { return 1; } +intptr_t FakeTrapFuncTwo(const arch_seccomp_data& data, void* aux) { return 2; } + +// Test that FakeTrapRegistry correctly assigns trap IDs to trap handlers. +TEST(FakeTrapRegistry, TrapIDs) { + struct { + TrapRegistry::TrapFnc fnc; + const void* aux; + } funcs[] = { + {FakeTrapFuncOne, nullptr}, + {FakeTrapFuncTwo, nullptr}, + {FakeTrapFuncOne, funcs}, + {FakeTrapFuncTwo, funcs}, + }; + + FakeTrapRegistry traps; + + // Add traps twice to test that IDs are reused correctly. + for (int i = 0; i < 2; ++i) { + for (size_t j = 0; j < arraysize(funcs); ++j) { + // Trap IDs start at 1. + EXPECT_EQ(j + 1, traps.Add(funcs[j].fnc, funcs[j].aux, true)); + } + } +} + +class PolicyEmulator { + public: + explicit PolicyEmulator(const Policy* policy) : program_(), traps_() { + program_ = *PolicyCompiler(policy, &traps_).Compile(true /* verify */); + } + ~PolicyEmulator() {} + + uint32_t Emulate(const struct arch_seccomp_data& data) const { + const char* err = nullptr; + uint32_t res = Verifier::EvaluateBPF(program_, data, &err); + if (err) { + ADD_FAILURE() << err; + return 0; + } + return res; } - static int setresuid(uid_t ruid, uid_t euid, uid_t suid) { - return Syscall::Call(__NR_setresuid, ruid, euid, suid); + void ExpectAllow(const struct arch_seccomp_data& data) const { + EXPECT_EQ(SECCOMP_RET_ALLOW, Emulate(data)); } -#if !defined(ARCH_CPU_X86) - static int socketpair(int domain, int type, int protocol, int sv[2]) { - return Syscall::Call(__NR_socketpair, domain, type, protocol, sv); + void ExpectErrno(uint16_t err, const struct arch_seccomp_data& data) const { + EXPECT_EQ(SECCOMP_RET_ERRNO | err, Emulate(data)); } -#endif + + private: + CodeGen::Program program_; + FakeTrapRegistry traps_; + + DISALLOW_COPY_AND_ASSIGN(PolicyEmulator); }; class BasicPolicy : public Policy { @@ -83,12 +160,15 @@ DISALLOW_COPY_AND_ASSIGN(BasicPolicy); }; -BPF_TEST_C(BPFDSL, Basic, BasicPolicy) { - ASSERT_SYSCALL_RESULT(-EPERM, getpgid, 0); - ASSERT_SYSCALL_RESULT(-EINVAL, getpgid, 1); +TEST(BPFDSL, Basic) { + BasicPolicy policy; + PolicyEmulator emulator(&policy); - ASSERT_SYSCALL_RESULT(-ENOMEM, setuid, 42); - ASSERT_SYSCALL_RESULT(-ESRCH, setuid, 43); + emulator.ExpectErrno(EPERM, FakeSyscall(__NR_getpgid, 0)); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_getpgid, 1)); + + emulator.ExpectErrno(ENOMEM, FakeSyscall(__NR_setuid, 42)); + emulator.ExpectErrno(ESRCH, FakeSyscall(__NR_setuid, 43)); } /* On IA-32, socketpair() is implemented via socketcall(). :-( */ @@ -112,22 +192,30 @@ DISALLOW_COPY_AND_ASSIGN(BooleanLogicPolicy); }; -BPF_TEST_C(BPFDSL, BooleanLogic, BooleanLogicPolicy) { - int sv[2]; +TEST(BPFDSL, BooleanLogic) { + BooleanLogicPolicy policy; + PolicyEmulator emulator(&policy); + + const intptr_t kFakeSV = 0x12345; // Acceptable combinations that should return EPERM. - ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_STREAM, 0, sv); - ASSERT_SYSCALL_RESULT(-EPERM, socketpair, AF_UNIX, SOCK_DGRAM, 0, sv); + emulator.ExpectErrno( + EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_STREAM, 0, kFakeSV)); + emulator.ExpectErrno( + EPERM, FakeSyscall(__NR_socketpair, AF_UNIX, SOCK_DGRAM, 0, kFakeSV)); // Combinations that are invalid for only one reason; should return EINVAL. - ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_INET, SOCK_STREAM, 0, sv); - ASSERT_SYSCALL_RESULT(-EINVAL, socketpair, AF_UNIX, SOCK_SEQPACKET, 0, sv); - ASSERT_SYSCALL_RESULT( - -EINVAL, socketpair, AF_UNIX, SOCK_STREAM, IPPROTO_TCP, sv); + emulator.ExpectErrno( + EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_STREAM, 0, kFakeSV)); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX, + SOCK_SEQPACKET, 0, kFakeSV)); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_socketpair, AF_UNIX, + SOCK_STREAM, IPPROTO_TCP, kFakeSV)); // Completely unacceptable combination; should also return EINVAL. - ASSERT_SYSCALL_RESULT( - -EINVAL, socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP, sv); + emulator.ExpectErrno( + EINVAL, FakeSyscall(__NR_socketpair, AF_INET, SOCK_SEQPACKET, IPPROTO_UDP, + kFakeSV)); } #endif // !ARCH_CPU_X86 @@ -149,20 +237,23 @@ DISALLOW_COPY_AND_ASSIGN(MoreBooleanLogicPolicy); }; -BPF_TEST_C(BPFDSL, MoreBooleanLogic, MoreBooleanLogicPolicy) { +TEST(BPFDSL, MoreBooleanLogic) { + MoreBooleanLogicPolicy policy; + PolicyEmulator emulator(&policy); + // Expect EPERM if any set to 0. - ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 0, 5, 5); - ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 0, 5); - ASSERT_SYSCALL_RESULT(-EPERM, setresuid, 5, 5, 0); + emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 0, 5, 5)); + emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 0, 5)); + emulator.ExpectErrno(EPERM, FakeSyscall(__NR_setresuid, 5, 5, 0)); // Expect EAGAIN if all set to 1. - ASSERT_SYSCALL_RESULT(-EAGAIN, setresuid, 1, 1, 1); + emulator.ExpectErrno(EAGAIN, FakeSyscall(__NR_setresuid, 1, 1, 1)); // Expect EINVAL for anything else. - ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 5, 1, 1); - ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 5, 1); - ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 1, 1, 5); - ASSERT_SYSCALL_RESULT(-EINVAL, setresuid, 3, 4, 5); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 5, 1, 1)); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 5, 1)); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 1, 1, 5)); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setresuid, 3, 4, 5)); } static const uintptr_t kDeadBeefAddr = @@ -184,13 +275,17 @@ DISALLOW_COPY_AND_ASSIGN(ArgSizePolicy); }; -BPF_TEST_C(BPFDSL, ArgSizeTest, ArgSizePolicy) { - struct utsname buf; - ASSERT_SYSCALL_RESULT(0, uname, &buf); - ASSERT_SYSCALL_RESULT( - -EPERM, uname, reinterpret_cast<struct utsname*>(kDeadBeefAddr)); +TEST(BPFDSL, ArgSizeTest) { + ArgSizePolicy policy; + PolicyEmulator emulator(&policy); + + emulator.ExpectAllow(FakeSyscall(__NR_uname, 0)); + emulator.ExpectErrno(EPERM, FakeSyscall(__NR_uname, kDeadBeefAddr)); } +#if 0 +// TODO(mdempsky): This is really an integration test. + class TrappingPolicy : public Policy { public: TrappingPolicy() {} @@ -220,6 +315,7 @@ ASSERT_SYSCALL_RESULT(2, uname, NULL); ASSERT_SYSCALL_RESULT(3, uname, NULL); } +#endif class MaskingPolicy : public Policy { public: @@ -245,20 +341,23 @@ DISALLOW_COPY_AND_ASSIGN(MaskingPolicy); }; -BPF_TEST_C(BPFDSL, MaskTest, MaskingPolicy) { +TEST(BPFDSL, MaskTest) { + MaskingPolicy policy; + PolicyEmulator emulator(&policy); + for (uid_t uid = 0; uid < 0x100; ++uid) { const int expect_errno = (uid & 0xf) == 0 ? EINVAL : EACCES; - ASSERT_SYSCALL_RESULT(-expect_errno, setuid, uid); + emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setuid, uid)); } for (gid_t gid = 0; gid < 0x100; ++gid) { const int expect_errno = (gid & 0xf0) == 0xf0 ? EINVAL : EACCES; - ASSERT_SYSCALL_RESULT(-expect_errno, setgid, gid); + emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setgid, gid)); } for (pid_t pid = 0; pid < 0x100; ++pid) { const int expect_errno = (pid & 0xa5) == 0xa0 ? EINVAL : EACCES; - ASSERT_SYSCALL_RESULT(-expect_errno, setpgid, pid, 0); + emulator.ExpectErrno(expect_errno, FakeSyscall(__NR_setpgid, pid, 0)); } } @@ -281,17 +380,20 @@ DISALLOW_COPY_AND_ASSIGN(ElseIfPolicy); }; -BPF_TEST_C(BPFDSL, ElseIfTest, ElseIfPolicy) { - ASSERT_SYSCALL_RESULT(0, setuid, 0); +TEST(BPFDSL, ElseIfTest) { + ElseIfPolicy policy; + PolicyEmulator emulator(&policy); - ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0001); - ASSERT_SYSCALL_RESULT(-EINVAL, setuid, 0x0002); + emulator.ExpectErrno(0, FakeSyscall(__NR_setuid, 0)); - ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0011); - ASSERT_SYSCALL_RESULT(-EEXIST, setuid, 0x0022); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0001)); + emulator.ExpectErrno(EINVAL, FakeSyscall(__NR_setuid, 0x0002)); - ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0111); - ASSERT_SYSCALL_RESULT(-EACCES, setuid, 0x0222); + emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0011)); + emulator.ExpectErrno(EEXIST, FakeSyscall(__NR_setuid, 0x0022)); + + emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0111)); + emulator.ExpectErrno(EACCES, FakeSyscall(__NR_setuid, 0x0222)); } class SwitchPolicy : public Policy { @@ -315,19 +417,25 @@ DISALLOW_COPY_AND_ASSIGN(SwitchPolicy); }; -BPF_TEST_C(BPFDSL, SwitchTest, SwitchPolicy) { - base::ScopedFD sock_fd(socket(AF_UNIX, SOCK_STREAM, 0)); - BPF_ASSERT(sock_fd.is_valid()); +TEST(BPFDSL, SwitchTest) { + SwitchPolicy policy; + PolicyEmulator emulator(&policy); - ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFD); - ASSERT_SYSCALL_RESULT(-ENOENT, fcntl, sock_fd.get(), F_GETFL); + const int kFakeSockFD = 42; - ASSERT_SYSCALL_RESULT(0, fcntl, sock_fd.get(), F_SETFD, O_CLOEXEC); - ASSERT_SYSCALL_RESULT(-EINVAL, fcntl, sock_fd.get(), F_SETFD, 0); + emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFD)); + emulator.ExpectErrno(ENOENT, FakeSyscall(__NR_fcntl, kFakeSockFD, F_GETFL)); - ASSERT_SYSCALL_RESULT(-EPERM, fcntl, sock_fd.get(), F_SETFL, O_RDONLY); + emulator.ExpectAllow( + FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, O_CLOEXEC)); + emulator.ExpectErrno(EINVAL, + FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFD, 0)); - ASSERT_SYSCALL_RESULT(-EACCES, fcntl, sock_fd.get(), F_DUPFD, 0); + emulator.ExpectErrno(EPERM, + FakeSyscall(__NR_fcntl, kFakeSockFD, F_SETFL, O_RDONLY)); + + emulator.ExpectErrno(EACCES, + FakeSyscall(__NR_fcntl, kFakeSockFD, F_DUPFD, 0)); } static intptr_t DummyTrap(const struct arch_seccomp_data& data, void* aux) {
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc index 18ed7be..f508b30 100644 --- a/sandbox/linux/bpf_dsl/policy_compiler.cc +++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -15,12 +15,12 @@ #include "sandbox/linux/bpf_dsl/bpf_dsl.h" #include "sandbox/linux/bpf_dsl/bpf_dsl_impl.h" #include "sandbox/linux/bpf_dsl/codegen.h" +#include "sandbox/linux/bpf_dsl/dump_bpf.h" #include "sandbox/linux/bpf_dsl/policy.h" #include "sandbox/linux/bpf_dsl/seccomp_macros.h" #include "sandbox/linux/bpf_dsl/syscall_set.h" -#include "sandbox/linux/seccomp-bpf/die.h" +#include "sandbox/linux/bpf_dsl/verifier.h" #include "sandbox/linux/seccomp-bpf/errorcode.h" -#include "sandbox/linux/seccomp-bpf/syscall.h" #include "sandbox/linux/system_headers/linux_seccomp.h" namespace sandbox { @@ -86,6 +86,7 @@ PolicyCompiler::PolicyCompiler(const Policy* policy, TrapRegistry* registry) : policy_(policy), registry_(registry), + escapepc_(0), conds_(), gen_(), has_unsafe_traps_(HasUnsafeTraps(policy_)) { @@ -95,47 +96,46 @@ PolicyCompiler::~PolicyCompiler() { } -scoped_ptr<CodeGen::Program> PolicyCompiler::Compile() { - if (!policy_->InvalidSyscall()->IsDeny()) { - SANDBOX_DIE("Policies should deny invalid system calls."); - } +scoped_ptr<CodeGen::Program> PolicyCompiler::Compile(bool verify) { + CHECK(policy_->InvalidSyscall()->IsDeny()) + << "Policies should deny invalid system calls"; // If our BPF program has unsafe traps, enable support for them. if (has_unsafe_traps_) { - // As support for unsafe jumps essentially defeats all the security - // measures that the sandbox provides, we print a big warning message -- - // and of course, we make sure to only ever enable this feature if it - // is actually requested by the sandbox policy. - if (Syscall::Call(-1) == -1 && errno == ENOSYS) { - SANDBOX_DIE( - "Support for UnsafeTrap() has not yet been ported to this " - "architecture"); - } + CHECK_NE(0U, escapepc_) << "UnsafeTrap() requires a valid escape PC"; for (int sysnum : kSyscallsRequiredForUnsafeTraps) { - if (!policy_->EvaluateSyscall(sysnum)->IsAllow()) { - SANDBOX_DIE( - "Policies that use UnsafeTrap() must unconditionally allow all " - "required system calls"); - } + CHECK(policy_->EvaluateSyscall(sysnum)->IsAllow()) + << "Policies that use UnsafeTrap() must unconditionally allow all " + "required system calls"; } - if (!registry_->EnableUnsafeTraps()) { - // We should never be able to get here, as UnsafeTrap() should never - // actually return a valid ErrorCode object unless the user set the - // CHROME_SANDBOX_DEBUGGING environment variable; and therefore, - // "has_unsafe_traps" would always be false. But better double-check - // than enabling dangerous code. - SANDBOX_DIE("We'd rather die than enable unsafe traps"); - } + CHECK(registry_->EnableUnsafeTraps()) + << "We'd rather die than enable unsafe traps"; } // Assemble the BPF filter program. scoped_ptr<CodeGen::Program> program(new CodeGen::Program()); gen_.Compile(AssemblePolicy(), program.get()); + + // Make sure compilation resulted in a BPF program that executes + // correctly. Otherwise, there is an internal error in our BPF compiler. + // There is really nothing the caller can do until the bug is fixed. + if (verify) { + const char* err = nullptr; + if (!Verifier::VerifyBPF(this, *program, *policy_, &err)) { + DumpBPF::PrintProgram(*program); + LOG(FATAL) << err; + } + } + return program.Pass(); } +void PolicyCompiler::DangerousSetEscapePC(uint64_t escapepc) { + escapepc_ = escapepc; +} + CodeGen::Node PolicyCompiler::AssemblePolicy() { // A compiled policy consists of three logical parts: // 1. Check that the "arch" field matches the expected architecture. @@ -162,12 +162,13 @@ return rest; } - // Allow system calls, if they originate from our magic return address - // (which we can query by calling Syscall::Call(-1)). - uint64_t syscall_entry_point = - static_cast<uint64_t>(static_cast<uintptr_t>(Syscall::Call(-1))); - uint32_t low = static_cast<uint32_t>(syscall_entry_point); - uint32_t hi = static_cast<uint32_t>(syscall_entry_point >> 32); + // We already enabled unsafe traps in Compile, but enable them again to give + // the trap registry a second chance to complain before we add the backdoor. + CHECK(registry_->EnableUnsafeTraps()); + + // Allow system calls, if they originate from our magic return address. + const uint32_t lopc = static_cast<uint32_t>(escapepc_); + const uint32_t hipc = static_cast<uint32_t>(escapepc_ >> 32); // BPF cannot do native 64-bit comparisons, so we have to compare // both 32-bit halves of the instruction pointer. If they match what @@ -179,10 +180,10 @@ return gen_.MakeInstruction( BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_LSB_IDX, gen_.MakeInstruction( - BPF_JMP + BPF_JEQ + BPF_K, low, + BPF_JMP + BPF_JEQ + BPF_K, lopc, gen_.MakeInstruction( BPF_LD + BPF_W + BPF_ABS, SECCOMP_IP_MSB_IDX, - gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hi, + gen_.MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, hipc, CompileResult(Allow()), rest)), rest)); } @@ -259,9 +260,9 @@ // a binary search over the ranges. // As a sanity check, we need to have at least one distinct ranges for us // to be able to build a jump table. - if (stop - start <= 0) { - SANDBOX_DIE("Invalid set of system call ranges"); - } else if (stop - start == 1) { + CHECK(start < stop) << "Invalid iterator range"; + const auto n = stop - start; + if (n == 1) { // If we have narrowed things down to a single range object, we can // return from the BPF filter program. return start->node; @@ -271,7 +272,7 @@ // We compare our system call number against the lowest valid system call // number in this range object. If our number is lower, it is outside of // this range object. If it is greater or equal, it might be inside. - Ranges::const_iterator mid = start + (stop - start) / 2; + Ranges::const_iterator mid = start + n / 2; // Sub-divide the list of ranges and continue recursively. CodeGen::Node jf = AssembleJumpTable(start, mid); @@ -291,31 +292,30 @@ case ErrorCode::ET_TRAP: return gen_.MakeInstruction(BPF_RET + BPF_K, err.err()); default: - SANDBOX_DIE("ErrorCode is not suitable for returning from a BPF program"); + LOG(FATAL) + << "ErrorCode is not suitable for returning from a BPF program"; + return CodeGen::kNullNode; } } CodeGen::Node PolicyCompiler::CondExpression(const ErrorCode& cond) { // Sanity check that |cond| makes sense. - if (cond.argno_ < 0 || cond.argno_ >= 6) { - SANDBOX_DIE("sandbox_bpf: invalid argument number"); + CHECK(cond.argno_ >= 0 && cond.argno_ < 6) << "Invalid argument number " + << cond.argno_; + CHECK(cond.width_ == ErrorCode::TP_32BIT || + cond.width_ == ErrorCode::TP_64BIT) + << "Invalid argument width " << cond.width_; + CHECK_NE(0U, cond.mask_) << "Zero mask is invalid"; + CHECK_EQ(cond.value_, cond.value_ & cond.mask_) + << "Value contains masked out bits"; + if (sizeof(void*) == 4) { + CHECK_EQ(ErrorCode::TP_32BIT, cond.width_) + << "Invalid width on 32-bit platform"; } - if (cond.width_ != ErrorCode::TP_32BIT && - cond.width_ != ErrorCode::TP_64BIT) { - SANDBOX_DIE("sandbox_bpf: invalid argument width"); + if (cond.width_ == ErrorCode::TP_32BIT) { + CHECK_EQ(0U, cond.mask_ >> 32) << "Mask exceeds argument size"; + CHECK_EQ(0U, cond.value_ >> 32) << "Value exceeds argument size"; } - if (cond.mask_ == 0) { - SANDBOX_DIE("sandbox_bpf: zero mask is invalid"); - } - if ((cond.value_ & cond.mask_) != cond.value_) { - SANDBOX_DIE("sandbox_bpf: value contains masked out bits"); - } - if (cond.width_ == ErrorCode::TP_32BIT && - ((cond.mask_ >> 32) != 0 || (cond.value_ >> 32) != 0)) { - SANDBOX_DIE("sandbox_bpf: test exceeds argument size"); - } - // TODO(mdempsky): Reject TP_64BIT on 32-bit platforms. For now we allow it - // because some SandboxBPF unit tests exercise it. CodeGen::Node passed = RetExpression(*cond.passed_); CodeGen::Node failed = RetExpression(*cond.failed_);
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.h b/sandbox/linux/bpf_dsl/policy_compiler.h index faf6be5..df38d4c 100644 --- a/sandbox/linux/bpf_dsl/policy_compiler.h +++ b/sandbox/linux/bpf_dsl/policy_compiler.h
@@ -32,7 +32,11 @@ // Compile registers any trap handlers needed by the policy and // compiles the policy to a BPF program, which it returns. - scoped_ptr<CodeGen::Program> Compile(); + scoped_ptr<CodeGen::Program> Compile(bool verify); + + // DangerousSetEscapePC sets the "escape PC" that is allowed to issue any + // system calls, regardless of policy. + void DangerousSetEscapePC(uint64_t escapepc); // Error returns an ErrorCode to indicate the system call should fail with // the specified error number. @@ -88,7 +92,7 @@ CodeGen::Node CheckArch(CodeGen::Node passed); // If |has_unsafe_traps_| is true, returns an instruction sequence - // that allows all system calls from Syscall::Call(), and otherwise + // that allows all system calls from |escapepc_|, and otherwise // passes control to |rest|. Otherwise, simply returns |rest|. CodeGen::Node MaybeAddEscapeHatch(CodeGen::Node rest); @@ -140,6 +144,7 @@ const Policy* policy_; TrapRegistry* registry_; + uint64_t escapepc_; Conds conds_; CodeGen gen_;
diff --git a/sandbox/linux/bpf_dsl/seccomp_macros.h b/sandbox/linux/bpf_dsl/seccomp_macros.h index b72357a..7fd0e67 100644 --- a/sandbox/linux/bpf_dsl/seccomp_macros.h +++ b/sandbox/linux/bpf_dsl/seccomp_macros.h
@@ -21,6 +21,8 @@ #endif #endif +#include "sandbox/linux/system_headers/linux_seccomp.h" // For AUDIT_ARCH_* + // Impose some reasonable maximum BPF program size. Realistically, the // kernel probably has much lower limits. But by limiting to less than // 30 bits, we can ease requirements on some of our data types.
diff --git a/sandbox/linux/bpf_dsl/trap_registry.h b/sandbox/linux/bpf_dsl/trap_registry.h index 94d4722..0a5d2f1 100644 --- a/sandbox/linux/bpf_dsl/trap_registry.h +++ b/sandbox/linux/bpf_dsl/trap_registry.h
@@ -49,10 +49,19 @@ // EnableUnsafeTraps tries to enable unsafe traps and returns // whether it was successful. This is a one-way operation. + // + // CAUTION: Enabling unsafe traps effectively defeats the security + // guarantees provided by the sandbox policy. TrapRegistry + // implementations should ensure unsafe traps are only enabled + // during testing. virtual bool EnableUnsafeTraps() = 0; protected: TrapRegistry() {} + + // TrapRegistry's destructor is intentionally non-virtual so that + // implementations can omit their destructor. Instead we protect against + // misuse by marking it protected. ~TrapRegistry() {} DISALLOW_COPY_AND_ASSIGN(TrapRegistry);
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/bpf_dsl/verifier.cc similarity index 89% rename from sandbox/linux/seccomp-bpf/verifier.cc rename to sandbox/linux/bpf_dsl/verifier.cc index e533b2d..adbc960 100644 --- a/sandbox/linux/seccomp-bpf/verifier.cc +++ b/sandbox/linux/bpf_dsl/verifier.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "sandbox/linux/seccomp-bpf/verifier.h" +#include "sandbox/linux/bpf_dsl/verifier.h" #include <string.h> @@ -15,16 +15,15 @@ #include "sandbox/linux/bpf_dsl/seccomp_macros.h" #include "sandbox/linux/bpf_dsl/syscall_set.h" #include "sandbox/linux/seccomp-bpf/errorcode.h" -#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" #include "sandbox/linux/system_headers/linux_seccomp.h" namespace sandbox { +namespace bpf_dsl { namespace { const uint64_t kLower32Bits = std::numeric_limits<uint32_t>::max(); const uint64_t kUpper32Bits = static_cast<uint64_t>(kLower32Bits) << 32; -const uint64_t kFull64Bits = std::numeric_limits<uint64_t>::max(); struct State { State(const std::vector<struct sock_filter>& p, @@ -54,8 +53,8 @@ return compiler->Unexpected64bitArgument().err(); } bool equal = (data.args[code.argno()] & code.mask()) == code.value(); - return EvaluateErrorCode( - compiler, equal ? *code.passed() : *code.failed(), data); + return EvaluateErrorCode(compiler, equal ? *code.passed() : *code.failed(), + data); } else { return SECCOMP_RET_INVALID; } @@ -69,10 +68,12 @@ const char** err) { if (code.error_type() == ErrorCode::ET_SIMPLE || code.error_type() == ErrorCode::ET_TRAP) { - uint32_t computed_ret = Verifier::EvaluateBPF(program, *data, err); + const uint32_t computed_ret = Verifier::EvaluateBPF(program, *data, err); if (*err) { return false; - } else if (computed_ret != EvaluateErrorCode(compiler, root_code, *data)) { + } + const uint32_t policy_ret = EvaluateErrorCode(compiler, root_code, *data); + if (computed_ret != policy_ret) { // For efficiency's sake, we'd much rather compare "computed_ret" // against "code.err()". This works most of the time, but it doesn't // always work for nested conditional expressions. The test values @@ -97,8 +98,8 @@ // Verify that we can check a value for simple equality. data->args[code.argno()] = code.value(); - if (!VerifyErrorCode( - compiler, program, data, root_code, *code.passed(), err)) { + if (!VerifyErrorCode(compiler, program, data, root_code, *code.passed(), + err)) { return false; } @@ -110,15 +111,15 @@ } if ((ignored_bits & kLower32Bits) != 0) { data->args[code.argno()] = code.value() | (ignored_bits & kLower32Bits); - if (!VerifyErrorCode( - compiler, program, data, root_code, *code.passed(), err)) { + if (!VerifyErrorCode(compiler, program, data, root_code, *code.passed(), + err)) { return false; } } if ((ignored_bits & kUpper32Bits) != 0) { data->args[code.argno()] = code.value() | (ignored_bits & kUpper32Bits); - if (!VerifyErrorCode( - compiler, program, data, root_code, *code.passed(), err)) { + if (!VerifyErrorCode(compiler, program, data, root_code, *code.passed(), + err)) { return false; } } @@ -126,15 +127,15 @@ // Verify that changing bits included in the mask is detected as inequality. if ((code.mask() & kLower32Bits) != 0) { data->args[code.argno()] = code.value() ^ (code.mask() & kLower32Bits); - if (!VerifyErrorCode( - compiler, program, data, root_code, *code.failed(), err)) { + if (!VerifyErrorCode(compiler, program, data, root_code, *code.failed(), + err)) { return false; } } if ((code.mask() & kUpper32Bits) != 0) { data->args[code.argno()] = code.value() ^ (code.mask() & kUpper32Bits); - if (!VerifyErrorCode( - compiler, program, data, root_code, *code.failed(), err)) { + if (!VerifyErrorCode(compiler, program, data, root_code, *code.failed(), + err)) { return false; } } @@ -145,24 +146,16 @@ // Arbitrary 64-bit values should be rejected. data->args[code.argno()] = 1ULL << 32; - if (!VerifyErrorCode(compiler, - program, - data, - root_code, - compiler->Unexpected64bitArgument(), - err)) { + if (!VerifyErrorCode(compiler, program, data, root_code, + compiler->Unexpected64bitArgument(), err)) { return false; } // Upper 32-bits set without the MSB of the lower 32-bits set should be // rejected too. data->args[code.argno()] = kUpper32Bits; - if (!VerifyErrorCode(compiler, - program, - data, - root_code, - compiler->Unexpected64bitArgument(), - err)) { + if (!VerifyErrorCode(compiler, program, data, root_code, + compiler->Unexpected64bitArgument(), err)) { return false; } } @@ -182,8 +175,7 @@ if (insn.k < sizeof(struct arch_seccomp_data) && (insn.k & 3) == 0) { // We only allow loading of properly aligned 32bit quantities. memcpy(&state->accumulator, - reinterpret_cast<const char*>(&state->data) + insn.k, - 4); + reinterpret_cast<const char*>(&state->data) + insn.k, 4); } else { *err = "Invalid operand in BPF_LD instruction"; return; @@ -399,4 +391,5 @@ return 0; } +} // namespace bpf_dsl } // namespace sandbox
diff --git a/sandbox/linux/seccomp-bpf/verifier.h b/sandbox/linux/bpf_dsl/verifier.h similarity index 89% rename from sandbox/linux/seccomp-bpf/verifier.h rename to sandbox/linux/bpf_dsl/verifier.h index 6bd747b..b0435d1 100644 --- a/sandbox/linux/seccomp-bpf/verifier.h +++ b/sandbox/linux/bpf_dsl/verifier.h
@@ -2,25 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_LINUX_SECCOMP_BPF_VERIFIER_H__ -#define SANDBOX_LINUX_SECCOMP_BPF_VERIFIER_H__ +#ifndef SANDBOX_LINUX_BPF_DSL_VERIFIER_H__ +#define SANDBOX_LINUX_BPF_DSL_VERIFIER_H__ #include <stdint.h> #include <vector> #include "base/macros.h" +#include "sandbox/sandbox_export.h" struct sock_filter; namespace sandbox { struct arch_seccomp_data; + namespace bpf_dsl { class Policy; class PolicyCompiler; -} -class Verifier { +class SANDBOX_EXPORT Verifier { public: // Evaluate the BPF program for all possible inputs and verify that it // computes the correct result. We use the "evaluators" to determine @@ -50,6 +51,7 @@ DISALLOW_IMPLICIT_CONSTRUCTORS(Verifier); }; +} // namespace bpf_dsl } // namespace sandbox -#endif // SANDBOX_LINUX_SECCOMP_BPF_VERIFIER_H__ +#endif // SANDBOX_LINUX_BPF_DSL_VERIFIER_H__
diff --git a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc index 8e7e144..e884774 100644 --- a/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc +++ b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
@@ -557,11 +557,11 @@ Die::SuppressInfoMessages(true); unsetenv(kSandboxDebuggingEnv); - SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false); + SANDBOX_ASSERT(Trap::Registry()->EnableUnsafeTraps() == false); setenv(kSandboxDebuggingEnv, "", 1); - SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == false); + SANDBOX_ASSERT(Trap::Registry()->EnableUnsafeTraps() == false); setenv(kSandboxDebuggingEnv, "t", 1); - SANDBOX_ASSERT(Trap::EnableUnsafeTrapsInSigSysHandler() == true); + SANDBOX_ASSERT(Trap::Registry()->EnableUnsafeTraps() == true); } intptr_t PrctlHandler(const struct arch_seccomp_data& args, void*) {
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi index a623971..6111fd3 100644 --- a/sandbox/linux/sandbox_linux.gypi +++ b/sandbox/linux/sandbox_linux.gypi
@@ -137,6 +137,8 @@ 'bpf_dsl/syscall_set.cc', 'bpf_dsl/syscall_set.h', 'bpf_dsl/trap_registry.h', + 'bpf_dsl/verifier.cc', + 'bpf_dsl/verifier.h', 'seccomp-bpf/die.cc', 'seccomp-bpf/die.h', 'seccomp-bpf/errorcode.cc', @@ -147,8 +149,6 @@ 'seccomp-bpf/syscall.h', 'seccomp-bpf/trap.cc', 'seccomp-bpf/trap.h', - 'seccomp-bpf/verifier.cc', - 'seccomp-bpf/verifier.h', ], 'dependencies': [ '../base/base.gyp:base',
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc index b6553d7..c96642e 100644 --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -24,16 +24,13 @@ #include "base/posix/eintr_wrapper.h" #include "base/third_party/valgrind/valgrind.h" #include "sandbox/linux/bpf_dsl/codegen.h" -#include "sandbox/linux/bpf_dsl/dump_bpf.h" #include "sandbox/linux/bpf_dsl/policy.h" #include "sandbox/linux/bpf_dsl/policy_compiler.h" #include "sandbox/linux/bpf_dsl/seccomp_macros.h" #include "sandbox/linux/bpf_dsl/syscall_set.h" #include "sandbox/linux/seccomp-bpf/die.h" -#include "sandbox/linux/seccomp-bpf/errorcode.h" #include "sandbox/linux/seccomp-bpf/syscall.h" #include "sandbox/linux/seccomp-bpf/trap.h" -#include "sandbox/linux/seccomp-bpf/verifier.h" #include "sandbox/linux/services/proc_util.h" #include "sandbox/linux/services/syscall_wrappers.h" #include "sandbox/linux/services/thread_helpers.h" @@ -79,6 +76,14 @@ } } +uint64_t EscapePC() { + intptr_t rv = Syscall::Call(-1); + if (rv == -1 && errno == ENOSYS) { + return 0; + } + return static_cast<uint64_t>(static_cast<uintptr_t>(rv)); +} + } // namespace SandboxBPF::SandboxBPF(bpf_dsl::Policy* policy) @@ -184,25 +189,12 @@ force_verification = true; #endif DCHECK(policy_); + bpf_dsl::PolicyCompiler compiler(policy_.get(), Trap::Registry()); - scoped_ptr<CodeGen::Program> program = compiler.Compile(); - - // Make sure compilation resulted in a BPF program that executes - // correctly. Otherwise, there is an internal error in our BPF compiler. - // There is really nothing the caller can do until the bug is fixed. - if (force_verification) { - // Verification is expensive. We only perform this step, if we are - // compiled in debug mode, or if the caller explicitly requested - // verification. - - const char* err = NULL; - if (!Verifier::VerifyBPF(&compiler, *program, *policy_, &err)) { - bpf_dsl::DumpBPF::PrintProgram(*program); - SANDBOX_DIE(err); - } + if (Trap::SandboxDebuggingAllowedByUser()) { + compiler.DangerousSetEscapePC(EscapePC()); } - - return program.Pass(); + return compiler.Compile(force_verification); } void SandboxBPF::InstallFilter(bool must_sync_threads) {
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc index c87bb00..145e624 100644 --- a/sandbox/linux/seccomp-bpf/trap.cc +++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -251,10 +251,6 @@ } } -uint16_t Trap::MakeTrap(TrapFnc fnc, const void* aux, bool safe) { - return Registry()->Add(fnc, aux, safe); -} - uint16_t Trap::Add(TrapFnc fnc, const void* aux, bool safe) { if (!safe && !SandboxDebuggingAllowedByUser()) { // Unless the user set the CHROME_SANDBOX_DEBUGGING environment variable, @@ -353,15 +349,11 @@ return id; } -bool Trap::SandboxDebuggingAllowedByUser() const { +bool Trap::SandboxDebuggingAllowedByUser() { const char* debug_flag = getenv(kSandboxDebuggingEnv); return debug_flag && *debug_flag; } -bool Trap::EnableUnsafeTrapsInSigSysHandler() { - return Registry()->EnableUnsafeTraps(); -} - bool Trap::EnableUnsafeTraps() { if (!has_unsafe_traps_) { // Unsafe traps are a one-way fuse. Once enabled, they can never be turned
diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h index fea0052..4073bfe 100644 --- a/sandbox/linux/seccomp-bpf/trap.h +++ b/sandbox/linux/seccomp-bpf/trap.h
@@ -34,23 +34,9 @@ // creating it if necessary. static bpf_dsl::TrapRegistry* Registry(); - // Registers a new trap handler and sets up the appropriate SIGSYS handler - // as needed. - // N.B.: This makes a permanent state change. Traps cannot be unregistered, - // as that would break existing BPF filters that are still active. - // TODO(mdempsky): Deprecated; remove. - static uint16_t MakeTrap(TrapFnc fnc, const void* aux, bool safe); - - // Enables support for unsafe traps in the SIGSYS signal handler. This is a - // one-way fuse. It works in conjunction with the BPF compiler emitting code - // that unconditionally allows system calls, if they have a magic return - // address (i.e. SandboxSyscall(-1)). - // Once unsafe traps are enabled, the sandbox is essentially compromised. - // But this is still a very useful feature for debugging purposes. Use with - // care. This feature is availably only if enabled by the user (see above). - // Returns "true", if unsafe traps were turned on. - // TODO(mdempsky): Deprecated; remove. - static bool EnableUnsafeTrapsInSigSysHandler(); + // SandboxDebuggingAllowedByUser returns whether the + // "CHROME_SANDBOX_DEBUGGING" environment variable is set. + static bool SandboxDebuggingAllowedByUser(); private: struct TrapKey { @@ -67,9 +53,9 @@ // automatically as needed. Trap(); - // The destructor is unimplemented. Don't ever attempt to destruct this - // object. It'll break subsequent system calls that trigger a SIGSYS. - ~Trap(); + // The destructor is unimplemented as destroying this object would + // break subsequent system calls that trigger a SIGSYS. + ~Trap() = delete; static void SigSysAction(int nr, siginfo_t* info, void* void_context); @@ -77,8 +63,6 @@ // dumps. void SigSys(int nr, siginfo_t* info, void* void_context) __attribute__((noinline)); - bool SandboxDebuggingAllowedByUser() const; - // We have a global singleton that handles all of our SIGSYS traps. This // variable must never be deallocated after it has been set up initially, as // there is no way to reset in-kernel BPF filters that generate SIGSYS
diff --git a/sdch/BUILD.gn b/sdch/BUILD.gn new file mode 100644 index 0000000..3ceeeb4 --- /dev/null +++ b/sdch/BUILD.gn
@@ -0,0 +1,99 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +config("sdch_config") { + include_dirs = [ "open-vcdiff/src" ] +} + +static_library("sdch") { + sources = [ + "logging_forward.h", + "open-vcdiff/src/addrcache.cc", + "open-vcdiff/src/blockhash.cc", + "open-vcdiff/src/blockhash.h", + "open-vcdiff/src/checksum.h", + "open-vcdiff/src/codetable.cc", + "open-vcdiff/src/codetable.h", + "open-vcdiff/src/compile_assert.h", + "open-vcdiff/src/decodetable.cc", + "open-vcdiff/src/decodetable.h", + "open-vcdiff/src/encodetable.cc", + "open-vcdiff/src/encodetable.h", + "open-vcdiff/src/google/output_string.h", + "open-vcdiff/src/google/vcdecoder.h", + "open-vcdiff/src/google/vcencoder.h", + "open-vcdiff/src/headerparser.cc", + "open-vcdiff/src/headerparser.h", + "open-vcdiff/src/instruction_map.cc", + "open-vcdiff/src/instruction_map.h", + "open-vcdiff/src/jsonwriter.cc", + "open-vcdiff/src/jsonwriter.h", + "open-vcdiff/src/rolling_hash.h", + "open-vcdiff/src/testing.h", + "open-vcdiff/src/varint_bigendian.cc", + "open-vcdiff/src/varint_bigendian.h", + "open-vcdiff/src/vcdecoder.cc", + "open-vcdiff/src/vcdiff_defs.h", + "open-vcdiff/src/vcdiffengine.cc", + "open-vcdiff/src/vcdiffengine.h", + "open-vcdiff/src/vcencoder.cc", + "open-vcdiff/vsprojects/config.h", + "open-vcdiff/vsprojects/stdint.h", + ] + + public_configs = [ ":sdch_config" ] + + deps = [ + "//base", + "//third_party/zlib", + ] + + # gn orders flags on a target before flags from configs. The default config + # adds -Wall, and these flags have to be after -Wall -- so they need to come + # from a config and can't be on the target directly. + config("sdch_warnings") { + cflags = [] + if (is_linux) { + # TODO(mostynb): remove this if open-vcdiff is ever updated for c++11: + cflags += [ "-Wno-deprecated-declarations" ] + } + + if (is_clang) { + # sdch uses the pre-c++11 typedef-as-static_assert hack. + # https://code.google.com/p/open-vcdiff/issues/detail?id=44 + cflags += [ "-Wno-unused-local-typedef" ] + } + } + configs += [ ":sdch_warnings" ] + + if (is_linux || is_android) { + include_dirs = [ "linux" ] + } else if (is_ios) { + include_dirs = [ "ios" ] + } else if (is_mac) { + include_dirs = [ "mac" ] + } else if (is_win) { + include_dirs = [ "win" ] + } + + # open-vcdiff's logging.h introduces static initializers. This was + # reported upstream years ago ( + # https://code.google.com/p/open-vcdiff/issues/detail?id=33 ). Since + # upstream won't fix this, work around it on the chromium side: + # Inject a header that forwards to base/logging.h instead (which doesn't + # introduce static initializers, and which prevents open-vcdiff's + # logging.h from being used). + if (is_win) { + cflags = [ + "/FI", + "sdch/logging_forward.h", + ] + } else { + logging_file = rebase_path("logging_forward.h", root_build_dir) + cflags = [ + "-include", + logging_file, + ] + } +}
diff --git a/sdch/OWNERS b/sdch/OWNERS new file mode 100644 index 0000000..b68fa81 --- /dev/null +++ b/sdch/OWNERS
@@ -0,0 +1,3 @@ +jar@chromium.org +mark@chromium.org +wtc@chromium.org
diff --git a/sdch/README.chromium b/sdch/README.chromium new file mode 100644 index 0000000..93ae6a0 --- /dev/null +++ b/sdch/README.chromium
@@ -0,0 +1,19 @@ +The linux directory contains a config.h generated from a run of configure on +Ubuntu 10.04.1 LTS x86_64, with VCDIFF_USE_BLOCK_COMPARE_WORDS manually +changed to match the $host_cpu test in configure. + +The mac directory contains a config.h generated from a run of configure on a +Mac, with VCDIFF_USE_BLOCK_COMPARE_WORDS manually changed to match the +$host_cpu test in configure. + +The ios directory contains a config.h generated from a run of configure +--host=arm-apple-darwin10 on a Mac with the following environment variables: + CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -x c -arch armv6 + CFLAGS=-mno-thumb -miphoneos-version-min=4.2 + CPPFLAGS=-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk + CXX=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -x c++ -arch armv6 + CXXFLAGS=-mno-thumb -miphoneos-version-min=4.2 + +The win directory contains a config.h that forwards to one provided with +open-vcdiff. We have this to avoid putting open-vcdiff's minimal stdint.h hack +into our include path.
diff --git a/sdch/bsd/config.h b/sdch/bsd/config.h new file mode 100644 index 0000000..44417b4 --- /dev/null +++ b/sdch/bsd/config.h
@@ -0,0 +1,113 @@ +/* src/config.h. Generated by SCons. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the <ext/rope> header file. */ +/* #undef HAVE_EXT_ROPE */ + +/* Define to 1 if you have the <fnmatch.h> header file. */ +/* #undef HAVE_FNMATCH_H */ + +/* Define to 1 if you have the <getopt.h> header file. */ +/* #undef HAVE_GETOPT_H */ + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +/* #undef HAVE_INTTYPES_H */ + +/* Define to 1 if you have the <malloc.h> header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define to 1 if you have the `memalign' function. */ +/* #undef HAVE_MEMALIGN */ + +/* Define to 1 if you have the <memory.h> header file. */ +/* #undef HAVE_MEMORY_H */ + +/* Define to 1 if you have the `mprotect' function. */ +/* #undef HAVE_MPROTECT */ + +/* Define to 1 if you have the `posix_memalign' function. */ +/* #undef HAVE_POSIX_MEMALIGN */ + +/* Define to 1 if you have the `QueryPerformanceCounter' function. */ +/* #undef HAVE_QUERYPERFORMANCECOUNTER */ + +/* Define to 1 if you have the <stdint.h> header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the <stdlib.h> header file. */ +/* #undef HAVE_STDLIB_H */ + +/* Define to 1 if you have the <strings.h> header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the <string.h> header file. */ +/* #undef HAVE_STRING_H */ + +/* Define to 1 if you have the `strtoll' function. */ +/* #undef HAVE_STRTOLL */ + +/* Define to 1 if you have the `strtoq' function. */ +/* #undef HAVE_STRTOQ */ + +/* Define to 1 if you have the <sys/mman.h> header file. */ +/* #undef HAVE_SYS_MMAN_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +/* #undef HAVE_SYS_STAT_H */ + +/* Define to 1 if you have the <sys/time.h> header file. */ +/* #undef HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the <sys/types.h> header file. */ +/* #undef HAVE_SYS_TYPES_H */ + +/* Define to 1 if the system has the type `uint16_t'. */ +/* #undef HAVE_UINT16_T */ + +/* Define to 1 if you have the <unistd.h> header file. */ +/* #undef HAVE_UNISTD_H */ + +/* Define to 1 if the system has the type `u_int16_t'. */ +/* #undef HAVE_U_INT16_T */ + +/* Define to 1 if you have the <windows.h> header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* define if your compiler has __attribute__ */ +/* #undef HAVE___ATTRIBUTE__ */ + +/* Define to 1 if the system has the type `__int16'. */ +/* #undef HAVE___INT16 */ + +/* Name of package */ +/* #undef PACKAGE */ + +/* Define to the address where bug reports for this package should be sent. */ +/* #undef PACKAGE_BUGREPORT */ + +/* Define to the full name of this package. */ +/* #undef PACKAGE_NAME */ + +/* Define to the full name and version of this package. */ +/* #undef PACKAGE_STRING */ + +/* Define to the one symbol short name of this package. */ +/* #undef PACKAGE_TARNAME */ + +/* Define to the version of this package. */ +/* #undef PACKAGE_VERSION */ + +/* Define to 1 if you have the ANSI C header files. */ +/* #undef STDC_HEADERS */ + +/* Use custom compare function instead of memcmp */ +/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */ + +/* Version number of package */ +/* #undef VERSION */
diff --git a/sdch/ios/config.h b/sdch/ios/config.h new file mode 100644 index 0000000..5dde8c9 --- /dev/null +++ b/sdch/ios/config.h
@@ -0,0 +1,113 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <ext/rope> header file. */ +/* #undef HAVE_EXT_ROPE */ + +/* Define to 1 if you have the <fnmatch.h> header file. */ +#define HAVE_FNMATCH_H 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <malloc.h> header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define to 1 if you have the `memalign' function. */ +/* #undef HAVE_MEMALIGN */ + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mprotect' function. */ +#define HAVE_MPROTECT 1 + +/* Define to 1 if you have the `posix_memalign' function. */ +#define HAVE_POSIX_MEMALIGN 1 + +/* Define to 1 if you have the `QueryPerformanceCounter' function. */ +/* #undef HAVE_QUERYPERFORMANCECOUNTER */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +#define HAVE_STRTOQ 1 + +/* Define to 1 if you have the <sys/mman.h> header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define HAVE_UINT16_T 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type `u_int16_t'. */ +#define HAVE_U_INT16_T 1 + +/* Define to 1 if you have the <windows.h> header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* define if your compiler has __attribute__ */ +#define HAVE___ATTRIBUTE__ 1 + +/* Define to 1 if the system has the type `__int16'. */ +/* #undef HAVE___INT16 */ + +/* Name of package */ +#define PACKAGE "open-vcdiff" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "opensource@google.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "open-vcdiff" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "open-vcdiff 0.7" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "open-vcdiff" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.7" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Use custom compare function instead of memcmp */ +/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */ + +/* Version number of package */ +#define VERSION "0.7"
diff --git a/sdch/linux/config.h b/sdch/linux/config.h new file mode 100644 index 0000000..3232eae --- /dev/null +++ b/sdch/linux/config.h
@@ -0,0 +1,119 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <ext/rope> header file. */ +/* #undef HAVE_EXT_ROPE */ + +/* Define to 1 if you have the <fnmatch.h> header file. */ +#define HAVE_FNMATCH_H 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <malloc.h> header file. */ +/* Manual edit: This is defined in AndroidConfig.h. */ +#undef HAVE_MALLOC_H +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memalign' function. */ +#define HAVE_MEMALIGN 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mprotect' function. */ +#define HAVE_MPROTECT 1 + +/* Define to 1 if you have the `posix_memalign' function. */ +#define HAVE_POSIX_MEMALIGN 1 + +/* Define to 1 if you have the `QueryPerformanceCounter' function. */ +/* #undef HAVE_QUERYPERFORMANCECOUNTER */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +#define HAVE_STRTOQ 1 + +/* Define to 1 if you have the <sys/mman.h> header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define HAVE_UINT16_T 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type `u_int16_t'. */ +#define HAVE_U_INT16_T 1 + +/* Define to 1 if you have the <windows.h> header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* define if your compiler has __attribute__ */ +#define HAVE___ATTRIBUTE__ 1 + +/* Define to 1 if the system has the type `__int16'. */ +/* #undef HAVE___INT16 */ + +/* Name of package */ +#define PACKAGE "open-vcdiff" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "opensource@google.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "open-vcdiff" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "open-vcdiff 0.7" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "open-vcdiff" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.7" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Use custom compare function instead of memcmp */ +#if defined(__i386__) || defined(__x86_64__) +#define VCDIFF_USE_BLOCK_COMPARE_WORDS 1 +#else +/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */ +#endif + +/* Version number of package */ +#define VERSION "0.7"
diff --git a/sdch/logging_forward.h b/sdch/logging_forward.h new file mode 100644 index 0000000..fc0d327 --- /dev/null +++ b/sdch/logging_forward.h
@@ -0,0 +1,22 @@ +// 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 SDCH_LOGGING_FORWARD_H_ +#define SDCH_LOGGING_FORWARD_H_ + +// Define open-vcdiff's logging.h header guard, so that it doesn't get used. +#define OPEN_VCDIFF_LOGGING_H_ + +#include "base/logging.h" + +// open-vcdiff's logging.h includes iostream, which adds static initializers +// to several compilation units. To prevent this, provide this replacement +// header which forwards open-vcdiffs logging macros to chromium's base logging +// mechanism. +#define VCD_WARNING LOG(WARNING) +#define VCD_ERROR LOG(ERROR) +#define VCD_DFATAL LOG(DFATAL) +#define VCD_ENDL "\n" + +#endif // SDCH_LOGGING_FORWARD_H_
diff --git a/sdch/mac/config.h b/sdch/mac/config.h new file mode 100644 index 0000000..e9ee90e --- /dev/null +++ b/sdch/mac/config.h
@@ -0,0 +1,117 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <ext/rope> header file. */ +/* #undef HAVE_EXT_ROPE */ + +/* Define to 1 if you have the <fnmatch.h> header file. */ +#define HAVE_FNMATCH_H 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <malloc.h> header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define to 1 if you have the `memalign' function. */ +/* #undef HAVE_MEMALIGN */ + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mprotect' function. */ +#define HAVE_MPROTECT 1 + +/* Define to 1 if you have the `posix_memalign' function. */ +/* #undef HAVE_POSIX_MEMALIGN */ + +/* Define to 1 if you have the `QueryPerformanceCounter' function. */ +/* #undef HAVE_QUERYPERFORMANCECOUNTER */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +#define HAVE_STRTOQ 1 + +/* Define to 1 if you have the <sys/mman.h> header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if the system has the type `uint16_t'. */ +#define HAVE_UINT16_T 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type `u_int16_t'. */ +#define HAVE_U_INT16_T 1 + +/* Define to 1 if you have the <windows.h> header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* define if your compiler has __attribute__ */ +#define HAVE___ATTRIBUTE__ 1 + +/* Define to 1 if the system has the type `__int16'. */ +/* #undef HAVE___INT16 */ + +/* Name of package */ +#define PACKAGE "open-vcdiff" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "opensource@google.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "open-vcdiff" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "open-vcdiff 0.7" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "open-vcdiff" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.7" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Use custom compare function instead of memcmp */ +#if defined(__i386__) || defined(__x86_64__) +#define VCDIFF_USE_BLOCK_COMPARE_WORDS 1 +#else +/* #undef VCDIFF_USE_BLOCK_COMPARE_WORDS */ +#endif + +/* Version number of package */ +#define VERSION "0.7"
diff --git a/sdch/sdch.gyp b/sdch/sdch.gyp new file mode 100644 index 0000000..e886288 --- /dev/null +++ b/sdch/sdch.gyp
@@ -0,0 +1,109 @@ +# Copyright (c) 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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + 'target_name': 'sdch', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../third_party/zlib/zlib.gyp:zlib', + ], + 'sources': [ + 'logging_forward.h', + 'open-vcdiff/src/addrcache.cc', + 'open-vcdiff/src/blockhash.cc', + 'open-vcdiff/src/blockhash.h', + 'open-vcdiff/src/checksum.h', + 'open-vcdiff/src/codetable.cc', + 'open-vcdiff/src/codetable.h', + 'open-vcdiff/src/compile_assert.h', + 'open-vcdiff/src/decodetable.cc', + 'open-vcdiff/src/decodetable.h', + 'open-vcdiff/src/encodetable.cc', + 'open-vcdiff/src/encodetable.h', + 'open-vcdiff/src/google/output_string.h', + 'open-vcdiff/src/google/vcdecoder.h', + 'open-vcdiff/src/google/vcencoder.h', + 'open-vcdiff/src/headerparser.cc', + 'open-vcdiff/src/headerparser.h', + 'open-vcdiff/src/instruction_map.cc', + 'open-vcdiff/src/instruction_map.h', + 'open-vcdiff/src/jsonwriter.h', + 'open-vcdiff/src/jsonwriter.cc', + 'open-vcdiff/src/rolling_hash.h', + 'open-vcdiff/src/testing.h', + 'open-vcdiff/src/varint_bigendian.cc', + 'open-vcdiff/src/varint_bigendian.h', + 'open-vcdiff/src/vcdecoder.cc', + 'open-vcdiff/src/vcencoder.cc', + 'open-vcdiff/src/vcdiff_defs.h', + 'open-vcdiff/src/vcdiffengine.cc', + 'open-vcdiff/src/vcdiffengine.h', + 'open-vcdiff/vsprojects/config.h', + 'open-vcdiff/vsprojects/stdint.h', + ], + 'include_dirs': [ + 'open-vcdiff/src', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'open-vcdiff/src', + ], + }, + 'conditions': [ + [ 'OS == "linux" or OS == "android"', { 'include_dirs': [ 'linux' ] } ], + [ 'os_bsd==1 or OS=="solaris"', { 'include_dirs': [ 'bsd' ] } ], + [ 'OS == "ios"', { 'include_dirs': [ 'ios' ] } ], + [ 'OS == "mac"', { 'include_dirs': [ 'mac' ] } ], + [ 'OS == "win"', { 'include_dirs': [ 'win' ] } ], + ], + # open-vcdiff's logging.h introduces static initializers. This was + # reported upstream years ago ( + # https://code.google.com/p/open-vcdiff/issues/detail?id=33 ). Since + # upstream won't fix this, work around it on the chromium side: + # Inject a header that forwards to base/logging.h instead (which doesn't + # introduce static initializers, and which prevents open-vcdiff's + # logging.h from being used). + 'variables': { + 'clang_warning_flags': [ + # sdch uses the pre-c++11 typedef-as-static_assert hack. + # https://code.google.com/p/open-vcdiff/issues/detail?id=44 + '-Wno-unused-local-typedef', + ], + 'logging_path': 'logging_forward.h', + 'conditions': [ + # gyp leaves unspecified what the cwd is when running the compiler, + # and gyp/linux doesn't have a built-in way for forcing an include. + # So hardcode the base directory. If this spreads, provide native + # support in gyp, like we have for gyp/mac and gyp/windows. + # path. + ['"<(GENERATOR)"=="ninja"', { 'logging_dir': '../..' }, + { 'logging_dir': '.' } + ], + ], + }, + # GCC_PREFIX_HEADER is relative to the current directory, + # ForcedIncludeFiles is relative to include_dirs, cflags relative to the + # build directory. + 'xcode_settings': { 'GCC_PREFIX_HEADER': '<(logging_path)' }, + 'msvs_settings': { + 'VCCLCompilerTool': { + 'ForcedIncludeFiles': [ + 'sdch/<(logging_path)', + ] + } + }, + 'cflags': [ + '-include', '<(logging_dir)/sdch/<(logging_path)', + # TODO(mostynb): remove this if open-vcdiff is ever updated for c++11: + '-Wno-deprecated-declarations', + ], + }, + ], +}
diff --git a/sdch/win/config.h b/sdch/win/config.h new file mode 100644 index 0000000..b5fb37c --- /dev/null +++ b/sdch/win/config.h
@@ -0,0 +1,14 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file and directory exist so that we can use the provided config.h +// without putting vsprojects into our include path (which would also give us an +// incorrect/incompatible stdint.h). + +#ifndef SDCH_WIN_CONFIG_H_ +#define SDCH_WIN_CONFIG_H_ + +#include "../open-vcdiff/vsprojects/config.h" + +#endif // SDCH_WIN_CONFIG_H_
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 472a8cf..2357a7f 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -116,9 +116,6 @@ "//third_party/skia/include/pipe", "//third_party/skia/include/ports", "//third_party/skia/include/utils", - - # need to move this to internal. see crbug.com/457691 - "//third_party/skia/src/core", ] defines = gypi_skia_defines.skia_for_chromium_defines @@ -126,7 +123,10 @@ defines += [] if (component_mode == "shared_library") { - defines += [ "SKIA_DLL" ] + defines += [ + "SKIA_DLL", + "GR_GL_IGNORE_ES3_MSAA=0", + ] } if (skia_support_gpu) { @@ -157,6 +157,7 @@ # exported to dependents. It's not clear if this is on purpose, but this # matches the GYP build. include_dirs = [ + "//third_party/skia/src/core", "//third_party/skia/src/image", "//third_party/skia/src/opts", "//third_party/skia/src/pdf", @@ -231,7 +232,12 @@ "//third_party/skia/src/utils/win", ] - defines += [ "SK_FONTHOST_USES_FONTMGR" ] + defines += [ + # On windows, GDI handles are a scarse system-wide resource so we have to + # keep the glyph cache, which holds up to 4 GDI handles per entry, to a + # fairly small size. http://crbug.com/314387 + "SK_DEFAULT_FONT_CACHE_COUNT_LIMIT=256", + ] cflags = [ "/wd4244", # conversion from 'type1( __int64)' to 'type2 (unsigned int)' @@ -242,6 +248,7 @@ "/wd4554", # 'operator' : check operator precedence for possible error "/wd4748", # compiler will disable optimizations if a function has inline # assembly code contains flow control(jmp or jcc) statements. + "/wd4800", # forcing value to bool 'true/false'(assigning int to bool). ] } @@ -486,14 +493,6 @@ "//third_party/zlib", ] - if (is_win) { - configs -= [ - # Some files define WIN32_LEAN_AND_MEAN and we want to avoid a duplicate - # definition warning. - "//build/config/win:lean_and_mean", - ] - } - if (is_linux) { configs += [ "//build/config/linux:fontconfig", @@ -617,3 +616,28 @@ "//ui/gfx/geometry", ] } + +if (is_linux && !is_chromeos) { + # TODO(GYP): Figure out which of these work and are needed on other platforms. + executable("image_operations_bench") { + sources = [ + "ext/image_operations_bench.cc", + ] + + deps = [ + ":skia", + "//base", + ] + } + + executable("filter_fuzz_stub") { + sources = [ + "tools/filter_fuzz_stub/filter_fuzz_stub.cc", + ] + + deps = [ + ":skia", + "//base", + ] + } +}
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index d9b6297..6369e34 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -261,10 +261,6 @@ # define SK_IGNORE_GPU_DITHER #endif -#ifndef SK_SUPPORT_LEGACY_ADDOVAL -# define SK_SUPPORT_LEGACY_ADDOVAL -#endif - #ifndef SK_LEGACY_STROKE_CURVES # define SK_LEGACY_STROKE_CURVES #endif
diff --git a/skia/ext/SkDiscardableMemory_chrome.cc b/skia/ext/SkDiscardableMemory_chrome.cc index 7103100..50e7f2e 100644 --- a/skia/ext/SkDiscardableMemory_chrome.cc +++ b/skia/ext/SkDiscardableMemory_chrome.cc
@@ -7,17 +7,7 @@ SkDiscardableMemoryChrome::~SkDiscardableMemoryChrome() {} bool SkDiscardableMemoryChrome::lock() { - const base::DiscardableMemoryLockStatus status = discardable_->Lock(); - switch (status) { - case base::DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS: - return true; - case base::DISCARDABLE_MEMORY_LOCK_STATUS_PURGED: - discardable_->Unlock(); - return false; - default: - discardable_.reset(); - return false; - } + return discardable_->Lock(); } void* SkDiscardableMemoryChrome::data() { @@ -34,9 +24,6 @@ } SkDiscardableMemory* SkDiscardableMemory::Create(size_t bytes) { - scoped_ptr<base::DiscardableMemory> discardable( + return new SkDiscardableMemoryChrome( base::DiscardableMemory::CreateLockedMemory(bytes)); - if (!discardable) - return NULL; - return new SkDiscardableMemoryChrome(discardable.Pass()); }
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc index fe447c7..0ff1660 100644 --- a/skia/ext/analysis_canvas.cc +++ b/skia/ext/analysis_canvas.cc
@@ -418,7 +418,7 @@ SkXfermode::Mode xfermode = SkXfermode::kSrc_Mode; if (paint) SkXfermode::AsMode(paint->getXfermode(), &xfermode); - if (xfermode != SkXfermode::kSrc_Mode) { + if (xfermode != SkXfermode::kDst_Mode) { if (force_not_transparent_stack_level_ == kNoLayer) { force_not_transparent_stack_level_ = saved_stack_size_; SetForceNotTransparent(true);
diff --git a/skia/ext/analysis_canvas_unittest.cc b/skia/ext/analysis_canvas_unittest.cc index 5bb18eb..8263075 100644 --- a/skia/ext/analysis_canvas_unittest.cc +++ b/skia/ext/analysis_canvas_unittest.cc
@@ -222,6 +222,49 @@ EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); } +TEST(AnalysisCanvasTest, SaveLayerWithXfermode) { + skia::AnalysisCanvas canvas(255, 255); + SkRect bounds = SkRect::MakeWH(255, 255); + SkColor outputColor; + + EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); + EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); + SkPaint paint; + + // Note: nothing is draw to the the save layer, but solid color + // and transparency are handled conservatively in case the layer's + // SkPaint draws something. For example, there could be an + // SkPictureImageFilter. If someday analysis_canvas starts doing + // a deeper analysis of the SkPaint, this test may need to be + // redesigned. + TransparentFill(canvas); + EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); + EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); + canvas.saveLayer(&bounds, &paint); + canvas.restore(); + EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); + + TransparentFill(canvas); + EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); + EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + canvas.saveLayer(&bounds, &paint); + canvas.restore(); + EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); + + // Layer with dst xfermode is a no-op, so this is the only case + // where solid color is unaffected by the layer. + TransparentFill(canvas); + EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); + EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); + paint.setXfermodeMode(SkXfermode::kDst_Mode); + canvas.saveLayer(&bounds, &paint); + canvas.restore(); + EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); + EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); +} + TEST(AnalysisCanvasTest, SaveLayerRestore) { skia::AnalysisCanvas canvas(255, 255);
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc index 0dd6949..dbe851a 100644 --- a/skia/ext/benchmarking_canvas.cc +++ b/skia/ext/benchmarking_canvas.cc
@@ -8,8 +8,10 @@ #include "skia/ext/benchmarking_canvas.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkImageFilter.h" +#include "third_party/skia/include/core/SkTLazy.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkRegion.h" +#include "third_party/skia/include/core/SkString.h" #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/core/SkXfermode.h" @@ -406,6 +408,47 @@ return val.Pass(); } +class OverdrawXfermode : public SkXfermode { +public: + SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override { + // This table encodes the color progression of the overdraw visualization + static const SkPMColor gTable[] = { + SkPackARGB32(0x00, 0x00, 0x00, 0x00), + SkPackARGB32(0xFF, 128, 158, 255), + SkPackARGB32(0xFF, 170, 185, 212), + SkPackARGB32(0xFF, 213, 195, 170), + SkPackARGB32(0xFF, 255, 192, 127), + SkPackARGB32(0xFF, 255, 185, 85), + SkPackARGB32(0xFF, 255, 165, 42), + SkPackARGB32(0xFF, 255, 135, 0), + SkPackARGB32(0xFF, 255, 95, 0), + SkPackARGB32(0xFF, 255, 50, 0), + SkPackARGB32(0xFF, 255, 0, 0) + }; + + size_t idx; + if (SkColorGetR(dst) < 64) { // 0 + idx = 0; + } else if (SkColorGetG(dst) < 25) { // 10 + idx = 9; // cap at 9 for upcoming increment + } else if ((SkColorGetB(dst) + 21) / 42 > 0) { // 1-6 + idx = 7 - (SkColorGetB(dst) + 21) / 42; + } else { // 7-9 + idx = 10 - (SkColorGetG(dst) + 22) / 45; + } + + ++idx; + SkASSERT(idx < SK_ARRAY_COUNT(gTable)); + + return gTable[idx]; + } + + Factory getFactory() const override { return NULL; } +#ifndef SK_IGNORE_TO_STRING + void toString(SkString* str) const override { str->set("OverdrawXfermode"); } +#endif +}; + } // namespace namespace skia { @@ -416,7 +459,10 @@ const SkPaint* paint = nullptr) : canvas_(canvas) , op_record_(new base::DictionaryValue()) - , op_params_(new base::ListValue()) { + , op_params_(new base::ListValue()) + // AutoOp objects are always scoped within draw call frames, + // so the paint is guaranteed to be valid for their lifetime. + , paint_(paint) { DCHECK(canvas); DCHECK(op_name); @@ -427,6 +473,14 @@ if (paint) this->addParam("paint", AsValue(*paint)); + if (canvas->flags_ & kOverdrawVisualization_Flag) { + DCHECK(canvas->overdraw_xfermode_); + + paint_ = paint ? filtered_paint_.set(*paint) : filtered_paint_.init(); + filtered_paint_.get()->setXfermode(canvas->overdraw_xfermode_.get()); + filtered_paint_.get()->setAntiAlias(false); + } + start_ticks_ = base::TimeTicks::Now(); } @@ -444,11 +498,16 @@ op_params_->Append(param.release()); } + const SkPaint* paint() const { return paint_; } + private: BenchmarkingCanvas* canvas_; base::DictionaryValue* op_record_; base::ListValue* op_params_; base::TimeTicks start_ticks_; + + const SkPaint* paint_; + SkTLazy<SkPaint> filtered_paint_; }; BenchmarkingCanvas::BenchmarkingCanvas(SkCanvas* canvas, unsigned flags) @@ -456,6 +515,9 @@ canvas->imageInfo().height()) , flags_(flags) { addCanvas(canvas); + + if (flags & kOverdrawVisualization_Flag) + overdraw_xfermode_ = AdoptRef(new OverdrawXfermode); } BenchmarkingCanvas::~BenchmarkingCanvas() { @@ -493,12 +555,10 @@ AutoOp op(this, "SaveLayer", paint); if (rect) op.addParam("bounds", AsValue(*rect)); - if (paint) - op.addParam("paint", AsValue(*paint)); if (flags) op.addParam("flags", AsValue(flags)); - return INHERITED::willSaveLayer(rect, paint, flags); + return INHERITED::willSaveLayer(rect, op.paint(), flags); } void BenchmarkingCanvas::willRestore() { @@ -566,7 +626,7 @@ void BenchmarkingCanvas::onDrawPaint(const SkPaint& paint) { AutoOp op(this, "DrawPaint", &paint); - INHERITED::onDrawPaint(paint); + INHERITED::onDrawPaint(*op.paint()); } void BenchmarkingCanvas::onDrawPoints(PointMode mode, size_t count, @@ -575,28 +635,28 @@ op.addParam("mode", AsValue(mode)); op.addParam("points", AsListValue(pts, count)); - INHERITED::onDrawPoints(mode, count, pts, paint); + INHERITED::onDrawPoints(mode, count, pts, *op.paint()); } void BenchmarkingCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { AutoOp op(this, "DrawRect", &paint); op.addParam("rect", AsValue(rect)); - INHERITED::onDrawRect(rect, paint); + INHERITED::onDrawRect(rect, *op.paint()); } void BenchmarkingCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { AutoOp op(this, "DrawOval", &paint); op.addParam("rect", AsValue(rect)); - INHERITED::onDrawOval(rect, paint); + INHERITED::onDrawOval(rect, *op.paint()); } void BenchmarkingCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { AutoOp op(this, "DrawRRect", &paint); op.addParam("rrect", AsValue(rrect)); - INHERITED::onDrawRRect(rrect, paint); + INHERITED::onDrawRRect(rrect, *op.paint()); } void BenchmarkingCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, @@ -605,14 +665,14 @@ op.addParam("outer", AsValue(outer)); op.addParam("inner", AsValue(inner)); - INHERITED::onDrawDRRect(outer, inner, paint); + INHERITED::onDrawDRRect(outer, inner, *op.paint()); } void BenchmarkingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { AutoOp op(this, "DrawPath", &paint); op.addParam("path", AsValue(path)); - INHERITED::onDrawPath(path, paint); + INHERITED::onDrawPath(path, *op.paint()); } void BenchmarkingCanvas::onDrawPicture(const SkPicture* picture, @@ -624,7 +684,7 @@ if (matrix) op.addParam("matrix", AsValue(*matrix)); - INHERITED::drawPicture(picture, matrix, paint); + INHERITED::onDrawPicture(picture, matrix, op.paint()); } void BenchmarkingCanvas::onDrawBitmap(const SkBitmap& bitmap, @@ -636,7 +696,7 @@ op.addParam("left", AsValue(left)); op.addParam("top", AsValue(top)); - INHERITED::onDrawBitmap(bitmap, left, top, paint); + INHERITED::onDrawBitmap(bitmap, left, top, op.paint()); } void BenchmarkingCanvas::onDrawBitmapRect(const SkBitmap& bitmap, @@ -650,7 +710,7 @@ op.addParam("src", AsValue(*src)); op.addParam("dst", AsValue(dst)); - INHERITED::onDrawBitmapRect(bitmap, src, dst, paint, flags); + INHERITED::onDrawBitmapRect(bitmap, src, dst, op.paint(), flags); } void BenchmarkingCanvas::onDrawImage(const SkImage* image, @@ -663,7 +723,7 @@ op.addParam("left", AsValue(left)); op.addParam("top", AsValue(top)); - INHERITED::onDrawImage(image, left, top, paint); + INHERITED::onDrawImage(image, left, top, op.paint()); } void BenchmarkingCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, @@ -675,7 +735,7 @@ op.addParam("src", AsValue(*src)); op.addParam("dst", AsValue(dst)); - INHERITED::onDrawImageRect(image, src, dst, paint); + INHERITED::onDrawImageRect(image, src, dst, op.paint()); } void BenchmarkingCanvas::onDrawBitmapNine(const SkBitmap& bitmap, @@ -687,7 +747,7 @@ op.addParam("center", AsValue(SkRect::Make(center))); op.addParam("dst", AsValue(dst)); - INHERITED::onDrawBitmapNine(bitmap, center, dst, paint); + INHERITED::onDrawBitmapNine(bitmap, center, dst, op.paint()); } void BenchmarkingCanvas::onDrawSprite(const SkBitmap& bitmap, int left, int top, @@ -697,7 +757,7 @@ op.addParam("left", AsValue(SkIntToScalar(left))); op.addParam("top", AsValue(SkIntToScalar(top))); - INHERITED::onDrawSprite(bitmap, left, top, paint); + INHERITED::onDrawSprite(bitmap, left, top, op.paint()); } void BenchmarkingCanvas::onDrawText(const void* text, size_t byteLength, @@ -708,7 +768,7 @@ op.addParam("x", AsValue(x)); op.addParam("y", AsValue(y)); - INHERITED::onDrawText(text, byteLength, x, y, paint); + INHERITED::onDrawText(text, byteLength, x, y, *op.paint()); } void BenchmarkingCanvas::onDrawPosText(const void* text, size_t byteLength, @@ -719,7 +779,7 @@ op.addParam("count", AsValue(SkIntToScalar(count))); op.addParam("pos", AsListValue(pos, count)); - INHERITED::onDrawPosText(text, byteLength, pos, paint); + INHERITED::onDrawPosText(text, byteLength, pos, *op.paint()); } void BenchmarkingCanvas::onDrawPosTextH(const void* text, size_t byteLength, @@ -732,7 +792,7 @@ op.addParam("count", AsValue(SkIntToScalar(count))); op.addParam("pos", AsListValue(xpos, count)); - INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, paint); + INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, *op.paint()); } void BenchmarkingCanvas::onDrawTextOnPath(const void* text, size_t byteLength, @@ -744,7 +804,7 @@ if (matrix) op.addParam("matrix", AsValue(*matrix)); - INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, paint); + INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, *op.paint()); } void BenchmarkingCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, @@ -755,7 +815,7 @@ op.addParam("x", AsValue(x)); op.addParam("y", AsValue(y)); - INHERITED::onDrawTextBlob(blob, x, y, paint); + INHERITED::onDrawTextBlob(blob, x, y, *op.paint()); } } // namespace skia
diff --git a/skia/ext/benchmarking_canvas.h b/skia/ext/benchmarking_canvas.h index 4f2e257..a33c42d 100644 --- a/skia/ext/benchmarking_canvas.h +++ b/skia/ext/benchmarking_canvas.h
@@ -6,8 +6,11 @@ #define SKIA_EXT_BENCHMARKING_CANVAS_H_ #include "base/values.h" +#include "skia/ext/refptr.h" #include "third_party/skia/include/utils/SkNWayCanvas.h" +class SkXfermode; + namespace skia { class SK_API BenchmarkingCanvas : public SkNWayCanvas { @@ -16,8 +19,6 @@ ~BenchmarkingCanvas() override; enum Flags { - // TODO(fmalita): add overdraw visualization support - // (http://crbug.com/461534) kOverdrawVisualization_Flag = 0x01, }; @@ -85,6 +86,7 @@ base::ListValue op_records_; unsigned flags_; + RefPtr<SkXfermode> overdraw_xfermode_; }; }
diff --git a/skia/skia_gn_files.gypi b/skia/skia_gn_files.gypi index f066bc5..ae99261 100644 --- a/skia/skia_gn_files.gypi +++ b/skia/skia_gn_files.gypi
@@ -42,12 +42,6 @@ '<(skia_src_path)/sfnt/SkOTTable_name.h', '<(skia_src_path)/sfnt/SkOTUtils.cpp', '<(skia_src_path)/sfnt/SkOTUtils.h', - '<(skia_src_path)/utils/debugger/SkDebugCanvas.cpp', - '<(skia_src_path)/utils/debugger/SkDebugCanvas.h', - '<(skia_src_path)/utils/debugger/SkDrawCommand.cpp', - '<(skia_src_path)/utils/debugger/SkDrawCommand.h', - '<(skia_src_path)/utils/debugger/SkObjectParser.cpp', - '<(skia_src_path)/utils/debugger/SkObjectParser.h', #mac '<(skia_src_path)/utils/mac/SkStream_mac.cpp',
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi index 04e428a..b138e4d 100644 --- a/skia/skia_library.gypi +++ b/skia/skia_library.gypi
@@ -68,13 +68,6 @@ '../third_party/skia/src/sfnt/SkOTUtils.cpp', '../third_party/skia/src/sfnt/SkOTUtils.h', - '../third_party/skia/src/utils/debugger/SkDebugCanvas.cpp', - '../third_party/skia/src/utils/debugger/SkDebugCanvas.h', - '../third_party/skia/src/utils/debugger/SkDrawCommand.cpp', - '../third_party/skia/src/utils/debugger/SkDrawCommand.h', - '../third_party/skia/src/utils/debugger/SkObjectParser.cpp', - '../third_party/skia/src/utils/debugger/SkObjectParser.h', - '../third_party/skia/include/core/SkFontStyle.h', '../third_party/skia/include/images/SkMovie.h', @@ -360,9 +353,6 @@ 'direct_dependent_settings': { 'include_dirs': [ - #temporary until we can hide SkFontHost - '../third_party/skia/src/core', - '../third_party/skia/include/core', '../third_party/skia/include/effects', '../third_party/skia/include/pdf',
diff --git a/skia/skia_test_expectations.txt b/skia/skia_test_expectations.txt index 5927d5c..4327f6e 100644 --- a/skia/skia_test_expectations.txt +++ b/skia/skia_test_expectations.txt
@@ -48,7 +48,4 @@ # # START OVERRIDES HERE -# We fixed a blending bug. -crbug.com/459579 virtual/gpu/fast/canvas/canvas-composite-transformclip.html [ ImageOnlyFailure ] - # END OVERRIDES HERE (this line ensures that the file is newline-terminated)
diff --git a/sky/tests/TestExpectations b/sky/tests/TestExpectations index 4b6c6c6..0e4f586 100644 --- a/sky/tests/TestExpectations +++ b/sky/tests/TestExpectations
@@ -41,3 +41,8 @@ crbug.com/2 modules/script-import.sky [ Skip ] crbug.com/2 parser/script.sky [ Skip ] crbug.com/2 services/iframe-service-provider.sky [ Skip ] + +# Started failing on DEPS roll. +# https://codereview.chromium.org/1001833005/ +https://github.com/domokit/mojo/issues/64 framework/flights-app-pixels.sky [ Skip ] +https://github.com/domokit/mojo/issues/64 lowlevel/layers.sky [ Skip ]
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 71e67ad..a839c45 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -338,7 +338,7 @@ { "test": "content_unittests", "args": ["--site-per-process"] }, { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] }, { "test": "unit_tests", "args": ["--site-per-process"] }, - { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*"] } + { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] } ] }, "Site Isolation Win": { @@ -346,7 +346,7 @@ { "test": "content_unittests", "args": ["--site-per-process"] }, { "test": "content_browsertests", "args": ["--site-per-process", "--gtest_filter=-*.AllowTargetedNavigationsAfterSwap:*.SupportCrossProcessPostMessage:*.DisownOpener:*.DontPreemptNavigationWithFrameTreeUpdate:*.ProcessExitWithSwappedOutViews:*.SupportCrossProcessPostMessageWithMessagePort"] }, { "test": "unit_tests", "args": ["--site-per-process"] }, - { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*"] } + { "test": "browser_tests", "args": ["--site-per-process", "--gtest_filter=-AppApiTest.*:AutofillDialogControllerTest.*:BlockedAppApiTest.*:BookmarkOverrideTest.*:BrowserTest.OtherRedirectsDontForkProcess:ChromeAppAPITest.*:ChromeRenderProcessHostTest.*:ChromeRenderProcessHostTestWithCommandLine.*:DevToolsExperimentalExtensionTest.*:DevToolsExtensionTest.*:DnsProbeBrowserTest.*:ErrorPageTest.*:ExecuteScriptApiTest.ExecuteScriptPermissions:ExtensionApiTest.ContentScriptExtensionIframe:ExtensionApiTest.ContentScriptOtherExtensions:ExtensionApiTest.ContentScriptExtensionProcess:ExtensionApiTest.TabsOnUpdated:ExtensionApiTest.WindowOpenPopupIframe:ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded:ExtensionCrxInstallerTest.InstallDelayedUntilNextUpdate:ExtensionOptionsApiTest.ExtensionCanEmbedOwnOptions:ExtensionSettingsApiTest.SimpleTest:ExtensionWebUITest.CanEmbedExtensionOptions:ExtensionWebUITest.ReceivesExtensionOptionsOnClose:ExternallyConnectableMessagingTest.*:GeolocationBrowserTest.*:HistoryBrowserTest.*:InlineLoginUISafeIframeBrowserTest.*:IsolatedAppTest.*:LaunchWebAuthFlowFunctionTest.*:MimeHandlerViewTest.*:NaClBrowserTestNonSfiMode.*:OptionsUIBrowserTest.*:PhishingClassifierTest.*:PhishingDOMFeatureExtractorTest.*:PlatformAppUrlRedirectorBrowserTest.*:PopupBlockerBrowserTest.*:PortForwardingTest.*:PrerenderBrowserTest.*:ProcessManagementTest.*:ProfileManagerBrowserTest.*:RedirectTest.*:ReferrerPolicyTest.*:SandboxStatusUITest.*:SSLUITest.*:SyncFileSystemApiTest.GetFileStatuses:SyncFileSystemTest.*:WebNavigationApiTest.CrossProcessFragment:WebNavigationApiTest.ServerRedirectSingleProcess:WebNavigationApiTest.CrossProcessHistory:WebViewDPITest.*:WebViewPluginTest.*:WebViewTest.*:ZoomControllerBrowserTest.*:*.NavigateFromNTPToOptionsInSameTab:*.ProfilesWithoutPagesNotLaunched:*.TabMove:*.WhitelistedExtension:*.NewTabPageURL:*.HomepageLocation:RestoreOnStartupPolicyTest*:ExtensionApiTest.ActiveTab:PhishingClassifierDelegateTest.*:WebUIWebViewBrowserTest.ExecuteScriptCode"] } ] }, "Browser Side Navigation Linux": {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index 6e748c7..e9f616a 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -41,20 +41,10 @@ }, "Mac 10.8 Perf (1)": { "scripts": [ - { - "name": "gpu_perftests", - "script": "gtest_perf_test.py", - "args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"] - } ] }, "Mac 10.9 Perf (1)": { "scripts": [ - { - "name": "gpu_perftests", - "script": "gtest_perf_test.py", - "args": ["gpu_perftests", "--test-launcher-print-test-stdio=always"] - } ] } }
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json index a469ddd..ed45362 100644 --- a/testing/buildbot/trybot_analyze_config.json +++ b/testing/buildbot/trybot_analyze_config.json
@@ -11,6 +11,7 @@ "build/linux/sysroot_ld_path.sh", "DEPS", "testing/buildbot/.*", + "testing/test_env.py", "tools/clang/blink_gc_plugin/CMakeLists.txt", "tools/whitespace.txt" ] @@ -34,7 +35,6 @@ "third_party/accessibility-audit/axs_testing.js", "third_party/hunspell_dictionaries/.*", "third_party/zlib/google/test/data/.*", - "tools/clang/scripts/plugin_flags.py", "tools/clang/scripts/update.py", "tools/clang/scripts/update.sh", "tools/metrics/histograms/histograms.xml",
diff --git a/testing/chromoting/chromoting_integration_tests.isolate b/testing/chromoting/chromoting_integration_tests.isolate index 82bf5f1..8dcbe5d 100644 --- a/testing/chromoting/chromoting_integration_tests.isolate +++ b/testing/chromoting/chromoting_integration_tests.isolate
@@ -68,6 +68,7 @@ 'files': [ '<(PRODUCT_DIR)/chrome_elf.dll', '<(PRODUCT_DIR)/ffmpegsumo.dll', + '<(PRODUCT_DIR)/libglesv2.dll', ], }, }],
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json index a335f78..6ca3384 100644 --- a/testing/commit_queue/config.json +++ b/testing/commit_queue/config.json
@@ -6,11 +6,12 @@ "launched": { "tryserver.chromium.linux": { "android_amp_rel_tests_recipe": ["defaulttests"], + "android_n5_rel_tests_recipe": ["defaulttests"], "cast_shell": ["defaulttests"], "cast_shell_apk": ["defaulttests"], - "linux_android_rel_ng": ["defaulttests"], "linux_arm_compile": ["defaulttests"], - "linux_chromium_asan_rel_ng": ["defaulttests"] + "linux_chromium_asan_rel_ng": ["defaulttests"], + "linux_chromium_chromeos_ozone_rel_ng": ["defaulttests"] }, "tryserver.chromium.mac": { "mac_chromium_gn_rel": ["defaulttests"] @@ -59,6 +60,7 @@ "android_chromium_gn_compile_rel": ["defaulttests"], "android_compile_rel": ["defaulttests"], "chromium_presubmit": ["defaulttests"], + "linux_android_rel_ng": ["defaulttests"], "linux_chromium_asan_rel": ["defaulttests"], "linux_chromium_chromeos_compile_dbg_ng": ["defaulttests"], "linux_chromium_chromeos_rel_ng": ["defaulttests"], @@ -67,7 +69,6 @@ "linux_chromium_gn_dbg": ["defaulttests"], "linux_chromium_gn_rel": ["defaulttests"], "linux_chromium_rel_ng": ["defaulttests"], - "android_rel_tests_recipe": ["defaulttests"], "android_arm64_dbg_recipe": ["defaulttests"], "android_clang_dbg_recipe": ["defaulttests"], "android_aosp": ["compile"],
diff --git a/testing/legion/examples/subprocess/subprocess_test.py b/testing/legion/examples/subprocess/subprocess_test.py index 0377800..1a28ddd 100755 --- a/testing/legion/examples/subprocess/subprocess_test.py +++ b/testing/legion/examples/subprocess/subprocess_test.py
@@ -32,7 +32,7 @@ self.task = self.CreateNewTask( isolated_hash=args.task_hash, - dimensions={'os': 'Ubuntu-14.04', 'pool': 'Legion'}, + dimensions={'os': 'Ubuntu-14.04', 'pool': 'Chromoting'}, idle_timeout_secs=90, connection_timeout_secs=90, verbosity=logging.DEBUG) self.task.Create() @@ -47,8 +47,10 @@ def TestMultipleProcesses(self): start = time.time() - sleep20 = self.task.rpc.subprocess.Popen(['sleep', '20']) - sleep10 = self.task.rpc.subprocess.Popen(['sleep', '10']) + sleep20 = self.task.rpc.subprocess.Process(['sleep', '20']) + self.task.rpc.subprocess.Start(sleep20) + sleep10 = self.task.rpc.subprocess.Process(['sleep', '10']) + self.task.rpc.subprocess.Start(sleep10) self.task.rpc.subprocess.Wait(sleep10) elapsed = time.time() - start @@ -63,16 +65,20 @@ def TestTerminate(self): start = time.time() - proc = self.task.rpc.subprocess.Popen(['sleep', '20']) - self.task.rpc.subprocess.Terminate(proc) # Implicitly deleted + proc = self.task.rpc.subprocess.Process(['sleep', '20']) + self.task.rpc.subprocess.Start(proc) + self.task.rpc.subprocess.Terminate(proc) try: self.task.rpc.subprocess.Wait(proc) except xmlrpclib.Fault: pass + finally: + self.task.rpc.subprocess.Delete(proc) assert time.time() - start < 20 def TestLs(self): - proc = self.task.rpc.subprocess.Popen(['ls']) + proc = self.task.rpc.subprocess.Process(['ls']) + self.task.rpc.subprocess.Start(proc) self.task.rpc.subprocess.Wait(proc) assert self.task.rpc.subprocess.GetReturncode(proc) == 0 assert 'task.isolate' in self.task.rpc.subprocess.ReadStdout(proc)
diff --git a/testing/legion/rpc_methods.py b/testing/legion/rpc_methods.py index 7f17e23..1a59f28 100644 --- a/testing/legion/rpc_methods.py +++ b/testing/legion/rpc_methods.py
@@ -41,6 +41,10 @@ logging.info('Echoing %s', message) return 'echo %s' % str(message) + def AbsPath(self, path): + """Returns the absolute path.""" + return os.path.abspath(path) + def Quit(self): """Call _server.shutdown in another thread. @@ -58,6 +62,10 @@ This non-blocking subprocess allows the caller to continue operating while also able to interact with this subprocess based on a key returned to the caller at the time of creation. + + Creation args are set via Set* methods called after calling Process but + before calling Start. This is due to a limitation of the XML-RPC + implementation not supporting keyword arguments. """ _processes = {} @@ -65,23 +73,38 @@ _creation_lock = threading.Lock() def __init__(self, cmd): - self.proc = subprocess42.Popen(cmd, stdout=subprocess42.PIPE, - stderr=subprocess42.PIPE) self.stdout = '' self.stderr = '' + self.cmd = cmd + self.proc = None + self.cwd = None + self.verbose = False + self.detached = False self.data_lock = threading.Lock() - threading.Thread(target=self._run).start() - def _run(self): + def __str__(self): + return '%r, cwd=%r, verbose=%r, detached=%r' % ( + self.cmd, self.cwd, self.verbose, self.detached) + + def _reader(self): for pipe, data in self.proc.yield_any(): with self.data_lock: if pipe == 'stdout': self.stdout += data + if self.verbose: + sys.stdout.write(data) else: self.stderr += data + if self.verbose: + sys.stderr.write(data) @classmethod - def Popen(cls, cmd): + def KillAll(cls): + for key in cls._processes: + cls.Kill(key) + + @classmethod + def Process(cls, cmd): with cls._creation_lock: key = 'Process%d' % cls._process_next_id cls._process_next_id += 1 @@ -90,18 +113,50 @@ cls._processes[key] = process return key + def _Start(self): + logging.info('Starting process %s', self) + self.proc = subprocess42.Popen(self.cmd, stdout=subprocess42.PIPE, + stderr=subprocess42.PIPE, + detached=self.detached, cwd=self.cwd) + threading.Thread(target=self._reader).start() + + @classmethod + def Start(cls, key): + cls._processes[key]._Start() + + @classmethod + def SetCwd(cls, key, cwd): + """Sets the process's cwd.""" + logging.debug('Setting %s cwd to %s', key, cwd) + cls._processes[key].cwd = cwd + + @classmethod + def SetDetached(cls, key): + """Creates a detached process.""" + logging.debug('Setting %s to run detached', key) + cls._processes[key].detached = True + + @classmethod + def SetVerbose(cls, key): + """Sets the stdout and stderr to be emitted locally.""" + logging.debug('Setting %s to be verbose', key) + cls._processes[key].verbose = True + @classmethod def Terminate(cls, key): - logging.debug('Terminating and deleting process %s', key) - return cls._processes.pop(key).proc.terminate() + logging.debug('Terminating process %s', key) + cls._processes[key].proc.terminate() @classmethod def Kill(cls, key): - logging.debug('Killing and deleting process %s', key) - return cls._processes.pop(key).proc.kill() + logging.debug('Killing process %s', key) + cls._processes[key].proc.kill() @classmethod def Delete(cls, key): + if cls.GetReturncode(key) is None: + logging.warning('Killing %s before deleting it', key) + cls.Kill(key) logging.debug('Deleting process %s', key) cls._processes.pop(key) @@ -139,6 +194,14 @@ return stderr @classmethod + def ReadOutput(cls, key): + """Returns the (stdout, stderr) since the last Read* call. + + See ReadStdout for additional details. + """ + return cls.ReadStdout(key), cls.ReadStderr(key) + + @classmethod def Wait(cls, key): return cls._processes[key].proc.wait()
diff --git a/testing/legion/run_task.py b/testing/legion/run_task.py index 6a55073..26c6e5c 100755 --- a/testing/legion/run_task.py +++ b/testing/legion/run_task.py
@@ -34,12 +34,13 @@ logging.info( 'Registering with registration server at %s using OTP "%s"', args.controller, args.otp) - server = common_lib.ConnectToServer(args.controller).RegisterTask( + common_lib.ConnectToServer(args.controller).RegisterTask( args.otp, common_lib.MY_IP) server = rpc_server.RPCServer(args.controller, args.idle_timeout) server.serve_forever() + logging.info('Server shutdown complete') return 0
diff --git a/testing/scripts/gtest_perf_test.py b/testing/scripts/gtest_perf_test.py index 5518cb1..6243a79 100755 --- a/testing/scripts/gtest_perf_test.py +++ b/testing/scripts/gtest_perf_test.py
@@ -31,6 +31,7 @@ '--builder-name', args.properties.get('buildername'), '--build-number', str(args.properties.get('buildnumber')), '--log-processor-output-file', tempfile_path, + '--test-type', test_suite, ] if 'android' == args.properties.get('target_platform'): @@ -43,7 +44,7 @@ '--verbose', ]) else: - gtest_args.extend(['--xvfb', '--test-type', test_suite]) + gtest_args.extend(['--xvfb']) gtest_args.extend(script_args) rc = common.run_runtest(args, gtest_args + filter_tests)
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index d44071e..d2fc5d4 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi
@@ -7,6 +7,7 @@ { 'variables': { 'boringssl_lib_sources': [ + 'err_data.c', 'src/crypto/aes/aes.c', 'src/crypto/aes/mode_wrappers.c', 'src/crypto/asn1/a_bitstr.c',
diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c new file mode 100644 index 0000000..65bc34f --- /dev/null +++ b/third_party/boringssl/err_data.c
@@ -0,0 +1,2570 @@ +/* Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + + /* This file was generated by err_data_generate.go. */ + +#include <openssl/base.h> +#include <openssl/err.h> +#include <openssl/type_check.h> + + +OPENSSL_COMPILE_ASSERT(ERR_LIB_NONE == 1, library_values_changed_1); +OPENSSL_COMPILE_ASSERT(ERR_LIB_SYS == 2, library_values_changed_2); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BN == 3, library_values_changed_3); +OPENSSL_COMPILE_ASSERT(ERR_LIB_RSA == 4, library_values_changed_4); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DH == 5, library_values_changed_5); +OPENSSL_COMPILE_ASSERT(ERR_LIB_EVP == 6, library_values_changed_6); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BUF == 7, library_values_changed_7); +OPENSSL_COMPILE_ASSERT(ERR_LIB_OBJ == 8, library_values_changed_8); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PEM == 9, library_values_changed_9); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DSA == 10, library_values_changed_10); +OPENSSL_COMPILE_ASSERT(ERR_LIB_X509 == 11, library_values_changed_11); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ASN1 == 12, library_values_changed_12); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CONF == 13, library_values_changed_13); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CRYPTO == 14, library_values_changed_14); +OPENSSL_COMPILE_ASSERT(ERR_LIB_EC == 15, library_values_changed_15); +OPENSSL_COMPILE_ASSERT(ERR_LIB_SSL == 16, library_values_changed_16); +OPENSSL_COMPILE_ASSERT(ERR_LIB_BIO == 17, library_values_changed_17); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS7 == 18, library_values_changed_18); +OPENSSL_COMPILE_ASSERT(ERR_LIB_PKCS8 == 19, library_values_changed_19); +OPENSSL_COMPILE_ASSERT(ERR_LIB_X509V3 == 20, library_values_changed_20); +OPENSSL_COMPILE_ASSERT(ERR_LIB_RAND == 21, library_values_changed_21); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ENGINE == 22, library_values_changed_22); +OPENSSL_COMPILE_ASSERT(ERR_LIB_OCSP == 23, library_values_changed_23); +OPENSSL_COMPILE_ASSERT(ERR_LIB_UI == 24, library_values_changed_24); +OPENSSL_COMPILE_ASSERT(ERR_LIB_COMP == 25, library_values_changed_25); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDSA == 26, library_values_changed_26); +OPENSSL_COMPILE_ASSERT(ERR_LIB_ECDH == 27, library_values_changed_27); +OPENSSL_COMPILE_ASSERT(ERR_LIB_HMAC == 28, library_values_changed_28); +OPENSSL_COMPILE_ASSERT(ERR_LIB_DIGEST == 29, library_values_changed_29); +OPENSSL_COMPILE_ASSERT(ERR_LIB_CIPHER == 30, library_values_changed_30); +OPENSSL_COMPILE_ASSERT(ERR_LIB_USER == 31, library_values_changed_31); +OPENSSL_COMPILE_ASSERT(ERR_LIB_HKDF == 32, library_values_changed_32); +OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num); + +const uint32_t kOpenSSLFunctionValues[] = { + 0xc320540, + 0xc32854b, + 0xc330556, + 0xc338563, + 0xc34056d, + 0xc348577, + 0xc35057e, + 0xc35858a, + 0xc360591, + 0xc3685a7, + 0xc3705bc, + 0xc3785cd, + 0xc3805dd, + 0xc3885f7, + 0xc39060c, + 0xc39861b, + 0xc3a0634, + 0xc3a8648, + 0xc3b0654, + 0xc3b865b, + 0xc3c0663, + 0xc3c8671, + 0xc3d0679, + 0xc3d8681, + 0xc3e068c, + 0x10321744, + 0x1032975b, + 0x10331774, + 0x1033978a, + 0x1034179a, + 0x103497ad, + 0x103517bb, + 0x103597ca, + 0x103617ea, + 0x10369809, + 0x10371826, + 0x10379843, + 0x10381858, + 0x1038987a, + 0x10391899, + 0x103998b8, + 0x103a18cf, + 0x103a98e6, + 0x103b18ef, + 0x103b98fa, + 0x103c1914, + 0x103c991c, + 0x103d1924, + 0x103d992b, + 0x103e193e, + 0x103e9950, + 0x103f1963, + 0x103f996c, + 0x143209cb, + 0x143289d9, + 0x143309e5, + 0x143389f2, + 0x1832100b, + 0x18329023, + 0x18331045, + 0x18339057, + 0x18341068, + 0x18349081, + 0x18351092, + 0x183590a8, + 0x183610b8, + 0x183690cd, + 0x183710e6, + 0x183790f7, + 0x1838110d, + 0x1838911e, + 0x18391130, + 0x18399145, + 0x183a1157, + 0x183a9167, + 0x183b117c, + 0x183b9189, + 0x183c119b, + 0x183c91a9, + 0x183d11bc, + 0x183d91cc, + 0x183e11e1, + 0x183e91f2, + 0x183f1205, + 0x183f9214, + 0x18401224, + 0x18409231, + 0x18411240, + 0x18419251, + 0x18421264, + 0x18429276, + 0x18431288, + 0x18439299, + 0x184412aa, + 0x184492bb, + 0x184512cc, + 0x184592d9, + 0x184612e7, + 0x184692fa, + 0x1847130e, + 0x1847931b, + 0x1848132a, + 0x18489339, + 0x1849134a, + 0x18499357, + 0x184a1365, + 0x184a9376, + 0x184b1387, + 0x184b9395, + 0x184c13a5, + 0x184c93cb, + 0x184d13da, + 0x184d93ea, + 0x184e13fa, + 0x184e9409, + 0x1c320699, + 0x1c3286a5, + 0x1c3306b0, + 0x1c3386bc, + 0x2032141d, + 0x20329428, + 0x20331430, + 0x2033943c, + 0x24321448, + 0x24329456, + 0x24331468, + 0x24339477, + 0x2434148a, + 0x2434949d, + 0x243514b4, + 0x243594cc, + 0x243614da, + 0x243694f2, + 0x243714fb, + 0x2437950d, + 0x24381521, + 0x2438952e, + 0x24391544, + 0x2439955c, + 0x243a1574, + 0x243a957e, + 0x243b1593, + 0x243b95a1, + 0x243c15b9, + 0x243c95d0, + 0x243d15db, + 0x243d95e9, + 0x28320a2b, + 0x28328a3a, + 0x28330a45, + 0x28338a4a, + 0x28340a55, + 0x2c322850, + 0x2c32a85c, + 0x2c33286f, + 0x2c33a880, + 0x2c342899, + 0x2c34a8c1, + 0x2c3528d8, + 0x2c35a8f5, + 0x2c362912, + 0x2c36a92f, + 0x2c372948, + 0x2c37a961, + 0x2c382977, + 0x2c38a985, + 0x2c392997, + 0x2c39a9b4, + 0x2c3a29d1, + 0x2c3aa9df, + 0x2c3b29fd, + 0x2c3baa1b, + 0x2c3c2a36, + 0x2c3caa4a, + 0x2c3d2a5c, + 0x2c3daa6c, + 0x2c3e2a7a, + 0x2c3eaa8a, + 0x2c3f2a9a, + 0x2c3faab5, + 0x2c402ac6, + 0x2c40aae1, + 0x2c412af5, + 0x2c41ab08, + 0x2c422b27, + 0x2c42ab3b, + 0x2c432b4e, + 0x2c43ab5d, + 0x2c442b6c, + 0x2c44ab83, + 0x2c452b9e, + 0x2c45abb6, + 0x2c462bca, + 0x2c46abdd, + 0x2c472bee, + 0x2c47abff, + 0x2c482c10, + 0x2c48ac21, + 0x2c492c30, + 0x2c49ac3d, + 0x2c4a2c4a, + 0x2c4aac57, + 0x2c4b2c60, + 0x2c4bac74, + 0x2c4c2c83, + 0x2c4cac91, + 0x2c4d2cb3, + 0x2c4dacc4, + 0x2c4e2cd5, + 0x2c4eaca0, + 0x2c4f28b2, + 0x30320000, + 0x30328018, + 0x3033002c, + 0x30338042, + 0x3034005b, + 0x3034806c, + 0x3035007f, + 0x3035808f, + 0x3036009d, + 0x303680b3, + 0x303700c3, + 0x303780d8, + 0x303800e6, + 0x303880f7, + 0x30390103, + 0x3039810c, + 0x303a011d, + 0x303a812d, + 0x303b013a, + 0x303b8146, + 0x303c0157, + 0x303c8165, + 0x303d0176, + 0x303d8188, + 0x303e0199, + 0x303e81a8, + 0x303f01b9, + 0x303f81cd, + 0x304001df, + 0x304081ec, + 0x30410202, + 0x30418215, + 0x30420225, + 0x30428239, + 0x3043024a, + 0x3043825a, + 0x30440265, + 0x3044826d, + 0x3045027d, + 0x30458294, + 0x304602a1, + 0x304682b7, + 0x304702c9, + 0x304782d5, + 0x304802e1, + 0x304882ef, + 0x30490308, + 0x30498316, + 0x304a032b, + 0x304a8343, + 0x304b034d, + 0x304b8361, + 0x304c0372, + 0x304c8382, + 0x304d038f, + 0x304d83a0, + 0x304e03b0, + 0x304e83c2, + 0x304f03d3, + 0x304f83e2, + 0x305003f6, + 0x30508404, + 0x30510413, + 0x3051841c, + 0x3432095d, + 0x3432896d, + 0x34330978, + 0x34338985, + 0x3832098e, + 0x383289a1, + 0x383309ab, + 0x383389bd, + 0x3c320a5c, + 0x3c328a6a, + 0x3c330a81, + 0x3c338a95, + 0x3c340ab0, + 0x3c348ac1, + 0x3c350acd, + 0x3c358ae1, + 0x3c360af3, + 0x3c368b1c, + 0x3c370b29, + 0x3c378b36, + 0x3c380b44, + 0x3c388b51, + 0x3c390b5e, + 0x3c398b82, + 0x3c3a0b92, + 0x3c3a8baa, + 0x3c3b0bbf, + 0x3c3b8bd4, + 0x3c3c0be1, + 0x3c3c8bf4, + 0x3c3d0c07, + 0x3c3d8c2b, + 0x3c3e0c53, + 0x3c3e8c6c, + 0x3c3f0c82, + 0x3c3f8c8f, + 0x3c400ca2, + 0x3c408cb3, + 0x3c410cc4, + 0x3c418cdd, + 0x3c420cf6, + 0x3c428d0c, + 0x3c430d29, + 0x3c438d3f, + 0x3c440d5b, + 0x3c448d82, + 0x3c450da0, + 0x3c458dba, + 0x3c460dd2, + 0x3c468dea, + 0x3c470e15, + 0x3c478e40, + 0x3c480e61, + 0x3c488e8a, + 0x3c490ea5, + 0x3c498ec0, + 0x3c4a0ecd, + 0x3c4a8ee4, + 0x3c4b0efb, + 0x3c4b8f24, + 0x3c4c0f34, + 0x3c4c8f40, + 0x3c4d0f58, + 0x3c4d8f6b, + 0x3c4e0f7c, + 0x3c4e8f8d, + 0x3c4f0f9d, + 0x40321977, + 0x40329991, + 0x4033199d, + 0x403399b5, + 0x403419d3, + 0x403499f2, + 0x40351a09, + 0x40359a25, + 0x40361a41, + 0x40369a5b, + 0x40371a7a, + 0x40379a99, + 0x40381ab1, + 0x40389ace, + 0x40391af1, + 0x40399b0e, + 0x403a1b2c, + 0x403a9b3c, + 0x403b1b51, + 0x403b9b6d, + 0x403c1b87, + 0x403c9b92, + 0x403d1bb5, + 0x403d9bd9, + 0x403e1bef, + 0x403e9bf9, + 0x403f1c05, + 0x403f9c16, + 0x40401c2e, + 0x40409c36, + 0x40411c3f, + 0x40419c48, + 0x40421c58, + 0x40429c6c, + 0x40431c77, + 0x40439c83, + 0x40441c9e, + 0x40449caa, + 0x40451cb7, + 0x40459cca, + 0x40461ce2, + 0x40469cfa, + 0x40471d10, + 0x40479d2b, + 0x40481d46, + 0x40489d5a, + 0x40491d73, + 0x40499d8c, + 0x404a1da6, + 0x404a9db0, + 0x404b1dc0, + 0x404b9de1, + 0x404c1dfc, + 0x404c9e0a, + 0x404d1e17, + 0x404d9e2b, + 0x404e1e43, + 0x404e9e51, + 0x404f1e7b, + 0x404f9e92, + 0x40501ea4, + 0x40509ed5, + 0x40511f06, + 0x40519f1b, + 0x40521f2c, + 0x40529f4c, + 0x40531f67, + 0x40539f77, + 0x40541f83, + 0x40549f96, + 0x40551fac, + 0x40559fca, + 0x40561fd7, + 0x40569fe1, + 0x40571fef, + 0x4057a00a, + 0x40582025, + 0x4058a044, + 0x40592059, + 0x4059a06e, + 0x405a208b, + 0x405aa09f, + 0x405b20bb, + 0x405ba0d1, + 0x405c20ee, + 0x405ca100, + 0x405d2117, + 0x405da128, + 0x405e2144, + 0x405ea158, + 0x405f2168, + 0x405fa184, + 0x40602199, + 0x4060a1af, + 0x406121cc, + 0x4061a1e5, + 0x406221f8, + 0x4062a201, + 0x40632211, + 0x4063a21d, + 0x40642233, + 0x4064a251, + 0x40652266, + 0x4065a283, + 0x4066229a, + 0x4066a2b8, + 0x406722d5, + 0x4067a2ec, + 0x4068230a, + 0x4068a321, + 0x40692339, + 0x4069a34a, + 0x406a235d, + 0x406aa370, + 0x406b2384, + 0x406ba3a8, + 0x406c23c3, + 0x406ca3e4, + 0x406d2408, + 0x406da423, + 0x406e2444, + 0x406ea459, + 0x406f2472, + 0x406fa47f, + 0x4070248d, + 0x4070a49a, + 0x407124b7, + 0x4071a4d7, + 0x407224f2, + 0x4072a50b, + 0x40732522, + 0x4073a53c, + 0x40742560, + 0x4074a576, + 0x4075258a, + 0x4075a59f, + 0x407625b9, + 0x4076a5cb, + 0x407725e0, + 0x4077a606, + 0x40782623, + 0x4078a646, + 0x4079266c, + 0x4079a689, + 0x407a26ac, + 0x407aa6c8, + 0x407b26e4, + 0x407ba6f6, + 0x407c2703, + 0x407ca710, + 0x407d272d, + 0x407da744, + 0x407e2760, + 0x407ea776, + 0x407f278e, + 0x407fa7a1, + 0x408027b6, + 0x4080a7cf, + 0x408127ed, + 0x4081a80d, + 0x40822816, + 0x4082a832, + 0x4083283b, + 0x40839e60, + 0x40841eef, + 0x40849ebf, + 0x4432042a, + 0x4432843c, + 0x44330445, + 0x4433844d, + 0x4434045a, + 0x4434846a, + 0x44350485, + 0x443584a5, + 0x443604c1, + 0x443684e2, + 0x443704e9, + 0x443784f7, + 0x44380501, + 0x4438850d, + 0x44390517, + 0x44398522, + 0x443a052c, + 0x443a8536, + 0x4c3215f1, + 0x4c329600, + 0x4c33160f, + 0x4c339628, + 0x4c341643, + 0x4c34965f, + 0x4c351671, + 0x4c35967f, + 0x4c361694, + 0x4c3696a5, + 0x4c3716b3, + 0x4c3796c1, + 0x4c3816d3, + 0x4c3896e3, + 0x4c3916ed, + 0x4c399705, + 0x4c3a171d, + 0x4c3a9730, + 0x50322ce6, + 0x5032acfb, + 0x50332d0c, + 0x5033ad1f, + 0x50342d30, + 0x5034ad43, + 0x50352d52, + 0x5035ad67, + 0x50362d77, + 0x5036ad86, + 0x50372d97, + 0x5037ada7, + 0x50382db8, + 0x5038adcb, + 0x50392ddd, + 0x5039adf3, + 0x503a2e05, + 0x503aae16, + 0x503b2e27, + 0x503bae38, + 0x503c2e43, + 0x503cae4f, + 0x503d2e5a, + 0x503dae65, + 0x503e2e72, + 0x503eae87, + 0x503f2e95, + 0x503faea9, + 0x50402ebc, + 0x5040aecd, + 0x50412ee7, + 0x5041aef6, + 0x50422eff, + 0x5042af0e, + 0x50432f20, + 0x5043af2c, + 0x50442f34, + 0x5044af47, + 0x50452f58, + 0x5045af6e, + 0x50462f7a, + 0x5046af8e, + 0x50472f9c, + 0x5047afb0, + 0x50482fca, + 0x5048afde, + 0x50492ff4, + 0x5049b00b, + 0x504a301d, + 0x504ab031, + 0x504b3046, + 0x504bb05d, + 0x504c3071, + 0x504cb07a, + 0x504d3082, + 0x504db091, + 0x504e30a1, + 0x68320fbe, + 0x68328fcf, + 0x68330fdf, + 0x68338fed, + 0x68340ffa, + 0x6c320fad, + 0x74320a06, + 0x74328a18, + 0x783206c9, + 0x783286fc, + 0x7833070e, + 0x78338720, + 0x78340734, + 0x78348748, + 0x78350766, + 0x78358778, + 0x7836078c, + 0x783687a0, + 0x783707b2, + 0x783787c4, + 0x783807d6, + 0x783887ed, + 0x78390804, + 0x7839881b, + 0x783a0837, + 0x783a8853, + 0x783b086f, + 0x783b8885, + 0x783c089b, + 0x783c88b1, + 0x783d08ce, + 0x783d88dd, + 0x783e08ec, + 0x783e88fb, + 0x783f0917, + 0x783f8925, + 0x78400933, + 0x78408941, + 0x7841094e, + 0x784186db, + 0x80321418, +}; + +const size_t kOpenSSLFunctionValuesLen = sizeof(kOpenSSLFunctionValues) / sizeof(kOpenSSLFunctionValues[0]); + +const char kOpenSSLFunctionStringData[] = + "ASN1_BIT_STRING_set_bit\0" + "ASN1_ENUMERATED_set\0" + "ASN1_ENUMERATED_to_BN\0" + "ASN1_GENERALIZEDTIME_adj\0" + "ASN1_INTEGER_set\0" + "ASN1_INTEGER_to_BN\0" + "ASN1_OBJECT_new\0" + "ASN1_PCTX_new\0" + "ASN1_STRING_TABLE_add\0" + "ASN1_STRING_set\0" + "ASN1_STRING_type_new\0" + "ASN1_TIME_adj\0" + "ASN1_UTCTIME_adj\0" + "ASN1_d2i_fp\0" + "ASN1_dup\0" + "ASN1_generate_v3\0" + "ASN1_get_object\0" + "ASN1_i2d_bio\0" + "ASN1_i2d_fp\0" + "ASN1_item_d2i_fp\0" + "ASN1_item_dup\0" + "ASN1_item_ex_d2i\0" + "ASN1_item_i2d_bio\0" + "ASN1_item_i2d_fp\0" + "ASN1_item_pack\0" + "ASN1_item_unpack\0" + "ASN1_mbstring_ncopy\0" + "ASN1_template_new\0" + "BIO_new_NDEF\0" + "BN_to_ASN1_ENUMERATED\0" + "BN_to_ASN1_INTEGER\0" + "a2d_ASN1_OBJECT\0" + "a2i_ASN1_ENUMERATED\0" + "a2i_ASN1_INTEGER\0" + "a2i_ASN1_STRING\0" + "append_exp\0" + "asn1_cb\0" + "asn1_check_tlen\0" + "asn1_collate_primitive\0" + "asn1_collect\0" + "asn1_d2i_ex_primitive\0" + "asn1_d2i_read_bio\0" + "asn1_do_adb\0" + "asn1_ex_c2i\0" + "asn1_find_end\0" + "asn1_item_ex_combine_new\0" + "asn1_str2type\0" + "asn1_template_ex_d2i\0" + "asn1_template_noexp_d2i\0" + "bitstr_cb\0" + "c2i_ASN1_BIT_STRING\0" + "c2i_ASN1_INTEGER\0" + "c2i_ASN1_OBJECT\0" + "collect_data\0" + "d2i_ASN1_BOOLEAN\0" + "d2i_ASN1_OBJECT\0" + "d2i_ASN1_UINTEGER\0" + "d2i_ASN1_UTCTIME\0" + "d2i_ASN1_bytes\0" + "d2i_ASN1_type_bytes\0" + "i2d_ASN1_TIME\0" + "i2d_PrivateKey\0" + "long_c2i\0" + "parse_tagging\0" + "BIO_callback_ctrl\0" + "BIO_ctrl\0" + "BIO_new\0" + "BIO_new_file\0" + "BIO_new_mem_buf\0" + "BIO_zero_copy_get_read_buf\0" + "BIO_zero_copy_get_read_buf_done\0" + "BIO_zero_copy_get_write_buf\0" + "BIO_zero_copy_get_write_buf_done\0" + "bio_io\0" + "bio_make_pair\0" + "bio_write\0" + "buffer_ctrl\0" + "conn_ctrl\0" + "conn_state\0" + "file_ctrl\0" + "file_read\0" + "mem_write\0" + "BN_CTX_get\0" + "BN_CTX_new\0" + "BN_CTX_start\0" + "BN_bn2dec\0" + "BN_bn2hex\0" + "BN_div\0" + "BN_div_recp\0" + "BN_exp\0" + "BN_generate_dsa_nonce\0" + "BN_generate_prime_ex\0" + "BN_mod_exp2_mont\0" + "BN_mod_exp_mont\0" + "BN_mod_exp_mont_consttime\0" + "BN_mod_exp_mont_word\0" + "BN_mod_inverse\0" + "BN_mod_inverse_no_branch\0" + "BN_mod_lshift_quick\0" + "BN_mod_sqrt\0" + "BN_new\0" + "BN_rand\0" + "BN_rand_range\0" + "BN_sqrt\0" + "BN_usub\0" + "bn_wexpand\0" + "mod_exp_recp\0" + "BUF_MEM_new\0" + "BUF_memdup\0" + "BUF_strndup\0" + "buf_mem_grow\0" + "EVP_AEAD_CTX_init\0" + "EVP_AEAD_CTX_init_with_direction\0" + "EVP_AEAD_CTX_open\0" + "EVP_AEAD_CTX_seal\0" + "EVP_CIPHER_CTX_copy\0" + "EVP_CIPHER_CTX_ctrl\0" + "EVP_CIPHER_CTX_set_key_length\0" + "EVP_CipherInit_ex\0" + "EVP_DecryptFinal_ex\0" + "EVP_EncryptFinal_ex\0" + "aead_aes_gcm_init\0" + "aead_aes_gcm_open\0" + "aead_aes_gcm_seal\0" + "aead_aes_key_wrap_init\0" + "aead_aes_key_wrap_open\0" + "aead_aes_key_wrap_seal\0" + "aead_chacha20_poly1305_init\0" + "aead_chacha20_poly1305_open\0" + "aead_chacha20_poly1305_seal\0" + "aead_rc4_md5_tls_init\0" + "aead_rc4_md5_tls_open\0" + "aead_rc4_md5_tls_seal\0" + "aead_ssl3_ensure_cipher_init\0" + "aead_ssl3_init\0" + "aead_ssl3_open\0" + "aead_ssl3_seal\0" + "aead_tls_ensure_cipher_init\0" + "aead_tls_init\0" + "aead_tls_open\0" + "aead_tls_seal\0" + "aes_init_key\0" + "aesni_init_key\0" + "CONF_parse_list\0" + "NCONF_load\0" + "def_load_bio\0" + "str_copy\0" + "CRYPTO_set_ex_data\0" + "get_class\0" + "get_func_pointers\0" + "get_new_index\0" + "DH_new_method\0" + "compute_key\0" + "generate_key\0" + "generate_parameters\0" + "EVP_DigestInit_ex\0" + "EVP_MD_CTX_copy_ex\0" + "DSA_new_method\0" + "dsa_sig_cb\0" + "sign\0" + "sign_setup\0" + "verify\0" + "EC_GROUP_copy\0" + "EC_GROUP_get_curve_GFp\0" + "EC_GROUP_get_degree\0" + "EC_GROUP_new_by_curve_name\0" + "EC_KEY_check_key\0" + "EC_KEY_copy\0" + "EC_KEY_generate_key\0" + "EC_KEY_new_method\0" + "EC_KEY_set_public_key_affine_coordinates\0" + "EC_POINT_add\0" + "EC_POINT_cmp\0" + "EC_POINT_copy\0" + "EC_POINT_dbl\0" + "EC_POINT_dup\0" + "EC_POINT_get_affine_coordinates_GFp\0" + "EC_POINT_invert\0" + "EC_POINT_is_at_infinity\0" + "EC_POINT_is_on_curve\0" + "EC_POINT_make_affine\0" + "EC_POINT_new\0" + "EC_POINT_oct2point\0" + "EC_POINT_point2oct\0" + "EC_POINT_set_affine_coordinates_GFp\0" + "EC_POINT_set_compressed_coordinates_GFp\0" + "EC_POINT_set_to_infinity\0" + "EC_POINTs_make_affine\0" + "compute_wNAF\0" + "d2i_ECPKParameters\0" + "d2i_ECParameters\0" + "d2i_ECPrivateKey\0" + "ec_GFp_mont_field_decode\0" + "ec_GFp_mont_field_encode\0" + "ec_GFp_mont_field_mul\0" + "ec_GFp_mont_field_set_to_one\0" + "ec_GFp_mont_field_sqr\0" + "ec_GFp_mont_group_set_curve\0" + "ec_GFp_simple_group_check_discriminant\0" + "ec_GFp_simple_group_set_curve\0" + "ec_GFp_simple_make_affine\0" + "ec_GFp_simple_oct2point\0" + "ec_GFp_simple_point2oct\0" + "ec_GFp_simple_point_get_affine_coordinates\0" + "ec_GFp_simple_point_set_affine_coordinates\0" + "ec_GFp_simple_points_make_affine\0" + "ec_GFp_simple_set_compressed_coordinates\0" + "ec_asn1_group2pkparameters\0" + "ec_asn1_pkparameters2group\0" + "ec_group_new\0" + "ec_group_new_curve_GFp\0" + "ec_group_new_from_data\0" + "ec_point_set_Jprojective_coordinates_GFp\0" + "ec_pre_comp_new\0" + "ec_wNAF_mul\0" + "ec_wNAF_precompute_mult\0" + "i2d_ECPKParameters\0" + "i2d_ECParameters\0" + "i2d_ECPrivateKey\0" + "i2o_ECPublicKey\0" + "o2i_ECPublicKey\0" + "ECDH_compute_key\0" + "ECDSA_do_sign_ex\0" + "ECDSA_do_verify\0" + "ECDSA_sign_ex\0" + "digest_to_bn\0" + "ecdsa_sign_setup\0" + "EVP_DigestSignAlgorithm\0" + "EVP_DigestVerifyInitFromAlgorithm\0" + "EVP_PKEY_CTX_ctrl\0" + "EVP_PKEY_CTX_dup\0" + "EVP_PKEY_copy_parameters\0" + "EVP_PKEY_decrypt\0" + "EVP_PKEY_decrypt_init\0" + "EVP_PKEY_derive\0" + "EVP_PKEY_derive_init\0" + "EVP_PKEY_derive_set_peer\0" + "EVP_PKEY_encrypt\0" + "EVP_PKEY_encrypt_init\0" + "EVP_PKEY_get1_DH\0" + "EVP_PKEY_get1_DSA\0" + "EVP_PKEY_get1_EC_KEY\0" + "EVP_PKEY_get1_RSA\0" + "EVP_PKEY_keygen\0" + "EVP_PKEY_keygen_init\0" + "EVP_PKEY_new\0" + "EVP_PKEY_set_type\0" + "EVP_PKEY_sign\0" + "EVP_PKEY_sign_init\0" + "EVP_PKEY_verify\0" + "EVP_PKEY_verify_init\0" + "check_padding_md\0" + "d2i_AutoPrivateKey\0" + "d2i_PrivateKey\0" + "do_EC_KEY_print\0" + "do_rsa_print\0" + "do_sigver_init\0" + "eckey_param2type\0" + "eckey_param_decode\0" + "eckey_priv_decode\0" + "eckey_priv_encode\0" + "eckey_pub_decode\0" + "eckey_pub_encode\0" + "eckey_type2param\0" + "evp_pkey_ctx_new\0" + "hmac_signctx\0" + "i2d_PublicKey\0" + "old_ec_priv_decode\0" + "old_rsa_priv_decode\0" + "pkey_ec_ctrl\0" + "pkey_ec_derive\0" + "pkey_ec_keygen\0" + "pkey_ec_paramgen\0" + "pkey_ec_sign\0" + "pkey_rsa_ctrl\0" + "pkey_rsa_decrypt\0" + "pkey_rsa_encrypt\0" + "pkey_rsa_sign\0" + "rsa_algor_to_md\0" + "rsa_digest_verify_init_from_algorithm\0" + "rsa_mgf1_to_md\0" + "rsa_priv_decode\0" + "rsa_priv_encode\0" + "rsa_pss_to_ctx\0" + "rsa_pub_decode\0" + "HKDF\0" + "OBJ_create\0" + "OBJ_dup\0" + "OBJ_nid2obj\0" + "OBJ_txt2obj\0" + "PEM_ASN1_read\0" + "PEM_ASN1_read_bio\0" + "PEM_ASN1_write\0" + "PEM_ASN1_write_bio\0" + "PEM_X509_INFO_read\0" + "PEM_X509_INFO_read_bio\0" + "PEM_X509_INFO_write_bio\0" + "PEM_do_header\0" + "PEM_get_EVP_CIPHER_INFO\0" + "PEM_read\0" + "PEM_read_DHparams\0" + "PEM_read_PrivateKey\0" + "PEM_read_bio\0" + "PEM_read_bio_DHparams\0" + "PEM_read_bio_Parameters\0" + "PEM_read_bio_PrivateKey\0" + "PEM_write\0" + "PEM_write_PrivateKey\0" + "PEM_write_bio\0" + "d2i_PKCS8PrivateKey_bio\0" + "d2i_PKCS8PrivateKey_fp\0" + "do_pk8pkey\0" + "do_pk8pkey_fp\0" + "load_iv\0" + "EVP_PKCS82PKEY\0" + "EVP_PKEY2PKCS8\0" + "PKCS12_get_key_and_certs\0" + "PKCS12_handle_content_info\0" + "PKCS12_handle_content_infos\0" + "PKCS5_pbe2_set_iv\0" + "PKCS5_pbe_set\0" + "PKCS5_pbe_set0_algor\0" + "PKCS5_pbkdf2_set\0" + "PKCS8_decrypt\0" + "PKCS8_encrypt\0" + "PKCS8_encrypt_pbe\0" + "pbe_cipher_init\0" + "pbe_crypt\0" + "pkcs12_item_decrypt_d2i\0" + "pkcs12_item_i2d_encrypt\0" + "pkcs12_key_gen_raw\0" + "pkcs12_pbe_keyivgen\0" + "BN_BLINDING_convert_ex\0" + "BN_BLINDING_create_param\0" + "BN_BLINDING_invert_ex\0" + "BN_BLINDING_new\0" + "BN_BLINDING_update\0" + "RSA_check_key\0" + "RSA_new_method\0" + "RSA_padding_add_PKCS1_OAEP_mgf1\0" + "RSA_padding_add_PKCS1_PSS_mgf1\0" + "RSA_padding_add_PKCS1_type_1\0" + "RSA_padding_add_PKCS1_type_2\0" + "RSA_padding_add_none\0" + "RSA_padding_check_PKCS1_OAEP_mgf1\0" + "RSA_padding_check_PKCS1_type_1\0" + "RSA_padding_check_PKCS1_type_2\0" + "RSA_padding_check_none\0" + "RSA_recover_crt_params\0" + "RSA_sign\0" + "RSA_verify\0" + "RSA_verify_PKCS1_PSS_mgf1\0" + "decrypt\0" + "encrypt\0" + "keygen\0" + "pkcs1_prefixed_msg\0" + "private_transform\0" + "rsa_setup_blinding\0" + "sign_raw\0" + "verify_raw\0" + "SSL_CTX_check_private_key\0" + "SSL_CTX_new\0" + "SSL_CTX_set_cipher_list\0" + "SSL_CTX_set_cipher_list_tls11\0" + "SSL_CTX_set_session_id_context\0" + "SSL_CTX_use_PrivateKey\0" + "SSL_CTX_use_PrivateKey_ASN1\0" + "SSL_CTX_use_PrivateKey_file\0" + "SSL_CTX_use_RSAPrivateKey\0" + "SSL_CTX_use_RSAPrivateKey_ASN1\0" + "SSL_CTX_use_RSAPrivateKey_file\0" + "SSL_CTX_use_certificate\0" + "SSL_CTX_use_certificate_ASN1\0" + "SSL_CTX_use_certificate_chain_file\0" + "SSL_CTX_use_certificate_file\0" + "SSL_CTX_use_psk_identity_hint\0" + "SSL_SESSION_new\0" + "SSL_SESSION_print_fp\0" + "SSL_SESSION_set1_id_context\0" + "SSL_SESSION_to_bytes_full\0" + "SSL_accept\0" + "SSL_add_dir_cert_subjects_to_stack\0" + "SSL_add_file_cert_subjects_to_stack\0" + "SSL_check_private_key\0" + "SSL_clear\0" + "SSL_connect\0" + "SSL_do_handshake\0" + "SSL_load_client_CA_file\0" + "SSL_new\0" + "SSL_peek\0" + "SSL_read\0" + "SSL_renegotiate\0" + "SSL_set_cipher_list\0" + "SSL_set_fd\0" + "SSL_set_rfd\0" + "SSL_set_session_id_context\0" + "SSL_set_wfd\0" + "SSL_shutdown\0" + "SSL_use_PrivateKey\0" + "SSL_use_PrivateKey_ASN1\0" + "SSL_use_PrivateKey_file\0" + "SSL_use_RSAPrivateKey\0" + "SSL_use_RSAPrivateKey_ASN1\0" + "SSL_use_RSAPrivateKey_file\0" + "SSL_use_certificate\0" + "SSL_use_certificate_ASN1\0" + "SSL_use_certificate_file\0" + "SSL_use_psk_identity_hint\0" + "SSL_write\0" + "d2i_SSL_SESSION\0" + "d2i_SSL_SESSION_get_octet_string\0" + "d2i_SSL_SESSION_get_string\0" + "do_ssl3_write\0" + "dtls1_accept\0" + "dtls1_buffer_record\0" + "dtls1_check_timeout_num\0" + "dtls1_connect\0" + "dtls1_do_write\0" + "dtls1_get_buffered_message\0" + "dtls1_get_hello_verify\0" + "dtls1_get_message\0" + "dtls1_get_message_fragment\0" + "dtls1_hm_fragment_new\0" + "dtls1_preprocess_fragment\0" + "dtls1_process_fragment\0" + "dtls1_process_record\0" + "dtls1_read_bytes\0" + "dtls1_send_hello_verify_request\0" + "dtls1_write_app_data_bytes\0" + "i2d_SSL_SESSION\0" + "ssl3_accept\0" + "ssl3_callback_ctrl\0" + "ssl3_cert_verify_hash\0" + "ssl3_check_cert_and_algorithm\0" + "ssl3_connect\0" + "ssl3_ctrl\0" + "ssl3_ctx_ctrl\0" + "ssl3_digest_cached_records\0" + "ssl3_do_change_cipher_spec\0" + "ssl3_expect_change_cipher_spec\0" + "ssl3_get_cert_status\0" + "ssl3_get_cert_verify\0" + "ssl3_get_certificate_request\0" + "ssl3_get_channel_id\0" + "ssl3_get_client_certificate\0" + "ssl3_get_client_hello\0" + "ssl3_get_client_key_exchange\0" + "ssl3_get_finished\0" + "ssl3_get_initial_bytes\0" + "ssl3_get_message\0" + "ssl3_get_new_session_ticket\0" + "ssl3_get_next_proto\0" + "ssl3_get_record\0" + "ssl3_get_server_certificate\0" + "ssl3_get_server_done\0" + "ssl3_get_server_hello\0" + "ssl3_get_server_key_exchange\0" + "ssl3_get_v2_client_hello\0" + "ssl3_handshake_mac\0" + "ssl3_prf\0" + "ssl3_read_bytes\0" + "ssl3_read_n\0" + "ssl3_send_cert_verify\0" + "ssl3_send_certificate_request\0" + "ssl3_send_channel_id\0" + "ssl3_send_client_certificate\0" + "ssl3_send_client_hello\0" + "ssl3_send_client_key_exchange\0" + "ssl3_send_server_certificate\0" + "ssl3_send_server_hello\0" + "ssl3_send_server_key_exchange\0" + "ssl3_setup_read_buffer\0" + "ssl3_setup_write_buffer\0" + "ssl3_write_bytes\0" + "ssl3_write_pending\0" + "ssl_add_cert_chain\0" + "ssl_add_cert_to_buf\0" + "ssl_add_clienthello_renegotiate_ext\0" + "ssl_add_clienthello_tlsext\0" + "ssl_add_clienthello_use_srtp_ext\0" + "ssl_add_serverhello_renegotiate_ext\0" + "ssl_add_serverhello_tlsext\0" + "ssl_add_serverhello_use_srtp_ext\0" + "ssl_build_cert_chain\0" + "ssl_bytes_to_cipher_list\0" + "ssl_cert_dup\0" + "ssl_cert_inst\0" + "ssl_cert_new\0" + "ssl_check_serverhello_tlsext\0" + "ssl_check_srvr_ecc_cert_and_alg\0" + "ssl_cipher_process_rulestr\0" + "ssl_cipher_strength_sort\0" + "ssl_create_cipher_list\0" + "ssl_ctx_log_master_secret\0" + "ssl_ctx_log_rsa_client_key_exchange\0" + "ssl_ctx_make_profiles\0" + "ssl_get_new_session\0" + "ssl_get_prev_session\0" + "ssl_get_server_cert_index\0" + "ssl_get_sign_pkey\0" + "ssl_init_wbio_buffer\0" + "ssl_parse_clienthello_renegotiate_ext\0" + "ssl_parse_clienthello_tlsext\0" + "ssl_parse_clienthello_use_srtp_ext\0" + "ssl_parse_serverhello_renegotiate_ext\0" + "ssl_parse_serverhello_tlsext\0" + "ssl_parse_serverhello_use_srtp_ext\0" + "ssl_scan_clienthello_tlsext\0" + "ssl_scan_serverhello_tlsext\0" + "ssl_sess_cert_new\0" + "ssl_set_cert\0" + "ssl_set_pkey\0" + "ssl_undefined_const_function\0" + "ssl_undefined_function\0" + "ssl_undefined_void_function\0" + "ssl_verify_cert_chain\0" + "tls12_check_peer_sigalg\0" + "tls1_aead_ctx_init\0" + "tls1_cert_verify_mac\0" + "tls1_change_cipher_state\0" + "tls1_change_cipher_state_aead\0" + "tls1_check_duplicate_extensions\0" + "tls1_enc\0" + "tls1_export_keying_material\0" + "tls1_prf\0" + "tls1_setup_key_block\0" + "ASN1_digest\0" + "ASN1_item_sign_ctx\0" + "ASN1_item_verify\0" + "NETSCAPE_SPKI_b64_decode\0" + "NETSCAPE_SPKI_b64_encode\0" + "PKCS7_get_CRLs\0" + "PKCS7_get_certificates\0" + "X509_ATTRIBUTE_create_by_NID\0" + "X509_ATTRIBUTE_create_by_OBJ\0" + "X509_ATTRIBUTE_create_by_txt\0" + "X509_ATTRIBUTE_get0_data\0" + "X509_ATTRIBUTE_set1_data\0" + "X509_CRL_add0_revoked\0" + "X509_CRL_diff\0" + "X509_CRL_print_fp\0" + "X509_EXTENSION_create_by_NID\0" + "X509_EXTENSION_create_by_OBJ\0" + "X509_INFO_new\0" + "X509_NAME_ENTRY_create_by_NID\0" + "X509_NAME_ENTRY_create_by_txt\0" + "X509_NAME_ENTRY_set_object\0" + "X509_NAME_add_entry\0" + "X509_NAME_oneline\0" + "X509_NAME_print\0" + "X509_PKEY_new\0" + "X509_PUBKEY_get\0" + "X509_PUBKEY_set\0" + "X509_REQ_check_private_key\0" + "X509_REQ_to_X509\0" + "X509_STORE_CTX_get1_issuer\0" + "X509_STORE_CTX_init\0" + "X509_STORE_CTX_new\0" + "X509_STORE_CTX_purpose_inherit\0" + "X509_STORE_add_cert\0" + "X509_STORE_add_crl\0" + "X509_TRUST_add\0" + "X509_TRUST_set\0" + "X509_check_private_key\0" + "X509_get_pubkey_parameters\0" + "X509_load_cert_crl_file\0" + "X509_load_cert_file\0" + "X509_load_crl_file\0" + "X509_print_ex_fp\0" + "X509_to_X509_REQ\0" + "X509_verify_cert\0" + "X509at_add1_attr\0" + "X509v3_add_ext\0" + "add_cert_dir\0" + "by_file_ctrl\0" + "check_policy\0" + "dir_ctrl\0" + "get_cert_by_subject\0" + "i2d_DSA_PUBKEY\0" + "i2d_EC_PUBKEY\0" + "i2d_RSA_PUBKEY\0" + "pkcs7_parse_header\0" + "x509_name_encode\0" + "x509_name_ex_d2i\0" + "x509_name_ex_new\0" + "SXNET_add_id_INTEGER\0" + "SXNET_add_id_asc\0" + "SXNET_add_id_ulong\0" + "SXNET_get_id_asc\0" + "SXNET_get_id_ulong\0" + "X509V3_EXT_add\0" + "X509V3_EXT_add_alias\0" + "X509V3_EXT_free\0" + "X509V3_EXT_i2d\0" + "X509V3_EXT_nconf\0" + "X509V3_add1_i2d\0" + "X509V3_add_value\0" + "X509V3_get_section\0" + "X509V3_get_string\0" + "X509V3_get_value_bool\0" + "X509V3_parse_list\0" + "X509_PURPOSE_add\0" + "X509_PURPOSE_set\0" + "a2i_GENERAL_NAME\0" + "copy_email\0" + "copy_issuer\0" + "do_dirname\0" + "do_ext_i2d\0" + "do_ext_nconf\0" + "gnames_from_sectname\0" + "hex_to_string\0" + "i2s_ASN1_ENUMERATED\0" + "i2s_ASN1_IA5STRING\0" + "i2s_ASN1_INTEGER\0" + "i2v_AUTHORITY_INFO_ACCESS\0" + "notice_section\0" + "nref_nos\0" + "policy_section\0" + "process_pci_value\0" + "r2i_certpol\0" + "r2i_pci\0" + "s2i_ASN1_IA5STRING\0" + "s2i_ASN1_INTEGER\0" + "s2i_ASN1_OCTET_STRING\0" + "s2i_skey_id\0" + "set_dist_point_name\0" + "string_to_hex\0" + "v2i_ASN1_BIT_STRING\0" + "v2i_AUTHORITY_INFO_ACCESS\0" + "v2i_AUTHORITY_KEYID\0" + "v2i_BASIC_CONSTRAINTS\0" + "v2i_EXTENDED_KEY_USAGE\0" + "v2i_GENERAL_NAMES\0" + "v2i_GENERAL_NAME_ex\0" + "v2i_NAME_CONSTRAINTS\0" + "v2i_POLICY_CONSTRAINTS\0" + "v2i_POLICY_MAPPINGS\0" + "v2i_crld\0" + "v2i_idp\0" + "v2i_issuer_alt\0" + "v2i_subject_alt\0" + "v3_generic_extension\0" + ""; + +const uint32_t kOpenSSLReasonValues[] = { + 0xc3207ba, + 0xc3287c7, + 0xc3307d6, + 0xc3387e6, + 0xc3407f5, + 0xc34880e, + 0xc35081a, + 0xc358837, + 0xc360849, + 0xc368857, + 0xc370867, + 0xc378874, + 0xc380884, + 0xc38888f, + 0xc3908a5, + 0xc3988b4, + 0xc3a08c8, + 0x10321417, + 0x10329423, + 0x1033143c, + 0x1033944f, + 0x10340da9, + 0x10349462, + 0x10351477, + 0x1035948a, + 0x103614a3, + 0x103694b8, + 0x103714d6, + 0x103794e5, + 0x10381501, + 0x1038951c, + 0x1039152b, + 0x10399547, + 0x103a1562, + 0x103a9579, + 0x103b158a, + 0x103b959e, + 0x103c15bd, + 0x103c95cc, + 0x103d15e3, + 0x103d95f6, + 0x103e0b5f, + 0x103e9609, + 0x103f161c, + 0x103f9636, + 0x10401646, + 0x1040965a, + 0x10411670, + 0x10419688, + 0x1042169d, + 0x104296b1, + 0x104316c3, + 0x104385d0, + 0x104408b4, + 0x104496d8, + 0x104516ef, + 0x10459704, + 0x10461712, + 0x14320b42, + 0x14328b50, + 0x14330b5f, + 0x14338b71, + 0x18320083, + 0x18328dff, + 0x18330e15, + 0x18338094, + 0x18340e2d, + 0x18348e41, + 0x18350e56, + 0x18358e78, + 0x18360e90, + 0x18368ea5, + 0x18370eb8, + 0x18378ecc, + 0x18380ef0, + 0x18388efe, + 0x18390f14, + 0x18398f28, + 0x183a0f38, + 0x183a89cc, + 0x183b0f48, + 0x183b8f5d, + 0x183c0f74, + 0x183c8f88, + 0x183d0f9c, + 0x183d8fac, + 0x183e0b8e, + 0x183e8fb9, + 0x183f0fcb, + 0x183f8fd6, + 0x18400fe6, + 0x18408ff7, + 0x18411008, + 0x1841901a, + 0x18421043, + 0x1842905c, + 0x1843106b, + 0x1843907f, + 0x184410a0, + 0x184490b8, + 0x184510d4, + 0x184590ea, + 0x18461105, + 0x1846866b, + 0x18471120, + 0x1847913b, + 0x20321162, + 0x2432116e, + 0x243288fa, + 0x24331180, + 0x2433918d, + 0x2434119a, + 0x243491ac, + 0x243511bb, + 0x243591d8, + 0x243611e5, + 0x243691f3, + 0x24371201, + 0x2437920f, + 0x24381218, + 0x24389225, + 0x24391238, + 0x28320b82, + 0x28328b8e, + 0x28330b5f, + 0x28338ba1, + 0x2c3229d2, + 0x2c32a9e0, + 0x2c3329f2, + 0x2c33aa04, + 0x2c342a18, + 0x2c34aa2a, + 0x2c352a45, + 0x2c35aa57, + 0x2c362a6a, + 0x2c3682f3, + 0x2c372a77, + 0x2c37aa89, + 0x2c382a9c, + 0x2c38aaaa, + 0x2c392aba, + 0x2c39aacc, + 0x2c3a2ae0, + 0x2c3aaaf1, + 0x2c3b12f8, + 0x2c3bab02, + 0x2c3c2b16, + 0x2c3cab2c, + 0x2c3d2b45, + 0x2c3dab73, + 0x2c3e2b81, + 0x2c3eab99, + 0x2c3f2bb1, + 0x2c3fabbe, + 0x2c402be1, + 0x2c40ac00, + 0x2c411162, + 0x2c41ac11, + 0x2c422c24, + 0x2c4290d4, + 0x2c432c35, + 0x2c4386a2, + 0x2c442b62, + 0x30320000, + 0x30328015, + 0x3033001f, + 0x30338038, + 0x3034004a, + 0x30348064, + 0x3035006b, + 0x30358083, + 0x30360094, + 0x303680a1, + 0x303700b0, + 0x303780bd, + 0x303800d0, + 0x303880eb, + 0x30390100, + 0x30398114, + 0x303a0128, + 0x303a8139, + 0x303b0152, + 0x303b816f, + 0x303c017d, + 0x303c8191, + 0x303d01a1, + 0x303d81ba, + 0x303e01ca, + 0x303e81dd, + 0x303f01ec, + 0x303f81f8, + 0x3040020d, + 0x3040821d, + 0x30410234, + 0x30418241, + 0x30420254, + 0x30428263, + 0x30430278, + 0x30438299, + 0x304402ac, + 0x304482bf, + 0x304502d8, + 0x304582f3, + 0x30460310, + 0x30468329, + 0x30470337, + 0x30478348, + 0x30480357, + 0x3048836f, + 0x30490381, + 0x30498395, + 0x304a03b4, + 0x304a83c7, + 0x304b03d2, + 0x304b83e1, + 0x304c03f2, + 0x304c83fe, + 0x304d0414, + 0x304d8422, + 0x304e0438, + 0x304e844a, + 0x304f045c, + 0x304f846f, + 0x30500482, + 0x30508493, + 0x305104a3, + 0x305184bb, + 0x305204d0, + 0x305284e8, + 0x305304fc, + 0x30538514, + 0x3054052d, + 0x30548546, + 0x30550563, + 0x3055856e, + 0x30560586, + 0x30568596, + 0x305705a7, + 0x305785ba, + 0x305805d0, + 0x305885d9, + 0x305905ee, + 0x30598601, + 0x305a0610, + 0x305a8630, + 0x305b063f, + 0x305b864b, + 0x305c066b, + 0x305c8687, + 0x305d0698, + 0x305d86a2, + 0x34320abc, + 0x34328ad0, + 0x34330aed, + 0x34338b00, + 0x34340b0f, + 0x34348b2c, + 0x3c320083, + 0x3c328bb7, + 0x3c330bd0, + 0x3c338beb, + 0x3c340c08, + 0x3c348c23, + 0x3c350c3e, + 0x3c358c53, + 0x3c360c6c, + 0x3c368c84, + 0x3c370c95, + 0x3c378ca3, + 0x3c380cb0, + 0x3c388cc4, + 0x3c390b8e, + 0x3c398cd8, + 0x3c3a0cec, + 0x3c3a8874, + 0x3c3b0cfc, + 0x3c3b8d17, + 0x3c3c0d29, + 0x3c3c8d3f, + 0x3c3d0d49, + 0x3c3d8d5d, + 0x3c3e0d6b, + 0x3c3e8d79, + 0x40321729, + 0x4032973f, + 0x4033176d, + 0x40339777, + 0x4034178e, + 0x403497ac, + 0x403517bc, + 0x403597ce, + 0x403617db, + 0x403697e7, + 0x403717fc, + 0x40379811, + 0x40381823, + 0x4038982e, + 0x40391840, + 0x40398da9, + 0x403a1850, + 0x403a9863, + 0x403b1884, + 0x403b9895, + 0x403c18a5, + 0x403c8064, + 0x403d18b1, + 0x403d98cd, + 0x403e18e3, + 0x403e98f2, + 0x403f1905, + 0x403f991f, + 0x4040192d, + 0x40409942, + 0x40411956, + 0x40419973, + 0x4042198c, + 0x404299a7, + 0x404319c0, + 0x404399d3, + 0x404419e7, + 0x404499ff, + 0x40451a0f, + 0x40459a1d, + 0x40461a3b, + 0x40468094, + 0x40471a50, + 0x40479a62, + 0x40481a86, + 0x40489aa6, + 0x40491aba, + 0x40499acf, + 0x404a1ae8, + 0x404a9b0b, + 0x404b1b25, + 0x404b9b43, + 0x404c1b5e, + 0x404c9b78, + 0x404d1b8f, + 0x404d9bb7, + 0x404e1bce, + 0x404e9bea, + 0x404f1c06, + 0x404f9c27, + 0x40501c49, + 0x40509c65, + 0x40511c79, + 0x40519c86, + 0x40521c9d, + 0x40529cad, + 0x40531cbd, + 0x40539cd1, + 0x40541cec, + 0x40549cfc, + 0x40551d13, + 0x40559d22, + 0x40561d3d, + 0x40569d55, + 0x40571d71, + 0x40579d8a, + 0x40581d9d, + 0x40589db2, + 0x40591dd5, + 0x40599de3, + 0x405a1df0, + 0x405a9e09, + 0x405b1e21, + 0x405b9e34, + 0x405c1e49, + 0x405c9e5b, + 0x405d1e70, + 0x405d9e80, + 0x405e1e99, + 0x405e9ead, + 0x405f1ebd, + 0x405f9ed5, + 0x40601ee6, + 0x40609ef9, + 0x40611f0a, + 0x40619f28, + 0x40621f39, + 0x40629f46, + 0x40631f5d, + 0x40639f7d, + 0x40641f94, + 0x40649fa1, + 0x40651faf, + 0x40659fd1, + 0x40661ff9, + 0x4066a00e, + 0x40672025, + 0x4067a036, + 0x40682047, + 0x4068a058, + 0x4069206d, + 0x4069a084, + 0x406a2095, + 0x406aa0ae, + 0x406b20c9, + 0x406ba0e0, + 0x406c20f8, + 0x406ca119, + 0x406d212c, + 0x406da14d, + 0x406e2168, + 0x406ea183, + 0x406f21a4, + 0x406fa1ca, + 0x407021ea, + 0x4070a206, + 0x40712393, + 0x4071a3b6, + 0x407223cc, + 0x4072a3eb, + 0x40732403, + 0x4073a423, + 0x4074264d, + 0x4074a672, + 0x4075268d, + 0x4075a6ac, + 0x407626db, + 0x4076a703, + 0x4077271c, + 0x4077a73b, + 0x40782760, + 0x4078a777, + 0x4079278a, + 0x4079a7a7, + 0x407a0782, + 0x407aa7b9, + 0x407b27cc, + 0x407ba7e5, + 0x407c27fd, + 0x407c905c, + 0x407d2811, + 0x407da82b, + 0x407e283c, + 0x407ea850, + 0x407f285e, + 0x407fa879, + 0x40801225, + 0x4080a89e, + 0x408128c0, + 0x4081a8db, + 0x408228f0, + 0x4082a908, + 0x40832920, + 0x4083a937, + 0x4084294d, + 0x4084a959, + 0x4085296c, + 0x4085a981, + 0x40862993, + 0x4086a9a8, + 0x408729b1, + 0x40879ba5, + 0x41f422be, + 0x41f92350, + 0x41fe2243, + 0x41fea474, + 0x41ff2565, + 0x420322d7, + 0x420822f9, + 0x4208a335, + 0x42092227, + 0x4209a36f, + 0x420a227e, + 0x420aa25e, + 0x420b229e, + 0x420ba317, + 0x420c2581, + 0x420ca441, + 0x420d245b, + 0x420da492, + 0x421224ac, + 0x42172548, + 0x4217a4ee, + 0x421c2510, + 0x421f24cb, + 0x42212598, + 0x4226252b, + 0x422b2631, + 0x422ba5fa, + 0x422c2619, + 0x422ca5d4, + 0x422d25b3, + 0x443206ad, + 0x443286bc, + 0x443306c8, + 0x443386d6, + 0x443406e9, + 0x443486fa, + 0x44350701, + 0x4435870b, + 0x4436071e, + 0x44368734, + 0x44370746, + 0x44378753, + 0x44380762, + 0x4438876a, + 0x44390782, + 0x44398790, + 0x443a07a3, + 0x4c32124f, + 0x4c32925f, + 0x4c331272, + 0x4c339292, + 0x4c340094, + 0x4c3480b0, + 0x4c35129e, + 0x4c3592ac, + 0x4c3612c8, + 0x4c3692db, + 0x4c3712ea, + 0x4c3792f8, + 0x4c38130d, + 0x4c389319, + 0x4c391339, + 0x4c399363, + 0x4c3a137c, + 0x4c3a9395, + 0x4c3b05d0, + 0x4c3b93ae, + 0x4c3c13c0, + 0x4c3c93cf, + 0x4c3d105c, + 0x4c3d93e8, + 0x4c3e13f5, + 0x50322c47, + 0x5032ac56, + 0x50332c61, + 0x5033ac71, + 0x50342c8a, + 0x5034aca4, + 0x50352cb2, + 0x5035acc8, + 0x50362cda, + 0x5036acf0, + 0x50372d09, + 0x5037ad1c, + 0x50382d34, + 0x5038ad45, + 0x50392d5a, + 0x5039ad6e, + 0x503a2d8e, + 0x503aada4, + 0x503b2dbc, + 0x503badce, + 0x503c2dea, + 0x503cae01, + 0x503d2e1a, + 0x503dae30, + 0x503e2e3d, + 0x503eae53, + 0x503f2e65, + 0x503f8348, + 0x50402e78, + 0x5040ae88, + 0x50412ea2, + 0x5041aeb1, + 0x50422ecb, + 0x5042aee8, + 0x50432ef8, + 0x5043af08, + 0x50442f17, + 0x50448414, + 0x50452f2b, + 0x5045af49, + 0x50462f5c, + 0x5046af72, + 0x50472f84, + 0x5047af99, + 0x50482fbf, + 0x5048afcd, + 0x50492fe0, + 0x5049aff5, + 0x504a300b, + 0x504ab01b, + 0x504b303b, + 0x504bb04e, + 0x504c3071, + 0x504cb09f, + 0x504d30b1, + 0x504db0ce, + 0x504e30e9, + 0x504eb105, + 0x504f3117, + 0x504fb12e, + 0x5050313d, + 0x50508687, + 0x50513150, + 0x58320de7, + 0x68320da9, + 0x68328b8e, + 0x68330ba1, + 0x68338db7, + 0x68340dc7, + 0x6c320d85, + 0x6c328b71, + 0x6c330d90, + 0x74320980, + 0x783208e5, + 0x783288fa, + 0x78330906, + 0x78338083, + 0x78340915, + 0x7834892a, + 0x78350949, + 0x7835896b, + 0x78360980, + 0x78368996, + 0x783709a6, + 0x783789b9, + 0x783809cc, + 0x783889de, + 0x783909eb, + 0x78398a0a, + 0x783a0a1f, + 0x783a8a2d, + 0x783b0a37, + 0x783b8a4b, + 0x783c0a62, + 0x783c8a77, + 0x783d0a8e, + 0x783d8aa3, + 0x783e09f9, + 0x80321151, +}; + +const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); + +const char kOpenSSLReasonStringData[] = + "ASN1_LENGTH_MISMATCH\0" + "AUX_ERROR\0" + "BAD_GET_ASN1_OBJECT_CALL\0" + "BAD_OBJECT_HEADER\0" + "BMPSTRING_IS_WRONG_LENGTH\0" + "BN_LIB\0" + "BOOLEAN_IS_WRONG_LENGTH\0" + "BUFFER_TOO_SMALL\0" + "DECODE_ERROR\0" + "DEPTH_EXCEEDED\0" + "ENCODE_ERROR\0" + "ERROR_GETTING_TIME\0" + "EXPECTING_AN_ASN1_SEQUENCE\0" + "EXPECTING_AN_INTEGER\0" + "EXPECTING_AN_OBJECT\0" + "EXPECTING_A_BOOLEAN\0" + "EXPECTING_A_TIME\0" + "EXPLICIT_LENGTH_MISMATCH\0" + "EXPLICIT_TAG_NOT_CONSTRUCTED\0" + "FIELD_MISSING\0" + "FIRST_NUM_TOO_LARGE\0" + "HEADER_TOO_LONG\0" + "ILLEGAL_BITSTRING_FORMAT\0" + "ILLEGAL_BOOLEAN\0" + "ILLEGAL_CHARACTERS\0" + "ILLEGAL_FORMAT\0" + "ILLEGAL_HEX\0" + "ILLEGAL_IMPLICIT_TAG\0" + "ILLEGAL_INTEGER\0" + "ILLEGAL_NESTED_TAGGING\0" + "ILLEGAL_NULL\0" + "ILLEGAL_NULL_VALUE\0" + "ILLEGAL_OBJECT\0" + "ILLEGAL_OPTIONAL_ANY\0" + "ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE\0" + "ILLEGAL_TAGGED_ANY\0" + "ILLEGAL_TIME_VALUE\0" + "INTEGER_NOT_ASCII_FORMAT\0" + "INTEGER_TOO_LARGE_FOR_LONG\0" + "INVALID_BIT_STRING_BITS_LEFT\0" + "INVALID_BMPSTRING_LENGTH\0" + "INVALID_DIGIT\0" + "INVALID_MODIFIER\0" + "INVALID_NUMBER\0" + "INVALID_OBJECT_ENCODING\0" + "INVALID_SEPARATOR\0" + "INVALID_TIME_FORMAT\0" + "INVALID_UNIVERSALSTRING_LENGTH\0" + "INVALID_UTF8STRING\0" + "LIST_ERROR\0" + "MALLOC_FAILURE\0" + "MISSING_ASN1_EOS\0" + "MISSING_EOC\0" + "MISSING_SECOND_NUMBER\0" + "MISSING_VALUE\0" + "MSTRING_NOT_UNIVERSAL\0" + "MSTRING_WRONG_TAG\0" + "NESTED_ASN1_ERROR\0" + "NESTED_ASN1_STRING\0" + "NON_HEX_CHARACTERS\0" + "NOT_ASCII_FORMAT\0" + "NOT_ENOUGH_DATA\0" + "NO_MATCHING_CHOICE_TYPE\0" + "NULL_IS_WRONG_LENGTH\0" + "OBJECT_NOT_ASCII_FORMAT\0" + "ODD_NUMBER_OF_CHARS\0" + "SECOND_NUMBER_TOO_LARGE\0" + "SEQUENCE_LENGTH_MISMATCH\0" + "SEQUENCE_NOT_CONSTRUCTED\0" + "SEQUENCE_OR_SET_NEEDS_CONFIG\0" + "SHORT_LINE\0" + "STREAMING_NOT_SUPPORTED\0" + "STRING_TOO_LONG\0" + "STRING_TOO_SHORT\0" + "TAG_VALUE_TOO_HIGH\0" + "TIME_NOT_ASCII_FORMAT\0" + "TOO_LONG\0" + "TYPE_NOT_CONSTRUCTED\0" + "TYPE_NOT_PRIMITIVE\0" + "UNEXPECTED_EOC\0" + "UNIVERSALSTRING_IS_WRONG_LENGTH\0" + "UNKNOWN_FORMAT\0" + "UNKNOWN_TAG\0" + "UNSUPPORTED_ANY_DEFINED_BY_TYPE\0" + "UNSUPPORTED_PUBLIC_KEY_TYPE\0" + "UNSUPPORTED_TYPE\0" + "WRONG_TAG\0" + "WRONG_TYPE\0" + "BAD_FOPEN_MODE\0" + "BROKEN_PIPE\0" + "CONNECT_ERROR\0" + "ERROR_SETTING_NBIO\0" + "INVALID_ARGUMENT\0" + "IN_USE\0" + "KEEPALIVE\0" + "NBIO_CONNECT_ERROR\0" + "NO_HOSTNAME_SPECIFIED\0" + "NO_PORT_SPECIFIED\0" + "NO_SUCH_FILE\0" + "NULL_PARAMETER\0" + "SYS_LIB\0" + "UNABLE_TO_CREATE_SOCKET\0" + "UNINITIALIZED\0" + "UNSUPPORTED_METHOD\0" + "WRITE_TO_READ_ONLY_BIO\0" + "ARG2_LT_ARG3\0" + "BAD_RECIPROCAL\0" + "BIGNUM_TOO_LONG\0" + "BITS_TOO_SMALL\0" + "CALLED_WITH_EVEN_MODULUS\0" + "DIV_BY_ZERO\0" + "EXPAND_ON_STATIC_BIGNUM_DATA\0" + "INPUT_NOT_REDUCED\0" + "INVALID_RANGE\0" + "NEGATIVE_NUMBER\0" + "NOT_A_SQUARE\0" + "NOT_INITIALIZED\0" + "NO_INVERSE\0" + "PRIVATE_KEY_TOO_LARGE\0" + "P_IS_NOT_PRIME\0" + "TOO_MANY_ITERATIONS\0" + "TOO_MANY_TEMPORARY_VARIABLES\0" + "AES_KEY_SETUP_FAILED\0" + "BAD_DECRYPT\0" + "BAD_KEY_LENGTH\0" + "CTRL_NOT_IMPLEMENTED\0" + "CTRL_OPERATION_NOT_IMPLEMENTED\0" + "DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH\0" + "INITIALIZATION_ERROR\0" + "INPUT_NOT_INITIALIZED\0" + "INVALID_AD_SIZE\0" + "INVALID_KEY_LENGTH\0" + "INVALID_NONCE_SIZE\0" + "INVALID_OPERATION\0" + "IV_TOO_LARGE\0" + "NO_CIPHER_SET\0" + "NO_DIRECTION_SET\0" + "OUTPUT_ALIASES_INPUT\0" + "TAG_TOO_LARGE\0" + "TOO_LARGE\0" + "UNSUPPORTED_AD_SIZE\0" + "UNSUPPORTED_INPUT_SIZE\0" + "UNSUPPORTED_KEY_SIZE\0" + "UNSUPPORTED_NONCE_SIZE\0" + "UNSUPPORTED_TAG_SIZE\0" + "WRONG_FINAL_BLOCK_LENGTH\0" + "LIST_CANNOT_BE_NULL\0" + "MISSING_CLOSE_SQUARE_BRACKET\0" + "MISSING_EQUAL_SIGN\0" + "NO_CLOSE_BRACE\0" + "UNABLE_TO_CREATE_NEW_SECTION\0" + "VARIABLE_HAS_NO_VALUE\0" + "BAD_GENERATOR\0" + "INVALID_PUBKEY\0" + "MODULUS_TOO_LARGE\0" + "NO_PRIVATE_VALUE\0" + "BAD_Q_VALUE\0" + "MISSING_PARAMETERS\0" + "NEED_NEW_SETUP_VALUES\0" + "COORDINATES_OUT_OF_RANGE\0" + "D2I_ECPKPARAMETERS_FAILURE\0" + "EC_GROUP_NEW_BY_NAME_FAILURE\0" + "GROUP2PKPARAMETERS_FAILURE\0" + "I2D_ECPKPARAMETERS_FAILURE\0" + "INCOMPATIBLE_OBJECTS\0" + "INVALID_COMPRESSED_POINT\0" + "INVALID_COMPRESSION_BIT\0" + "INVALID_ENCODING\0" + "INVALID_FIELD\0" + "INVALID_FORM\0" + "INVALID_GROUP_ORDER\0" + "INVALID_PRIVATE_KEY\0" + "MISSING_PRIVATE_KEY\0" + "NON_NAMED_CURVE\0" + "PKPARAMETERS2GROUP_FAILURE\0" + "POINT_AT_INFINITY\0" + "POINT_IS_NOT_ON_CURVE\0" + "SLOT_FULL\0" + "UNDEFINED_GENERATOR\0" + "UNKNOWN_GROUP\0" + "UNKNOWN_ORDER\0" + "WRONG_ORDER\0" + "KDF_FAILED\0" + "POINT_ARITHMETIC_FAILURE\0" + "BAD_SIGNATURE\0" + "NOT_IMPLEMENTED\0" + "RANDOM_NUMBER_GENERATION_FAILED\0" + "OPERATION_NOT_SUPPORTED\0" + "COMMAND_NOT_SUPPORTED\0" + "CONTEXT_NOT_INITIALISED\0" + "DIFFERENT_KEY_TYPES\0" + "DIFFERENT_PARAMETERS\0" + "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\0" + "EXPECTING_AN_EC_KEY_KEY\0" + "EXPECTING_AN_RSA_KEY\0" + "EXPECTING_A_DH_KEY\0" + "EXPECTING_A_DSA_KEY\0" + "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0" + "INVALID_CURVE\0" + "INVALID_DIGEST_LENGTH\0" + "INVALID_DIGEST_TYPE\0" + "INVALID_KEYBITS\0" + "INVALID_MGF1_MD\0" + "INVALID_PADDING_MODE\0" + "INVALID_PSS_PARAMETERS\0" + "INVALID_PSS_SALTLEN\0" + "INVALID_SALT_LENGTH\0" + "INVALID_TRAILER\0" + "KEYS_NOT_SET\0" + "NO_DEFAULT_DIGEST\0" + "NO_KEY_SET\0" + "NO_MDC2_SUPPORT\0" + "NO_NID_FOR_CURVE\0" + "NO_OPERATION_SET\0" + "NO_PARAMETERS_SET\0" + "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0" + "OPERATON_NOT_INITIALIZED\0" + "UNKNOWN_DIGEST\0" + "UNKNOWN_MASK_DIGEST\0" + "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0" + "UNKNOWN_PUBLIC_KEY_TYPE\0" + "UNKNOWN_SIGNATURE_ALGORITHM\0" + "UNSUPPORTED_ALGORITHM\0" + "UNSUPPORTED_MASK_ALGORITHM\0" + "UNSUPPORTED_MASK_PARAMETER\0" + "UNSUPPORTED_SIGNATURE_TYPE\0" + "WRONG_PUBLIC_KEY_TYPE\0" + "OUTPUT_TOO_LARGE\0" + "UNKNOWN_NID\0" + "BAD_BASE64_DECODE\0" + "BAD_END_LINE\0" + "BAD_IV_CHARS\0" + "BAD_PASSWORD_READ\0" + "CIPHER_IS_NULL\0" + "ERROR_CONVERTING_PRIVATE_KEY\0" + "NOT_DEK_INFO\0" + "NOT_ENCRYPTED\0" + "NOT_PROC_TYPE\0" + "NO_START_LINE\0" + "READ_KEY\0" + "SHORT_HEADER\0" + "UNSUPPORTED_CIPHER\0" + "UNSUPPORTED_ENCRYPTION\0" + "BAD_PKCS12_DATA\0" + "BAD_PKCS12_VERSION\0" + "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0" + "CRYPT_ERROR\0" + "ENCRYPT_ERROR\0" + "ERROR_SETTING_CIPHER_PARAMS\0" + "INCORRECT_PASSWORD\0" + "KEYGEN_FAILURE\0" + "KEY_GEN_ERROR\0" + "METHOD_NOT_SUPPORTED\0" + "MISSING_MAC\0" + "MULTIPLE_PRIVATE_KEYS_IN_PKCS12\0" + "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED\0" + "PKCS12_TOO_DEEPLY_NESTED\0" + "PRIVATE_KEY_DECODE_ERROR\0" + "PRIVATE_KEY_ENCODE_ERROR\0" + "UNKNOWN_ALGORITHM\0" + "UNKNOWN_CIPHER\0" + "UNKNOWN_CIPHER_ALGORITHM\0" + "UNKNOWN_HASH\0" + "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\0" + "BAD_E_VALUE\0" + "BAD_FIXED_HEADER_DECRYPT\0" + "BAD_PAD_BYTE_COUNT\0" + "BAD_RSA_PARAMETERS\0" + "BLOCK_TYPE_IS_NOT_01\0" + "BN_NOT_INITIALIZED\0" + "CRT_PARAMS_ALREADY_GIVEN\0" + "CRT_VALUES_INCORRECT\0" + "DATA_LEN_NOT_EQUAL_TO_MOD_LEN\0" + "DATA_TOO_LARGE\0" + "DATA_TOO_LARGE_FOR_KEY_SIZE\0" + "DATA_TOO_LARGE_FOR_MODULUS\0" + "DATA_TOO_SMALL\0" + "DATA_TOO_SMALL_FOR_KEY_SIZE\0" + "DIGEST_TOO_BIG_FOR_RSA_KEY\0" + "D_E_NOT_CONGRUENT_TO_1\0" + "EMPTY_PUBLIC_KEY\0" + "FIRST_OCTET_INVALID\0" + "INCONSISTENT_SET_OF_CRT_VALUES\0" + "INTERNAL_ERROR\0" + "INVALID_MESSAGE_LENGTH\0" + "KEY_SIZE_TOO_SMALL\0" + "LAST_OCTET_INVALID\0" + "NO_PUBLIC_EXPONENT\0" + "NULL_BEFORE_BLOCK_MISSING\0" + "N_NOT_EQUAL_P_Q\0" + "OAEP_DECODING_ERROR\0" + "ONLY_ONE_OF_P_Q_GIVEN\0" + "OUTPUT_BUFFER_TOO_SMALL\0" + "PADDING_CHECK_FAILED\0" + "PKCS_DECODING_ERROR\0" + "SLEN_CHECK_FAILED\0" + "SLEN_RECOVERY_FAILED\0" + "UNKNOWN_ALGORITHM_TYPE\0" + "UNKNOWN_PADDING_TYPE\0" + "VALUE_MISSING\0" + "WRONG_SIGNATURE_LENGTH\0" + "APP_DATA_IN_HANDSHAKE\0" + "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\0" + "BAD_ALERT\0" + "BAD_CHANGE_CIPHER_SPEC\0" + "BAD_DATA_RETURNED_BY_CALLBACK\0" + "BAD_DH_P_LENGTH\0" + "BAD_DIGEST_LENGTH\0" + "BAD_ECC_CERT\0" + "BAD_ECPOINT\0" + "BAD_HANDSHAKE_LENGTH\0" + "BAD_HANDSHAKE_RECORD\0" + "BAD_HELLO_REQUEST\0" + "BAD_LENGTH\0" + "BAD_PACKET_LENGTH\0" + "BAD_RSA_ENCRYPT\0" + "BAD_SRTP_MKI_VALUE\0" + "BAD_SRTP_PROTECTION_PROFILE_LIST\0" + "BAD_SSL_FILETYPE\0" + "BAD_WRITE_RETRY\0" + "BIO_NOT_SET\0" + "CANNOT_SERIALIZE_PUBLIC_KEY\0" + "CA_DN_LENGTH_MISMATCH\0" + "CA_DN_TOO_LONG\0" + "CCS_RECEIVED_EARLY\0" + "CERTIFICATE_VERIFY_FAILED\0" + "CERT_CB_ERROR\0" + "CERT_LENGTH_MISMATCH\0" + "CHANNEL_ID_NOT_P256\0" + "CHANNEL_ID_SIGNATURE_INVALID\0" + "CIPHER_CODE_WRONG_LENGTH\0" + "CIPHER_OR_HASH_UNAVAILABLE\0" + "CLIENTHELLO_PARSE_FAILED\0" + "CLIENTHELLO_TLSEXT\0" + "CONNECTION_REJECTED\0" + "CONNECTION_TYPE_NOT_SET\0" + "COOKIE_MISMATCH\0" + "D2I_ECDSA_SIG\0" + "DATA_BETWEEN_CCS_AND_FINISHED\0" + "DATA_LENGTH_TOO_LONG\0" + "DECRYPTION_FAILED\0" + "DECRYPTION_FAILED_OR_BAD_RECORD_MAC\0" + "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\0" + "DIGEST_CHECK_FAILED\0" + "DTLS_MESSAGE_TOO_BIG\0" + "ECC_CERT_NOT_FOR_SIGNING\0" + "EMPTY_SRTP_PROTECTION_PROFILE_LIST\0" + "ENCRYPTED_LENGTH_TOO_LONG\0" + "ERROR_IN_RECEIVED_CIPHER_LIST\0" + "EVP_DIGESTSIGNFINAL_FAILED\0" + "EVP_DIGESTSIGNINIT_FAILED\0" + "EXCESSIVE_MESSAGE_SIZE\0" + "EXTRA_DATA_IN_MESSAGE\0" + "FRAGMENT_MISMATCH\0" + "GOT_A_FIN_BEFORE_A_CCS\0" + "GOT_CHANNEL_ID_BEFORE_A_CCS\0" + "GOT_NEXT_PROTO_BEFORE_A_CCS\0" + "GOT_NEXT_PROTO_WITHOUT_EXTENSION\0" + "HANDSHAKE_FAILURE_ON_CLIENT_HELLO\0" + "HANDSHAKE_RECORD_BEFORE_CCS\0" + "HTTPS_PROXY_REQUEST\0" + "HTTP_REQUEST\0" + "INAPPROPRIATE_FALLBACK\0" + "INVALID_COMMAND\0" + "INVALID_MESSAGE\0" + "INVALID_SSL_SESSION\0" + "INVALID_TICKET_KEYS_LENGTH\0" + "LENGTH_MISMATCH\0" + "LIBRARY_HAS_NO_CIPHERS\0" + "MISSING_DH_KEY\0" + "MISSING_ECDSA_SIGNING_CERT\0" + "MISSING_RSA_CERTIFICATE\0" + "MISSING_RSA_ENCRYPTING_CERT\0" + "MISSING_RSA_SIGNING_CERT\0" + "MISSING_TMP_DH_KEY\0" + "MISSING_TMP_ECDH_KEY\0" + "MIXED_SPECIAL_OPERATOR_WITH_GROUPS\0" + "MTU_TOO_SMALL\0" + "NESTED_GROUP\0" + "NO_CERTIFICATES_RETURNED\0" + "NO_CERTIFICATE_ASSIGNED\0" + "NO_CERTIFICATE_SET\0" + "NO_CIPHERS_AVAILABLE\0" + "NO_CIPHERS_PASSED\0" + "NO_CIPHERS_SPECIFIED\0" + "NO_CIPHER_MATCH\0" + "NO_COMPRESSION_SPECIFIED\0" + "NO_METHOD_SPECIFIED\0" + "NO_P256_SUPPORT\0" + "NO_PRIVATE_KEY_ASSIGNED\0" + "NO_RENEGOTIATION\0" + "NO_REQUIRED_DIGEST\0" + "NO_SHARED_CIPHER\0" + "NO_SHARED_SIGATURE_ALGORITHMS\0" + "NO_SRTP_PROFILES\0" + "NULL_SSL_CTX\0" + "NULL_SSL_METHOD_PASSED\0" + "OLD_SESSION_CIPHER_NOT_RETURNED\0" + "PACKET_LENGTH_TOO_LONG\0" + "PARSE_TLSEXT\0" + "PATH_TOO_LONG\0" + "PEER_DID_NOT_RETURN_A_CERTIFICATE\0" + "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0" + "PROTOCOL_IS_SHUTDOWN\0" + "PSK_IDENTITY_NOT_FOUND\0" + "PSK_NO_CLIENT_CB\0" + "PSK_NO_SERVER_CB\0" + "READ_BIO_NOT_SET\0" + "READ_TIMEOUT_EXPIRED\0" + "RECORD_LENGTH_MISMATCH\0" + "RECORD_TOO_LARGE\0" + "RENEGOTIATE_EXT_TOO_LONG\0" + "RENEGOTIATION_ENCODING_ERR\0" + "RENEGOTIATION_MISMATCH\0" + "REQUIRED_CIPHER_MISSING\0" + "SCSV_RECEIVED_WHEN_RENEGOTIATING\0" + "SERVERHELLO_TLSEXT\0" + "SESSION_ID_CONTEXT_UNINITIALIZED\0" + "SESSION_MAY_NOT_BE_CREATED\0" + "SIGNATURE_ALGORITHMS_ERROR\0" + "SRTP_COULD_NOT_ALLOCATE_PROFILES\0" + "SRTP_PROTECTION_PROFILE_LIST_TOO_LONG\0" + "SRTP_UNKNOWN_PROTECTION_PROFILE\0" + "SSL3_EXT_INVALID_SERVERNAME\0" + "SSL3_EXT_INVALID_SERVERNAME_TYPE\0" + "SSLV3_ALERT_BAD_CERTIFICATE\0" + "SSLV3_ALERT_BAD_RECORD_MAC\0" + "SSLV3_ALERT_CERTIFICATE_EXPIRED\0" + "SSLV3_ALERT_CERTIFICATE_REVOKED\0" + "SSLV3_ALERT_CERTIFICATE_UNKNOWN\0" + "SSLV3_ALERT_CLOSE_NOTIFY\0" + "SSLV3_ALERT_DECOMPRESSION_FAILURE\0" + "SSLV3_ALERT_HANDSHAKE_FAILURE\0" + "SSLV3_ALERT_ILLEGAL_PARAMETER\0" + "SSLV3_ALERT_NO_CERTIFICATE\0" + "SSLV3_ALERT_UNEXPECTED_MESSAGE\0" + "SSLV3_ALERT_UNSUPPORTED_CERTIFICATE\0" + "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\0" + "SSL_HANDSHAKE_FAILURE\0" + "SSL_SESSION_ID_CALLBACK_FAILED\0" + "SSL_SESSION_ID_CONFLICT\0" + "SSL_SESSION_ID_CONTEXT_TOO_LONG\0" + "SSL_SESSION_ID_HAS_BAD_LENGTH\0" + "TLSV1_ALERT_ACCESS_DENIED\0" + "TLSV1_ALERT_DECODE_ERROR\0" + "TLSV1_ALERT_DECRYPTION_FAILED\0" + "TLSV1_ALERT_DECRYPT_ERROR\0" + "TLSV1_ALERT_EXPORT_RESTRICTION\0" + "TLSV1_ALERT_INAPPROPRIATE_FALLBACK\0" + "TLSV1_ALERT_INSUFFICIENT_SECURITY\0" + "TLSV1_ALERT_INTERNAL_ERROR\0" + "TLSV1_ALERT_NO_RENEGOTIATION\0" + "TLSV1_ALERT_PROTOCOL_VERSION\0" + "TLSV1_ALERT_RECORD_OVERFLOW\0" + "TLSV1_ALERT_UNKNOWN_CA\0" + "TLSV1_ALERT_USER_CANCELLED\0" + "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0" + "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0" + "TLSV1_CERTIFICATE_UNOBTAINABLE\0" + "TLSV1_UNRECOGNIZED_NAME\0" + "TLSV1_UNSUPPORTED_EXTENSION\0" + "TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER\0" + "TLS_ILLEGAL_EXPORTER_LABEL\0" + "TLS_INVALID_ECPOINTFORMAT_LIST\0" + "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0" + "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\0" + "TOO_MANY_EMPTY_FRAGMENTS\0" + "UNABLE_TO_FIND_ECDH_PARAMETERS\0" + "UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS\0" + "UNEXPECTED_GROUP_CLOSE\0" + "UNEXPECTED_MESSAGE\0" + "UNEXPECTED_OPERATOR_IN_GROUP\0" + "UNEXPECTED_RECORD\0" + "UNKNOWN_ALERT_TYPE\0" + "UNKNOWN_CERTIFICATE_TYPE\0" + "UNKNOWN_CIPHER_RETURNED\0" + "UNKNOWN_CIPHER_TYPE\0" + "UNKNOWN_KEY_EXCHANGE_TYPE\0" + "UNKNOWN_PROTOCOL\0" + "UNKNOWN_SSL_VERSION\0" + "UNKNOWN_STATE\0" + "UNPROCESSED_HANDSHAKE_DATA\0" + "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\0" + "UNSUPPORTED_COMPRESSION_ALGORITHM\0" + "UNSUPPORTED_ELLIPTIC_CURVE\0" + "UNSUPPORTED_PROTOCOL\0" + "UNSUPPORTED_SSL_VERSION\0" + "USE_SRTP_NOT_NEGOTIATED\0" + "WRONG_CERTIFICATE_TYPE\0" + "WRONG_CIPHER_RETURNED\0" + "WRONG_CURVE\0" + "WRONG_MESSAGE_TYPE\0" + "WRONG_SIGNATURE_TYPE\0" + "WRONG_SSL_VERSION\0" + "WRONG_VERSION_NUMBER\0" + "X509_LIB\0" + "X509_VERIFICATION_SETUP_PROBLEMS\0" + "AKID_MISMATCH\0" + "BAD_PKCS7_VERSION\0" + "BAD_X509_FILETYPE\0" + "BASE64_DECODE_ERROR\0" + "CANT_CHECK_DH_KEY\0" + "CERT_ALREADY_IN_HASH_TABLE\0" + "CRL_ALREADY_DELTA\0" + "CRL_VERIFY_FAILURE\0" + "IDP_MISMATCH\0" + "INVALID_DIRECTORY\0" + "INVALID_FIELD_NAME\0" + "INVALID_TRUST\0" + "ISSUER_MISMATCH\0" + "KEY_TYPE_MISMATCH\0" + "KEY_VALUES_MISMATCH\0" + "LOADING_CERT_DIR\0" + "LOADING_DEFAULTS\0" + "NEWER_CRL_NOT_NEWER\0" + "NOT_PKCS7_SIGNED_DATA\0" + "NO_CERTIFICATES_INCLUDED\0" + "NO_CERT_SET_FOR_US_TO_VERIFY\0" + "NO_CRLS_INCLUDED\0" + "NO_CRL_NUMBER\0" + "PUBLIC_KEY_DECODE_ERROR\0" + "PUBLIC_KEY_ENCODE_ERROR\0" + "SHOULD_RETRY\0" + "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN\0" + "UNABLE_TO_GET_CERTS_PUBLIC_KEY\0" + "UNKNOWN_KEY_TYPE\0" + "UNKNOWN_PURPOSE_ID\0" + "UNKNOWN_TRUST_ID\0" + "WRONG_LOOKUP_TYPE\0" + "BAD_IP_ADDRESS\0" + "BAD_OBJECT\0" + "BN_DEC2BN_ERROR\0" + "BN_TO_ASN1_INTEGER_ERROR\0" + "CANNOT_FIND_FREE_FUNCTION\0" + "DIRNAME_ERROR\0" + "DISTPOINT_ALREADY_SET\0" + "DUPLICATE_ZONE_ID\0" + "ERROR_CONVERTING_ZONE\0" + "ERROR_CREATING_EXTENSION\0" + "ERROR_IN_EXTENSION\0" + "EXPECTED_A_SECTION_NAME\0" + "EXTENSION_EXISTS\0" + "EXTENSION_NAME_ERROR\0" + "EXTENSION_NOT_FOUND\0" + "EXTENSION_SETTING_NOT_SUPPORTED\0" + "EXTENSION_VALUE_ERROR\0" + "ILLEGAL_EMPTY_EXTENSION\0" + "ILLEGAL_HEX_DIGIT\0" + "INCORRECT_POLICY_SYNTAX_TAG\0" + "INVALID_BOOLEAN_STRING\0" + "INVALID_EXTENSION_STRING\0" + "INVALID_MULTIPLE_RDNS\0" + "INVALID_NAME\0" + "INVALID_NULL_ARGUMENT\0" + "INVALID_NULL_NAME\0" + "INVALID_NULL_VALUE\0" + "INVALID_NUMBERS\0" + "INVALID_OBJECT_IDENTIFIER\0" + "INVALID_OPTION\0" + "INVALID_POLICY_IDENTIFIER\0" + "INVALID_PROXY_POLICY_SETTING\0" + "INVALID_PURPOSE\0" + "INVALID_SECTION\0" + "INVALID_SYNTAX\0" + "ISSUER_DECODE_ERROR\0" + "NEED_ORGANIZATION_AND_NUMBERS\0" + "NO_CONFIG_DATABASE\0" + "NO_ISSUER_CERTIFICATE\0" + "NO_ISSUER_DETAILS\0" + "NO_POLICY_IDENTIFIER\0" + "NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED\0" + "NO_PUBLIC_KEY\0" + "NO_SUBJECT_DETAILS\0" + "ODD_NUMBER_OF_DIGITS\0" + "OPERATION_NOT_DEFINED\0" + "OTHERNAME_ERROR\0" + "POLICY_LANGUAGE_ALREADY_DEFINED\0" + "POLICY_PATH_LENGTH\0" + "POLICY_PATH_LENGTH_ALREADY_DEFINED\0" + "POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY\0" + "SECTION_NOT_FOUND\0" + "UNABLE_TO_GET_ISSUER_DETAILS\0" + "UNABLE_TO_GET_ISSUER_KEYID\0" + "UNKNOWN_BIT_STRING_ARGUMENT\0" + "UNKNOWN_EXTENSION\0" + "UNKNOWN_EXTENSION_NAME\0" + "UNKNOWN_OPTION\0" + "UNSUPPORTED_OPTION\0" + "USER_TOO_LONG\0" + ""; +
diff --git a/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S index b01ad7f..5f4b057 100644 --- a/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/aes/aes-x86_64.S
@@ -1294,7 +1294,8 @@ .globl asm_AES_cbc_encrypt .hidden asm_AES_cbc_encrypt .type asm_AES_cbc_encrypt,@function - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .hidden asm_AES_cbc_encrypt asm_AES_cbc_encrypt: cmpq $0,%rdx
diff --git a/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S index 9ab973d..ecefbe5 100644 --- a/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/aes/aesni-x86_64.S
@@ -1,6 +1,7 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl aesni_encrypt .hidden aesni_encrypt .type aesni_encrypt,@function
diff --git a/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S index 2960e95..8cfa4df 100644 --- a/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/aes/bsaes-x86_64.S
@@ -1,8 +1,10 @@ #if defined(__x86_64__) .text - - +.extern asm_AES_encrypt +.hidden asm_AES_encrypt +.extern asm_AES_decrypt +.hidden asm_AES_decrypt .type _bsaes_encrypt8,@function .align 64 @@ -1063,7 +1065,8 @@ .byte 0xf3,0xc3 .size _bsaes_key_convert,.-_bsaes_key_convert - +.extern asm_AES_cbc_encrypt +.hidden asm_AES_cbc_encrypt .globl bsaes_cbc_encrypt .hidden bsaes_cbc_encrypt .type bsaes_cbc_encrypt,@function
diff --git a/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S index fe0eed5..dd3d310 100644 --- a/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/bn/rsaz-x86_64.S
@@ -1,7 +1,8 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl rsaz_512_sqr .hidden rsaz_512_sqr
diff --git a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S index ebe7678..4d401c6 100644 --- a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S +++ b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont.S
@@ -1,7 +1,8 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl bn_mul_mont .hidden bn_mul_mont @@ -610,7 +611,8 @@ .Lmul4x_epilogue: .byte 0xf3,0xc3 .size bn_mul4x_mont,.-bn_mul4x_mont - +.extern bn_sqr8x_internal +.hidden bn_sqr8x_internal .type bn_sqr8x_mont,@function .align 32
diff --git a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S index 357bc11..02edc69 100644 --- a/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S +++ b/third_party/boringssl/linux-x86_64/crypto/bn/x86_64-mont5.S
@@ -1,7 +1,8 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl bn_mul_mont_gather5 .hidden bn_mul_mont_gather5
diff --git a/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S index bd1b17f..1db7d69 100644 --- a/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/modes/ghash-x86_64.S
@@ -1,6 +1,7 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl gcm_gmult_4bit .hidden gcm_gmult_4bit
diff --git a/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S index d546154..c4d1002 100644 --- a/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/rc4/rc4-x86_64.S
@@ -1,6 +1,7 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl asm_RC4 .hidden asm_RC4
diff --git a/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S index ea2f403..7668c2b 100644 --- a/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/sha/sha1-x86_64.S
@@ -1,6 +1,7 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl sha1_block_data_order .hidden sha1_block_data_order
diff --git a/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S index 4649baf..f526de5 100644 --- a/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/sha/sha256-x86_64.S
@@ -1,7 +1,8 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl sha256_block_data_order .hidden sha256_block_data_order .type sha256_block_data_order,@function
diff --git a/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S index 89fd5bf..ca3a3a1 100644 --- a/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S +++ b/third_party/boringssl/linux-x86_64/crypto/sha/sha512-x86_64.S
@@ -1,7 +1,8 @@ #if defined(__x86_64__) .text - +.extern OPENSSL_ia32cap_P +.hidden OPENSSL_ia32cap_P .globl sha512_block_data_order .hidden sha512_block_data_order .type sha512_block_data_order,@function
diff --git a/third_party/boringssl/update_gypi_and_asm.py b/third_party/boringssl/update_gypi_and_asm.py index db11e64..1835695 100644 --- a/third_party/boringssl/update_gypi_and_asm.py +++ b/third_party/boringssl/update_gypi_and_asm.py
@@ -193,6 +193,13 @@ crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTests) ssl_c_files = FindCFiles(os.path.join('src', 'ssl'), NoTests) + # Generate err_data.c + with open('err_data.c', 'w+') as err_data: + subprocess.check_call(['go', 'run', 'err_data_generate.go'], + cwd=os.path.join('src', 'crypto', 'err'), + stdout=err_data) + crypto_c_files.append('err_data.c') + with open('boringssl.gypi', 'w+') as gypi: gypi.write(FILE_HEADER + '{\n \'variables\': {\n')
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium index 368d604..fc027b0 100644 --- a/third_party/qcms/README.chromium +++ b/third_party/qcms/README.chromium
@@ -55,5 +55,7 @@ - https://code.google.com/p/chromium/issues/detail?id=443863 - Add bgra (z,y,x) sampled transform lookup table api - https://code.google.com/p/chromium/issues/detail?id=443863 + - Apply upstream fix reject invalid sizes from + - https://bugzilla.mozilla.org/show_bug.cgi?id=1132468 To regenerate google.patch: git diff b8456f38 src > google.patch
diff --git a/third_party/qcms/google.patch b/third_party/qcms/google.patch index ce60f9f..dea54fc 100644 --- a/third_party/qcms/google.patch +++ b/third_party/qcms/google.patch
@@ -1,5 +1,5 @@ diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c -index 36b7011..aca19d3 100644 +index 36b7011..6cec34a 100644 --- a/third_party/qcms/src/iccread.c +++ b/third_party/qcms/src/iccread.c @@ -266,7 +266,7 @@ qcms_bool qcms_profile_is_bogus(qcms_profile *profile) @@ -42,12 +42,13 @@ static struct tag *find_tag(struct tag_index index, uint32_t tag_id) { -@@ -344,6 +354,47 @@ static struct tag *find_tag(struct tag_index index, uint32_t tag_id) +@@ -344,6 +354,152 @@ static struct tag *find_tag(struct tag_index index, uint32_t tag_id) return tag; } +#define DESC_TYPE 0x64657363 // 'desc' +#define MLUC_TYPE 0x6d6c7563 // 'mluc' ++#define MMOD_TYPE 0x6D6D6F64 // 'mmod' + +static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) +{ @@ -57,23 +58,31 @@ + uint32_t offset = tag->offset; + uint32_t type = read_u32(src, offset); + uint32_t length = read_u32(src, offset+8); -+ uint32_t i, description; ++ uint32_t i, description_offset; ++ bool mluc = false; + if (length && type == MLUC_TYPE) { + length = read_u32(src, offset+20); + if (!length || (length & 1) || (read_u32(src, offset+12) != 12)) + goto invalid_desc_tag; -+ description = offset + read_u32(src, offset+24); ++ description_offset = offset + read_u32(src, offset+24); + if (!src->valid) + goto invalid_desc_tag; ++ mluc = true; + } else if (length && type == DESC_TYPE) { -+ description = offset + 12; ++ description_offset = offset + 12; + } else { + goto invalid_desc_tag; + } + if (length >= limit) + length = limit - 1; -+ for (i = 0; i < length; ++i) -+ profile->description[i] = read_u8(src, description+i); ++ for (i = 0; i < length; ++i) { ++ uint8_t value = read_u8(src, description_offset + i); ++ if (!src->valid) ++ goto invalid_desc_tag; ++ if (mluc && !value) ++ value = '.'; ++ profile->description[i] = value; ++ } + profile->description[length] = 0; + } else { + goto invalid_desc_tag; @@ -87,10 +96,106 @@ + return false; +} + ++#if defined(__APPLE__) ++ ++// Use the dscm tag to change profile description "Display" to its more specific en-localized monitor name, if any. ++ ++#define TAG_dscm 0x6473636D // 'dscm' ++ ++static bool read_tag_dscmType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) ++{ ++ if (strcmp(profile->description, "Display") != 0) ++ return true; ++ ++ struct tag *tag = find_tag(index, tag_id); ++ if (tag) { ++ uint32_t offset = tag->offset; ++ uint32_t type = read_u32(src, offset); ++ uint32_t records = read_u32(src, offset+8); ++ ++ if (!src->valid || !records || type != MLUC_TYPE) ++ goto invalid_dscm_tag; ++ if (read_u32(src, offset+12) != 12) // MLUC record size: bytes ++ goto invalid_dscm_tag; ++ ++ for (uint32_t i = 0; i < records; ++i) { ++ const uint32_t limit = sizeof profile->description; ++ const uint16_t isoen = 0x656E; // ISO-3166-1 language 'en' ++ ++ uint16_t language = read_u16(src, offset + 16 + (i * 12) + 0); ++ uint32_t length = read_u32(src, offset + 16 + (i * 12) + 4); ++ uint32_t description_offset = read_u32(src, offset + 16 + (i * 12) + 8); ++ ++ if (!src->valid || !length || (length & 1)) ++ goto invalid_dscm_tag; ++ if (language != isoen) ++ continue; ++ ++ // Use a prefix to identify the display description source ++ strcpy(profile->description, "dscm:"); ++ length += 5; ++ ++ if (length >= limit) ++ length = limit - 1; ++ for (uint32_t j = 5; j < length; ++j) { ++ uint8_t value = read_u8(src, offset + description_offset + j - 5); ++ if (!src->valid) ++ goto invalid_dscm_tag; ++ profile->description[j] = value ? value : '.'; ++ } ++ profile->description[length] = 0; ++ break; ++ } ++ } ++ ++ if (src->valid) ++ return true; ++ ++invalid_dscm_tag: ++ invalid_source(src, "invalid dscm tag"); ++ return false; ++} ++ ++// Use the mmod tag to change profile description "Display" to its specific mmod maker model data, if any. ++ ++#define TAG_mmod 0x6D6D6F64 // 'mmod' ++ ++static bool read_tag_mmodType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) ++{ ++ if (strcmp(profile->description, "Display") != 0) ++ return true; ++ ++ struct tag *tag = find_tag(index, tag_id); ++ if (tag) { ++ const uint8_t length = 4 * 4; // Four 4-byte fields: 'mmod', 0, maker, model. ++ ++ uint32_t offset = tag->offset; ++ if (tag->size < 40 || read_u32(src, offset) != MMOD_TYPE) ++ goto invalid_mmod_tag; ++ ++ for (uint8_t i = 0; i < length; ++i) { ++ uint8_t value = read_u8(src, offset + i); ++ if (!src->valid) ++ goto invalid_mmod_tag; ++ profile->description[i] = value ? value : '.'; ++ } ++ profile->description[length] = 0; ++ } ++ ++ if (src->valid) ++ return true; ++ ++invalid_mmod_tag: ++ invalid_source(src, "invalid mmod tag"); ++ return false; ++} ++ ++#endif // __APPLE__ ++ #define XYZ_TYPE 0x58595a20 // 'XYZ ' #define CURVE_TYPE 0x63757276 // 'curv' #define PARAMETRIC_CURVE_TYPE 0x70617261 // 'para' -@@ -402,7 +453,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_inde +@@ -402,7 +558,7 @@ static struct XYZNumber read_tag_XYZType(struct mem_source *src, struct tag_inde // present that are not part of the tag_index. static struct curveType *read_curveType(struct mem_source *src, uint32_t offset, uint32_t *len) { @@ -99,7 +204,7 @@ struct curveType *curve = NULL; uint32_t type = read_u32(src, offset); uint32_t count; -@@ -484,19 +535,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu +@@ -484,19 +640,23 @@ static void read_nested_curveType(struct mem_source *src, struct curveType *(*cu uint32_t channel_offset = 0; int i; for (i = 0; i < num_channels; i++) { @@ -125,7 +230,7 @@ } static void mAB_release(struct lutmABType *lut) -@@ -657,7 +712,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index +@@ -657,7 +817,7 @@ static struct lutType *read_tag_lutType(struct mem_source *src, struct tag_index uint16_t num_input_table_entries; uint16_t num_output_table_entries; uint8_t in_chan, grid_points, out_chan; @@ -134,7 +239,7 @@ uint32_t clut_size; size_t entry_size; struct lutType *lut; -@@ -979,6 +1034,9 @@ qcms_profile* qcms_profile_sRGB(void) +@@ -979,6 +1139,9 @@ qcms_profile* qcms_profile_sRGB(void) return NO_MEM_PROFILE; profile = qcms_profile_create_rgb_with_table(D65, Rec709Primaries, table, 1024); @@ -144,7 +249,7 @@ free(table); return profile; } -@@ -997,6 +1055,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) +@@ -997,6 +1160,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) source.size = size; source.valid = true; @@ -154,17 +259,23 @@ length = read_u32(src, 0); if (length <= size) { // shrink the area that we can read if appropriate -@@ -1028,6 +1089,9 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) +@@ -1028,6 +1194,15 @@ qcms_profile* qcms_profile_from_memory(const void *mem, size_t size) if (!src->valid || !index.tags) goto invalid_tag_table; + if (!read_tag_descType(profile, src, index, TAG_desc)) + goto invalid_tag_table; ++#if defined(__APPLE__) ++ if (!read_tag_dscmType(profile, src, index, TAG_dscm)) ++ goto invalid_tag_table; ++ if (!read_tag_mmodType(profile, src, index, TAG_mmod)) ++ goto invalid_tag_table; ++#endif // __APPLE__ + if (find_tag(index, TAG_CHAD)) { profile->chromaticAdaption = read_tag_s15Fixed16ArrayType(src, index, TAG_CHAD); } else { -@@ -1098,6 +1162,16 @@ invalid_profile: +@@ -1098,6 +1273,16 @@ invalid_profile: return INVALID_PROFILE; } @@ -182,7 +293,7 @@ { return profile->rendering_intent; diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h -index 7d83623..c69a772 100644 +index 7d83623..e9c0b09 100644 --- a/third_party/qcms/src/qcms.h +++ b/third_party/qcms/src/qcms.h @@ -40,6 +40,12 @@ sale, use or other dealings in this Software without written @@ -221,11 +332,19 @@ void qcms_profile_precache_output_transform(qcms_profile *profile); qcms_transform* qcms_transform_create( -@@ -146,6 +161,7 @@ qcms_transform* qcms_transform_create( - void qcms_transform_release(qcms_transform *); +@@ -143,9 +158,14 @@ qcms_transform* qcms_transform_create( + qcms_profile* out, qcms_data_type out_type, + qcms_intent intent); + +-void qcms_transform_release(qcms_transform *); ++qcms_bool qcms_transform_create_LUT_zyx_bgra( ++ qcms_profile *in, qcms_profile* out, qcms_intent intent, ++ int samples, unsigned char* lut); void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_t length); +void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest, size_t length, qcms_output_type type); ++ ++void qcms_transform_release(qcms_transform *); void qcms_enable_iccv4(); @@ -565,7 +684,7 @@ + dest[b_out] = otdata_b[output[2]]; } diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c -index 9a6562b..08db142 100644 +index 9a6562b..f669a6b 100644 --- a/third_party/qcms/src/transform.c +++ b/third_party/qcms/src/transform.c @@ -181,11 +181,20 @@ compute_chromatic_adaption(struct CIE_XYZ source_white_point, @@ -981,8 +1100,53 @@ /* don't precache if we do not have the TRC curves */ if (!profile->redTRC || !profile->greenTRC || !profile->blueTRC) -@@ -1078,7 +1153,8 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms - //XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed +@@ -1043,28 +1118,31 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms + float* src = NULL; + float* dest = NULL; + float* lut = NULL; ++ float inverse; + + src = malloc(lutSize*sizeof(float)); + dest = malloc(lutSize*sizeof(float)); + + if (src && dest) { +- /* Prepare a list of points we want to sample */ ++ /* Prepare a list of points we want to sample: x, y, z order */ + l = 0; ++ inverse = 1 / (float)(samples-1); + for (x = 0; x < samples; x++) { + for (y = 0; y < samples; y++) { + for (z = 0; z < samples; z++) { +- src[l++] = x / (float)(samples-1); +- src[l++] = y / (float)(samples-1); +- src[l++] = z / (float)(samples-1); ++ src[l++] = x * inverse; // r ++ src[l++] = y * inverse; // g ++ src[l++] = z * inverse; // b + } + } + } + + lut = qcms_chain_transform(in, out, src, dest, lutSize); ++ + if (lut) { +- transform->r_clut = &lut[0]; +- transform->g_clut = &lut[1]; +- transform->b_clut = &lut[2]; ++ transform->r_clut = &lut[0]; // r ++ transform->g_clut = &lut[1]; // g ++ transform->b_clut = &lut[2]; // b + transform->grid_size = samples; + if (in_type == QCMS_DATA_RGBA_8) { + transform->transform_fn = qcms_transform_data_tetra_clut_rgba; +@@ -1074,11 +1152,12 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms + } + } + +- +- //XXX: qcms_modular_transform_data may return either the src or dest buffer. If so it must not be free-ed ++ // XXX: qcms_modular_transform_data may return the lut in either the src or the ++ // dest buffer. If so, it must not be free-ed. if (src && lut != src) { free(src); - } else if (dest && lut != src) { @@ -991,7 +1155,79 @@ free(dest); } -@@ -1157,14 +1233,14 @@ qcms_transform* qcms_transform_create( +@@ -1088,6 +1167,71 @@ qcms_transform* qcms_transform_precacheLUT_float(qcms_transform *transform, qcms + return transform; + } + ++/* Create a transform LUT using the given number of sample points. The transform LUT data is stored ++ in the output (cube) in bgra format in zyx sample order. */ ++qcms_bool qcms_transform_create_LUT_zyx_bgra(qcms_profile *in, qcms_profile *out, qcms_intent intent, ++ int samples, unsigned char* cube) ++{ ++ uint16_t z,y,x; ++ uint32_t l,index; ++ uint32_t lutSize = 3 * samples * samples * samples; ++ ++ float* src = NULL; ++ float* dest = NULL; ++ float* lut = NULL; ++ float inverse; ++ ++ src = malloc(lutSize*sizeof(float)); ++ dest = malloc(lutSize*sizeof(float)); ++ ++ if (src && dest) { ++ /* Prepare a list of points we want to sample: z, y, x order */ ++ l = 0; ++ inverse = 1 / (float)(samples-1); ++ for (z = 0; z < samples; z++) { ++ for (y = 0; y < samples; y++) { ++ for (x = 0; x < samples; x++) { ++ src[l++] = x * inverse; // r ++ src[l++] = y * inverse; // g ++ src[l++] = z * inverse; // b ++ } ++ } ++ } ++ ++ lut = qcms_chain_transform(in, out, src, dest, lutSize); ++ ++ if (lut) { ++ index = l = 0; ++ for (z = 0; z < samples; z++) { ++ for (y = 0; y < samples; y++) { ++ for (x = 0; x < samples; x++) { ++ cube[index++] = (int)floorf(lut[l + 2] * 255.0f + 0.5f); // b ++ cube[index++] = (int)floorf(lut[l + 1] * 255.0f + 0.5f); // g ++ cube[index++] = (int)floorf(lut[l + 0] * 255.0f + 0.5f); // r ++ cube[index++] = 255; // a ++ l += 3; ++ } ++ } ++ } ++ } ++ } ++ ++ // XXX: qcms_modular_transform_data may return the lut data in either the src or ++ // dest buffer so free src, dest, and lut with care. ++ ++ if (src && lut != src) ++ free(src); ++ if (dest && lut != dest) ++ free(dest); ++ ++ if (lut) { ++ free(lut); ++ return true; ++ } ++ ++ return false; ++} ++ + #define NO_MEM_TRANSFORM NULL + + qcms_transform* qcms_transform_create( +@@ -1157,14 +1301,14 @@ qcms_transform* qcms_transform_create( return NULL; } if (precache) { @@ -1008,7 +1244,7 @@ /* Microsoft Compiler for x64 doesn't support MMX. * SSE code uses MMX so that we disable on x64 */ } else -@@ -1256,13 +1332,34 @@ qcms_transform* qcms_transform_create( +@@ -1256,13 +1400,34 @@ qcms_transform* qcms_transform_create( return transform; }
diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c index 6cec34a..208ebee 100644 --- a/third_party/qcms/src/iccread.c +++ b/third_party/qcms/src/iccread.c
@@ -700,7 +700,7 @@ // We require 3in/out channels since we only support RGB->XYZ (or RGB->LAB) // XXX: If we remove this restriction make sure that the number of channels // is less or equal to the maximum number of mAB curves in qcmsint.h - // also check for clut_size overflow. + // also check for clut_size overflow. Also make sure it's != 0 if (num_in_channels != 3 || num_out_channels != 3) return NULL; @@ -730,6 +730,9 @@ // clut_size can not overflow since lg(256^num_in_channels) = 24 bits. for (i = 0; i < num_in_channels; i++) { clut_size *= read_u8(src, clut_offset + i); + if (clut_size == 0) { + invalid_source(src, "bad clut_size"); + } } } else { clut_size = 0; @@ -750,6 +753,9 @@ for (i = 0; i < num_in_channels; i++) { lut->num_grid_points[i] = read_u8(src, clut_offset + i); + if (lut->num_grid_points[i] == 0) { + invalid_source(src, "bad grid_points"); + } } // Reverse the processing of transformation elements for mBA type. @@ -832,6 +838,10 @@ } else if (type == LUT16_TYPE) { num_input_table_entries = read_u16(src, offset + 48); num_output_table_entries = read_u16(src, offset + 50); + if (num_input_table_entries == 0 || num_output_table_entries == 0) { + invalid_source(src, "Bad channel count"); + return NULL; + } entry_size = 2; } else { assert(0); // the caller checks that this doesn't happen @@ -845,15 +855,18 @@ clut_size = pow(grid_points, in_chan); if (clut_size > MAX_CLUT_SIZE) { + invalid_source(src, "CLUT too large"); return NULL; } if (in_chan != 3 || out_chan != 3) { + invalid_source(src, "CLUT only supports RGB"); return NULL; } lut = malloc(sizeof(struct lutType) + (num_input_table_entries * in_chan + clut_size*out_chan + num_output_table_entries * out_chan)*sizeof(float)); if (!lut) { + invalid_source(src, "CLUT too large"); return NULL; } @@ -864,9 +877,9 @@ lut->num_input_table_entries = num_input_table_entries; lut->num_output_table_entries = num_output_table_entries; - lut->num_input_channels = read_u8(src, offset + 8); - lut->num_output_channels = read_u8(src, offset + 9); - lut->num_clut_grid_points = read_u8(src, offset + 10); + lut->num_input_channels = in_chan; + lut->num_output_channels = out_chan; + lut->num_clut_grid_points = grid_points; lut->e00 = read_s15Fixed16Number(src, offset+12); lut->e01 = read_s15Fixed16Number(src, offset+16); lut->e02 = read_s15Fixed16Number(src, offset+20);
diff --git a/third_party/yasm/yasm.gyp b/third_party/yasm/yasm.gyp index 0c21b83..6a5e692 100644 --- a/third_party/yasm/yasm.gyp +++ b/third_party/yasm/yasm.gyp
@@ -56,6 +56,10 @@ 'version_file': 'version.mac', # Generated by genversion. 'genmodule_source': 'genmodule_outfile.c', }, + 'target_defaults': { + # Silence warnings in libc++ builds (C code doesn't need this flag). + 'ldflags!': [ '-stdlib=libc++', ], + }, 'targets': [ { 'target_name': 'yasm',
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp index fe868c0..770e255 100644 --- a/tools/clang/plugins/FindBadConstructsConsumer.cpp +++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -296,8 +296,9 @@ emitWarning(it->getInnerLocStart(), "Complex constructor has an inlined body."); } - } else if (it->isInlined() && (!it->isCopyOrMoveConstructor() || - it->isExplicitlyDefaulted())) { + } else if (it->isInlined() && !it->isInlineSpecified() && + !it->isDeleted() && (!it->isCopyOrMoveConstructor() || + it->isExplicitlyDefaulted())) { // isInlined() is a more reliable check than hasInlineBody(), but // unfortunately, it results in warnings for implicit copy/move // constructors in the previously mentioned situation. To preserve @@ -318,7 +319,8 @@ "Complex class/struct needs an explicit out-of-line " "destructor."); } else if (CXXDestructorDecl* dtor = record->getDestructor()) { - if (dtor->isInlined()) { + if (dtor->isInlined() && !dtor->isInlineSpecified() && + !dtor->isDeleted()) { emitWarning(dtor->getInnerLocStart(), "Complex destructor has an inline body."); }
diff --git a/tools/clang/plugins/tests/inline_ctor.h b/tools/clang/plugins/tests/inline_ctor.h index d053b2f..9c6c286 100644 --- a/tools/clang/plugins/tests/inline_ctor.h +++ b/tools/clang/plugins/tests/inline_ctor.h
@@ -18,4 +18,36 @@ std::vector<std::string> two_; }; +class DeletedMembersInHeaderAreOKThough { + public: + DeletedMembersInHeaderAreOKThough() = delete; + ~DeletedMembersInHeaderAreOKThough() = delete; + DeletedMembersInHeaderAreOKThough(const DeletedMembersInHeaderAreOKThough&) = + delete; + + private: + std::vector<int> one_; + std::vector<std::string> two_; +}; + +class ExplicitlyInlinedIsAlsoOK { + ExplicitlyInlinedIsAlsoOK(); + ~ExplicitlyInlinedIsAlsoOK(); + ExplicitlyInlinedIsAlsoOK(const ExplicitlyInlinedIsAlsoOK&); + + private: + std::vector<int> one_; + std::vector<std::string> two_; +}; + +inline ExplicitlyInlinedIsAlsoOK::ExplicitlyInlinedIsAlsoOK() { +} + +inline ExplicitlyInlinedIsAlsoOK::~ExplicitlyInlinedIsAlsoOK() { +} + +inline ExplicitlyInlinedIsAlsoOK::ExplicitlyInlinedIsAlsoOK( + const ExplicitlyInlinedIsAlsoOK&) { +} + #endif // INLINE_CTOR_H_
diff --git a/tools/clang/scripts/plugin_flags.py b/tools/clang/scripts/plugin_flags.py deleted file mode 100755 index 3f61d6b..0000000 --- a/tools/clang/scripts/plugin_flags.py +++ /dev/null
@@ -1,29 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This script returns the flags that should be used when GYP_DEFINES contains -# clang_use_chrome_plugins. The flags are stored in a script so that they can -# be changed on the bots without requiring a master restart. - -import os -import sys - -# Path constants. (All of these should be absolute paths.) -THIS_DIR = os.path.abspath(os.path.dirname(__file__)) -CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..')) -CLANG_LIB_PATH = os.path.join(CHROMIUM_DIR, 'third_party', 'llvm-build', - 'Release+Asserts', 'lib') - -if sys.platform == 'darwin': - LIBSUFFIX = 'dylib' -else: - LIBSUFFIX = 'so' - -LIB_PATH = os.path.join( - CLANG_LIB_PATH, - 'libFindBadConstructs.' + LIBSUFFIX) - -print ('-Xclang -load -Xclang %s' - ' -Xclang -add-plugin -Xclang find-bad-constructs') % LIB_PATH
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index cb0878d..2cc6958 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -24,7 +24,7 @@ # in bringup. Use a pinned revision to make it slightly more stable. if (re.search(r'\b(asan)=1', os.environ.get('GYP_DEFINES', '')) and not 'LLVM_FORCE_HEAD_REVISION' in os.environ): - LLVM_WIN_REVISION = '229860' + LLVM_WIN_REVISION = '231949' # Path constants. (All of these should be absolute paths.) THIS_DIR = os.path.abspath(os.path.dirname(__file__))
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh index ae90743..c842a58 100755 --- a/tools/clang/scripts/update.sh +++ b/tools/clang/scripts/update.sh
@@ -8,7 +8,7 @@ # Do NOT CHANGE this if you don't know what you're doing -- see # https://code.google.com/p/chromium/wiki/UpdatingClang # Reverting problematic clang rolls is safe, though. -CLANG_REVISION=231191 +CLANG_REVISION=231690 # This is incremented when pushing a new build of Clang at the same revision. CLANG_SUB_REVISION=1
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index d2b3ede..a64ae83 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -245,6 +245,9 @@ "chrome/browser/devtools/device/webrtc/resources.grd": { "includes": [30800], }, + "chrome/browser/resources/settings/settings_resources.grd": { + "structures": [30900], + }, # These files don't need to reserve resource ids, but are listed here so that # translation scripts know of their existence.
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py index bfe6698..bdd6dc7 100755 --- a/tools/idl_parser/idl_parser.py +++ b/tools/idl_parser/idl_parser.py
@@ -264,6 +264,11 @@ p[2].AddChildren(p[1]) p[0] = ListFromConcat(p[2], p[3]) + # [9.1] Error recovery for InterfaceMembers + def p_InterfaceMembersError(self, p): + """InterfaceMembers : error""" + p[0] = self.BuildError(p, 'InterfaceMembers') + # [10] Removed unsupported: Serializer def p_InterfaceMember(self, p): """InterfaceMember : Const
diff --git a/tools/idl_parser/test_parser/interface_web.idl b/tools/idl_parser/test_parser/interface_web.idl index 9e69e9f..b1f3278 100644 --- a/tools/idl_parser/test_parser/interface_web.idl +++ b/tools/idl_parser/test_parser/interface_web.idl
@@ -72,6 +72,23 @@ }; /* TREE + *Interface(MyIFaceContainsUnresolvedConflictDiff) + * Operation(foo) + * Arguments() + * Type() + * PrimitiveType(DOMString) + * Error(Unexpected "<" after ";".) + */ +interface MyIFaceContainsUnresolvedConflictDiff { + DOMString foo(); +<<<<<< ours + DOMString bar(); + iterable<long>; +====== +>>>>>> theirs +}; + +/* TREE *Interface(MyIFaceBig) * Const(setString) * PrimitiveType(DOMString)
diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py index 0107406..898edf4 100755 --- a/tools/valgrind/asan/asan_symbolize.py +++ b/tools/valgrind/asan/asan_symbolize.py
@@ -246,6 +246,9 @@ disable_buffering() set_symbolizer_path() + # Disallow fallback to addr2line/atos if llvm-symbolizer is not present. Those + # are slow and we don't want to use them ever. + asan_symbolize.allow_system_symbolizer = False asan_symbolize.demangle = True asan_symbolize.fix_filename_patterns = args.strip_path_prefix # Most source paths for Chromium binaries start with
diff --git a/tools/valgrind/asan/third_party/README.chromium b/tools/valgrind/asan/third_party/README.chromium index 5c363ea..63a1761 100644 --- a/tools/valgrind/asan/third_party/README.chromium +++ b/tools/valgrind/asan/third_party/README.chromium
@@ -1,6 +1,6 @@ Name: asan_symbolize.py License: University of Illinois Open Source License. -Version: r227327 +Version: r231492 URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py?view=co&content-type=text%2Fplain Security Critical: no
diff --git a/tools/valgrind/asan/third_party/asan_symbolize.py b/tools/valgrind/asan/third_party/asan_symbolize.py index 59fceaa..b9d3ad3 100755 --- a/tools/valgrind/asan/third_party/asan_symbolize.py +++ b/tools/valgrind/asan/third_party/asan_symbolize.py
@@ -23,6 +23,7 @@ binary_name_filter = None fix_filename_patterns = None logfile = sys.stdin +allow_system_symbolizer = True # FIXME: merge the code that calls fix_filename(). def fix_filename(file_name): @@ -392,6 +393,8 @@ [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]]) result = symbolizers[binary].symbolize(addr, binary, offset) if result is None: + if not allow_system_symbolizer: + raise Exception('Failed to launch or use llvm-symbolizer.') # Initialize system symbolizer only if other symbolizers failed. symbolizers[binary].append_symbolizer( SystemSymbolizerFactory(self.system, addr, binary))
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt index eae85e5..dfe57e2 100644 --- a/tools/valgrind/drmemory/suppressions_full.txt +++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1821,6 +1821,10 @@ KERNEL32.dll!WriteFile mojo_system_impl.dll!mojo::system::`anonymous namespace'::RawChannelWin::WriteNoLock +UNINITIALIZED READ +name=bug_399842 +skia.dll!S32A_Opaque_BlitRow32_SSE4 + HANDLE LEAK name=bug_403544 system call NtCreateSemaphore @@ -1886,9 +1890,10 @@ *!ash::test::ShelfViewTest_OverflowBubbleSize_Test::TestBody *!testing::internal::HandleExceptionsInMethodIfSupported<> -UNINITIALIZED READ -name=bug_399842 -skia.dll!S32A_Opaque_BlitRow32_SSE4 +UNADDRESSABLE ACCESS +name=bug_442969 +*!testing::internal::CmpHelperNE<> +*!extensions::WebrtcAudioPrivateTest_GetAndSetWithMediaStream_Test::RunTestOnMainThread UNINITIALIZED READ name=bug_455417
diff --git a/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt b/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt index 636878e..64ab6ab 100644 --- a/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt +++ b/tools/valgrind/gtest_exclude/ash_unittests.gtest-memcheck.txt
@@ -5,5 +5,4 @@ # http://crbug.com/383384 SystemGestureEventFilterTest.TwoFingerDragDelayed # http://crbug.com/421888 -SystemTrayTest.*TouchFeedback* -TrayDetailsViewTest.*TouchFeedback* +WebNotificationTrayTest.*TouchFeedback*
diff --git a/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt deleted file mode 100644 index f1382da..0000000 --- a/tools/valgrind/gtest_exclude/chrome_app_unittests.gtest-drmemory_win32.txt +++ /dev/null
@@ -1,2 +0,0 @@ -# crbug.com/455536 -ChromeWatcherCommandLineTest.BasicTest
diff --git a/tools/valgrind/memcheck/suppressions_mac.txt b/tools/valgrind/memcheck/suppressions_mac.txt index f0e9d32..c9ed9bf 100644 --- a/tools/valgrind/memcheck/suppressions_mac.txt +++ b/tools/valgrind/memcheck/suppressions_mac.txt
@@ -271,3 +271,12 @@ fun:_ZN4base3mac30PathForFrameworkBundleResourceEPK10__CFString fun:_ZN3gin13IsolateHolder14LoadV8SnapshotEv } +{ + bug_464850 + Memcheck:Uninitialized + fun:_ZN2v88internal9ExitFrame23GetStateForFramePointerEPhPNS0_10StackFrame5StateE + fun:_ZN2v88internal18StackFrameIterator5ResetEPNS0_14ThreadLocalTopE + fun:_ZN2v88internal18StackFrameIteratorC2EPNS0_7IsolateE + fun:_ZN2v88internal18StackFrameIteratorC1EPNS0_7IsolateE + fun:_ZN2v88internal7Isolate11FindHandlerEv +}
diff --git a/ui/events/platform/platform_event_source.cc b/ui/events/platform/platform_event_source.cc index 9607ab7..bf957f0 100644 --- a/ui/events/platform/platform_event_source.cc +++ b/ui/events/platform/platform_event_source.cc
@@ -51,6 +51,9 @@ new ScopedEventDispatcher(&overridden_dispatcher_, dispatcher)); } +void PlatformEventSource::StopCurrentEventStream() { +} + void PlatformEventSource::AddPlatformEventObserver( PlatformEventObserver* observer) { CHECK(observer); @@ -73,7 +76,7 @@ if ((action & POST_DISPATCH_PERFORM_DEFAULT) && dispatchers_.might_have_observers()) { - ObserverList<PlatformEventDispatcher>::Iterator iter(dispatchers_); + ObserverList<PlatformEventDispatcher>::Iterator iter(&dispatchers_); while (PlatformEventDispatcher* dispatcher = iter.GetNext()) { if (dispatcher->CanDispatchEvent(platform_event)) action = dispatcher->DispatchEvent(platform_event); @@ -97,9 +100,6 @@ return action; } -void PlatformEventSource::StopCurrentEventStream() { -} - void PlatformEventSource::OnDispatcherListChanged() { }
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 07de9ac..f683761 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -62,6 +62,8 @@ "frame_time.h", "gpu_memory_buffer.cc", "gpu_memory_buffer.h", + "hud_font.cc", + "hud_font.h", "native_widget_types.h", "sequential_id_generator.cc", "sequential_id_generator.h",
diff --git a/ui/gfx/geometry/quad_f.h b/ui/gfx/geometry/quad_f.h index ada5c54..d795064 100644 --- a/ui/gfx/geometry/quad_f.h +++ b/ui/gfx/geometry/quad_f.h
@@ -10,6 +10,7 @@ #include <iosfwd> #include <string> +#include "base/logging.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/gfx_export.h" @@ -67,6 +68,18 @@ return RectF(rl, rt, rr - rl, rb - rt); } + // Realigns the corners in the quad by rotating them n corners to the right. + void Realign(size_t times) { + DCHECK_LE(times, 4u); + for (size_t i = 0; i < times; ++i) { + PointF temp = p1_; + p1_ = p2_; + p2_ = p3_; + p3_ = p4_; + p4_ = temp; + } + } + // Add a vector to the quad, offseting each point in the quad by the vector. void operator+=(const Vector2dF& rhs); // Subtract a vector from the quad, offseting each point in the quad by the
diff --git a/ui/gfx/hud_font.cc b/ui/gfx/hud_font.cc new file mode 100644 index 0000000..8151778 --- /dev/null +++ b/ui/gfx/hud_font.cc
@@ -0,0 +1,25 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gfx/hud_font.h" + +#include "base/lazy_instance.h" +#include "third_party/skia/include/core/SkTypeface.h" + +namespace gfx { + +namespace { +base::LazyInstance<skia::RefPtr<SkTypeface>> g_hud_typeface; +} // namespace + +void SetHudTypeface(skia::RefPtr<SkTypeface> typeface) { + g_hud_typeface.Get() = typeface; +} + +skia::RefPtr<SkTypeface> GetHudTypeface() { + // nullptr is fine; caller will create its own in that case. + return g_hud_typeface.Get(); +} + +} // namespace gfx
diff --git a/ui/gfx/hud_font.h b/ui/gfx/hud_font.h new file mode 100644 index 0000000..f72a050 --- /dev/null +++ b/ui/gfx/hud_font.h
@@ -0,0 +1,20 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GFX_HUD_FONT_H_ +#define UI_GFX_HUD_FONT_H_ + +#include "skia/ext/refptr.h" +#include "ui/gfx/gfx_export.h" + +class SkTypeface; + +namespace gfx { + +GFX_EXPORT void SetHudTypeface(skia::RefPtr<SkTypeface> typeface); +GFX_EXPORT skia::RefPtr<SkTypeface> GetHudTypeface(); + +} // namespace gfx + +#endif // UI_GFX_HUD_FONT_H_
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc index ac98f49..15df1ea 100644 --- a/ui/gfx/skia_util.cc +++ b/ui/gfx/skia_util.cc
@@ -11,8 +11,9 @@ #include "third_party/skia/include/effects/SkBlurMaskFilter.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/rect_f.h" +#include "ui/gfx/geometry/quad_f.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/transform.h" namespace gfx { @@ -45,6 +46,15 @@ SkScalarToFloat(rect.height())); } +SkSize SizeFToSkSize(const SizeF& size) { + return SkSize::Make(SkFloatToScalar(size.width()), + SkFloatToScalar(size.height())); +} + +SizeF SkSizeToSizeF(const SkSize& size) { + return SizeF(SkScalarToFloat(size.width()), SkScalarToFloat(size.height())); +} + void TransformToFlattenedSkMatrix(const gfx::Transform& transform, SkMatrix* flattened) { // Convert from 4x4 to 3x3 by dropping the third row and column. @@ -99,7 +109,7 @@ const uint32_t pixel_in = *reinterpret_cast<const uint32_t*>(&skia[i]); // Pack the components here. - int alpha = SkGetPackedA32(pixel_in); + SkAlpha alpha = SkGetPackedA32(pixel_in); if (alpha != 0 && alpha != 255) { SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(pixel_in); rgba[i + 0] = SkColorGetR(unmultiplied); @@ -115,4 +125,11 @@ } } +void QuadFToSkPoints(const gfx::QuadF& quad, SkPoint points[4]) { + points[0] = SkPoint::Make(quad.p1().x(), quad.p1().y()); + points[1] = SkPoint::Make(quad.p2().x(), quad.p2().y()); + points[2] = SkPoint::Make(quad.p3().x(), quad.p3().y()); + points[3] = SkPoint::Make(quad.p4().x(), quad.p4().y()); +} + } // namespace gfx
diff --git a/ui/gfx/skia_util.h b/ui/gfx/skia_util.h index 3e611ea..44c9a09 100644 --- a/ui/gfx/skia_util.h +++ b/ui/gfx/skia_util.h
@@ -12,6 +12,8 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkShader.h" +#include "ui/gfx/geometry/quad_f.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/gfx_export.h" class SkBitmap; @@ -31,10 +33,33 @@ GFX_EXPORT Rect SkIRectToRect(const SkIRect& rect); GFX_EXPORT SkRect RectFToSkRect(const RectF& rect); GFX_EXPORT RectF SkRectToRectF(const SkRect& rect); +GFX_EXPORT SkSize SizeFToSkSize(const SizeF& size); +GFX_EXPORT SizeF SkSizeToSizeF(const SkSize& size); + +GFX_EXPORT void QuadFToSkPoints(const gfx::QuadF& quad, SkPoint points[4]); GFX_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform, SkMatrix* flattened); +// Creates a bitmap shader for the image rep with the image rep's scale factor. +// Sets the created shader's local matrix such that it displays the image rep at +// the correct scale factor. +// The shader's local matrix should not be changed after the shader is created. +// TODO(pkotwicz): Allow shader's local matrix to be changed after the shader +// is created. +// +GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShader( + const gfx::ImageSkiaRep& image_rep, + SkShader::TileMode tile_mode, + const SkMatrix& local_matrix); + +// Creates a bitmap shader for the image rep with the passed in scale factor. +GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShaderForScale( + const gfx::ImageSkiaRep& image_rep, + SkShader::TileMode tile_mode, + const SkMatrix& local_matrix, + SkScalar scale); + // Creates a vertical gradient shader. The caller owns the shader. // Example usage to avoid leaks: GFX_EXPORT skia::RefPtr<SkShader> CreateGradientShader(int start_point, @@ -42,6 +67,12 @@ SkColor start_color, SkColor end_color); +// Creates a draw looper to generate |shadows|. The caller owns the draw looper. +// NULL is returned if |shadows| is empty since no draw looper is needed in +// this case. +GFX_EXPORT skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper( + const std::vector<ShadowValue>& shadows); + // Returns true if the two bitmaps contain the same pixels. GFX_EXPORT bool BitmapsAreEqual(const SkBitmap& bitmap1, const SkBitmap& bitmap2);
diff --git a/ui/gfx/x/x11_types.h b/ui/gfx/x/x11_types.h index 945776d..82ce838 100644 --- a/ui/gfx/x/x11_types.h +++ b/ui/gfx/x/x11_types.h
@@ -6,6 +6,7 @@ #define UI_GFX_X_X11_UTIL_H_ #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "ui/gfx/gfx_export.h" typedef unsigned long XAtom; @@ -14,8 +15,20 @@ typedef struct _XGC *GC; typedef struct _XDisplay XDisplay; +extern "C" { +int XFree(void*); +} + namespace gfx { +template <class T, class R, R (*F)(T*)> +struct XObjectDeleter { + inline void operator()(void* ptr) const { F(static_cast<T*>(ptr)); } +}; + +template <class T, class D = XObjectDeleter<void, int, XFree>> +using XScopedPtr = scoped_ptr<T, D>; + // TODO(oshima|evan): This assume there is one display and doesn't work // undef multiple displays/monitor environment. Remove this and change the // chrome codebase to get the display from window.
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 12a44cc..88b4c36 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -183,6 +183,8 @@ } if (is_win) { sources += [ + "angle_platform_impl.cc", + "angle_platform_impl.h", "gl_bindings_autogen_wgl.cc", "gl_bindings_autogen_wgl.h", "gl_context_wgl.cc", @@ -195,6 +197,8 @@ "gl_wgl_api_implementation.h", ] + deps += [ "//third_party/angle:libGLESv2" ] + libs = [ "dwmapi.lib" ] ldflags = [ "/DELAYLOAD:dwmapi.dll" ] }
diff --git a/ui/gl/DEPS b/ui/gl/DEPS index 862c555..e582c0d 100644 --- a/ui/gl/DEPS +++ b/ui/gl/DEPS
@@ -12,5 +12,9 @@ # get access to desktop OpenGL. "gl_surface_osmesa.cc": [ "+third_party/mesa/src/include/GL/osmesa.h", - ] + ], +# Allow us to include ANGLE's base platform implementation. + "angle_platform_impl.h": [ + "+third_party/angle/include/platform/Platform.h", + ], }
diff --git a/ui/gl/angle_platform_impl.cc b/ui/gl/angle_platform_impl.cc new file mode 100644 index 0000000..2ce12b8 --- /dev/null +++ b/ui/gl/angle_platform_impl.cc
@@ -0,0 +1,50 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/angle_platform_impl.h" + +#include "base/metrics/histogram.h" +#include "base/metrics/sparse_histogram.h" + +namespace gfx { + +ANGLEPlatformImpl::ANGLEPlatformImpl() { +} + +ANGLEPlatformImpl::~ANGLEPlatformImpl() { +} + +void ANGLEPlatformImpl::histogramCustomCounts(const char* name, + int sample, + int min, + int max, + int bucket_count) { + // Copied from histogram macro, but without the static variable caching + // the histogram because name is dynamic. + base::HistogramBase* counter = base::Histogram::FactoryGet( + name, min, max, bucket_count, + base::HistogramBase::kUmaTargetedHistogramFlag); + DCHECK_EQ(name, counter->histogram_name()); + counter->Add(sample); +} + +void ANGLEPlatformImpl::histogramEnumeration(const char* name, + int sample, + int boundary_value) { + // Copied from histogram macro, but without the static variable caching + // the histogram because name is dynamic. + base::HistogramBase* counter = base::LinearHistogram::FactoryGet( + name, 1, boundary_value, boundary_value + 1, + base::HistogramBase::kUmaTargetedHistogramFlag); + DCHECK_EQ(name, counter->histogram_name()); + counter->Add(sample); +} + +void ANGLEPlatformImpl::histogramSparse(const char* name, int sample) { + // For sparse histograms, we can use the macro, as it does not incorporate a + // static. + UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample); +} + +} // namespace gfx
diff --git a/ui/gl/angle_platform_impl.h b/ui/gl/angle_platform_impl.h new file mode 100644 index 0000000..2d12f60 --- /dev/null +++ b/ui/gl/angle_platform_impl.h
@@ -0,0 +1,39 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_ANGLE_PLATFORM_IMPL_H_ +#define UI_GL_ANGLE_PLATFORM_IMPL_H_ + +// Implements the ANGLE platform interface, for functionality like +// histograms and trace profiling. + +#include "base/macros.h" +#include "third_party/angle/include/platform/Platform.h" + +namespace gfx { + +// Derives the base ANGLE platform and provides implementations +class ANGLEPlatformImpl : public angle::Platform { + public: + ANGLEPlatformImpl(); + ~ANGLEPlatformImpl() override; + + // angle::Platform: + void histogramCustomCounts(const char* name, + int sample, + int min, + int max, + int bucket_count) override; + void histogramEnumeration(const char* name, + int sample, + int boundary_value) override; + void histogramSparse(const char* name, int sample) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ANGLEPlatformImpl); +}; + +} // namespace gfx + +#endif // UI_GL_ANGLE_PLATFORM_IMPL_H_
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp index 0538107..d62950a 100644 --- a/ui/gl/gl.gyp +++ b/ui/gl/gl.gyp
@@ -186,6 +186,8 @@ }], ['OS=="win"', { 'sources': [ + 'angle_platform_impl.cc', + 'angle_platform_impl.h', 'gl_bindings_autogen_wgl.cc', 'gl_bindings_autogen_wgl.h', 'gl_context_wgl.cc', @@ -197,6 +199,11 @@ 'gl_wgl_api_implementation.cc', 'gl_wgl_api_implementation.h', ], + 'dependencies': [ + # TODO(jmadill): Use ANGLE on other platforms. + '<(angle_path)/src/angle.gyp:libEGL', + '<(angle_path)/src/angle.gyp:libGLESv2', + ], 'msvs_settings': { 'VCLinkerTool': { 'DelayLoadDLLs': [
diff --git a/ui/gl/gl_image_glx.cc b/ui/gl/gl_image_glx.cc index 84c4d0c..dea6cd6 100644 --- a/ui/gl/gl_image_glx.cc +++ b/ui/gl/gl_image_glx.cc
@@ -16,13 +16,6 @@ namespace { -// scoped_ptr functor for XFree(). Use as follows: -// scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...); -// where "XVisualInfo" is any X type that is freed with XFree. -struct ScopedPtrXFree { - void operator()(void* x) const { ::XFree(x); } -}; - bool ValidFormat(unsigned internalformat) { switch (internalformat) { case GL_RGB: @@ -141,11 +134,9 @@ BindToTextureFormat(internalformat_), GL_TRUE, 0}; int num_elements = 0; - scoped_ptr<GLXFBConfig, ScopedPtrXFree> config( - glXChooseFBConfig(gfx::GetXDisplay(), - DefaultScreen(gfx::GetXDisplay()), - config_attribs, - &num_elements)); + gfx::XScopedPtr<GLXFBConfig> config( + glXChooseFBConfig(gfx::GetXDisplay(), DefaultScreen(gfx::GetXDisplay()), + config_attribs, &num_elements)); if (!config.get()) { DVLOG(0) << "glXChooseFBConfig failed."; return false;
diff --git a/ui/gl/gl_implementation_win.cc b/ui/gl/gl_implementation_win.cc index 477f5a5..618250d 100644 --- a/ui/gl/gl_implementation_win.cc +++ b/ui/gl/gl_implementation_win.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/files/file_path.h" +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/native_library.h" #include "base/path_service.h" @@ -16,6 +17,8 @@ #include "base/threading/thread_restrictions.h" #include "base/trace_event/trace_event.h" #include "base/win/windows_version.h" +// TODO(jmadill): Apply to all platforms eventually +#include "ui/gl/angle_platform_impl.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context_stub_with_extensions.h" #include "ui/gl/gl_egl_api_implementation.h" @@ -97,6 +100,10 @@ GetCategoryEnabledFlagFunc get_category_enabled_flag, AddTraceEventFunc add_trace_event_func); +// TODO(jmadill): Apply to all platforms eventually +base::LazyInstance<ANGLEPlatformImpl> g_angle_platform_impl = + LAZY_INSTANCE_INITIALIZER; + } // namespace void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) { @@ -111,6 +118,10 @@ // later switch to another GL implementation. DCHECK_EQ(kGLImplementationNone, GetGLImplementation()); + // Init ANGLE platform here, before we call GetPlatformDisplay(). + // TODO(jmadill): Apply to all platforms eventually + angle::Platform::initialize(&g_angle_platform_impl.Get()); + // Allow the main thread or another to initialize these bindings // after instituting restrictions on I/O. Going forward they will // likely be used in the browser process on most platforms. The @@ -348,6 +359,9 @@ } void ClearGLBindings() { + // TODO(jmadill): Apply to all platforms eventually + angle::Platform::shutdown(); + ClearGLBindingsEGL(); ClearGLBindingsGL(); ClearGLBindingsOSMESA();
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc index 5a3eafd..d66078c 100644 --- a/ui/gl/gl_surface_glx.cc +++ b/ui/gl/gl_surface_glx.cc
@@ -33,15 +33,6 @@ namespace { -// scoped_ptr functor for XFree(). Use as follows: -// scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...); -// where "XVisualInfo" is any X type that is freed with XFree. -struct ScopedPtrXFree { - void operator()(void* x) const { - ::XFree(x); - } -}; - Display* g_display = NULL; const char* g_glx_extensions = NULL; bool g_glx_context_create = false; @@ -180,9 +171,8 @@ visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); int visual_info_count = 0; - scoped_ptr<XVisualInfo, ScopedPtrXFree> visual_info_list( - XGetVisualInfo(display_, VisualIDMask, - &visual_info_template, &visual_info_count)); + gfx::XScopedPtr<XVisualInfo> visual_info_list(XGetVisualInfo( + display_, VisualIDMask, &visual_info_template, &visual_info_count)); DCHECK(visual_info_list.get()); if (visual_info_count == 0) { @@ -553,10 +543,8 @@ int visual_id = XVisualIDFromVisual(attributes.visual); int num_elements = 0; - scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs( - glXGetFBConfigs(g_display, - DefaultScreen(g_display), - &num_elements)); + gfx::XScopedPtr<GLXFBConfig> configs( + glXGetFBConfigs(g_display, DefaultScreen(g_display), &num_elements)); if (!configs.get()) { LOG(ERROR) << "glXGetFBConfigs failed."; return NULL; @@ -628,11 +616,8 @@ }; int num_elements = 0; - scoped_ptr<GLXFBConfig, ScopedPtrXFree> configs( - glXChooseFBConfig(g_display, - DefaultScreen(g_display), - config_attributes, - &num_elements)); + gfx::XScopedPtr<GLXFBConfig> configs(glXChooseFBConfig( + g_display, DefaultScreen(g_display), config_attributes, &num_elements)); if (!configs.get()) { LOG(ERROR) << "glXChooseFBConfig failed."; return false;
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc index 47ea8d6..800be17 100644 --- a/ui/gl/gl_surface_ozone.cc +++ b/ui/gl/gl_surface_ozone.cc
@@ -5,8 +5,12 @@ #include "ui/gl/gl_surface.h" #include "base/bind.h" +#include "base/callback.h" +#include "base/location.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/worker_pool.h" #include "ui/gfx/native_widget_types.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_image.h" @@ -25,6 +29,11 @@ namespace { +void WaitForFence(EGLDisplay display, EGLSyncKHR fence) { + eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + EGL_FOREVER_KHR); +} + // A thin wrapper around GLSurfaceEGL that owns the EGLNativeWindow class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL { public: @@ -111,7 +120,9 @@ ozone_surface_(ozone_surface.Pass()), widget_(widget), has_implicit_external_sync_( - HasEGLExtension("EGL_ARM_implicit_external_sync")) {} + HasEGLExtension("EGL_ARM_implicit_external_sync")), + last_swap_buffers_result_(true), + weak_factory_(this) {} bool Initialize() override { if (!SurfacelessEGL::Initialize()) @@ -128,8 +139,21 @@ return SurfacelessEGL::Resize(size); } bool SwapBuffers() override { - if (!Flush()) - return false; + glFlush(); + // TODO: the following should be replaced by a per surface flush as it gets + // implemented in GL drivers. + if (has_implicit_external_sync_) { + EGLSyncKHR fence = InsertFence(); + if (!fence) + return false; + + EGLDisplay display = GetDisplay(); + WaitForFence(display, fence); + eglDestroySyncKHR(display, fence); + } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { + glFinish(); + } + return ozone_surface_->OnSwapBuffers(); } bool ScheduleOverlayPlane(int z_order, @@ -149,8 +173,33 @@ return true; } bool SwapBuffersAsync(const SwapCompletionCallback& callback) override { - if (!Flush()) - return false; + glFlush(); + // TODO: the following should be replaced by a per surface flush as it gets + // implemented in GL drivers. + if (has_implicit_external_sync_) { + // If last swap failed, don't try to schedule new ones. + if (!last_swap_buffers_result_) { + last_swap_buffers_result_ = true; + return false; + } + + EGLSyncKHR fence = InsertFence(); + if (!fence) + return false; + + base::Closure fence_wait_task = + base::Bind(&WaitForFence, GetDisplay(), fence); + + base::Closure fence_retired_callback = + base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, + weak_factory_.GetWeakPtr(), fence, callback); + + base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, + fence_retired_callback, false); + return true; + } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { + glFinish(); + } return ozone_surface_->OnSwapBuffersAsync(callback); } bool PostSubBufferAsync(int x, @@ -166,30 +215,16 @@ Destroy(); // EGL surface must be destroyed before SurfaceOzone } - bool Flush() { - glFlush(); - // TODO: crbug.com/462360 the following should be replaced by a per surface - // flush as it gets implemented in GL drivers. - if (has_implicit_external_sync_) { - const EGLint attrib_list[] = { - EGL_SYNC_CONDITION_KHR, - EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, - EGL_NONE}; - EGLSyncKHR fence = - eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); - if (fence) { - // TODO(dbehr): piman@ suggests we could improve here by moving - // following wait to right before drmModePageFlip crbug.com/456417. - eglClientWaitSyncKHR(GetDisplay(), fence, - EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); - eglDestroySyncKHR(GetDisplay(), fence); - } else { - return false; - } - } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { - glFinish(); - } - return true; + EGLSyncKHR InsertFence() { + const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR, + EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM, + EGL_NONE}; + return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list); + } + + void FenceRetired(EGLSyncKHR fence, const SwapCompletionCallback& callback) { + eglDestroySyncKHR(GetDisplay(), fence); + last_swap_buffers_result_ = ozone_surface_->OnSwapBuffersAsync(callback); } // The native surface. Deleting this is allowed to free the EGLNativeWindow. @@ -197,6 +232,10 @@ AcceleratedWidget widget_; scoped_ptr<VSyncProvider> vsync_provider_; bool has_implicit_external_sync_; + bool last_swap_buffers_result_; + + base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless); };
diff --git a/ui/gl/gpu_timing.cc b/ui/gl/gpu_timing.cc index a3b697f..a744164 100644 --- a/ui/gl/gpu_timing.cc +++ b/ui/gl/gpu_timing.cc
@@ -20,6 +20,8 @@ timer_type_ = kTimerTypeDisjoint; } else if (context->HasExtension("GL_ARB_timer_query")) { timer_type_ = kTimerTypeARB; + } else if (context->HasExtension("GL_EXT_timer_query")) { + timer_type_ = kTimerTypeEXT; } } @@ -46,14 +48,35 @@ } void GPUTimer::Start() { - // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. - glQueryCounter(queries_[0], GL_TIMESTAMP); + switch (gpu_timing_client_->gpu_timing_->timer_type_) { + case GPUTiming::kTimerTypeARB: + case GPUTiming::kTimerTypeDisjoint: + // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. + glQueryCounter(queries_[0], GL_TIMESTAMP); + break; + case GPUTiming::kTimerTypeEXT: + glBeginQuery(GL_TIME_ELAPSED_EXT, queries_[0]); + break; + default: + NOTREACHED(); + } } void GPUTimer::End() { end_requested_ = true; - offset_ = gpu_timing_client_->CalculateTimerOffset(); - glQueryCounter(queries_[1], GL_TIMESTAMP); + DCHECK(gpu_timing_client_->gpu_timing_); + switch (gpu_timing_client_->gpu_timing_->timer_type_) { + case GPUTiming::kTimerTypeARB: + case GPUTiming::kTimerTypeDisjoint: + offset_ = gpu_timing_client_->CalculateTimerOffset(); + glQueryCounter(queries_[1], GL_TIMESTAMP); + break; + case GPUTiming::kTimerTypeEXT: + glEndQuery(GL_TIME_ELAPSED_EXT); + break; + default: + NOTREACHED(); + } } bool GPUTimer::IsAvailable() { @@ -61,13 +84,17 @@ return false; } GLint done = 0; - glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); + glGetQueryObjectivARB(queries_[1] ? queries_[1] : queries_[0], + GL_QUERY_RESULT_AVAILABLE, &done); return done != 0; } void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) { DCHECK(start && end); DCHECK(IsAvailable()); + DCHECK(gpu_timing_client_->gpu_timing_); + DCHECK(gpu_timing_client_->gpu_timing_->timer_type_ != + GPUTiming::kTimerTypeEXT); GLuint64 begin_stamp = 0; GLuint64 end_stamp = 0; // TODO(dsinclair): It's possible for the timer to wrap during the start/end. @@ -81,17 +108,44 @@ } int64 GPUTimer::GetDeltaElapsed() { - int64 start = 0; - int64 end = 0; - GetStartEndTimestamps(&start, &end); - return end - start; + DCHECK(gpu_timing_client_->gpu_timing_); + switch (gpu_timing_client_->gpu_timing_->timer_type_) { + case GPUTiming::kTimerTypeARB: + case GPUTiming::kTimerTypeDisjoint: { + int64 start = 0; + int64 end = 0; + GetStartEndTimestamps(&start, &end); + return end - start; + } break; + case GPUTiming::kTimerTypeEXT: { + GLuint64 delta = 0; + glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &delta); + return static_cast<int64>(delta / base::Time::kNanosecondsPerMicrosecond); + } break; + default: + NOTREACHED(); + } + return 0; } GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client) : gpu_timing_client_(gpu_timing_client) { DCHECK(gpu_timing_client_); memset(queries_, 0, sizeof(queries_)); - glGenQueriesARB(2, queries_); + int queries = 0; + DCHECK(gpu_timing_client_->gpu_timing_); + switch (gpu_timing_client_->gpu_timing_->timer_type_) { + case GPUTiming::kTimerTypeARB: + case GPUTiming::kTimerTypeDisjoint: + queries = 2; + break; + case GPUTiming::kTimerTypeEXT: + queries = 1; + break; + default: + NOTREACHED(); + } + glGenQueriesARB(queries, queries_); } GPUTimingClient::GPUTimingClient(GPUTiming* gpu_timing) @@ -110,12 +164,19 @@ return timer_type_ != GPUTiming::kTimerTypeInvalid; } +bool GPUTimingClient::IsTimerOffsetAvailable() { + return timer_type_ == GPUTiming::kTimerTypeARB || + timer_type_ == GPUTiming::kTimerTypeDisjoint; +} + const char* GPUTimingClient::GetTimerTypeName() const { switch (timer_type_) { case GPUTiming::kTimerTypeDisjoint: return "GL_EXT_disjoint_timer_query"; case GPUTiming::kTimerTypeARB: return "GL_ARB_timer_query"; + case GPUTiming::kTimerTypeEXT: + return "GL_EXT_timer_query"; default: return "Unknown"; } @@ -133,6 +194,7 @@ } int64 GPUTimingClient::CalculateTimerOffset() { + DCHECK(IsTimerOffsetAvailable()); if (!offset_valid_) { GLint64 gl_now = 0; glGetInteger64v(GL_TIMESTAMP, &gl_now);
diff --git a/ui/gl/gpu_timing.h b/ui/gl/gpu_timing.h index 1c8f8cf..a749ef1 100644 --- a/ui/gl/gpu_timing.h +++ b/ui/gl/gpu_timing.h
@@ -2,16 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_ -#define GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_ +#ifndef UI_GL_GPU_TIMING_H_ +#define UI_GL_GPU_TIMING_H_ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "ui/gl/gl_export.h" // The gpu_timing classes handles the abstraction of GL GPU Timing extensions -// into a common set of functions. Currently the different timer extensions -// that are supported are ARB_timer_query and EXT_disjoint_timer_query. +// into a common set of functions. Currently the different timer extensions that +// are supported are EXT_timer_query, ARB_timer_query and +// EXT_disjoint_timer_query. // // Explanation of Classes: // GPUTiming - GPU Timing is a private class which is only owned by the @@ -28,11 +29,11 @@ // obtain various GPU times they would access CreateGPUTimingClient() from // their GLContext and use the returned object for their timing calls. // Each virtual context as well as any other classes which need GPU times -// will hold one of these. When they want to time a GPU trace they will -// create GPUTimer objects. -// GPUTimer - Once a user decides to trace something, the user creates a new +// will hold one of these. When they want to time a set of GL commands they +// will create GPUTimer objects. +// GPUTimer - Once a user decides to time something, the user creates a new // GPUTimer object from a GPUTimingClient and issue Start() and Stop() calls -// around various GL Calls. Once IsAvailable() returns true, the GPU times +// around various GL calls. Once IsAvailable() returns true, the GPU times // will be available through the various time stamp related functions. // The constructor and destructor of this object handles the actual // creation and deletion of the GL Queries within GL. @@ -47,6 +48,7 @@ enum TimerType { kTimerTypeInvalid = -1, + kTimerTypeEXT, // EXT_timer_query kTimerTypeARB, // ARB_timer_query kTimerTypeDisjoint // EXT_disjoint_timer_query }; @@ -57,6 +59,7 @@ private: friend struct base::DefaultDeleter<GPUTiming>; friend class GLContextReal; + friend class GPUTimer; explicit GPUTiming(GLContextReal* context); ~GPUTiming(); @@ -102,6 +105,8 @@ scoped_ptr<GPUTimer> CreateGPUTimer(); bool IsAvailable(); + bool IsTimerOffsetAvailable(); + const char* GetTimerTypeName() const; // CheckAndResetTimerErrors has to be called before reading timestamps @@ -136,4 +141,4 @@ } // namespace gfx -#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_ +#endif // UI_GL_GPU_TIMING_H_
diff --git a/url/url.gyp b/url/url.gyp index 0ffc51a..4114801 100644 --- a/url/url.gyp +++ b/url/url.gyp
@@ -33,28 +33,6 @@ 'defines': [ 'URL_IMPLEMENTATION', ], - 'conditions': [ - ['use_icu_alternatives_on_android==1', { - 'sources!': [ - 'url_canon_icu.cc', - 'url_canon_icu.h', - ], - 'dependencies!': [ - '../third_party/icu/icu.gyp:icui18n', - '../third_party/icu/icu.gyp:icuuc', - ], - }], - ['use_icu_alternatives_on_android==1 and OS=="android"', { - 'dependencies': [ - 'url_java', - 'url_jni_headers', - ], - 'sources': [ - 'url_canon_icu_alternatives_android.cc', - 'url_canon_icu_alternatives_android.h', - ], - }], - ], # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. 'msvs_disabled_warnings': [4267, ], }, @@ -84,23 +62,13 @@ ], } ], - ['use_icu_alternatives_on_android==1', - { - 'sources!': [ - 'url_canon_icu_unittest.cc', - ], - 'dependencies!': [ - '../third_party/icu/icu.gyp:icuuc', - ], - } - ], ], # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. 'msvs_disabled_warnings': [4267, ], }, ], 'conditions': [ - ['use_icu_alternatives_on_android==1 and OS=="android"', { + ['OS=="android"', { 'targets': [ { 'target_name': 'url_jni_headers', @@ -124,6 +92,35 @@ ], 'includes': [ '../build/java.gypi' ], }, + { + # Same as url_lib but using ICU alternatives on Android. + 'target_name': 'url_lib_use_icu_alternatives_on_android', + 'type': '<(component)', + 'dependencies': [ + '../base/base.gyp:base', + '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', + 'url_java', + 'url_jni_headers', + ], + 'sources': [ + '<@(gurl_sources)', + 'url_canon_icu_alternatives_android.cc', + 'url_canon_icu_alternatives_android.h', + ], + 'sources!': [ + 'url_canon_icu.cc', + 'url_canon_icu.h', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '..', + ], + }, + 'defines': [ + 'URL_IMPLEMENTATION', + 'USE_ICU_ALTERNATIVES_ON_ANDROID=1', + ], + }, ], }], ],