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',
+ ],
+ },
],
}],
],