Update from https://crrev.com/316786
List of manually-modified files:
gpu/command_buffer/service/in_process_command_buffer.cc
examples/sample_app/BUILD.gn
examples/sample_app/spinning_cube.cc
mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java
mojo/cc/context_provider_mojo.cc
mojo/cc/context_provider_mojo.h
mojo/common/trace_controller_impl.cc
mojo/gles2/command_buffer_client_impl.cc
mojo/gles2/command_buffer_client_impl.h
services/gles2/gpu_impl.cc
shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
sky/engine/core/dom/Node.cpp
sky/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java
ui/events/latency_info.cc
ui/gfx/transform.cc
ui/gfx/transform.h
ui/gfx/transform_util.cc
ui/gfx/transform_util.h
Review URL: https://codereview.chromium.org/935333002
diff --git a/DEPS b/DEPS
index 88662b7..996c547 100644
--- a/DEPS
+++ b/DEPS
@@ -21,19 +21,19 @@
'chromium_git': 'https://chromium.googlesource.com',
'dart_svn': 'https://dart.googlecode.com',
'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac',
- 'skia_revision': '02c8fd0ad5e5279004dd49ec49fbae00f8522ec0',
+ 'skia_revision': 'd1371a6019189820653aaf20f72ee8f5d0ee3fef',
# 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': '0aa5f75929fa3b383ec749555e045e47199ba6d5',
+ 'v8_revision': '055b865a326cdf6a28d2bbb0f197b36e09069fc1',
# 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': '592ab9dd91e653f5c2d4f7395267046d229e20c1',
+ 'angle_revision': '73edef0a2a162e943d5be7715f53bee5d9452b2e',
# 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.
- 'buildtools_revision': 'da0df3fdac6036e862addb1155a2d6c11b6c18d5',
+ 'buildtools_revision': '5c5e924788fe40f7d6e0a3841ac572de2475e689',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Dart
# and whatever else without interference from each other.
@@ -41,11 +41,11 @@
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling PDFium
# and whatever else without interference from each other.
- 'pdfium_revision': '7061d1af45752617fafa85e2242dc5b2844650b5',
+ 'pdfium_revision': '58985096a7852263df68e87d9bfc335a3e2759bf',
# 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': '8f5e2ebcee628ef02add9b21955402b0c6256624',
+ 'boringssl_revision': 'd306f165a462f47c2c0e8f3a0f2b4ae6950f70ed',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling lss
# and whatever else without interference from each other.
@@ -159,7 +159,7 @@
Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919',
'src/third_party/android_tools':
- Var('chromium_git') + '/android_tools.git' + '@' + 'f6e2370dff438125897bb3b3800de1ad7aa62c27',
+ Var('chromium_git') + '/android_tools.git' + '@' + 'fd5a8ec0c75d487635f7e6bd3bdc90eb23eba941',
'src/third_party/appurify-python/src':
Var('chromium_git') + '/external/github.com/appurify/appurify-python.git' + '@' + 'ee7abd5c5ae3106f72b2a0b9d2cb55094688e867',
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 44e656c..e417681 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -11,12 +11,6 @@
component("base") {
sources = [
- "third_party/dmg_fp/dmg_fp.h",
- "third_party/dmg_fp/g_fmt.cc",
- "third_party/dmg_fp/dtoa_wrapper.cc",
- "third_party/icu/icu_utf.cc",
- "third_party/icu/icu_utf.h",
- "third_party/superfasthash/superfasthash.c",
"allocator/allocator_extension.cc",
"allocator/allocator_extension.h",
"allocator/type_profiler_control.cc",
@@ -94,6 +88,8 @@
"auto_reset.h",
"barrier_closure.cc",
"barrier_closure.h",
+ "base64.cc",
+ "base64.h",
"base_export.h",
"base_paths.cc",
"base_paths.h",
@@ -106,8 +102,6 @@
"base_paths_win.cc",
"base_paths_win.h",
"base_switches.h",
- "base64.cc",
- "base64.h",
"basictypes.h",
"big_endian.cc",
"big_endian.h",
@@ -125,10 +119,10 @@
"callback_internal.cc",
"callback_internal.h",
"cancelable_callback.h",
- "command_line.cc",
- "command_line.h",
"chromeos/memory_pressure_observer_chromeos.cc",
"chromeos/memory_pressure_observer_chromeos.h",
+ "command_line.cc",
+ "command_line.h",
"compiler_specific.h",
"containers/adapters.h",
"containers/hash_tables.h",
@@ -154,6 +148,12 @@
"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
@@ -185,8 +185,6 @@
"files/dir_reader_linux.h",
"files/dir_reader_posix.h",
"files/file.cc",
- "files/file_posix.cc",
- "files/file_win.cc",
"files/file_enumerator.cc",
"files/file_enumerator.h",
"files/file_enumerator_posix.cc",
@@ -203,6 +201,7 @@
"files/file_path_watcher_linux.cc",
"files/file_path_watcher_mac.cc",
"files/file_path_watcher_win.cc",
+ "files/file_posix.cc",
"files/file_proxy.cc",
"files/file_proxy.h",
"files/file_util.cc",
@@ -214,6 +213,7 @@
"files/file_util_proxy.cc",
"files/file_util_proxy.h",
"files/file_util_win.cc",
+ "files/file_win.cc",
"files/important_file_writer.cc",
"files/important_file_writer.h",
"files/memory_mapped_file.cc",
@@ -280,8 +280,8 @@
"mac/launchd.h",
"mac/libdispatch_task_runner.cc",
"mac/libdispatch_task_runner.h",
- "mac/mac_logging.h",
"mac/mac_logging.cc",
+ "mac/mac_logging.h",
"mac/mac_util.h",
"mac/mac_util.mm",
"mac/mach_logging.cc",
@@ -378,19 +378,19 @@
"message_loop/message_pump_mac.mm",
"message_loop/message_pump_win.cc",
"message_loop/message_pump_win.h",
- "metrics/field_trial.cc",
- "metrics/field_trial.h",
- "metrics/sample_map.cc",
- "metrics/sample_map.h",
- "metrics/sample_vector.cc",
- "metrics/sample_vector.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.cc",
+ "metrics/sample_map.cc",
+ "metrics/sample_map.h",
+ "metrics/sample_vector.cc",
+ "metrics/sample_vector.h",
"metrics/histogram_delta_serialization.",
"metrics/histogram_flattener.h",
"metrics/histogram_macros.h",
@@ -402,10 +402,6 @@
"metrics/sparse_histogram.h",
"metrics/statistics_recorder.cc",
"metrics/statistics_recorder.h",
- "metrics/stats_counters.cc",
- "metrics/stats_counters.h",
- "metrics/stats_table.cc",
- "metrics/stats_table.h",
"metrics/user_metrics.cc",
"metrics/user_metrics.h",
"metrics/user_metrics_action.h",
@@ -414,14 +410,14 @@
"native_library_mac.mm",
"native_library_posix.cc",
"native_library_win.cc",
- "numerics/safe_conversions.h",
- "numerics/safe_conversions_impl.h",
- "numerics/safe_math.h",
- "numerics/safe_math_impl.h",
"nix/mime_util_xdg.cc",
"nix/mime_util_xdg.h",
"nix/xdg_util.cc",
"nix/xdg_util.h",
+ "numerics/safe_conversions.h",
+ "numerics/safe_conversions_impl.h",
+ "numerics/safe_math.h",
+ "numerics/safe_math_impl.h",
"observer_list.h",
"observer_list_threadsafe.h",
"os_compat_android.cc",
@@ -544,11 +540,11 @@
"strings/string16.cc",
"strings/string16.h",
"strings/string_number_conversions.cc",
- "strings/string_split.cc",
- "strings/string_split.h",
"strings/string_number_conversions.h",
"strings/string_piece.cc",
"strings/string_piece.h",
+ "strings/string_split.cc",
+ "strings/string_split.h",
"strings/string_tokenizer.h",
"strings/string_util.cc",
"strings/string_util.h",
@@ -590,8 +586,6 @@
"synchronization/waitable_event_watcher_posix.cc",
"synchronization/waitable_event_watcher_win.cc",
"synchronization/waitable_event_win.cc",
- "system_monitor/system_monitor.cc",
- "system_monitor/system_monitor.h",
"sys_byteorder.h",
"sys_info.cc",
"sys_info.h",
@@ -604,6 +598,8 @@
"sys_info_openbsd.cc",
"sys_info_posix.cc",
"sys_info_win.cc",
+ "system_monitor/system_monitor.cc",
+ "system_monitor/system_monitor.h",
"task/cancelable_task_tracker.cc",
"task/cancelable_task_tracker.h",
"task_runner.cc",
@@ -644,12 +640,12 @@
"threading/thread_local_storage_posix.cc",
"threading/thread_local_storage_win.cc",
"threading/thread_local_win.cc",
- "threading/thread_restrictions.h",
"threading/thread_restrictions.cc",
+ "threading/thread_restrictions.h",
"threading/watchdog.cc",
"threading/watchdog.h",
- "threading/worker_pool.h",
"threading/worker_pool.cc",
+ "threading/worker_pool.h",
"threading/worker_pool_posix.cc",
"threading/worker_pool_posix.h",
"threading/worker_pool_win.cc",
@@ -675,6 +671,11 @@
"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/trace_event.h",
"trace_event/trace_event_android.cc",
"trace_event/trace_event_argument.cc",
@@ -695,10 +696,10 @@
"tracking_info.cc",
"tracking_info.h",
"tuple.h",
- "values.cc",
- "values.h",
"value_conversions.cc",
"value_conversions.h",
+ "values.cc",
+ "values.h",
"version.cc",
"version.h",
"vlog.cc",
@@ -787,10 +788,10 @@
if (is_android) {
sources += [
- "memory/discardable_memory_ashmem_allocator.cc",
- "memory/discardable_memory_ashmem_allocator.h",
"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",
@@ -802,12 +803,12 @@
sources += [
"debug/proc_maps_linux.cc",
"files/file_path_watcher_linux.cc",
- "process/memory_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",
- "posix/unix_domain_socket_linux.cc",
"sys_info_linux.cc",
]
set_sources_assignment_filter(sources_assignment_filter)
@@ -835,24 +836,24 @@
"debug/stack_trace_posix.cc",
"files/file_enumerator_posix.cc",
"files/file_util_posix.cc",
+ "memory/shared_memory_posix.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",
- "metrics/field_trial.cc",
- "native_library_posix.cc",
- "memory/shared_memory_posix.cc",
"sync_socket_posix.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",
- "memory/shared_memory_nacl.cc",
]
}
@@ -1126,6 +1127,10 @@
sources = [
"files/protect_file_posix.cc",
]
+
+ deps = [
+ "//base",
+ ]
}
test("base_unittests") {
@@ -1183,10 +1188,9 @@
"gmock_unittest.cc",
"guid_unittest.cc",
"hash_unittest.cc",
- "id_map_unittest.cc",
"i18n/break_iterator_unittest.cc",
- "i18n/char_iterator_unittest.cc",
"i18n/case_conversion_unittest.cc",
+ "i18n/char_iterator_unittest.cc",
"i18n/file_util_icu_unittest.cc",
"i18n/icu_string_conversions_unittest.cc",
"i18n/number_formatting_unittest.cc",
@@ -1195,6 +1199,7 @@
"i18n/string_search_unittest.cc",
"i18n/time_formatting_unittest.cc",
"i18n/timezone_unittest.cc",
+ "id_map_unittest.cc",
"ios/device_util_unittest.mm",
"ios/weak_nsobject_unittest.mm",
"json/json_parser_unittest.cc",
@@ -1233,17 +1238,17 @@
"message_loop/message_loop_unittest.cc",
"message_loop/message_pump_glib_unittest.cc",
"message_loop/message_pump_io_ios_unittest.cc",
- "metrics/sample_map_unittest.cc",
- "metrics/sample_vector_unittest.cc",
"metrics/bucket_ranges_unittest.cc",
"metrics/field_trial_unittest.cc",
"metrics/histogram_base_unittest.cc",
"metrics/histogram_delta_serialization_unittest.cc",
"metrics/histogram_snapshot_manager_unittest.cc",
"metrics/histogram_unittest.cc",
+ "metrics/sample_map_unittest.cc",
+ "metrics/sample_vector_unittest.cc",
"metrics/sparse_histogram_unittest.cc",
- "metrics/stats_table_unittest.cc",
"metrics/statistics_recorder_unittest.cc",
+ "numerics/safe_numerics_unittest.cc",
"observer_list_unittest.cc",
"os_compat_android_unittest.cc",
"path_service_unittest.cc",
@@ -1271,7 +1276,6 @@
"process/process_util_unittest_ios.cc",
"profiler/tracked_time_unittest.cc",
"rand_util_unittest.cc",
- "numerics/safe_numerics_unittest.cc",
"scoped_clear_errno_unittest.cc",
"scoped_generic_unittest.cc",
"scoped_native_library_unittest.cc",
@@ -1282,13 +1286,13 @@
"strings/nullable_string16_unittest.cc",
"strings/safe_sprintf_unittest.cc",
"strings/string16_unittest.cc",
- "strings/stringprintf_unittest.cc",
"strings/string_number_conversions_unittest.cc",
"strings/string_piece_unittest.cc",
"strings/string_split_unittest.cc",
"strings/string_tokenizer_unittest.cc",
"strings/string_util_unittest.cc",
"strings/stringize_macros_unittest.cc",
+ "strings/stringprintf_unittest.cc",
"strings/sys_string_conversions_mac_unittest.mm",
"strings/sys_string_conversions_unittest.cc",
"strings/utf_offset_string_conversions_unittest.cc",
@@ -1330,6 +1334,7 @@
"timer/mock_timer_unittest.cc",
"timer/timer_unittest.cc",
"tools_sanity_unittest.cc",
+ "trace_event/memory_dump_manager_unittest.cc",
"trace_event/trace_event_argument_unittest.cc",
"trace_event/trace_event_memory_unittest.cc",
"trace_event/trace_event_synthetic_delay_unittest.cc",
@@ -1372,6 +1377,7 @@
"//base/test:run_all_unittests",
"//base/test:test_support",
"//base/third_party/dynamic_annotations",
+ "//base/third_party/nspr",
"//testing/gmock",
"//testing/gtest",
"//third_party/icu",
@@ -1386,7 +1392,6 @@
if (is_ios) {
sources -= [
- "metrics/stats_table_uinittest.cc", # Requires spawning a process.
"process/memory_unittest.cc",
"process/memory_unittest_mac.h",
"process/memory_unittest_mac.mm",
@@ -1509,16 +1514,19 @@
# GYP: //base.gyp:base_java_application_state
# GYP: //base.gyp:base_java_library_load_from_apk_status_codes
+ # GYP: //base.gyp:base_java_library_process_type
# GYP: //base.gyp:base_java_memory_pressure_level
java_cpp_enum("base_android_java_enums_srcjar") {
sources = [
"android/application_status_listener.h",
"android/library_loader/library_load_from_apk_status_codes.h",
+ "android/library_loader/library_loader_hooks.h",
"memory/memory_pressure_listener.h",
]
outputs = [
"org/chromium/base/ApplicationState.java",
"org/chromium/base/library_loader/LibraryLoadFromApkStatusCodes.java",
+ "org/chromium/base/library_loader/LibraryProcessType.java",
"org/chromium/base/MemoryPressureLevel.java",
]
}
diff --git a/base/allocator/BUILD.gn b/base/allocator/BUILD.gn
index 8d96317..e931b1c 100644
--- a/base/allocator/BUILD.gn
+++ b/base/allocator/BUILD.gn
@@ -46,6 +46,11 @@
source_set("tcmalloc") {
tcmalloc_dir = "//third_party/tcmalloc/chromium"
+ # Don't check tcmalloc's includes. These files include various files like
+ # base/foo.h and they actually refer to tcmalloc's forked copy of base
+ # rather than the regular one, which confuses the header checker.
+ check_includes = false
+
sources = [
# Generated for our configuration from tcmalloc"s build
# and checked in.
@@ -134,7 +139,6 @@
"$tcmalloc_dir/src/windows/port.cc",
"$tcmalloc_dir/src/windows/port.h",
"allocator_shim.cc",
- "allocator_shim.h",
"debugallocation_shim.cc",
# These are both #included by allocator_shim for maximal linking.
@@ -176,10 +180,10 @@
# cpuprofiler
"$tcmalloc_dir/src/base/thread_lister.c",
"$tcmalloc_dir/src/base/thread_lister.h",
- "$tcmalloc_dir/src/profiledata.cc",
- "$tcmalloc_dir/src/profiledata.h",
"$tcmalloc_dir/src/profile-handler.cc",
"$tcmalloc_dir/src/profile-handler.h",
+ "$tcmalloc_dir/src/profiledata.cc",
+ "$tcmalloc_dir/src/profiledata.h",
"$tcmalloc_dir/src/profiler.cc",
]
defines += [ "PERFTOOLS_DLL_DECL=" ]
diff --git a/base/allocator/allocator.gyp b/base/allocator/allocator.gyp
index c20325d..d426c9c 100644
--- a/base/allocator/allocator.gyp
+++ b/base/allocator/allocator.gyp
@@ -106,9 +106,9 @@
'<(tcmalloc_dir)/src/base/abort.cc',
'<(tcmalloc_dir)/src/base/abort.h',
'<(tcmalloc_dir)/src/base/arm_instruction_set_select.h',
- '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-arm-generic.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-arm-v6plus.h',
+ '<(tcmalloc_dir)/src/base/atomicops-internals-linuxppc.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-macosx.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-windows.h',
'<(tcmalloc_dir)/src/base/atomicops-internals-x86.cc',
@@ -322,10 +322,10 @@
# cpuprofiler
'<(tcmalloc_dir)/src/base/thread_lister.c',
'<(tcmalloc_dir)/src/base/thread_lister.h',
- '<(tcmalloc_dir)/src/profiledata.cc',
- '<(tcmalloc_dir)/src/profiledata.h',
'<(tcmalloc_dir)/src/profile-handler.cc',
'<(tcmalloc_dir)/src/profile-handler.h',
+ '<(tcmalloc_dir)/src/profiledata.cc',
+ '<(tcmalloc_dir)/src/profiledata.h',
'<(tcmalloc_dir)/src/profiler.cc',
],
}],
@@ -434,9 +434,9 @@
'../..',
],
'sources': [
- 'allocator_unittest.cc',
'../profiler/alternate_timer.cc',
'../profiler/alternate_timer.h',
+ 'allocator_unittest.cc',
],
},
],
@@ -499,10 +499,10 @@
'../..',
],
'sources': [
- 'type_profiler_tcmalloc.cc',
- 'type_profiler_tcmalloc.h',
'<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
'<(tcmalloc_dir)/src/type_profiler_map.cc',
+ 'type_profiler_tcmalloc.cc',
+ 'type_profiler_tcmalloc.h',
],
},
{
@@ -542,9 +542,9 @@
'../..',
],
'sources': [
- 'type_profiler_map_unittest.cc',
'<(tcmalloc_dir)/src/gperftools/type_profiler_map.h',
'<(tcmalloc_dir)/src/type_profiler_map.cc',
+ 'type_profiler_map_unittest.cc',
],
},
],
diff --git a/base/allocator/allocator_unittest.cc b/base/allocator/allocator_unittest.cc
index 9471e95..a1d1ef0 100644
--- a/base/allocator/allocator_unittest.cc
+++ b/base/allocator/allocator_unittest.cc
@@ -6,7 +6,7 @@
#include <stdlib.h>
#include <algorithm> // for min()
-#include "base/atomicops.h"
+#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
// Number of bits in a size_t.
@@ -15,10 +15,6 @@
static const size_t kMaxSize = ~static_cast<size_t>(0);
// Maximum positive size of a size_t if it were signed.
static const size_t kMaxSignedSize = ((size_t(1) << (kSizeBits-1)) - 1);
-// An allocation size which is not too big to be reasonable.
-static const size_t kNotTooBig = 100000;
-// An allocation size which is just too big.
-static const size_t kTooBig = ~static_cast<size_t>(0);
namespace {
@@ -82,197 +78,6 @@
}
}
-template <class AtomicType>
-static void TestAtomicIncrement() {
- // For now, we just test single threaded execution
-
- // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
- // outside the expected address bounds. This is in particular to
- // test that some future change to the asm code doesn't cause the
- // 32-bit NoBarrier_AtomicIncrement to do the wrong thing on 64-bit machines.
- struct {
- AtomicType prev_word;
- AtomicType count;
- AtomicType next_word;
- } s;
-
- AtomicType prev_word_value, next_word_value;
- memset(&prev_word_value, 0xFF, sizeof(AtomicType));
- memset(&next_word_value, 0xEE, sizeof(AtomicType));
-
- s.prev_word = prev_word_value;
- s.count = 0;
- s.next_word = next_word_value;
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
- EXPECT_EQ(s.count, 1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
- EXPECT_EQ(s.count, 3);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
- EXPECT_EQ(s.count, 6);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
- EXPECT_EQ(s.count, 3);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
- EXPECT_EQ(s.count, 1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
- EXPECT_EQ(s.count, 0);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
- EXPECT_EQ(s.count, -1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
- EXPECT_EQ(s.count, -5);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
- EXPECT_EQ(s.count, 0);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-}
-
-
-#define NUM_BITS(T) (sizeof(T) * 8)
-
-
-template <class AtomicType>
-static void TestCompareAndSwap() {
- AtomicType value = 0;
- AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
- EXPECT_EQ(1, value);
- EXPECT_EQ(0, prev);
-
- // Use test value that has non-zero bits in both halves, more for testing
- // 64-bit implementation on 32-bit platforms.
- const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
- (NUM_BITS(AtomicType) - 2)) + 11;
- value = k_test_val;
- prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
- EXPECT_EQ(k_test_val, value);
- EXPECT_EQ(k_test_val, prev);
-
- value = k_test_val;
- prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
- EXPECT_EQ(5, value);
- EXPECT_EQ(k_test_val, prev);
-}
-
-
-template <class AtomicType>
-static void TestAtomicExchange() {
- AtomicType value = 0;
- AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
- EXPECT_EQ(1, value);
- EXPECT_EQ(0, new_value);
-
- // Use test value that has non-zero bits in both halves, more for testing
- // 64-bit implementation on 32-bit platforms.
- const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
- (NUM_BITS(AtomicType) - 2)) + 11;
- value = k_test_val;
- new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
- EXPECT_EQ(k_test_val, value);
- EXPECT_EQ(k_test_val, new_value);
-
- value = k_test_val;
- new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
- EXPECT_EQ(5, value);
- EXPECT_EQ(k_test_val, new_value);
-}
-
-
-template <class AtomicType>
-static void TestAtomicIncrementBounds() {
- // Test increment at the half-width boundary of the atomic type.
- // It is primarily for testing at the 32-bit boundary for 64-bit atomic type.
- AtomicType test_val = static_cast<uint64_t>(1) << (NUM_BITS(AtomicType) / 2);
- AtomicType value = test_val - 1;
- AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
- EXPECT_EQ(test_val, value);
- EXPECT_EQ(value, new_value);
-
- base::subtle::NoBarrier_AtomicIncrement(&value, -1);
- EXPECT_EQ(test_val - 1, value);
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestStore() {
- const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
- const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
- AtomicType value;
-
- base::subtle::NoBarrier_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::NoBarrier_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-
- base::subtle::Acquire_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::Acquire_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-
- base::subtle::Release_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::Release_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestLoad() {
- const AtomicType kVal1 = static_cast<AtomicType>(0xa5a5a5a5a5a5a5a5LL);
- const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
- AtomicType value;
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
-}
-
-template <class AtomicType>
-static void TestAtomicOps() {
- TestCompareAndSwap<AtomicType>();
- TestAtomicExchange<AtomicType>();
- TestAtomicIncrementBounds<AtomicType>();
- TestStore<AtomicType>();
- TestLoad<AtomicType>();
-}
-
static void TestCalloc(size_t n, size_t s, bool ok) {
char* p = reinterpret_cast<char*>(calloc(n, s));
if (!ok) {
@@ -287,80 +92,10 @@
}
}
-// MSVC C4530 complains about exception handler usage when exceptions are
-// disabled. Temporarily disable that warning so we can test that they are, in
-// fact, disabled.
-#if defined(OS_WIN)
-#pragma warning(push)
-#pragma warning(disable: 4530)
-#endif
-
-// A global test counter for number of times the NewHandler is called.
-static int news_handled = 0;
-static void TestNewHandler() {
- ++news_handled;
- throw std::bad_alloc();
-}
-
-// Because we compile without exceptions, we expect these will not throw.
-static void TestOneNewWithoutExceptions(void* (*func)(size_t),
- bool should_throw) {
- // success test
- try {
- void* ptr = (*func)(kNotTooBig);
- EXPECT_NE(reinterpret_cast<void*>(NULL), ptr) <<
- "allocation should not have failed.";
- } catch(...) {
- EXPECT_EQ(0, 1) << "allocation threw unexpected exception.";
- }
-
- // failure test
- try {
- void* rv = (*func)(kTooBig);
- EXPECT_EQ(NULL, rv);
- EXPECT_FALSE(should_throw) << "allocation should have thrown.";
- } catch(...) {
- EXPECT_TRUE(should_throw) << "allocation threw unexpected exception.";
- }
-}
-
-static void TestNothrowNew(void* (*func)(size_t)) {
- news_handled = 0;
-
- // test without new_handler:
- std::new_handler saved_handler = std::set_new_handler(0);
- TestOneNewWithoutExceptions(func, false);
-
- // test with new_handler:
- std::set_new_handler(TestNewHandler);
- TestOneNewWithoutExceptions(func, true);
- EXPECT_EQ(news_handled, 1) << "nothrow new_handler was not called.";
- std::set_new_handler(saved_handler);
-}
-
-#if defined(OS_WIN)
-#pragma warning(pop)
-#endif
-
} // namespace
//-----------------------------------------------------------------------------
-TEST(Atomics, AtomicIncrementWord) {
- TestAtomicIncrement<base::subtle::AtomicWord>();
-}
-
-TEST(Atomics, AtomicIncrement32) {
- TestAtomicIncrement<base::subtle::Atomic32>();
-}
-
-TEST(Atomics, AtomicOpsWord) {
- TestAtomicIncrement<base::subtle::AtomicWord>();
-}
-
-TEST(Atomics, AtomicOps32) {
- TestAtomicIncrement<base::subtle::Atomic32>();
-}
TEST(Allocators, Malloc) {
// Try allocating data with a bunch of alignments and sizes
@@ -394,11 +129,6 @@
TestCalloc(kMaxSignedSize, kMaxSignedSize, false);
}
-TEST(Allocators, New) {
- TestNothrowNew(&::operator new);
- TestNothrowNew(&::operator new[]);
-}
-
// This makes sure that reallocing a small number of bytes in either
// direction doesn't cause us to allocate new memory.
TEST(Allocators, Realloc1) {
@@ -458,23 +188,6 @@
free(p);
}
-// tcmalloc uses these semantics but system allocators can return NULL for
-// realloc(ptr, 0).
-#if defined(USE_TCMALLOC)
-TEST(Allocators, ReallocZero) {
- // Test that realloc to zero does not return NULL.
- for (int size = 0; size >= 0; size = NextSize(size)) {
- char* ptr = reinterpret_cast<char*>(malloc(size));
- EXPECT_NE(static_cast<char*>(NULL), ptr);
- ptr = reinterpret_cast<char*>(realloc(ptr, 0));
- EXPECT_NE(static_cast<char*>(NULL), ptr);
- if (ptr)
- free(ptr);
- }
-}
-#endif
-
-#ifdef WIN32
// Test recalloc
TEST(Allocators, Recalloc) {
for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
@@ -499,7 +212,7 @@
// Try allocating data with a bunch of alignments and sizes
static const int kTestAlignments[] = {8, 16, 256, 4096, 8192, 16384};
for (int size = 1; size > 0; size = NextSize(size)) {
- for (int i = 0; i < ARRAYSIZE(kTestAlignments); ++i) {
+ for (int i = 0; i < arraysize(kTestAlignments); ++i) {
unsigned char* ptr = static_cast<unsigned char*>(
_aligned_malloc(size, kTestAlignments[i]));
CheckAlignment(ptr, kTestAlignments[i]);
@@ -526,9 +239,6 @@
}
}
-#endif
-
-
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/base/android/application_status_listener.cc b/base/android/application_status_listener.cc
index f487072..02178c4 100644
--- a/base/android/application_status_listener.cc
+++ b/base/android/application_status_listener.cc
@@ -60,7 +60,8 @@
// static
void ApplicationStatusListener::NotifyApplicationStateChange(
ApplicationState state) {
- g_observers.Get().Notify(&ApplicationStatusListener::Notify, state);
+ g_observers.Get().Notify(FROM_HERE, &ApplicationStatusListener::Notify,
+ state);
}
static void OnApplicationStateChange(JNIEnv* env,
diff --git a/base/android/build_info.h b/base/android/build_info.h
index cef8145..e4e84e8 100644
--- a/base/android/build_info.h
+++ b/base/android/build_info.h
@@ -15,6 +15,19 @@
namespace base {
namespace android {
+// This enumeration maps to the values returned by BuildInfo::sdk_int(),
+// indicating the Android release associated with a given SDK version.
+enum SdkVersion {
+ SDK_VERSION_ICE_CREAM_SANDWICH = 14,
+ SDK_VERSION_ICE_CREAM_SANDWICH_MR1 = 15,
+ SDK_VERSION_JELLY_BEAN = 16,
+ SDK_VERSION_JELLY_BEAN_MR1 = 17,
+ SDK_VERSION_JELLY_BEAN_MR2 = 18,
+ SDK_VERSION_KITKAT = 19,
+ SDK_VERSION_KITKAT_WEAR = 20,
+ SDK_VERSION_LOLLIPOP = 21
+};
+
// BuildInfo is a singleton class that stores android build and device
// information. It will be called from Android specific code and gets used
// primarily in crash reporting.
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 2168c21..d68fb4a 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -8,6 +8,7 @@
import android.os.SystemClock;
import android.util.Log;
+import org.chromium.base.CalledByNative;
import org.chromium.base.CommandLine;
import org.chromium.base.JNINamespace;
import org.chromium.base.TraceEvent;
@@ -40,41 +41,68 @@
// Guards all access to the libraries
private static final Object sLock = new Object();
+ // The singleton instance of LibraryLoader.
+ private static LibraryLoader sInstance;
+
// One-way switch becomes true when the libraries are loaded.
- private static boolean sLoaded = false;
+ private boolean mLoaded;
// One-way switch becomes true when the Java command line is switched to
// native.
- private static boolean sCommandLineSwitched = false;
+ private boolean mCommandLineSwitched;
// One-way switch becomes true when the libraries are initialized (
// by calling nativeLibraryLoaded, which forwards to LibraryLoaded(...) in
// library_loader_hooks.cc).
- private static boolean sInitialized = false;
+ private boolean mInitialized;
// One-way switches recording attempts to use Relro sharing in the browser.
// The flags are used to report UMA stats later.
- private static boolean sIsUsingBrowserSharedRelros = false;
- private static boolean sLoadAtFixedAddressFailed = false;
+ private boolean mIsUsingBrowserSharedRelros;
+ private boolean mLoadAtFixedAddressFailed;
// One-way switch becomes true if the device supports memory mapping the
// APK file with executable permissions.
- private static boolean sMapApkWithExecPermission = false;
+ private boolean mMapApkWithExecPermission;
// One-way switch to indicate whether we probe for memory mapping the APK
// file with executable permissions. We suppress the probe under some
// conditions.
// For more, see:
// https://code.google.com/p/chromium/issues/detail?id=448084
- private static boolean sProbeMapApkWithExecPermission = true;
+ private boolean mProbeMapApkWithExecPermission = true;
// One-way switch becomes true if the Chromium library was loaded from the
// APK file directly.
- private static boolean sLibraryWasLoadedFromApk = false;
+ private boolean mLibraryWasLoadedFromApk;
// One-way switch becomes false if the Chromium library should be loaded
// directly from the APK file but it was compressed or not aligned.
- private static boolean sLibraryIsMappableInApk = true;
+ private boolean mLibraryIsMappableInApk = true;
+
+ // The type of process the shared library is loaded in.
+ private int mLibraryProcessType;
+
+ /**
+ * @param libraryProcessType the process the shared library is loaded in. refer to
+ * LibraryProcessType for possible values.
+ * @return LibraryLoader if existing, otherwise create a new one.
+ */
+ public static LibraryLoader get(int libraryProcessType) throws ProcessInitException {
+ synchronized (sLock) {
+ if (sInstance != null) {
+ if (sInstance.mLibraryProcessType == libraryProcessType) return sInstance;
+ throw new ProcessInitException(
+ LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED);
+ }
+ sInstance = new LibraryLoader(libraryProcessType);
+ return sInstance;
+ }
+ }
+
+ private LibraryLoader(int libraryProcessType) {
+ mLibraryProcessType = libraryProcessType;
+ }
/**
* The same as ensureInitialized(null, false), should only be called
@@ -82,7 +110,7 @@
*
* @throws ProcessInitException
*/
- public static void ensureInitialized() throws ProcessInitException {
+ public void ensureInitialized() throws ProcessInitException {
ensureInitialized(null, false);
}
@@ -96,11 +124,11 @@
* @param shouldDeleteFallbackLibraries The flag tells whether the method
* should delete the fallback libraries or not.
*/
- public static void ensureInitialized(
+ public void ensureInitialized(
Context context, boolean shouldDeleteFallbackLibraries)
throws ProcessInitException {
synchronized (sLock) {
- if (sInitialized) {
+ if (mInitialized) {
// Already initialized, nothing to do.
return;
}
@@ -114,7 +142,7 @@
*/
public static boolean isInitialized() {
synchronized (sLock) {
- return sInitialized;
+ return sInstance != null && sInstance.mInitialized;
}
}
@@ -124,7 +152,7 @@
*
* @throws ProcessInitException
*/
- public static void loadNow() throws ProcessInitException {
+ public void loadNow() throws ProcessInitException {
loadNow(null, false);
}
@@ -141,7 +169,7 @@
*
* @throws ProcessInitException if the native library failed to load.
*/
- public static void loadNow(Context context, boolean shouldDeleteFallbackLibraries)
+ public void loadNow(Context context, boolean shouldDeleteFallbackLibraries)
throws ProcessInitException {
synchronized (sLock) {
loadAlreadyLocked(context, shouldDeleteFallbackLibraries);
@@ -153,19 +181,19 @@
* native will call its "main" thread. The library must have previously been
* loaded with loadNow.
*/
- public static void initialize() throws ProcessInitException {
+ public void initialize() throws ProcessInitException {
synchronized (sLock) {
initializeAlreadyLocked();
}
}
// Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code
- private static void loadAlreadyLocked(
+ private void loadAlreadyLocked(
Context context, boolean shouldDeleteFallbackLibraries)
throws ProcessInitException {
try {
- if (!sLoaded) {
- assert !sInitialized;
+ if (!mLoaded) {
+ assert !mInitialized;
long startTime = SystemClock.uptimeMillis();
boolean useChromiumLinker = Linker.isUsed();
@@ -183,17 +211,17 @@
if (manufacturer != null
&& manufacturer.toLowerCase(Locale.ENGLISH).contains("samsung")) {
Log.w(TAG, "Suppressed load from APK support check on this device");
- sProbeMapApkWithExecPermission = false;
+ mProbeMapApkWithExecPermission = false;
}
// Check if the device supports memory mapping the APK file
// with executable permissions.
if (context != null) {
apkFilePath = context.getApplicationInfo().sourceDir;
- if (sProbeMapApkWithExecPermission) {
- sMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
+ if (mProbeMapApkWithExecPermission) {
+ mMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
}
- if (!sMapApkWithExecPermission && Linker.isInZipFile()) {
+ if (!mMapApkWithExecPermission && Linker.isInZipFile()) {
Log.w(TAG, "the no map executable support fallback will be used because"
+ " memory mapping the APK file with executable permissions is"
+ " not supported");
@@ -222,9 +250,9 @@
if (apkFilePath != null && Linker.isInZipFile()) {
// The library is in the APK file.
if (!Linker.checkLibraryIsMappableInApk(apkFilePath, libFilePath)) {
- sLibraryIsMappableInApk = false;
+ mLibraryIsMappableInApk = false;
}
- if (sLibraryIsMappableInApk || useMapExecSupportFallback) {
+ if (mLibraryIsMappableInApk || useMapExecSupportFallback) {
// Load directly from the APK (or use the no map executable
// support fallback, see crazy_linker_elf_loader.cpp).
zipFilePath = apkFilePath;
@@ -251,7 +279,7 @@
// Load the library.
boolean isLoaded = false;
if (Linker.isUsingBrowserSharedRelros()) {
- sIsUsingBrowserSharedRelros = true;
+ mIsUsingBrowserSharedRelros = true;
try {
loadLibrary(zipFilePath, libFilePath);
isLoaded = true;
@@ -259,7 +287,7 @@
Log.w(TAG, "Failed to load native library with shared RELRO, "
+ "retrying without");
Linker.disableSharedRelros();
- sLoadAtFixedAddressFailed = true;
+ mLoadAtFixedAddressFailed = true;
}
}
if (!isLoaded) {
@@ -287,7 +315,7 @@
startTime % 10000,
stopTime % 10000));
- sLoaded = true;
+ mLoaded = true;
}
} catch (UnsatisfiedLinkError e) {
throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED, e);
@@ -305,17 +333,17 @@
// Load a native shared library with the Chromium linker. If the zip file
// path is not null, the library is loaded directly from the zip file.
- private static void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
+ private void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
Linker.loadLibrary(zipFilePath, libFilePath);
if (zipFilePath != null) {
- sLibraryWasLoadedFromApk = true;
+ mLibraryWasLoadedFromApk = true;
}
}
// The WebView requires the Command Line to be switched over before
// initialization is done. This is okay in the WebView's case since the
// JNI is already loaded by this point.
- public static void switchCommandLineForWebView() {
+ public void switchCommandLineForWebView() {
synchronized (sLock) {
ensureCommandLineSwitchedAlreadyLocked();
}
@@ -324,24 +352,24 @@
// Switch the CommandLine over from Java to native if it hasn't already been done.
// This must happen after the code is loaded and after JNI is ready (since after the
// switch the Java CommandLine will delegate all calls the native CommandLine).
- private static void ensureCommandLineSwitchedAlreadyLocked() {
- assert sLoaded;
- if (sCommandLineSwitched) {
+ private void ensureCommandLineSwitchedAlreadyLocked() {
+ assert mLoaded;
+ if (mCommandLineSwitched) {
return;
}
nativeInitCommandLine(CommandLine.getJavaSwitchesOrNull());
CommandLine.enableNativeProxy();
- sCommandLineSwitched = true;
+ mCommandLineSwitched = true;
}
// Invoke base::android::LibraryLoaded in library_loader_hooks.cc
- private static void initializeAlreadyLocked() throws ProcessInitException {
- if (sInitialized) {
+ private void initializeAlreadyLocked() throws ProcessInitException {
+ if (mInitialized) {
return;
}
// Setup the native command line if necessary.
- if (!sCommandLineSwitched) {
+ if (!mCommandLineSwitched) {
nativeInitCommandLine(CommandLine.getJavaSwitchesOrNull());
}
@@ -352,13 +380,13 @@
// From this point on, native code is ready to use and checkIsReady()
// shouldn't complain from now on (and in fact, it's used by the
// following calls).
- sInitialized = true;
+ mInitialized = true;
// The Chrome JNI is registered by now so we can switch the Java
// command line over to delegating to native if it's necessary.
- if (!sCommandLineSwitched) {
+ if (!mCommandLineSwitched) {
CommandLine.enableNativeProxy();
- sCommandLineSwitched = true;
+ mCommandLineSwitched = true;
}
// From now on, keep tracing in sync with native.
@@ -366,32 +394,32 @@
}
// Called after all native initializations are complete.
- public static void onNativeInitializationComplete(Context context) {
+ public void onNativeInitializationComplete(Context context) {
recordBrowserProcessHistogram(context);
}
// Record Chromium linker histogram state for the main browser process. Called from
// onNativeInitializationComplete().
- private static void recordBrowserProcessHistogram(Context context) {
+ private void recordBrowserProcessHistogram(Context context) {
if (Linker.isUsed()) {
- nativeRecordChromiumAndroidLinkerBrowserHistogram(sIsUsingBrowserSharedRelros,
- sLoadAtFixedAddressFailed,
+ nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSharedRelros,
+ mLoadAtFixedAddressFailed,
getLibraryLoadFromApkStatus(context));
}
}
// Returns the device's status for loading a library directly from the APK file.
// This method can only be called when the Chromium linker is used.
- private static int getLibraryLoadFromApkStatus(Context context) {
+ private int getLibraryLoadFromApkStatus(Context context) {
assert Linker.isUsed();
- if (sLibraryWasLoadedFromApk) {
- return sMapApkWithExecPermission
+ if (mLibraryWasLoadedFromApk) {
+ return mMapApkWithExecPermission
? LibraryLoadFromApkStatusCodes.SUCCESSFUL
: LibraryLoadFromApkStatusCodes.USED_NO_MAP_EXEC_SUPPORT_FALLBACK;
}
- if (!sLibraryIsMappableInApk) {
+ if (!mLibraryIsMappableInApk) {
return LibraryLoadFromApkStatusCodes.USED_UNPACK_LIBRARY_FALLBACK;
}
@@ -400,11 +428,11 @@
return LibraryLoadFromApkStatusCodes.UNKNOWN;
}
- if (!sProbeMapApkWithExecPermission) {
+ if (!mProbeMapApkWithExecPermission) {
return LibraryLoadFromApkStatusCodes.UNKNOWN;
}
- return sMapApkWithExecPermission
+ return mMapApkWithExecPermission
? LibraryLoadFromApkStatusCodes.SUPPORTED
: LibraryLoadFromApkStatusCodes.NOT_SUPPORTED;
}
@@ -413,15 +441,27 @@
// recorded as a histogram immediately because histograms and IPC are not ready at the
// time it are captured. This function stores a pending value, so that a later call to
// RecordChromiumAndroidLinkerRendererHistogram() will record it correctly.
- public static void registerRendererProcessHistogram(boolean requestedSharedRelro,
- boolean loadAtFixedAddressFailed) {
+ public void registerRendererProcessHistogram(boolean requestedSharedRelro,
+ boolean loadAtFixedAddressFailed) {
if (Linker.isUsed()) {
nativeRegisterChromiumAndroidLinkerRendererHistogram(requestedSharedRelro,
loadAtFixedAddressFailed);
}
}
- private static native void nativeInitCommandLine(String[] initCommandLine);
+ /**
+ * @return the process the shared library is loaded in, see the LibraryProcessType
+ * for possible values.
+ */
+ @CalledByNative
+ public static int getLibraryProcessType() {
+ synchronized (sLock) {
+ if (sInstance == null) return LibraryProcessType.PROCESS_UNINITIALIZED;
+ return sInstance.mLibraryProcessType;
+ }
+ }
+
+ private native void nativeInitCommandLine(String[] initCommandLine);
// Only methods needed before or during normal JNI registration are during System.OnLoad.
// nativeLibraryLoaded is then called to register everything else. This process is called
@@ -429,13 +469,13 @@
// definition in base/android/library_loader/library_loader_hooks.cc.
//
// Return true on success and false on failure.
- private static native boolean nativeLibraryLoaded();
+ private native boolean nativeLibraryLoaded();
// Method called to record statistics about the Chromium linker operation for the main
// browser process. Indicates whether the linker attempted relro sharing for the browser,
// and if it did, whether the library failed to load at a fixed address. Also records
// support for loading a library directly from the APK file.
- private static native void nativeRecordChromiumAndroidLinkerBrowserHistogram(
+ private native void nativeRecordChromiumAndroidLinkerBrowserHistogram(
boolean isUsingBrowserSharedRelros,
boolean loadAtFixedAddressFailed,
int libraryLoadFromApkStatus);
@@ -443,11 +483,11 @@
// Method called to register (for later recording) statistics about the Chromium linker
// operation for a renderer process. Indicates whether the linker attempted relro sharing,
// and if it did, whether the library failed to load at a fixed address.
- private static native void nativeRegisterChromiumAndroidLinkerRendererHistogram(
+ private native void nativeRegisterChromiumAndroidLinkerRendererHistogram(
boolean requestedSharedRelro,
boolean loadAtFixedAddressFailed);
// Get the version of the native library. This is needed so that we can check we
// have the right version before initializing the (rest of the) JNI.
- private static native String nativeGetVersionNumber();
+ private native String nativeGetVersionNumber();
}
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
index 050708c..08c314f 100644
--- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -7,16 +7,21 @@
import org.chromium.base.JNINamespace;
import org.chromium.base.VisibleForTesting;
+import java.util.concurrent.TimeUnit;
+
/**
- * Java API for recording UMA histograms. As opposed to macros used in native code, these calls are
- * not caching the histogram pointer; also, the JNI calls are relatively costly - avoid calling
- * these methods in performance-critical code.
+ * Java API for recording UMA histograms. Internally, the histogram will be cached by
+ * System.identityHashCode(name).
+ *
+ * Note: the JNI calls are relatively costly - avoid calling these methods in performance-critical
+ * code.
*/
@JNINamespace("base::android")
public class RecordHistogram {
/**
* Records a sample in a boolean UMA histogram of the given name. Boolean histogram has two
- * buckets, corresponding to success (true) and failure (false).
+ * buckets, corresponding to success (true) and failure (false). This is the Java equivalent of
+ * the UMA_HISTOGRAM_BOOLEAN C++ macro.
* @param name name of the histogram
* @param sample sample to be recorded, either true or false
*/
@@ -26,7 +31,8 @@
/**
* Records a sample in an enumerated histogram of the given name and boundary. Note that
- * |boundary| identifies the histogram - it should be the same at every invocation.
+ * |boundary| identifies the histogram - it should be the same at every invocation. This is the
+ * Java equivalent of the UMA_HISTOGRAM_ENUMERATION C++ macro.
* @param name name of the histogram
* @param sample sample to be recorded, at least 0 and at most |boundary| - 1
* @param boundary upper bound for legal sample values - all sample values has to be strictly
@@ -37,6 +43,64 @@
}
/**
+ * Records a sample in a histogram of times. Useful for recording short durations. This is the
+ * Java equivalent of the UMA_HISTOGRAM_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param timeUnit the unit of the duration argument
+ */
+ public static void recordTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+ recordCustomTimesHistogramMilliseconds(
+ name, timeUnit.toMillis(duration), 1, TimeUnit.SECONDS.toMillis(10), 50);
+ }
+
+ /**
+ * Records a sample in a histogram of times. Useful for recording medium durations. This is the
+ * Java equivalent of the UMA_HISTOGRAM_MEDIUM_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param timeUnit the unit of the duration argument
+ */
+ public static void recordMediumTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+ recordCustomTimesHistogramMilliseconds(
+ name, timeUnit.toMillis(duration), 10, TimeUnit.MINUTES.toMillis(3), 50);
+ }
+
+ /**
+ * Records a sample in a histogram of times. Useful for recording long durations. This is the
+ * Java equivalent of the UMA_HISTOGRAM_LONG_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param timeUnit the unit of the duration argument
+ */
+ public static void recordLongTimesHistogram(String name, long duration, TimeUnit timeUnit) {
+ recordCustomTimesHistogramMilliseconds(
+ name, timeUnit.toMillis(duration), 1, TimeUnit.HOURS.toMillis(1), 50);
+ }
+
+ /**
+ * Records a sample in a histogram of times with custom buckets. This is the Java equivalent of
+ * the UMA_HISTOGRAM_CUSTOM_TIMES C++ macro.
+ * @param name name of the histogram
+ * @param duration duration to be recorded
+ * @param min the minimum bucket value
+ * @param max the maximum bucket value
+ * @param timeUnit the unit of the duration, min, and max arguments
+ * @param numBuckets the number of buckets
+ */
+ public static void recordCustomTimesHistogram(
+ String name, long duration, long min, long max, TimeUnit timeUnit, int numBuckets) {
+ recordCustomTimesHistogramMilliseconds(name, timeUnit.toMillis(duration),
+ timeUnit.toMillis(min), timeUnit.toMillis(max), numBuckets);
+ }
+
+ private static void recordCustomTimesHistogramMilliseconds(
+ String name, long duration, long min, long max, int numBuckets) {
+ nativeRecordCustomTimesHistogramMilliseconds(
+ name, System.identityHashCode(name), duration, min, max, numBuckets);
+ }
+
+ /**
* Returns the number of samples recorded in the given bucket of the given histogram.
* @param name name of the histogram to look up
* @param sample the bucket containing this sample value will be looked up
@@ -53,6 +117,9 @@
nativeInitialize();
}
+ private static native void nativeRecordCustomTimesHistogramMilliseconds(
+ String name, int key, long duration, long min, long max, int numBuckets);
+
private static native void nativeRecordBooleanHistogram(String name, int key, boolean sample);
private static native void nativeRecordEnumeratedHistogram(
String name, int key, int sample, int boundary);
diff --git a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java b/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
index 82c1ca9..f0489d3 100644
--- a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
+++ b/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
@@ -8,8 +8,11 @@
import android.test.suitebuilder.annotation.SmallTest;
import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
+import java.util.concurrent.TimeUnit;
+
/**
* Tests for the Java API for recording UMA histograms.
*/
@@ -17,7 +20,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- LibraryLoader.ensureInitialized();
+ LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
RecordHistogram.initialize();
}
@@ -75,4 +78,41 @@
assertEquals(0, oneCount.getDelta());
assertEquals(1, twoCount.getDelta());
}
+
+ /**
+ * Tests recording of custom times histograms.
+ */
+ @SmallTest
+ public void testRecordCustomTimesHistogram() {
+ String histogram = "HelloWorld.CustomTimesMetric";
+ HistogramDelta zeroCount = new HistogramDelta(histogram, 0);
+ HistogramDelta oneCount = new HistogramDelta(histogram, 1);
+ HistogramDelta twoCount = new HistogramDelta(histogram, 100);
+
+ assertEquals(0, zeroCount.getDelta());
+ assertEquals(0, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ TimeUnit milli = TimeUnit.MILLISECONDS;
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
+ assertEquals(1, zeroCount.getDelta());
+ assertEquals(0, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
+ assertEquals(2, zeroCount.getDelta());
+ assertEquals(0, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 95, 1, 100, milli, 3);
+ assertEquals(2, zeroCount.getDelta());
+ assertEquals(1, oneCount.getDelta());
+ assertEquals(0, twoCount.getDelta());
+
+ RecordHistogram.recordCustomTimesHistogram(histogram, 200, 1, 100, milli, 3);
+ assertEquals(2, zeroCount.getDelta());
+ assertEquals(1, oneCount.getDelta());
+ assertEquals(1, twoCount.getDelta());
+ }
}
diff --git a/base/android/jni_array.cc b/base/android/jni_array.cc
index 4bebec7..a157354 100644
--- a/base/android/jni_array.cc
+++ b/base/android/jni_array.cc
@@ -7,7 +7,6 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
-#include "base/stl_util.h"
namespace base {
namespace android {
@@ -54,7 +53,7 @@
ScopedJavaLocalRef<jintArray> ToJavaIntArray(
JNIEnv* env, const std::vector<int>& ints) {
- return ToJavaIntArray(env, vector_as_array(&ints), ints.size());
+ return ToJavaIntArray(env, ints.begin(), ints.size());
}
ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
@@ -73,7 +72,7 @@
// Returns a new Java long array converted from the given int64 array.
BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
JNIEnv* env, const std::vector<int64>& longs) {
- return ToJavaLongArray(env, vector_as_array(&longs), longs.size());
+ return ToJavaLongArray(env, longs.begin(), longs.size());
}
ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py
index 53de365..6e39c13 100755
--- a/base/android/jni_generator/jni_generator.py
+++ b/base/android/jni_generator/jni_generator.py
@@ -209,7 +209,11 @@
@staticmethod
def ParseJavaPSignature(signature_line):
prefix = 'Signature: '
- return '"%s"' % signature_line[signature_line.index(prefix) + len(prefix):]
+ index = signature_line.find(prefix)
+ if index == -1:
+ prefix = 'descriptor: '
+ index = signature_line.index(prefix)
+ return '"%s"' % signature_line[index + len(prefix):]
@staticmethod
def JavaToJni(param):
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py
index a7ce537..7e39cda 100755
--- a/base/android/jni_generator/jni_generator_tests.py
+++ b/base/android/jni_generator/jni_generator_tests.py
@@ -722,7 +722,7 @@
self.assertEquals(1, len(jni_from_javap.called_by_natives))
self.assertGoldenTextEquals(jni_from_javap.GetContent())
- def testSnippnetJavap6_7(self):
+ def testSnippnetJavap6_7_8(self):
content_javap6 = """
public class java.util.HashSet {
public boolean add(java.lang.Object);
@@ -736,16 +736,30 @@
Signature: (Ljava/lang/Object;)Z
}
"""
+
+ content_javap8 = """
+public class java.util.HashSet {
+ public boolean add(E);
+ descriptor: (Ljava/lang/Object;)Z
+}
+"""
+
jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
TestOptions())
jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
TestOptions())
+ jni_from_javap8 = jni_generator.JNIFromJavaP(content_javap8.split('\n'),
+ TestOptions())
self.assertTrue(jni_from_javap6.GetContent())
self.assertTrue(jni_from_javap7.GetContent())
+ self.assertTrue(jni_from_javap8.GetContent())
# Ensure the javap7 is correctly parsed and uses the Signature field rather
# than the "E" parameter.
self.assertTextEquals(jni_from_javap6.GetContent(),
jni_from_javap7.GetContent())
+ # Ensure the javap8 is correctly parsed and uses the descriptor field.
+ self.assertTextEquals(jni_from_javap7.GetContent(),
+ jni_from_javap8.GetContent())
def testFromJavaP(self):
contents = self._ReadGoldenFile(os.path.join(os.path.dirname(sys.argv[0]),
diff --git a/base/android/library_loader/library_loader_hooks.cc b/base/android/library_loader/library_loader_hooks.cc
index 965d030..97aec8c 100644
--- a/base/android/library_loader/library_loader_hooks.cc
+++ b/base/android/library_loader/library_loader_hooks.cc
@@ -51,7 +51,7 @@
static void RegisterChromiumAndroidLinkerRendererHistogram(
JNIEnv* env,
- jclass clazz,
+ jobject jcaller,
jboolean requested_shared_relro,
jboolean load_at_fixed_address_failed) {
// Note a pending histogram value for later recording.
@@ -75,7 +75,7 @@
static void RecordChromiumAndroidLinkerBrowserHistogram(
JNIEnv* env,
- jclass clazz,
+ jobject jcaller,
jboolean is_using_browser_shared_relros,
jboolean load_at_fixed_address_failed,
jint library_load_from_apk_status) {
@@ -102,16 +102,17 @@
g_registration_callback = func;
}
-static void InitCommandLine(JNIEnv* env, jclass clazz,
+static void InitCommandLine(JNIEnv* env,
+ jobject jcaller,
jobjectArray init_command_line) {
InitNativeCommandLineFromJavaArray(env, init_command_line);
}
-static jboolean LibraryLoaded(JNIEnv* env, jclass clazz) {
+static jboolean LibraryLoaded(JNIEnv* env, jobject jcaller) {
if (g_registration_callback == NULL) {
return true;
}
- return g_registration_callback(env, clazz);
+ return g_registration_callback(env, NULL);
}
void LibraryLoaderExitHook() {
@@ -132,9 +133,14 @@
g_library_version_number = strdup(version_number);
}
-jstring GetVersionNumber(JNIEnv* env, jclass clazz) {
+jstring GetVersionNumber(JNIEnv* env, jobject jcaller) {
return ConvertUTF8ToJavaString(env, g_library_version_number).Release();
}
+LibraryProcessType GetLibraryProcessType(JNIEnv* env) {
+ return static_cast<LibraryProcessType>(
+ Java_LibraryLoader_getLibraryProcessType(env));
+}
+
} // 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 78dc535..6203eb0 100644
--- a/base/android/library_loader/library_loader_hooks.h
+++ b/base/android/library_loader/library_loader_hooks.h
@@ -12,6 +12,19 @@
namespace base {
namespace android {
+// The process the shared library is loaded in.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.library_loader
+enum LibraryProcessType {
+ // The LibraryLoad has not been initialized.
+ PROCESS_UNINITIALIZED = 0,
+ // Shared library is running in browser process.
+ PROCESS_BROWSER = 1,
+ // Shared library is running in child process.
+ PROCESS_CHILD = 2,
+ // Shared library is running in webview process.
+ PROCESS_WEBVIEW = 3,
+};
+
// Record any pending renderer histogram value as a histogram. Pending values
// are set by RegisterChromiumAndroidLinkerRendererHistogram.
BASE_EXPORT void RecordChromiumAndroidLinkerRendererHistogram();
@@ -48,6 +61,9 @@
// created.
BASE_EXPORT void LibraryLoaderExitHook();
+// Return the process type the shared library is loaded in.
+BASE_EXPORT LibraryProcessType GetLibraryProcesssType();
+
} // namespace android
} // namespace base
diff --git a/base/android/record_histogram.cc b/base/android/record_histogram.cc
index 9549adc..0df0487 100644
--- a/base/android/record_histogram.cc
+++ b/base/android/record_histogram.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/synchronization/lock.h"
+#include "base/time/time.h"
#include "jni/RecordHistogram_jni.h"
namespace base {
@@ -46,20 +47,45 @@
DCHECK(j_histogram_name);
DCHECK(j_histogram_key);
HistogramBase* histogram = FindLocked(j_histogram_key);
- if (histogram)
+ int boundary = static_cast<int>(j_boundary);
+ if (histogram) {
+ DCHECK(histogram->HasConstructionArguments(1, boundary, boundary + 1));
return histogram;
+ }
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- // Note: This caching bypasses the boundary validation that occurs between
- // repeated lookups by the same name. It is up to the caller to ensure that
- // the provided boundary remains consistent.
- int boundary = static_cast<int>(j_boundary);
histogram =
LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1,
HistogramBase::kUmaTargetedHistogramFlag);
return InsertLocked(j_histogram_key, histogram);
}
+ HistogramBase* CustomTimesHistogram(JNIEnv* env,
+ jstring j_histogram_name,
+ jint j_histogram_key,
+ jlong j_min,
+ jlong j_max,
+ jint j_bucket_count) {
+ DCHECK(j_histogram_name);
+ DCHECK(j_histogram_key);
+ HistogramBase* histogram = FindLocked(j_histogram_key);
+ int64 min = static_cast<int64>(j_min);
+ int64 max = static_cast<int64>(j_max);
+ int bucket_count = static_cast<int>(j_bucket_count);
+ if (histogram) {
+ DCHECK(histogram->HasConstructionArguments(min, max, bucket_count));
+ return histogram;
+ }
+
+ std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
+ // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet
+ // is just a convenience for constructing the underlying Histogram with
+ // TimeDelta arguments.
+ histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count,
+ HistogramBase::kUmaTargetedHistogramFlag);
+ return InsertLocked(j_histogram_key, histogram);
+ }
+
private:
HistogramBase* FindLocked(jint j_histogram_key) {
base::AutoLock locked(lock_);
@@ -107,6 +133,20 @@
->Add(sample);
}
+void RecordCustomTimesHistogramMilliseconds(JNIEnv* env,
+ jclass clazz,
+ jstring j_histogram_name,
+ jint j_histogram_key,
+ jlong j_duration,
+ jlong j_min,
+ jlong j_max,
+ jint j_num_buckets) {
+ g_histograms.Get()
+ .CustomTimesHistogram(env, j_histogram_name, j_histogram_key, j_min,
+ j_max, j_num_buckets)
+ ->AddTime(TimeDelta::FromMilliseconds(static_cast<int64>(j_duration)));
+}
+
void Initialize(JNIEnv* env, jclass) {
StatisticsRecorder::Initialize();
}
diff --git a/base/android/trace_event_binding.cc b/base/android/trace_event_binding.cc
index b8ce6d9..791b67f 100644
--- a/base/android/trace_event_binding.cc
+++ b/base/android/trace_event_binding.cc
@@ -55,7 +55,8 @@
DISALLOW_COPY_AND_ASSIGN(TraceEventDataConverter);
};
-class TraceEnabledObserver : public debug::TraceLog::EnabledStateObserver {
+class TraceEnabledObserver
+ : public trace_event::TraceLog::EnabledStateObserver {
public:
void OnTraceLogEnabled() override {
JNIEnv* env = base::android::AttachCurrentThread();
@@ -72,18 +73,18 @@
} // namespace
static void RegisterEnabledObserver(JNIEnv* env, jclass clazz) {
- bool enabled = debug::TraceLog::GetInstance()->IsEnabled();
+ bool enabled = trace_event::TraceLog::GetInstance()->IsEnabled();
base::android::Java_TraceEvent_setEnabled(env, enabled);
- debug::TraceLog::GetInstance()->AddEnabledStateObserver(
+ trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
g_trace_enabled_state_observer_.Pointer());
}
static void StartATrace(JNIEnv* env, jclass clazz) {
- base::debug::TraceLog::GetInstance()->StartATrace();
+ base::trace_event::TraceLog::GetInstance()->StartATrace();
}
static void StopATrace(JNIEnv* env, jclass clazz) {
- base::debug::TraceLog::GetInstance()->StopATrace();
+ base::trace_event::TraceLog::GetInstance()->StopATrace();
}
static void Instant(JNIEnv* env, jclass clazz,
diff --git a/base/base.gyp b/base/base.gyp
index 00244aa..8cd5d6a 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -494,10 +494,9 @@
'gmock_unittest.cc',
'guid_unittest.cc',
'hash_unittest.cc',
- 'id_map_unittest.cc',
'i18n/break_iterator_unittest.cc',
- 'i18n/char_iterator_unittest.cc',
'i18n/case_conversion_unittest.cc',
+ 'i18n/char_iterator_unittest.cc',
'i18n/file_util_icu_unittest.cc',
'i18n/icu_string_conversions_unittest.cc',
'i18n/number_formatting_unittest.cc',
@@ -506,6 +505,8 @@
'i18n/string_search_unittest.cc',
'i18n/time_formatting_unittest.cc',
'i18n/timezone_unittest.cc',
+ 'id_map_unittest.cc',
+ 'ios/crb_protocol_observers_unittest.mm',
'ios/device_util_unittest.mm',
'ios/weak_nsobject_unittest.mm',
'json/json_parser_unittest.cc',
@@ -545,17 +546,18 @@
'message_loop/message_pump_glib_unittest.cc',
'message_loop/message_pump_io_ios_unittest.cc',
'message_loop/message_pump_libevent_unittest.cc',
- 'metrics/sample_map_unittest.cc',
- 'metrics/sample_vector_unittest.cc',
'metrics/bucket_ranges_unittest.cc',
'metrics/field_trial_unittest.cc',
'metrics/histogram_base_unittest.cc',
'metrics/histogram_delta_serialization_unittest.cc',
+ 'metrics/histogram_macros_unittest.cc',
'metrics/histogram_snapshot_manager_unittest.cc',
'metrics/histogram_unittest.cc',
+ 'metrics/sample_map_unittest.cc',
+ 'metrics/sample_vector_unittest.cc',
'metrics/sparse_histogram_unittest.cc',
- 'metrics/stats_table_unittest.cc',
'metrics/statistics_recorder_unittest.cc',
+ 'numerics/safe_numerics_unittest.cc',
'observer_list_unittest.cc',
'os_compat_android_unittest.cc',
'path_service_unittest.cc',
@@ -583,7 +585,6 @@
'process/process_util_unittest.cc',
'profiler/tracked_time_unittest.cc',
'rand_util_unittest.cc',
- 'numerics/safe_numerics_unittest.cc',
'scoped_clear_errno_unittest.cc',
'scoped_generic_unittest.cc',
'scoped_native_library_unittest.cc',
@@ -594,13 +595,13 @@
'strings/nullable_string16_unittest.cc',
'strings/safe_sprintf_unittest.cc',
'strings/string16_unittest.cc',
- 'strings/stringprintf_unittest.cc',
'strings/string_number_conversions_unittest.cc',
'strings/string_piece_unittest.cc',
'strings/string_split_unittest.cc',
'strings/string_tokenizer_unittest.cc',
'strings/string_util_unittest.cc',
'strings/stringize_macros_unittest.cc',
+ 'strings/stringprintf_unittest.cc',
'strings/sys_string_conversions_mac_unittest.mm',
'strings/sys_string_conversions_unittest.cc',
'strings/utf_offset_string_conversions_unittest.cc',
@@ -643,6 +644,7 @@
'timer/mock_timer_unittest.cc',
'timer/timer_unittest.cc',
'tools_sanity_unittest.cc',
+ 'trace_event/memory_dump_manager_unittest.cc',
'trace_event/trace_event_argument_unittest.cc',
'trace_event/trace_event_memory_unittest.cc',
'trace_event/trace_event_synthetic_delay_unittest.cc',
@@ -708,8 +710,6 @@
['exclude', '^process/process_unittest\\.cc$'],
['exclude', '^process/process_util_unittest\\.cc$'],
['include', '^process/process_util_unittest_ios\\.cc$'],
- # Requires spawning processes.
- ['exclude', '^metrics/stats_table_unittest\\.cc$'],
# iOS does not use message_pump_libevent.
['exclude', '^message_loop/message_pump_libevent_unittest\\.cc$'],
],
@@ -765,8 +765,8 @@
'sources!': [
'file_descriptor_shuffle_unittest.cc',
'files/dir_reader_posix_unittest.cc',
- 'threading/worker_pool_posix_unittest.cc',
'message_loop/message_pump_libevent_unittest.cc',
+ 'threading/worker_pool_posix_unittest.cc',
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [
@@ -838,9 +838,9 @@
'../testing/gtest.gyp:gtest',
],
'sources': [
- 'threading/thread_perftest.cc',
'message_loop/message_pump_perftest.cc',
'test/run_all_unittests.cc',
+ 'threading/thread_perftest.cc',
'../testing/perf/perf_test.cc'
],
'conditions': [
@@ -912,6 +912,8 @@
'test/gtest_util.h',
'test/gtest_xml_util.cc',
'test/gtest_xml_util.h',
+ 'test/histogram_tester.cc',
+ 'test/histogram_tester.h',
'test/launcher/test_launcher.cc',
'test/launcher/test_launcher.h',
'test/launcher/test_result.cc',
@@ -952,8 +954,6 @@
'test/simple_test_clock.h',
'test/simple_test_tick_clock.cc',
'test/simple_test_tick_clock.h',
- 'test/histogram_tester.cc',
- 'test/histogram_tester.h',
'test/task_runner_test_template.cc',
'test/task_runner_test_template.h',
'test/test_file_util.cc',
@@ -1374,6 +1374,15 @@
'includes': [ '../build/android/java_cpp_template.gypi' ],
},
{
+ # GN: //base:base_android_java_enums_srcjar
+ 'target_name': 'base_java_library_process_type',
+ 'type': 'none',
+ 'variables': {
+ 'source_file': 'android/library_loader/library_loader_hooks.h',
+ },
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
+ },
+ {
# GN: //base:base_java
'target_name': 'base_java',
'type': 'none',
@@ -1384,6 +1393,7 @@
'dependencies': [
'base_java_application_state',
'base_java_library_load_from_apk_status_codes',
+ 'base_java_library_process_type',
'base_java_memory_pressure_level',
'base_native_libraries_gen',
],
diff --git a/base/base.gypi b/base/base.gypi
index 6dd6fcf..37a8171 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -13,15 +13,6 @@
['base_target==1', {
'sources': [
'../build/build_config.h',
- 'third_party/dmg_fp/dmg_fp.h',
- 'third_party/dmg_fp/g_fmt.cc',
- 'third_party/dmg_fp/dtoa_wrapper.cc',
- 'third_party/icu/icu_utf.cc',
- 'third_party/icu/icu_utf.h',
- 'third_party/nspr/prtime.cc',
- 'third_party/nspr/prtime.h',
- 'third_party/superfasthash/superfasthash.c',
- 'third_party/xdg_mime/xdgmime.h',
'allocator/allocator_extension.cc',
'allocator/allocator_extension.h',
'allocator/type_profiler_control.cc',
@@ -47,10 +38,8 @@
'android/fifo_utils.h',
'android/important_file_writer_android.cc',
'android/important_file_writer_android.h',
- 'android/locale_utils.h',
- 'android/locale_utils.cc',
- 'android/scoped_java_ref.cc',
- 'android/scoped_java_ref.h',
+ 'android/java_handler_thread.cc',
+ 'android/java_handler_thread.h',
'android/jni_android.cc',
'android/jni_android.h',
'android/jni_array.cc',
@@ -64,19 +53,21 @@
'android/jni_utils.h',
'android/jni_weak_ref.cc',
'android/jni_weak_ref.h',
+ 'android/library_loader/library_load_from_apk_status_codes.h',
'android/library_loader/library_loader_hooks.cc',
'android/library_loader/library_loader_hooks.h',
- 'android/library_loader/library_load_from_apk_status_codes.h',
+ 'android/locale_utils.cc',
+ 'android/locale_utils.h',
'android/memory_pressure_listener_android.cc',
'android/memory_pressure_listener_android.h',
- 'android/java_handler_thread.cc',
- 'android/java_handler_thread.h',
'android/path_service_android.cc',
'android/path_service_android.h',
'android/path_utils.cc',
'android/path_utils.h',
'android/record_histogram.cc',
'android/record_histogram.h',
+ 'android/scoped_java_ref.cc',
+ 'android/scoped_java_ref.h',
'android/sys_utils.cc',
'android/sys_utils.h',
'android/thread_utils.h',
@@ -218,8 +209,8 @@
'files/file_util_proxy.h',
'files/file_util_win.cc',
'files/file_win.cc',
- 'files/important_file_writer.h',
'files/important_file_writer.cc',
+ 'files/important_file_writer.h',
'files/memory_mapped_file.cc',
'files/memory_mapped_file.h',
'files/memory_mapped_file_posix.cc',
@@ -239,6 +230,8 @@
'hash.h',
'id_map.h',
'ios/block_types.h',
+ 'ios/crb_protocol_observers.h',
+ 'ios/crb_protocol_observers.mm',
'ios/device_util.h',
'ios/device_util.mm',
'ios/ios_util.h',
@@ -284,8 +277,8 @@
'mac/launchd.h',
'mac/libdispatch_task_runner.cc',
'mac/libdispatch_task_runner.h',
- 'mac/mac_logging.h',
'mac/mac_logging.cc',
+ 'mac/mac_logging.h',
'mac/mac_util.h',
'mac/mac_util.mm',
'mac/mach_logging.cc',
@@ -377,10 +370,6 @@
'message_loop/message_pump_win.cc',
'message_loop/message_pump_win.h',
'message_loop/timer_slack.h',
- 'metrics/sample_map.cc',
- 'metrics/sample_map.h',
- 'metrics/sample_vector.cc',
- 'metrics/sample_vector.h',
'metrics/bucket_ranges.cc',
'metrics/bucket_ranges.h',
'metrics/histogram.cc',
@@ -395,14 +384,14 @@
'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/stats_counters.cc',
- 'metrics/stats_counters.h',
- 'metrics/stats_table.cc',
- 'metrics/stats_table.h',
'metrics/user_metrics.cc',
'metrics/user_metrics.h',
'metrics/user_metrics_action.h',
@@ -415,6 +404,10 @@
'nix/mime_util_xdg.h',
'nix/xdg_util.cc',
'nix/xdg_util.h',
+ 'numerics/safe_conversions.h',
+ 'numerics/safe_conversions_impl.h',
+ 'numerics/safe_math.h',
+ 'numerics/safe_math_impl.h',
'observer_list.h',
'observer_list_threadsafe.h',
'os_compat_android.cc',
@@ -435,11 +428,11 @@
'posix/unix_domain_socket_linux.h',
'power_monitor/power_monitor.cc',
'power_monitor/power_monitor.h',
+ 'power_monitor/power_monitor_device_source.cc',
+ 'power_monitor/power_monitor_device_source.h',
'power_monitor/power_monitor_device_source_android.cc',
'power_monitor/power_monitor_device_source_android.h',
'power_monitor/power_monitor_device_source_chromeos.cc',
- 'power_monitor/power_monitor_device_source.cc',
- 'power_monitor/power_monitor_device_source.h',
'power_monitor/power_monitor_device_source_ios.mm',
'power_monitor/power_monitor_device_source_mac.mm',
'power_monitor/power_monitor_device_source_posix.cc',
@@ -460,8 +453,8 @@
'process/launch_mac.cc',
'process/launch_posix.cc',
'process/launch_win.cc',
- 'process/memory.h',
'process/memory.cc',
+ 'process/memory.h',
'process/memory_linux.cc',
'process/memory_mac.mm',
'process/memory_win.cc',
@@ -484,8 +477,8 @@
'process/process_iterator_openbsd.cc',
'process/process_iterator_win.cc',
'process/process_linux.cc',
- 'process/process_metrics.h',
'process/process_metrics.cc',
+ 'process/process_metrics.h',
'process/process_metrics_freebsd.cc',
'process/process_metrics_ios.cc',
'process/process_metrics_linux.cc',
@@ -510,10 +503,6 @@
'rand_util_win.cc',
'run_loop.cc',
'run_loop.h',
- 'numerics/safe_conversions.h',
- 'numerics/safe_conversions_impl.h',
- 'numerics/safe_math.h',
- 'numerics/safe_math_impl.h',
'safe_strerror_posix.cc',
'safe_strerror_posix.h',
'scoped_generic.h',
@@ -540,11 +529,11 @@
'strings/string16.cc',
'strings/string16.h',
'strings/string_number_conversions.cc',
- 'strings/string_split.cc',
- 'strings/string_split.h',
'strings/string_number_conversions.h',
'strings/string_piece.cc',
'strings/string_piece.h',
+ 'strings/string_split.cc',
+ 'strings/string_split.h',
'strings/string_tokenizer.h',
'strings/string_util.cc',
'strings/string_util.h',
@@ -583,8 +572,6 @@
'synchronization/waitable_event_watcher_posix.cc',
'synchronization/waitable_event_watcher_win.cc',
'synchronization/waitable_event_win.cc',
- 'system_monitor/system_monitor.cc',
- 'system_monitor/system_monitor.h',
'sys_byteorder.h',
'sys_info.cc',
'sys_info.h',
@@ -598,12 +585,23 @@
'sys_info_openbsd.cc',
'sys_info_posix.cc',
'sys_info_win.cc',
+ 'system_monitor/system_monitor.cc',
+ 'system_monitor/system_monitor.h',
'task/cancelable_task_tracker.cc',
'task/cancelable_task_tracker.h',
'task_runner.cc',
'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/nspr/prtime.cc',
+ 'third_party/nspr/prtime.h',
+ 'third_party/superfasthash/superfasthash.c',
+ 'third_party/xdg_mime/xdgmime.h',
'thread_task_runner_handle.cc',
'thread_task_runner_handle.h',
'threading/non_thread_safe.h',
@@ -638,12 +636,12 @@
'threading/thread_local_storage_posix.cc',
'threading/thread_local_storage_win.cc',
'threading/thread_local_win.cc',
- 'threading/thread_restrictions.h',
'threading/thread_restrictions.cc',
+ 'threading/thread_restrictions.h',
'threading/watchdog.cc',
'threading/watchdog.h',
- 'threading/worker_pool.h',
'threading/worker_pool.cc',
+ 'threading/worker_pool.h',
'threading/worker_pool_posix.cc',
'threading/worker_pool_posix.h',
'threading/worker_pool_win.cc',
@@ -669,6 +667,11 @@
'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/trace_event.h',
'trace_event/trace_event_android.cc',
'trace_event/trace_event_argument.cc',
@@ -689,10 +692,10 @@
'tracking_info.cc',
'tracking_info.h',
'tuple.h',
- 'values.cc',
- 'values.h',
'value_conversions.cc',
'value_conversions.h',
+ 'values.cc',
+ 'values.h',
'version.cc',
'version.h',
'vlog.cc',
@@ -795,6 +798,7 @@
'files/file_util_posix.cc',
'files/file_util_proxy.cc',
'files/important_file_writer.cc',
+ 'files/scoped_temp_dir.cc',
'memory/shared_memory_posix.cc',
'native_library_posix.cc',
'path_service.cc',
@@ -808,7 +812,6 @@
'process/process_posix.cc',
'rand_util_posix.cc',
'scoped_native_library.cc',
- 'files/scoped_temp_dir.cc',
'sys_info.cc',
'sys_info_posix.cc',
'third_party/dynamic_annotations/dynamic_annotations.c',
@@ -819,10 +822,10 @@
}],
['OS == "android" and _toolset == "target" and >(nacl_untrusted_build)==0', {
'sources': [
- 'memory/discardable_memory_ashmem_allocator.cc',
- 'memory/discardable_memory_ashmem_allocator.h',
'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', {
diff --git a/base/base_unittests.isolate b/base/base_unittests.isolate
index 0822b24..2e33cc0 100644
--- a/base/base_unittests.isolate
+++ b/base/base_unittests.isolate
@@ -58,7 +58,7 @@
],
},
}],
- ['OS=="mac" and asan==1', {
+ ['OS=="mac" and asan==1 and fastbuild==0', {
'variables': {
'files': [
'<(PRODUCT_DIR)/base_unittests.dSYM/',
diff --git a/base/bind_helpers.h b/base/bind_helpers.h
index f8e89bd..c49b5b8 100644
--- a/base/bind_helpers.h
+++ b/base/bind_helpers.h
@@ -535,23 +535,6 @@
template <typename List1, typename List2>
using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
-template <size_t n, typename List>
-struct NthTypeImpl;
-
-template <size_t n, typename T, typename... Types>
-struct NthTypeImpl<n, TypeList<T, Types...>>
- : NthTypeImpl<n - 1, TypeList<Types...>> {
-};
-
-template <typename T, typename... Types>
-struct NthTypeImpl<0, TypeList<T, Types...>> {
- typedef T Type;
-};
-
-// A type-level function that extracts |n|th type from a TypeList.
-template <size_t n, typename List>
-using NthType = typename NthTypeImpl<n, List>::Type;
-
// Used for MakeFunctionType implementation.
template <typename R, typename ArgList>
struct MakeFunctionTypeImpl;
diff --git a/base/containers/hash_tables.h b/base/containers/hash_tables.h
index 736e892..6bf029e 100644
--- a/base/containers/hash_tables.h
+++ b/base/containers/hash_tables.h
@@ -45,7 +45,7 @@
#undef __DEPRECATED
#endif
-#if defined(OS_ANDROID) && defined(USE_STLPORT)
+#if defined(OS_ANDROID)
#include <hash_map>
#include <hash_set>
#define BASE_HASH_IMPL_NAMESPACE std
@@ -84,7 +84,7 @@
}
};
-#if !defined(USE_STLPORT)
+#if !defined(OS_ANDROID)
// The GNU C++ library provides identity hash functions for many integral types,
// but not for |long long|. This hash function will truncate if |size_t| is
// narrower than |long long|. This is probably good enough for what we will
@@ -102,7 +102,7 @@
DEFINE_TRIVIAL_HASH(unsigned long long);
#undef DEFINE_TRIVIAL_HASH
-#endif // !defined(USE_STLPORT)
+#endif // !defined(OS_ANDROID)
// Implement string hash functions so that strings of various flavors can
// be used as keys in STL maps and sets. The hash algorithm comes from the
diff --git a/base/files/file_path.h b/base/files/file_path.h
index 67bbb4b..93f9ec9 100644
--- a/base/files/file_path.h
+++ b/base/files/file_path.h
@@ -53,7 +53,7 @@
// between char[]-based pathnames on POSIX systems and wchar_t[]-based
// pathnames on Windows.
//
-// Paths can't contain NULs as a precaution agaist premature truncation.
+// As a precaution against premature truncation, paths can't contain NULs.
//
// Because a FilePath object should not be instantiated at the global scope,
// instead, use a FilePath::CharType[] and initialize it with
@@ -83,9 +83,9 @@
// in case it ever comes across such a system. FilePath needs this support
// for Windows UNC paths, anyway.
// References:
-// The Open Group Base Specifications Issue 7, sections 3.266 ("Pathname")
+// The Open Group Base Specifications Issue 7, sections 3.267 ("Pathname")
// and 4.12 ("Pathname Resolution"), available at:
-// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_266
+// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_267
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12
//
// - Windows treats c:\\ the same way it treats \\. This was intended to
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc
index 60267df..06c517a 100644
--- a/base/files/file_path_watcher_linux.cc
+++ b/base/files/file_path_watcher_linux.cc
@@ -200,7 +200,7 @@
CHECK_LE(0, shutdown_fd);
CHECK_GT(FD_SETSIZE, shutdown_fd);
- debug::TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
+ trace_event::TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
while (true) {
fd_set rfds;
diff --git a/base/files/file_util_linux.cc b/base/files/file_util_linux.cc
index 532962f..b230fd9 100644
--- a/base/files/file_util_linux.cc
+++ b/base/files/file_util_linux.cc
@@ -10,21 +10,6 @@
#include "base/files/file_path.h"
-// Make sure some of the newer macros from magic.h are defined.
-// TODO(mostynb@opera.com): remove this after 2014.
-#ifndef BTRFS_SUPER_MAGIC
-#define BTRFS_SUPER_MAGIC 0x9123683E
-#endif
-#ifndef HUGETLBFS_MAGIC
-#define HUGETLBFS_MAGIC 0x958458f6
-#endif
-#ifndef RAMFS_MAGIC
-#define RAMFS_MAGIC 0x858458f6
-#endif
-#ifndef TMPFS_MAGIC
-#define TMPFS_MAGIC 0x01021994
-#endif
-
namespace base {
bool GetFileSystemType(const FilePath& path, FileSystemType* type) {
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
index 313ed03..af932ce 100644
--- a/base/files/file_util_unittest.cc
+++ b/base/files/file_util_unittest.cc
@@ -30,6 +30,7 @@
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_file_util.h"
#include "base/threading/platform_thread.h"
@@ -326,6 +327,13 @@
// |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
FilePath base_a = temp_dir_.path().Append(FPL("base_a"));
+#if defined(OS_WIN)
+ // TEMP can have a lower case drive letter.
+ string16 temp_base_a = base_a.value();
+ ASSERT_FALSE(temp_base_a.empty());
+ *temp_base_a.begin() = base::ToUpperASCII(*temp_base_a.begin());
+ base_a = FilePath(temp_base_a);
+#endif
ASSERT_TRUE(CreateDirectory(base_a));
FilePath sub_a = base_a.Append(FPL("sub_a"));
@@ -428,6 +436,7 @@
TEST_F(FileUtilTest, DevicePathToDriveLetter) {
// Get a drive letter.
std::wstring real_drive_letter = temp_dir_.path().value().substr(0, 2);
+ StringToUpperASCII(&real_drive_letter);
if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
LOG(ERROR) << "Can't get a drive letter to test with.";
return;
@@ -1388,19 +1397,15 @@
path.value().c_str(),
read_only ? (attrs | FILE_ATTRIBUTE_READONLY) :
(attrs & ~FILE_ATTRIBUTE_READONLY)));
- // Files in the temporary directory should not be indexed ever. If this
- // assumption change, fix this unit test accordingly.
- // FILE_ATTRIBUTE_NOT_CONTENT_INDEXED doesn't exist on XP.
+
DWORD expected = read_only ?
((attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY)) |
FILE_ATTRIBUTE_READONLY) :
(attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY));
- // TODO(ripp@yandex-team.ru): this seems out of place here. If we really think
- // it is important to verify that temp files are not indexed there should be
- // a dedicated test for that (create a file, inspect the attributes)
- if (win::GetVersion() >= win::VERSION_VISTA)
- expected |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
- attrs = GetFileAttributes(path.value().c_str());
+
+ // Ignore FILE_ATTRIBUTE_NOT_CONTENT_INDEXED if present.
+ attrs = GetFileAttributes(path.value().c_str()) &
+ ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
ASSERT_EQ(expected, attrs);
#else
// On all other platforms, it involves removing/setting the write bit.
diff --git a/base/i18n/time_formatting.cc b/base/i18n/time_formatting.cc
index 917ba43..15b34a3 100644
--- a/base/i18n/time_formatting.cc
+++ b/base/i18n/time_formatting.cc
@@ -106,6 +106,12 @@
return TimeFormat(formatter.get(), time);
}
+string16 TimeFormatShortDateAndTimeWithTimeZone(const Time& time) {
+ scoped_ptr<icu::DateFormat> formatter(icu::DateFormat::createDateTimeInstance(
+ icu::DateFormat::kShort, icu::DateFormat::kLong));
+ return TimeFormat(formatter.get(), time);
+}
+
string16 TimeFormatFriendlyDateAndTime(const Time& time) {
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull));
diff --git a/base/i18n/time_formatting.h b/base/i18n/time_formatting.h
index 226d1a9..2053c0b 100644
--- a/base/i18n/time_formatting.h
+++ b/base/i18n/time_formatting.h
@@ -48,6 +48,11 @@
// Returns a numeric date and time such as "12/13/52 2:44:30 PM".
BASE_I18N_EXPORT string16 TimeFormatShortDateAndTime(const Time& time);
+// Returns a numeric date and time with time zone such as
+// "12/13/52 2:44:30 PM PST".
+BASE_I18N_EXPORT string16
+TimeFormatShortDateAndTimeWithTimeZone(const Time& time);
+
// Formats a time in a friendly sentence format, e.g.
// "Monday, March 6, 2008 2:44:30 PM".
BASE_I18N_EXPORT string16 TimeFormatFriendlyDateAndTime(const Time& time);
diff --git a/base/i18n/time_formatting_unittest.cc b/base/i18n/time_formatting_unittest.cc
index 0c2a6e6..4739b62 100644
--- a/base/i18n/time_formatting_unittest.cc
+++ b/base/i18n/time_formatting_unittest.cc
@@ -5,10 +5,13 @@
#include "base/i18n/time_formatting.h"
#include "base/i18n/rtl.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/icu/source/common/unicode/uversion.h"
+#include "third_party/icu/source/i18n/unicode/calendar.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
namespace base {
namespace {
@@ -18,6 +21,13 @@
15, 42, 7, 0 // 15:42:07.000
};
+base::string16 GetShortTimeZone() {
+ scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+ icu::UnicodeString name;
+ zone->getDisplayName(true, icu::TimeZone::SHORT, name);
+ return base::string16(name.getBuffer(), name.length());
+}
+
TEST(TimeFormattingTest, TimeFormatTimeOfDayDefault12h) {
// Test for a locale defaulted to 12h clock.
// As an instance, we use third_party/icu/source/data/locales/en.txt.
@@ -129,6 +139,8 @@
EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM"),
TimeFormatShortDateAndTime(time));
+ EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM ") + GetShortTimeZone(),
+ TimeFormatShortDateAndTimeWithTimeZone(time));
EXPECT_EQ(ASCIIToUTF16("Saturday, April 30, 2011 at 3:42:07 PM"),
TimeFormatFriendlyDateAndTime(time));
@@ -148,6 +160,8 @@
EXPECT_EQ(ASCIIToUTF16("30/04/2011"), TimeFormatShortDateNumeric(time));
EXPECT_EQ(ASCIIToUTF16("30/04/2011 15:42:07"),
TimeFormatShortDateAndTime(time));
+ EXPECT_EQ(ASCIIToUTF16("30/04/2011 15:42:07 ") + GetShortTimeZone(),
+ TimeFormatShortDateAndTimeWithTimeZone(time));
EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011 15:42:07"),
TimeFormatFriendlyDateAndTime(time));
EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011"),
diff --git a/base/ios/crb_protocol_observers.h b/base/ios/crb_protocol_observers.h
new file mode 100644
index 0000000..15d1656
--- /dev/null
+++ b/base/ios/crb_protocol_observers.h
@@ -0,0 +1,36 @@
+// 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_IOS_CRB_PROTOCOL_OBSERVERS_H_
+#define BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
+
+#import <Foundation/Foundation.h>
+
+typedef void (^ExecutionWithObserverBlock)(id);
+
+// Implements a container for observers that implement a specific Objective-C
+// protocol. The container forwards method invocations to its contained
+// observers, so that sending a message to all the observers is as simple as
+// sending the message to the container.
+@interface CRBProtocolObservers : NSObject
+
+// The Objective-C protocol that the observers in this container conform to.
+@property(nonatomic, readonly) Protocol* protocol;
+
+// Returns a CRBProtocolObservers container for observers that conform to
+// |protocol|.
++ (CRBProtocolObservers*)observersWithProtocol:(Protocol*)protocol;
+
+// Adds |observer| to this container.
+- (void)addObserver:(id)observer;
+
+// Remove |observer| from this container.
+- (void)removeObserver:(id)observer;
+
+// Executes callback on every observer. |callback| cannot be nil.
+- (void)executeOnObservers:(ExecutionWithObserverBlock)callback;
+
+@end
+
+#endif // BASE_IOS_CRB_PROTOCOL_OBSERVERS_H_
diff --git a/base/ios/crb_protocol_observers.mm b/base/ios/crb_protocol_observers.mm
new file mode 100644
index 0000000..ee9e23f
--- /dev/null
+++ b/base/ios/crb_protocol_observers.mm
@@ -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.
+
+#import "base/ios/crb_protocol_observers.h"
+
+#include <objc/runtime.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
+
+@interface CRBProtocolObservers ()
+
+// Designated initializer.
+- (id)initWithProtocol:(Protocol*)protocol;
+
+@end
+
+@implementation CRBProtocolObservers {
+ base::scoped_nsobject<Protocol> _protocol;
+ base::scoped_nsobject<NSHashTable> _observers;
+}
+
++ (CRBProtocolObservers*)observersWithProtocol:(Protocol*)protocol {
+ return [[[self alloc] initWithProtocol:protocol] autorelease];
+}
+
+- (id)init {
+ NOTREACHED();
+ return nil;
+}
+
+- (id)initWithProtocol:(Protocol*)protocol {
+ self = [super init];
+ if (self) {
+ _protocol.reset([protocol retain]);
+ _observers.reset([[NSHashTable weakObjectsHashTable] retain]);
+ }
+ return self;
+}
+
+- (Protocol*)protocol {
+ return _protocol.get();
+}
+
+- (void)addObserver:(id)observer {
+ DCHECK([observer conformsToProtocol:self.protocol]);
+ [_observers addObject:observer];
+}
+
+- (void)removeObserver:(id)observer {
+ [_observers removeObject:observer];
+}
+
+#pragma mark - NSObject
+
+- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
+ NSMethodSignature* signature = [super methodSignatureForSelector:selector];
+ if (signature)
+ return signature;
+
+ // Look for a required method in the protocol. protocol_getMethodDescription
+ // returns a struct whose fields are null if a method for the selector was
+ // not found.
+ struct objc_method_description description =
+ protocol_getMethodDescription(self.protocol, selector, YES, YES);
+ if (description.types)
+ return [NSMethodSignature signatureWithObjCTypes:description.types];
+
+ // Look for an optional method in the protocol.
+ description = protocol_getMethodDescription(self.protocol, selector, NO, YES);
+ if (description.types)
+ return [NSMethodSignature signatureWithObjCTypes:description.types];
+
+ // There is neither a required nor optional method with this selector in the
+ // protocol, so invoke -[NSObject doesNotRecognizeSelector:] to raise
+ // NSInvalidArgumentException.
+ [self doesNotRecognizeSelector:selector];
+ return nil;
+}
+
+- (void)forwardInvocation:(NSInvocation*)invocation {
+ SEL selector = [invocation selector];
+ base::scoped_nsobject<NSArray> observers([[_observers allObjects] retain]);
+ for (id observer in observers.get()) {
+ if ([observer respondsToSelector:selector])
+ [invocation invokeWithTarget:observer];
+ }
+}
+
+- (void)executeOnObservers:(ExecutionWithObserverBlock)callback {
+ DCHECK(callback);
+ base::scoped_nsobject<NSArray> observers([[_observers allObjects] retain]);
+ for (id observer in observers.get()) {
+ callback(observer);
+ }
+}
+
+@end
diff --git a/base/ios/crb_protocol_observers_unittest.mm b/base/ios/crb_protocol_observers_unittest.mm
new file mode 100644
index 0000000..d235c98
--- /dev/null
+++ b/base/ios/crb_protocol_observers_unittest.mm
@@ -0,0 +1,159 @@
+// 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.
+
+#import "base/ios/crb_protocol_observers.h"
+#include "base/ios/weak_nsobject.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/mac/scoped_nsobject.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+@protocol TestObserver
+
+@required
+- (void)requiredMethod;
+- (void)reset;
+
+@optional
+- (void)optionalMethod;
+
+@end
+
+// Implements only the required methods in the TestObserver protocol.
+@interface TestPartialObserver : NSObject<TestObserver>
+@property(nonatomic, readonly) BOOL requiredMethodInvoked;
+@end
+
+// Implements all the methods in the TestObserver protocol.
+@interface TestCompleteObserver : TestPartialObserver<TestObserver>
+@property(nonatomic, readonly) BOOL optionalMethodInvoked;
+@end
+
+namespace {
+
+class CRBProtocolObserversTest : public PlatformTest {
+ public:
+ CRBProtocolObserversTest() {}
+
+ protected:
+ void SetUp() override {
+ PlatformTest::SetUp();
+
+ observers_.reset([[CRBProtocolObservers observersWithProtocol:
+ @protocol(TestObserver)] retain]);
+
+ partial_observer_.reset([[TestPartialObserver alloc] init]);
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+
+ complete_observer_.reset([[TestCompleteObserver alloc] init]);
+ EXPECT_FALSE([complete_observer_ requiredMethodInvoked]);
+ EXPECT_FALSE([complete_observer_ optionalMethodInvoked]);
+ }
+
+ base::scoped_nsobject<id> observers_;
+ base::scoped_nsobject<TestPartialObserver> partial_observer_;
+ base::scoped_nsobject<TestCompleteObserver> complete_observer_;
+};
+
+// Verifies basic functionality of -[CRBProtocolObservers addObserver:] and
+// -[CRBProtocolObservers removeObserver:].
+TEST_F(CRBProtocolObserversTest, AddRemoveObserver) {
+ // Add an observer and verify that the CRBProtocolObservers instance forwards
+ // an invocation to it.
+ [observers_ addObserver:partial_observer_];
+ [observers_ requiredMethod];
+ EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+
+ [partial_observer_ reset];
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+
+ // Remove the observer and verify that the CRBProtocolObservers instance no
+ // longer forwards an invocation to it.
+ [observers_ removeObserver:partial_observer_];
+ [observers_ requiredMethod];
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers correctly forwards the invocation of a
+// required method in the protocol.
+TEST_F(CRBProtocolObserversTest, RequiredMethods) {
+ [observers_ addObserver:partial_observer_];
+ [observers_ addObserver:complete_observer_];
+ [observers_ requiredMethod];
+ EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+ EXPECT_TRUE([complete_observer_ requiredMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers correctly forwards the invocation of an
+// optional method in the protocol.
+TEST_F(CRBProtocolObserversTest, OptionalMethods) {
+ [observers_ addObserver:partial_observer_];
+ [observers_ addObserver:complete_observer_];
+ [observers_ optionalMethod];
+ EXPECT_FALSE([partial_observer_ requiredMethodInvoked]);
+ EXPECT_FALSE([complete_observer_ requiredMethodInvoked]);
+ EXPECT_TRUE([complete_observer_ optionalMethodInvoked]);
+}
+
+// Verifies that CRBProtocolObservers only holds a weak reference to an
+// observer.
+TEST_F(CRBProtocolObserversTest, WeakReference) {
+ base::WeakNSObject<TestPartialObserver> weak_observer(
+ partial_observer_);
+ EXPECT_TRUE(weak_observer);
+
+ [observers_ addObserver:partial_observer_];
+
+ {
+ // Need an autorelease pool here, because
+ // -[CRBProtocolObservers forwardInvocation:] creates a temporary
+ // autoreleased array that holds all the observers.
+ base::mac::ScopedNSAutoreleasePool pool;
+ [observers_ requiredMethod];
+ EXPECT_TRUE([partial_observer_ requiredMethodInvoked]);
+ }
+
+ partial_observer_.reset();
+ EXPECT_FALSE(weak_observer.get());
+}
+
+} // namespace
+
+@implementation TestPartialObserver {
+ BOOL _requiredMethodInvoked;
+}
+
+- (BOOL)requiredMethodInvoked {
+ return _requiredMethodInvoked;
+}
+
+- (void)requiredMethod {
+ _requiredMethodInvoked = YES;
+}
+
+- (void)reset {
+ _requiredMethodInvoked = NO;
+}
+
+@end
+
+@implementation TestCompleteObserver {
+ BOOL _optionalMethodInvoked;
+}
+
+- (BOOL)optionalMethodInvoked {
+ return _optionalMethodInvoked;
+}
+
+- (void)optionalMethod {
+ _optionalMethodInvoked = YES;
+}
+
+- (void)reset {
+ [super reset];
+ _optionalMethodInvoked = NO;
+}
+
+@end
diff --git a/base/logging.h b/base/logging.h
index aa243a9..cc0a5aa 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -350,7 +350,7 @@
((verboselevel) <= ::logging::GetVlogLevel(__FILE__))
// Helper macro which avoids evaluating the arguments to a stream if
-// the condition doesn't hold.
+// the condition doesn't hold. Condition is evaluated once and only once.
#define LAZY_STREAM(stream, condition) \
!(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream)
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h
index faa36ea..2795b19 100644
--- a/base/mac/sdk_forward_declarations.h
+++ b/base/mac/sdk_forward_declarations.h
@@ -219,6 +219,55 @@
- (void)windowDidFailToExitFullScreen:(NSWindow*)window;
@end
+BASE_EXPORT extern "C" NSString* const CBAdvertisementDataServiceDataKey;
+
+enum {
+ CBPeripheralStateDisconnected = 0,
+ CBPeripheralStateConnecting,
+ CBPeripheralStateConnected,
+};
+typedef NSInteger CBPeripheralState;
+
+@interface CBPeripheral : NSObject
+@property(readonly, nonatomic) CFUUIDRef UUID;
+@property(retain, readonly) NSString* name;
+@property(readonly) BOOL isConnected;
+@end
+
+enum {
+ CBCentralManagerStateUnknown = 0,
+ CBCentralManagerStateResetting,
+ CBCentralManagerStateUnsupported,
+ CBCentralManagerStateUnauthorized,
+ CBCentralManagerStatePoweredOff,
+ CBCentralManagerStatePoweredOn,
+};
+typedef NSInteger CBCentralManagerState;
+
+@protocol CBCentralManagerDelegate;
+
+@interface CBCentralManager : NSObject
+@property(readonly) CBCentralManagerState state;
+- (id)initWithDelegate:(id<CBCentralManagerDelegate>)delegate
+ queue:(dispatch_queue_t)queue;
+- (void)scanForPeripheralsWithServices:(NSArray*)serviceUUIDs
+ options:(NSDictionary*)options;
+- (void)stopScan;
+@end
+
+@protocol CBCentralManagerDelegate<NSObject>
+- (void)centralManagerDidUpdateState:(CBCentralManager*)central;
+- (void)centralManager:(CBCentralManager*)central
+ didDiscoverPeripheral:(CBPeripheral*)peripheral
+ advertisementData:(NSDictionary*)advertisementData
+ RSSI:(NSNumber*)RSSI;
+@end
+
+@interface CBUUID : NSObject
+@property(nonatomic, readonly) NSData* data;
++ (CBUUID*)UUIDWithString:(NSString*)theString;
+@end
+
#endif // MAC_OS_X_VERSION_10_7
#if !defined(MAC_OS_X_VERSION_10_8) || \
@@ -232,6 +281,10 @@
- (CGColorRef)CGColor;
@end
+@interface NSUUID : NSObject
+- (NSString*)UUIDString;
+@end
+
#endif // MAC_OS_X_VERSION_10_8
@@ -304,6 +357,12 @@
NSWorkspaceLaunchWithErrorPresentation = 0x00000040
};
+@interface CBPeripheral (MavericksSDK)
+@property(readonly, nonatomic) NSUUID* identifier;
+@end
+
+BASE_EXPORT extern "C" NSString* const CBAdvertisementDataIsConnectable;
+
#else // !MAC_OS_X_VERSION_10_9
typedef enum {
@@ -345,6 +404,10 @@
BASE_EXPORT extern "C" NSString* const NSAppearanceNameVibrantDark;
+@interface CBUUID (YosemiteSDK)
+- (NSString*)UUIDString;
+@end
+
#endif // MAC_OS_X_VERSION_10_10
#endif // BASE_MAC_SDK_FORWARD_DECLARATIONS_H_
diff --git a/base/mac/sdk_forward_declarations.mm b/base/mac/sdk_forward_declarations.mm
index 7a57032..4edc710 100644
--- a/base/mac/sdk_forward_declarations.mm
+++ b/base/mac/sdk_forward_declarations.mm
@@ -23,6 +23,8 @@
NSString* const NSWindowDidChangeBackingPropertiesNotification =
@"NSWindowDidChangeBackingPropertiesNotification";
+NSString* const CBAdvertisementDataServiceDataKey = @"kCBAdvDataServiceData";
+
#endif // MAC_OS_X_VERSION_10_7
// Replicate specific 10.9 SDK declarations for building with prior SDKs.
@@ -32,6 +34,8 @@
NSString* const NSWindowDidChangeOcclusionStateNotification =
@"NSWindowDidChangeOcclusionStateNotification";
+NSString* const CBAdvertisementDataIsConnectable = @"kCBAdvDataIsConnectable";
+
#endif // MAC_OS_X_VERSION_10_9
// Replicate specific 10.10 SDK declarations for building with prior SDKs.
diff --git a/base/macros.h b/base/macros.h
index 15408bc..3ea576c 100644
--- a/base/macros.h
+++ b/base/macros.h
@@ -63,7 +63,7 @@
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif
-#define arraysize(array) (sizeof(ArraySizeHelper(array)))
+#define arraysize(array) (sizeof(::ArraySizeHelper(array)))
// Use implicit_cast as a safe version of static_cast or const_cast
diff --git a/base/memory/discardable_memory.h b/base/memory/discardable_memory.h
index d8b7a58..c49a99f 100644
--- a/base/memory/discardable_memory.h
+++ b/base/memory/discardable_memory.h
@@ -89,10 +89,6 @@
// Create a DiscardableMemory instance with preferred type and |size|.
static scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size);
- // Discardable memory implementations might use this to release memory
- // or resources assigned to instances that have been purged.
- static void ReleaseFreeMemory();
-
// 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
@@ -118,12 +114,6 @@
// Returns the memory address held by this object. The object must be locked
// before calling this. Otherwise, this will cause a DCHECK error.
virtual void* Memory() const = 0;
-
- // Testing utility calls.
-
- // Purge all discardable memory in the system. This call has global effects
- // across all running processes, so it should only be used for testing!
- static void PurgeForTesting();
};
} // namespace base
diff --git a/base/memory/discardable_memory_android.cc b/base/memory/discardable_memory_android.cc
index de71124..27b390f 100644
--- a/base/memory/discardable_memory_android.cc
+++ b/base/memory/discardable_memory_android.cc
@@ -44,11 +44,6 @@
} // namespace
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -104,11 +99,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- g_shared_state.Pointer()->manager.PurgeAll();
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/base/memory/discardable_memory_ashmem.cc b/base/memory/discardable_memory_ashmem.cc
index df0697c..a590e53 100644
--- a/base/memory/discardable_memory_ashmem.cc
+++ b/base/memory/discardable_memory_ashmem.cc
@@ -71,9 +71,5 @@
ashmem_chunk_.reset();
}
-bool DiscardableMemoryAshmem::IsMemoryResident() const {
- return true;
-}
-
} // namespace internal
} // namespace base
diff --git a/base/memory/discardable_memory_ashmem.h b/base/memory/discardable_memory_ashmem.h
index 100655b..1269cc2 100644
--- a/base/memory/discardable_memory_ashmem.h
+++ b/base/memory/discardable_memory_ashmem.h
@@ -38,7 +38,6 @@
bool AllocateAndAcquireLock() override;
void ReleaseLock() override;
void Purge() override;
- bool IsMemoryResident() const override;
private:
const size_t bytes_;
diff --git a/base/memory/discardable_memory_emulated.cc b/base/memory/discardable_memory_emulated.cc
index 4303400..b12d7ce 100644
--- a/base/memory/discardable_memory_emulated.cc
+++ b/base/memory/discardable_memory_emulated.cc
@@ -68,11 +68,6 @@
g_manager.Pointer()->ReduceMemoryUsageUntilWithinLimit(bytes);
}
-// static
-void DiscardableMemoryEmulated::PurgeForTesting() {
- g_manager.Pointer()->PurgeAll();
-}
-
bool DiscardableMemoryEmulated::Initialize() {
return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
}
@@ -113,9 +108,5 @@
memory_.reset();
}
-bool DiscardableMemoryEmulated::IsMemoryResident() const {
- return true;
-}
-
} // namespace internal
} // namespace base
diff --git a/base/memory/discardable_memory_emulated.h b/base/memory/discardable_memory_emulated.h
index 150c1ab..aa01a9d 100644
--- a/base/memory/discardable_memory_emulated.h
+++ b/base/memory/discardable_memory_emulated.h
@@ -26,8 +26,6 @@
// unavailable in kernel space. crbug.com/400423
BASE_EXPORT static void ReduceMemoryUsageUntilWithinLimit(size_t bytes);
- static void PurgeForTesting();
-
bool Initialize();
// Overridden from DiscardableMemory:
@@ -39,7 +37,6 @@
bool AllocateAndAcquireLock() override;
void ReleaseLock() override {}
void Purge() override;
- bool IsMemoryResident() const override;
private:
const size_t bytes_;
diff --git a/base/memory/discardable_memory_linux.cc b/base/memory/discardable_memory_linux.cc
index 9b4e940..977b029 100644
--- a/base/memory/discardable_memory_linux.cc
+++ b/base/memory/discardable_memory_linux.cc
@@ -11,11 +11,6 @@
namespace base {
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -61,10 +56,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/base/memory/discardable_memory_mac.cc b/base/memory/discardable_memory_mac.cc
index 18cf80a..c8669a6 100644
--- a/base/memory/discardable_memory_mac.cc
+++ b/base/memory/discardable_memory_mac.cc
@@ -14,11 +14,6 @@
namespace base {
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -72,11 +67,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- internal::DiscardableMemoryMach::PurgeForTesting();
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/base/memory/discardable_memory_mach.cc b/base/memory/discardable_memory_mach.cc
index 5fc43f2..d96de79 100644
--- a/base/memory/discardable_memory_mach.cc
+++ b/base/memory/discardable_memory_mach.cc
@@ -63,12 +63,6 @@
g_manager.Pointer()->Unregister(this);
}
-// static
-void DiscardableMemoryMach::PurgeForTesting() {
- int state = 0;
- vm_purgable_control(mach_task_self(), 0, VM_PURGABLE_PURGE_ALL, &state);
-}
-
bool DiscardableMemoryMach::Initialize() {
return Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
}
@@ -154,9 +148,5 @@
memory_.reset();
}
-bool DiscardableMemoryMach::IsMemoryResident() const {
- return true;
-}
-
} // namespace internal
} // namespace base
diff --git a/base/memory/discardable_memory_mach.h b/base/memory/discardable_memory_mach.h
index af2191f..b3b4b48 100644
--- a/base/memory/discardable_memory_mach.h
+++ b/base/memory/discardable_memory_mach.h
@@ -20,8 +20,6 @@
explicit DiscardableMemoryMach(size_t bytes);
~DiscardableMemoryMach() override;
- static void PurgeForTesting();
-
bool Initialize();
// Overridden from DiscardableMemory:
@@ -33,7 +31,6 @@
bool AllocateAndAcquireLock() override;
void ReleaseLock() override;
void Purge() override;
- bool IsMemoryResident() const override;
private:
mac::ScopedMachVM memory_;
diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc
index 09e63e3..cbbdb47 100644
--- a/base/memory/discardable_memory_manager.cc
+++ b/base/memory/discardable_memory_manager.cc
@@ -51,34 +51,6 @@
hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time;
}
-void DiscardableMemoryManager::ReleaseFreeMemory() {
- TRACE_EVENT0("base", "DiscardableMemoryManager::ReleaseFreeMemory");
-
- AutoLock lock(lock_);
- size_t bytes_allocated_before_releasing_memory = bytes_allocated_;
- for (auto& entry : allocations_) {
- Allocation* allocation = entry.first;
- AllocationInfo* info = &entry.second;
-
- if (!info->purgable)
- continue;
-
- // Skip if memory is still resident, otherwise purge and adjust
- // |bytes_allocated_|.
- if (allocation->IsMemoryResident())
- 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_releasing_memory)
- BytesAllocatedChanged(bytes_allocated_);
-}
-
bool DiscardableMemoryManager::ReduceMemoryUsage() {
return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit();
}
diff --git a/base/memory/discardable_memory_manager.h b/base/memory/discardable_memory_manager.h
index 8bf9289..43737f8 100644
--- a/base/memory/discardable_memory_manager.h
+++ b/base/memory/discardable_memory_manager.h
@@ -31,10 +31,6 @@
// is acquired on the allocation.
virtual void Purge() = 0;
- // Check if allocated memory is still resident. It is illegal to call this
- // while a lock is acquired on the allocation.
- virtual bool IsMemoryResident() const = 0;
-
protected:
virtual ~DiscardableMemoryManagerAllocation() {}
};
@@ -72,9 +68,6 @@
void SetHardMemoryLimitExpirationTime(
TimeDelta hard_memory_limit_expiration_time);
- // This will make sure that all purged memory is released to the OS.
- void ReleaseFreeMemory();
-
// 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.
diff --git a/base/memory/discardable_memory_manager_unittest.cc b/base/memory/discardable_memory_manager_unittest.cc
index 9f06e37..6717f09 100644
--- a/base/memory/discardable_memory_manager_unittest.cc
+++ b/base/memory/discardable_memory_manager_unittest.cc
@@ -33,10 +33,6 @@
DCHECK(is_allocated_);
is_allocated_ = false;
}
- bool IsMemoryResident() const override {
- DCHECK(is_allocated_);
- return true;
- }
bool is_locked() const { return is_locked_; }
diff --git a/base/memory/discardable_memory_shmem.cc b/base/memory/discardable_memory_shmem.cc
index 416fcf2..9056279 100644
--- a/base/memory/discardable_memory_shmem.cc
+++ b/base/memory/discardable_memory_shmem.cc
@@ -6,62 +6,17 @@
#include "base/lazy_instance.h"
#include "base/memory/discardable_memory_shmem_allocator.h"
-#include "base/memory/discardable_shared_memory.h"
namespace base {
-namespace {
-
-// Have the DiscardableMemoryManager trigger in-process eviction
-// when address space usage gets too high (e.g. 512 MBytes).
-const size_t kMemoryLimit = 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(
- kMemoryLimit, kMemoryLimit, TimeDelta::Max());
- }
- static void Delete(internal::DiscardableMemoryManager* instance) {
- instance->~DiscardableMemoryManager();
- }
-};
-
-LazyInstance<internal::DiscardableMemoryManager,
- DiscardableMemoryManagerLazyInstanceTraits> g_manager =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
namespace internal {
DiscardableMemoryShmem::DiscardableMemoryShmem(size_t bytes)
: bytes_(bytes), is_locked_(false) {
- g_manager.Pointer()->Register(this, bytes);
}
DiscardableMemoryShmem::~DiscardableMemoryShmem() {
if (is_locked_)
Unlock();
- g_manager.Pointer()->Unregister(this);
-}
-
-// static
-void DiscardableMemoryShmem::ReleaseFreeMemory() {
- g_manager.Pointer()->ReleaseFreeMemory();
-}
-
-// static
-void DiscardableMemoryShmem::PurgeForTesting() {
- g_manager.Pointer()->PurgeAll();
}
bool DiscardableMemoryShmem::Initialize() {
@@ -71,18 +26,24 @@
DiscardableMemoryLockStatus DiscardableMemoryShmem::Lock() {
DCHECK(!is_locked_);
- bool purged = false;
- if (!g_manager.Pointer()->AcquireLock(this, &purged))
+ if (chunk_ && chunk_->Lock()) {
+ is_locked_ = true;
+ return DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+ }
+
+ chunk_ = DiscardableMemoryShmemAllocator::GetInstance()
+ ->AllocateLockedDiscardableMemory(bytes_);
+ if (!chunk_)
return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
is_locked_ = true;
- return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
- : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+ return DISCARDABLE_MEMORY_LOCK_STATUS_PURGED;
}
void DiscardableMemoryShmem::Unlock() {
DCHECK(is_locked_);
- g_manager.Pointer()->ReleaseLock(this);
+ DCHECK(chunk_);
+ chunk_->Unlock();
is_locked_ = false;
}
@@ -92,28 +53,5 @@
return chunk_->Memory();
}
-bool DiscardableMemoryShmem::AllocateAndAcquireLock() {
- if (chunk_ && chunk_->Lock())
- return true;
-
- chunk_ = DiscardableMemoryShmemAllocator::GetInstance()
- ->AllocateLockedDiscardableMemory(bytes_);
- DCHECK(chunk_);
- return false;
-}
-
-void DiscardableMemoryShmem::ReleaseLock() {
- chunk_->Unlock();
-}
-
-void DiscardableMemoryShmem::Purge() {
- DCHECK(!is_locked_);
- chunk_.reset();
-}
-
-bool DiscardableMemoryShmem::IsMemoryResident() const {
- return chunk_->IsMemoryResident();
-}
-
} // namespace internal
} // namespace base
diff --git a/base/memory/discardable_memory_shmem.h b/base/memory/discardable_memory_shmem.h
index b04c9b1..98d3b97 100644
--- a/base/memory/discardable_memory_shmem.h
+++ b/base/memory/discardable_memory_shmem.h
@@ -7,24 +7,16 @@
#include "base/memory/discardable_memory.h"
-#include "base/memory/discardable_memory_manager.h"
-
namespace base {
class DiscardableMemoryShmemChunk;
namespace internal {
-class DiscardableMemoryShmem
- : public DiscardableMemory,
- public internal::DiscardableMemoryManagerAllocation {
+class DiscardableMemoryShmem : public DiscardableMemory {
public:
explicit DiscardableMemoryShmem(size_t bytes);
~DiscardableMemoryShmem() override;
- static void ReleaseFreeMemory();
-
- static void PurgeForTesting();
-
bool Initialize();
// Overridden from DiscardableMemory:
@@ -32,12 +24,6 @@
void Unlock() override;
void* Memory() const override;
- // Overridden from internal::DiscardableMemoryManagerAllocation:
- bool AllocateAndAcquireLock() override;
- void ReleaseLock() override;
- void Purge() override;
- bool IsMemoryResident() const override;
-
private:
const size_t bytes_;
scoped_ptr<DiscardableMemoryShmemChunk> chunk_;
diff --git a/base/memory/discardable_memory_shmem_allocator.cc b/base/memory/discardable_memory_shmem_allocator.cc
index 8abe456..761204f 100644
--- a/base/memory/discardable_memory_shmem_allocator.cc
+++ b/base/memory/discardable_memory_shmem_allocator.cc
@@ -18,16 +18,12 @@
: shared_memory_(shared_memory.Pass()) {}
// Overridden from DiscardableMemoryShmemChunk:
- bool Lock() override {
- auto result = shared_memory_->Lock(0, 0);
- DCHECK_NE(result, DiscardableSharedMemory::PURGED);
- return result == DiscardableSharedMemory::SUCCESS;
+ bool Lock() override { return false; }
+ void Unlock() override {
+ shared_memory_->Unlock(0, 0);
+ shared_memory_.reset();
}
- void Unlock() override { shared_memory_->Unlock(0, 0); }
void* Memory() const override { return shared_memory_->memory(); }
- bool IsMemoryResident() const override {
- return shared_memory_->IsMemoryResident();
- }
private:
scoped_ptr<DiscardableSharedMemory> shared_memory_;
diff --git a/base/memory/discardable_memory_shmem_allocator.h b/base/memory/discardable_memory_shmem_allocator.h
index ed40672..ac4118e 100644
--- a/base/memory/discardable_memory_shmem_allocator.h
+++ b/base/memory/discardable_memory_shmem_allocator.h
@@ -19,7 +19,6 @@
virtual bool Lock() = 0;
virtual void Unlock() = 0;
virtual void* Memory() const = 0;
- virtual bool IsMemoryResident() const = 0;
};
class BASE_EXPORT DiscardableMemoryShmemAllocator {
diff --git a/base/memory/discardable_memory_unittest.cc b/base/memory/discardable_memory_unittest.cc
index 4510413..fb1eba6 100644
--- a/base/memory/discardable_memory_unittest.cc
+++ b/base/memory/discardable_memory_unittest.cc
@@ -82,16 +82,6 @@
ASSERT_TRUE(memory);
}
-// Test forced purging.
-TEST_P(DiscardableMemoryTest, Purge) {
- const scoped_ptr<DiscardableMemory> memory(CreateLockedMemory(kSize));
- ASSERT_TRUE(memory);
- memory->Unlock();
-
- DiscardableMemory::PurgeForTesting();
- EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, memory->Lock());
-}
-
#if !defined(NDEBUG) && !defined(OS_ANDROID)
// Death tests are not supported with Android APKs.
TEST_P(DiscardableMemoryTest, UnlockedMemoryAccessCrashesInDebugMode) {
diff --git a/base/memory/discardable_memory_win.cc b/base/memory/discardable_memory_win.cc
index 9b4e940..977b029 100644
--- a/base/memory/discardable_memory_win.cc
+++ b/base/memory/discardable_memory_win.cc
@@ -11,11 +11,6 @@
namespace base {
// static
-void DiscardableMemory::ReleaseFreeMemory() {
- internal::DiscardableMemoryShmem::ReleaseFreeMemory();
-}
-
-// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
}
@@ -61,10 +56,4 @@
return nullptr;
}
-// static
-void DiscardableMemory::PurgeForTesting() {
- internal::DiscardableMemoryEmulated::PurgeForTesting();
- internal::DiscardableMemoryShmem::PurgeForTesting();
-}
-
} // namespace base
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index 3805bed..49e93cd 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -162,19 +162,19 @@
DCHECK_EQ(AlignToPageSize(offset), offset);
DCHECK_EQ(AlignToPageSize(length), length);
- // Calls to this function must synchronized properly.
+ // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_);
- // Return false when instance has been purged or not initialized properly by
- // checking if |last_known_usage_| is NULL.
- if (last_known_usage_.is_null())
- return FAILED;
-
DCHECK(shared_memory_.memory());
// We need to successfully acquire the platform independent lock before
// individual pages can be locked.
if (!locked_page_count_) {
+ // Return false when instance has been purged or not initialized properly
+ // by checking if |last_known_usage_| is NULL.
+ if (last_known_usage_.is_null())
+ return FAILED;
+
SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
SharedState new_state(SharedState::LOCKED, Time());
SharedState result(subtle::Acquire_CompareAndSwap(
@@ -226,7 +226,7 @@
DCHECK_EQ(AlignToPageSize(offset), offset);
DCHECK_EQ(AlignToPageSize(length), length);
- // Calls to this function must synchronized properly.
+ // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_);
// Zero for length means "everything onward".
@@ -294,7 +294,7 @@
}
bool DiscardableSharedMemory::Purge(Time current_time) {
- // Calls to this function must synchronized properly.
+ // Calls to this function must be synchronized properly.
DFAKE_SCOPED_LOCK(thread_collision_warner_);
// Early out if not mapped. This can happen if the segment was previously
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc
index 1f08aea..74d19a6 100644
--- a/base/memory/discardable_shared_memory_unittest.cc
+++ b/base/memory/discardable_shared_memory_unittest.cc
@@ -234,8 +234,6 @@
// Lock should fail as memory has been purged.
auto lock_rv = memory2.Lock(0, 0);
EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
- lock_rv = memory1.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
}
TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) {
@@ -263,27 +261,39 @@
rv = memory1.Purge(Time::FromDoubleT(2));
EXPECT_FALSE(rv);
- // Unlock second page.
+ // Lock first page again.
memory2.SetNow(Time::FromDoubleT(3));
+ auto lock_rv = memory2.Lock(0, base::GetPageSize());
+ EXPECT_NE(DiscardableSharedMemory::FAILED, lock_rv);
+
+ // Unlock first page.
+ memory2.SetNow(Time::FromDoubleT(4));
+ memory2.Unlock(0, base::GetPageSize());
+
+ rv = memory1.Purge(Time::FromDoubleT(5));
+ EXPECT_FALSE(rv);
+
+ // Unlock second page.
+ memory2.SetNow(Time::FromDoubleT(6));
memory2.Unlock(base::GetPageSize(), base::GetPageSize());
- rv = memory1.Purge(Time::FromDoubleT(4));
+ rv = memory1.Purge(Time::FromDoubleT(7));
EXPECT_FALSE(rv);
// Unlock anything onwards.
- memory2.SetNow(Time::FromDoubleT(5));
+ memory2.SetNow(Time::FromDoubleT(8));
memory2.Unlock(2 * base::GetPageSize(), 0);
// Memory is unlocked, but our usage timestamp is incorrect.
- rv = memory1.Purge(Time::FromDoubleT(6));
+ rv = memory1.Purge(Time::FromDoubleT(9));
EXPECT_FALSE(rv);
// The failed purge attempt should have updated usage time to the correct
// value.
- EXPECT_EQ(Time::FromDoubleT(5), memory1.last_known_usage());
+ EXPECT_EQ(Time::FromDoubleT(8), memory1.last_known_usage());
// Purge should now succeed.
- rv = memory1.Purge(Time::FromDoubleT(7));
+ rv = memory1.Purge(Time::FromDoubleT(10));
EXPECT_TRUE(rv);
}
diff --git a/base/memory/memory_pressure_listener.cc b/base/memory/memory_pressure_listener.cc
index d808502..6a8ed21 100644
--- a/base/memory/memory_pressure_listener.cc
+++ b/base/memory/memory_pressure_listener.cc
@@ -54,7 +54,7 @@
DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE);
TRACE_EVENT1("memory", "MemoryPressureListener::NotifyMemoryPressure",
"level", memory_pressure_level);
- g_observers.Get().Notify(&MemoryPressureListener::Notify,
+ g_observers.Get().Notify(FROM_HERE, &MemoryPressureListener::Notify,
memory_pressure_level);
}
diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h
index ae9eb0f..987ccfa 100644
--- a/base/memory/scoped_ptr.h
+++ b/base/memory/scoped_ptr.h
@@ -85,6 +85,7 @@
#include <stdlib.h>
#include <algorithm> // For std::swap().
+#include <iosfwd>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
@@ -585,4 +586,9 @@
return scoped_ptr<T>(ptr);
}
+template <typename T>
+std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
+ return out << p.get();
+}
+
#endif // BASE_MEMORY_SCOPED_PTR_H_
diff --git a/base/memory/scoped_ptr_unittest.cc b/base/memory/scoped_ptr_unittest.cc
index ca7cfbf..0887a99 100644
--- a/base/memory/scoped_ptr_unittest.cc
+++ b/base/memory/scoped_ptr_unittest.cc
@@ -4,9 +4,12 @@
#include "base/memory/scoped_ptr.h"
+#include <sstream>
+
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
+#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -678,3 +681,13 @@
scoped_ptr<int, NoOpDeleter> x(owner.get());
x.reset(x.get());
}
+
+// Logging a scoped_ptr<T> to an ostream shouldn't convert it to a boolean
+// value first.
+TEST(ScopedPtrTest, LoggingDoesntConvertToBoolean) {
+ scoped_ptr<int> x(new int);
+ std::stringstream s;
+ s << x;
+ std::string expected = base::StringPrintf("%p", x.get());
+ EXPECT_EQ(expected, s.str());
+}
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 86771e4..daa7782 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -152,7 +152,12 @@
MessageLoop::~MessageLoop() {
DCHECK_EQ(this, current());
+ // iOS just attaches to the loop, it doesn't Run it.
+ // TODO(stuartmorgan): Consider wiring up a Detach().
+#if !defined(OS_IOS)
DCHECK(!run_loop_);
+#endif
+
#if defined(OS_WIN)
if (in_high_res_mode_)
Time::ActivateHighResolutionTimer(false);
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index e03c94c..639f6d3 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -547,9 +547,8 @@
return;
global_->observer_list_->Notify(
- &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
- field_trial->trial_name(),
- field_trial->group_name_internal());
+ FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
+ field_trial->trial_name(), field_trial->group_name_internal());
}
// static
diff --git a/base/metrics/histogram_macros.h b/base/metrics/histogram_macros.h
index e9a871c..2aee1a5 100644
--- a/base/metrics/histogram_macros.h
+++ b/base/metrics/histogram_macros.h
@@ -229,4 +229,36 @@
base::CustomHistogram::FactoryGet(name, custom_ranges, \
base::HistogramBase::kUmaTargetedHistogramFlag))
+// Scoped class which logs its time on this earth as a UMA statistic. This is
+// recommended for when you want a histogram which measures the time it takes
+// for a method to execute. This measures up to 10 seconds.
+#define SCOPED_UMA_HISTOGRAM_TIMER(name) \
+ SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, false, __COUNTER__)
+
+// Similar scoped histogram timer, but this uses UMA_HISTOGRAM_LONG_TIMES_100,
+// which measures up to an hour, and uses 100 buckets. This is more expensive
+// to store, so only use if this often takes >10 seconds.
+#define SCOPED_UMA_HISTOGRAM_LONG_TIMER(name) \
+ SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, true, __COUNTER__)
+
+// This nested macro is necessary to expand __COUNTER__ to an actual value.
+#define SCOPED_UMA_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
+ SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
+
+#define SCOPED_UMA_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
+ class ScopedHistogramTimer##key { \
+ public: \
+ ScopedHistogramTimer##key() : constructed_(base::TimeTicks::Now()) {} \
+ ~ScopedHistogramTimer##key() { \
+ base::TimeDelta elapsed = base::TimeTicks::Now() - constructed_; \
+ if (is_long) { \
+ UMA_HISTOGRAM_LONG_TIMES_100(name, elapsed); \
+ } else { \
+ UMA_HISTOGRAM_TIMES(name, elapsed); \
+ } \
+ } \
+ private: \
+ base::TimeTicks constructed_; \
+ } scoped_histogram_timer_##key
+
#endif // BASE_METRICS_HISTOGRAM_MACROS_H_
diff --git a/base/metrics/histogram_macros_unittest.cc b/base/metrics/histogram_macros_unittest.cc
new file mode 100644
index 0000000..c599161
--- /dev/null
+++ b/base/metrics/histogram_macros_unittest.cc
@@ -0,0 +1,18 @@
+// 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/metrics/histogram_macros.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+TEST(ScopedHistogramTimer, TwoTimersOneScope) {
+ SCOPED_UMA_HISTOGRAM_TIMER("TestTimer0");
+ SCOPED_UMA_HISTOGRAM_TIMER("TestTimer1");
+ SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer0");
+ SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer1");
+}
+
+} // namespace base
diff --git a/base/metrics/stats_counters.cc b/base/metrics/stats_counters.cc
deleted file mode 100644
index 12416d9..0000000
--- a/base/metrics/stats_counters.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/metrics/stats_counters.h"
-
-namespace base {
-
-StatsCounter::StatsCounter(const std::string& name)
- : counter_id_(-1) {
- // We prepend the name with 'c:' to indicate that it is a counter.
- if (StatsTable::current()) {
- // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
- // static.
- name_ = "c:";
- name_.append(name);
- }
-}
-
-StatsCounter::~StatsCounter() {
-}
-
-void StatsCounter::Set(int value) {
- int* loc = GetPtr();
- if (loc)
- *loc = value;
-}
-
-void StatsCounter::Add(int value) {
- int* loc = GetPtr();
- if (loc)
- (*loc) += value;
-}
-
-StatsCounter::StatsCounter()
- : counter_id_(-1) {
-}
-
-int* StatsCounter::GetPtr() {
- StatsTable* table = StatsTable::current();
- if (!table)
- return NULL;
-
- // If counter_id_ is -1, then we haven't looked it up yet.
- if (counter_id_ == -1) {
- counter_id_ = table->FindCounter(name_);
- if (table->GetSlot() == 0) {
- if (!table->RegisterThread(std::string())) {
- // There is no room for this thread. This thread
- // cannot use counters.
- counter_id_ = 0;
- return NULL;
- }
- }
- }
-
- // If counter_id_ is > 0, then we have a valid counter.
- if (counter_id_ > 0)
- return table->GetLocation(counter_id_, table->GetSlot());
-
- // counter_id_ was zero, which means the table is full.
- return NULL;
-}
-
-
-StatsCounterTimer::StatsCounterTimer(const std::string& name) {
- // we prepend the name with 't:' to indicate that it is a timer.
- if (StatsTable::current()) {
- // TODO(mbelshe): name_ construction is racy and it may corrupt memory for
- // static.
- name_ = "t:";
- name_.append(name);
- }
-}
-
-StatsCounterTimer::~StatsCounterTimer() {
-}
-
-void StatsCounterTimer::Start() {
- if (!Enabled())
- return;
- start_time_ = TimeTicks::Now();
- stop_time_ = TimeTicks();
-}
-
-// Stop the timer and record the results.
-void StatsCounterTimer::Stop() {
- if (!Enabled() || !Running())
- return;
- stop_time_ = TimeTicks::Now();
- Record();
-}
-
-// Returns true if the timer is running.
-bool StatsCounterTimer::Running() {
- return Enabled() && !start_time_.is_null() && stop_time_.is_null();
-}
-
-// Accept a TimeDelta to increment.
-void StatsCounterTimer::AddTime(TimeDelta time) {
- Add(static_cast<int>(time.InMilliseconds()));
-}
-
-void StatsCounterTimer::Record() {
- AddTime(stop_time_ - start_time_);
-}
-
-
-StatsRate::StatsRate(const std::string& name)
- : StatsCounterTimer(name),
- counter_(name),
- largest_add_(std::string(" ").append(name).append("MAX")) {
-}
-
-StatsRate::~StatsRate() {
-}
-
-void StatsRate::Add(int value) {
- counter_.Increment();
- StatsCounterTimer::Add(value);
- if (value > largest_add_.value())
- largest_add_.Set(value);
-}
-
-} // namespace base
diff --git a/base/metrics/stats_counters.h b/base/metrics/stats_counters.h
deleted file mode 100644
index 0f8354f..0000000
--- a/base/metrics/stats_counters.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright (c) 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 BASE_METRICS_STATS_COUNTERS_H_
-#define BASE_METRICS_STATS_COUNTERS_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/compiler_specific.h"
-#include "base/metrics/stats_table.h"
-#include "base/time/time.h"
-
-namespace base {
-
-// StatsCounters are dynamically created values which can be tracked in
-// the StatsTable. They are designed to be lightweight to create and
-// easy to use.
-//
-// Since StatsCounters can be created dynamically by name, there is
-// a hash table lookup to find the counter in the table. A StatsCounter
-// object can be created once and used across multiple threads safely.
-//
-// Example usage:
-// {
-// StatsCounter request_count("RequestCount");
-// request_count.Increment();
-// }
-//
-// Note that creating counters on the stack does work, however creating
-// the counter object requires a hash table lookup. For inner loops, it
-// may be better to create the counter either as a member of another object
-// (or otherwise outside of the loop) for maximum performance.
-//
-// Internally, a counter represents a value in a row of a StatsTable.
-// The row has a 32bit value for each process/thread in the table and also
-// a name (stored in the table metadata).
-//
-// NOTE: In order to make stats_counters usable in lots of different code,
-// avoid any dependencies inside this header file.
-//
-
-//------------------------------------------------------------------------------
-// Define macros for ease of use. They also allow us to change definitions
-// as the implementation varies, or depending on compile options.
-//------------------------------------------------------------------------------
-// First provide generic macros, which exist in production as well as debug.
-#define STATS_COUNTER(name, delta) do { \
- base::StatsCounter counter(name); \
- counter.Add(delta); \
-} while (0)
-
-#define SIMPLE_STATS_COUNTER(name) STATS_COUNTER(name, 1)
-
-#define RATE_COUNTER(name, duration) do { \
- base::StatsRate hit_count(name); \
- hit_count.AddTime(duration); \
-} while (0)
-
-// Define Debug vs non-debug flavors of macros.
-#ifndef NDEBUG
-
-#define DSTATS_COUNTER(name, delta) STATS_COUNTER(name, delta)
-#define DSIMPLE_STATS_COUNTER(name) SIMPLE_STATS_COUNTER(name)
-#define DRATE_COUNTER(name, duration) RATE_COUNTER(name, duration)
-
-#else // NDEBUG
-
-#define DSTATS_COUNTER(name, delta) do {} while (0)
-#define DSIMPLE_STATS_COUNTER(name) do {} while (0)
-#define DRATE_COUNTER(name, duration) do {} while (0)
-
-#endif // NDEBUG
-
-//------------------------------------------------------------------------------
-// StatsCounter represents a counter in the StatsTable class.
-class BASE_EXPORT StatsCounter {
- public:
- // Create a StatsCounter object.
- explicit StatsCounter(const std::string& name);
- virtual ~StatsCounter();
-
- // Sets the counter to a specific value.
- void Set(int value);
-
- // Increments the counter.
- void Increment() {
- Add(1);
- }
-
- virtual void Add(int value);
-
- // Decrements the counter.
- void Decrement() {
- Add(-1);
- }
-
- void Subtract(int value) {
- Add(-value);
- }
-
- // Is this counter enabled?
- // Returns false if table is full.
- bool Enabled() {
- return GetPtr() != NULL;
- }
-
- int value() {
- int* loc = GetPtr();
- if (loc) return *loc;
- return 0;
- }
-
- protected:
- StatsCounter();
-
- // Returns the cached address of this counter location.
- int* GetPtr();
-
- std::string name_;
- // The counter id in the table. We initialize to -1 (an invalid value)
- // and then cache it once it has been looked up. The counter_id is
- // valid across all threads and processes.
- int32 counter_id_;
-};
-
-
-// A StatsCounterTimer is a StatsCounter which keeps a timer during
-// the scope of the StatsCounterTimer. On destruction, it will record
-// its time measurement.
-class BASE_EXPORT StatsCounterTimer : protected StatsCounter {
- public:
- // Constructs and starts the timer.
- explicit StatsCounterTimer(const std::string& name);
- ~StatsCounterTimer() override;
-
- // Start the timer.
- void Start();
-
- // Stop the timer and record the results.
- void Stop();
-
- // Returns true if the timer is running.
- bool Running();
-
- // Accept a TimeDelta to increment.
- virtual void AddTime(TimeDelta time);
-
- protected:
- // Compute the delta between start and stop, in milliseconds.
- void Record();
-
- TimeTicks start_time_;
- TimeTicks stop_time_;
-};
-
-// A StatsRate is a timer that keeps a count of the number of intervals added so
-// that several statistics can be produced:
-// min, max, avg, count, total
-class BASE_EXPORT StatsRate : public StatsCounterTimer {
- public:
- // Constructs and starts the timer.
- explicit StatsRate(const std::string& name);
- ~StatsRate() override;
-
- void Add(int value) override;
-
- private:
- StatsCounter counter_;
- StatsCounter largest_add_;
-};
-
-
-// Helper class for scoping a timer or rate.
-template<class T> class StatsScope {
- public:
- explicit StatsScope<T>(T& timer)
- : timer_(timer) {
- timer_.Start();
- }
-
- ~StatsScope() {
- timer_.Stop();
- }
-
- void Stop() {
- timer_.Stop();
- }
-
- private:
- T& timer_;
-};
-
-} // namespace base
-
-#endif // BASE_METRICS_STATS_COUNTERS_H_
diff --git a/base/metrics/stats_table.cc b/base/metrics/stats_table.cc
deleted file mode 100644
index 0986395..0000000
--- a/base/metrics/stats_table.cc
+++ /dev/null
@@ -1,617 +0,0 @@
-// Copyright (c) 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 "base/metrics/stats_table.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/shared_memory.h"
-#include "base/process/process_handle.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local_storage.h"
-
-namespace base {
-
-// The StatsTable uses a shared memory segment that is laid out as follows
-//
-// +-------------------------------------------+
-// | Version | Size | MaxCounters | MaxThreads |
-// +-------------------------------------------+
-// | Thread names table |
-// +-------------------------------------------+
-// | Thread TID table |
-// +-------------------------------------------+
-// | Thread PID table |
-// +-------------------------------------------+
-// | Counter names table |
-// +-------------------------------------------+
-// | Data |
-// +-------------------------------------------+
-//
-// The data layout is a grid, where the columns are the thread_ids and the
-// rows are the counter_ids.
-//
-// If the first character of the thread_name is '\0', then that column is
-// empty.
-// If the first character of the counter_name is '\0', then that row is
-// empty.
-//
-// About Locking:
-// This class is designed to be both multi-thread and multi-process safe.
-// Aside from initialization, this is done by partitioning the data which
-// each thread uses so that no locking is required. However, to allocate
-// the rows and columns of the table to particular threads, locking is
-// required.
-//
-// At the shared-memory level, we have a lock. This lock protects the
-// shared-memory table only, and is used when we create new counters (e.g.
-// use rows) or when we register new threads (e.g. use columns). Reading
-// data from the table does not require any locking at the shared memory
-// level.
-//
-// Each process which accesses the table will create a StatsTable object.
-// The StatsTable maintains a hash table of the existing counters in the
-// table for faster lookup. Since the hash table is process specific,
-// each process maintains its own cache. We avoid complexity here by never
-// de-allocating from the hash table. (Counters are dynamically added,
-// but not dynamically removed).
-
-// In order for external viewers to be able to read our shared memory,
-// we all need to use the same size ints.
-COMPILE_ASSERT(sizeof(int)==4, expect_4_byte_ints);
-
-namespace {
-
-// An internal version in case we ever change the format of this
-// file, and so that we can identify our table.
-const int kTableVersion = 0x13131313;
-
-// The name for un-named counters and threads in the table.
-const char kUnknownName[] = "<unknown>";
-
-// Calculates delta to align an offset to the size of an int
-inline int AlignOffset(int offset) {
- return (sizeof(int) - (offset % sizeof(int))) % sizeof(int);
-}
-
-inline int AlignedSize(int size) {
- return size + AlignOffset(size);
-}
-
-} // namespace
-
-// The StatsTable::Internal maintains convenience pointers into the
-// shared memory segment. Use this class to keep the data structure
-// clean and accessible.
-class StatsTable::Internal {
- public:
- // Various header information contained in the memory mapped segment.
- struct TableHeader {
- int version;
- int size;
- int max_counters;
- int max_threads;
- };
-
- // Construct a new Internal based on expected size parameters, or
- // return NULL on failure.
- static Internal* New(const StatsTable::TableIdentifier& table,
- int size,
- int max_threads,
- int max_counters);
-
- SharedMemory* shared_memory() { return shared_memory_.get(); }
-
- // Accessors for our header pointers
- TableHeader* table_header() const { return table_header_; }
- int version() const { return table_header_->version; }
- int size() const { return table_header_->size; }
- int max_counters() const { return table_header_->max_counters; }
- int max_threads() const { return table_header_->max_threads; }
-
- // Accessors for our tables
- char* thread_name(int slot_id) const {
- return &thread_names_table_[
- (slot_id-1) * (StatsTable::kMaxThreadNameLength)];
- }
- PlatformThreadId* thread_tid(int slot_id) const {
- return &(thread_tid_table_[slot_id-1]);
- }
- int* thread_pid(int slot_id) const {
- return &(thread_pid_table_[slot_id-1]);
- }
- char* counter_name(int counter_id) const {
- return &counter_names_table_[
- (counter_id-1) * (StatsTable::kMaxCounterNameLength)];
- }
- int* row(int counter_id) const {
- return &data_table_[(counter_id-1) * max_threads()];
- }
-
- private:
- // Constructor is private because you should use New() instead.
- explicit Internal(SharedMemory* shared_memory)
- : shared_memory_(shared_memory),
- table_header_(NULL),
- thread_names_table_(NULL),
- thread_tid_table_(NULL),
- thread_pid_table_(NULL),
- counter_names_table_(NULL),
- data_table_(NULL) {
- }
-
- // Create or open the SharedMemory used by the stats table.
- static SharedMemory* CreateSharedMemory(
- const StatsTable::TableIdentifier& table,
- int size);
-
- // Initializes the table on first access. Sets header values
- // appropriately and zeroes all counters.
- void InitializeTable(void* memory, int size, int max_counters,
- int max_threads);
-
- // Initializes our in-memory pointers into a pre-created StatsTable.
- void ComputeMappedPointers(void* memory);
-
- scoped_ptr<SharedMemory> shared_memory_;
- TableHeader* table_header_;
- char* thread_names_table_;
- PlatformThreadId* thread_tid_table_;
- int* thread_pid_table_;
- char* counter_names_table_;
- int* data_table_;
-
- DISALLOW_COPY_AND_ASSIGN(Internal);
-};
-
-// static
-StatsTable::Internal* StatsTable::Internal::New(
- const StatsTable::TableIdentifier& table,
- int size,
- int max_threads,
- int max_counters) {
- scoped_ptr<SharedMemory> shared_memory(CreateSharedMemory(table, size));
- if (!shared_memory.get())
- return NULL;
- if (!shared_memory->Map(size))
- return NULL;
- void* memory = shared_memory->memory();
-
- scoped_ptr<Internal> internal(new Internal(shared_memory.release()));
- TableHeader* header = static_cast<TableHeader*>(memory);
-
- // If the version does not match, then assume the table needs
- // to be initialized.
- if (header->version != kTableVersion)
- internal->InitializeTable(memory, size, max_counters, max_threads);
-
- // We have a valid table, so compute our pointers.
- internal->ComputeMappedPointers(memory);
-
- return internal.release();
-}
-
-// static
-SharedMemory* StatsTable::Internal::CreateSharedMemory(
- const StatsTable::TableIdentifier& table,
- int size) {
-#if defined(OS_POSIX)
- // Check for existing table.
- if (table.fd != -1)
- return new SharedMemory(table, false);
-
- // Otherwise we need to create it.
- scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
- if (!shared_memory->CreateAnonymous(size))
- return NULL;
- return shared_memory.release();
-#elif defined(OS_WIN)
- scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
- if (table.empty()) {
- // Create an anonymous table.
- if (!shared_memory->CreateAnonymous(size))
- return NULL;
- } else {
- // Create a named table for sharing between processes.
- if (!shared_memory->CreateNamedDeprecated(table, true, size))
- return NULL;
- }
- return shared_memory.release();
-#endif
-}
-
-void StatsTable::Internal::InitializeTable(void* memory, int size,
- int max_counters,
- int max_threads) {
- // Zero everything.
- memset(memory, 0, size);
-
- // Initialize the header.
- TableHeader* header = static_cast<TableHeader*>(memory);
- header->version = kTableVersion;
- header->size = size;
- header->max_counters = max_counters;
- header->max_threads = max_threads;
-}
-
-void StatsTable::Internal::ComputeMappedPointers(void* memory) {
- char* data = static_cast<char*>(memory);
- int offset = 0;
-
- table_header_ = reinterpret_cast<TableHeader*>(data);
- offset += sizeof(*table_header_);
- offset += AlignOffset(offset);
-
- // Verify we're looking at a valid StatsTable.
- DCHECK_EQ(table_header_->version, kTableVersion);
-
- thread_names_table_ = reinterpret_cast<char*>(data + offset);
- offset += sizeof(char) *
- max_threads() * StatsTable::kMaxThreadNameLength;
- offset += AlignOffset(offset);
-
- thread_tid_table_ = reinterpret_cast<PlatformThreadId*>(data + offset);
- offset += sizeof(int) * max_threads();
- offset += AlignOffset(offset);
-
- thread_pid_table_ = reinterpret_cast<int*>(data + offset);
- offset += sizeof(int) * max_threads();
- offset += AlignOffset(offset);
-
- counter_names_table_ = reinterpret_cast<char*>(data + offset);
- offset += sizeof(char) *
- max_counters() * StatsTable::kMaxCounterNameLength;
- offset += AlignOffset(offset);
-
- data_table_ = reinterpret_cast<int*>(data + offset);
- offset += sizeof(int) * max_threads() * max_counters();
-
- DCHECK_EQ(offset, size());
-}
-
-// TLSData carries the data stored in the TLS slots for the
-// StatsTable. This is used so that we can properly cleanup when the
-// thread exits and return the table slot.
-//
-// Each thread that calls RegisterThread in the StatsTable will have
-// a TLSData stored in its TLS.
-struct StatsTable::TLSData {
- StatsTable* table;
- int slot;
-};
-
-// We keep a singleton table which can be easily accessed.
-StatsTable* global_table = NULL;
-
-StatsTable::StatsTable(const TableIdentifier& table,
- int max_threads,
- int max_counters)
- : internal_(NULL),
- tls_index_(SlotReturnFunction) {
- int table_size =
- AlignedSize(sizeof(Internal::TableHeader)) +
- AlignedSize((max_counters * sizeof(char) * kMaxCounterNameLength)) +
- AlignedSize((max_threads * sizeof(char) * kMaxThreadNameLength)) +
- AlignedSize(max_threads * sizeof(int)) +
- AlignedSize(max_threads * sizeof(int)) +
- AlignedSize((sizeof(int) * (max_counters * max_threads)));
-
- internal_ = Internal::New(table, table_size, max_threads, max_counters);
-
- if (!internal_)
- DPLOG(ERROR) << "StatsTable did not initialize";
-}
-
-StatsTable::~StatsTable() {
- // Before we tear down our copy of the table, be sure to
- // unregister our thread.
- UnregisterThread();
-
- // Return ThreadLocalStorage. At this point, if any registered threads
- // still exist, they cannot Unregister.
- tls_index_.Free();
-
- // Cleanup our shared memory.
- delete internal_;
-
- // If we are the global table, unregister ourselves.
- if (global_table == this)
- global_table = NULL;
-}
-
-StatsTable* StatsTable::current() {
- return global_table;
-}
-
-void StatsTable::set_current(StatsTable* value) {
- global_table = value;
-}
-
-int StatsTable::GetSlot() const {
- TLSData* data = GetTLSData();
- if (!data)
- return 0;
- return data->slot;
-}
-
-int StatsTable::RegisterThread(const std::string& name) {
- int slot = 0;
- if (!internal_)
- return 0;
-
- // Registering a thread requires that we lock the shared memory
- // so that two threads don't grab the same slot. Fortunately,
- // thread creation shouldn't happen in inner loops.
- // TODO(viettrungluu): crbug.com/345734: Use a different locking mechanism.
- {
- SharedMemoryAutoLockDeprecated lock(internal_->shared_memory());
- slot = FindEmptyThread();
- if (!slot) {
- return 0;
- }
-
- // We have space, so consume a column in the table.
- std::string thread_name = name;
- if (name.empty())
- thread_name = kUnknownName;
- strlcpy(internal_->thread_name(slot), thread_name.c_str(),
- kMaxThreadNameLength);
- *(internal_->thread_tid(slot)) = PlatformThread::CurrentId();
- *(internal_->thread_pid(slot)) = GetCurrentProcId();
- }
-
- // Set our thread local storage.
- TLSData* data = new TLSData;
- data->table = this;
- data->slot = slot;
- tls_index_.Set(data);
- return slot;
-}
-
-int StatsTable::CountThreadsRegistered() const {
- if (!internal_)
- return 0;
-
- // Loop through the shared memory and count the threads that are active.
- // We intentionally do not lock the table during the operation.
- int count = 0;
- for (int index = 1; index <= internal_->max_threads(); index++) {
- char* name = internal_->thread_name(index);
- if (*name != '\0')
- count++;
- }
- return count;
-}
-
-int StatsTable::FindCounter(const std::string& name) {
- // Note: the API returns counters numbered from 1..N, although
- // internally, the array is 0..N-1. This is so that we can return
- // zero as "not found".
- if (!internal_)
- return 0;
-
- // Create a scope for our auto-lock.
- {
- AutoLock scoped_lock(counters_lock_);
-
- // Attempt to find the counter.
- CountersMap::const_iterator iter;
- iter = counters_.find(name);
- if (iter != counters_.end())
- return iter->second;
- }
-
- // Counter does not exist, so add it.
- return AddCounter(name);
-}
-
-int* StatsTable::GetLocation(int counter_id, int slot_id) const {
- if (!internal_)
- return NULL;
- if (slot_id > internal_->max_threads())
- return NULL;
-
- int* row = internal_->row(counter_id);
- return &(row[slot_id-1]);
-}
-
-const char* StatsTable::GetRowName(int index) const {
- if (!internal_)
- return NULL;
-
- return internal_->counter_name(index);
-}
-
-int StatsTable::GetRowValue(int index) const {
- return GetRowValue(index, 0);
-}
-
-int StatsTable::GetRowValue(int index, int pid) const {
- if (!internal_)
- return 0;
-
- int rv = 0;
- int* row = internal_->row(index);
- for (int slot_id = 1; slot_id <= internal_->max_threads(); slot_id++) {
- if (pid == 0 || *internal_->thread_pid(slot_id) == pid)
- rv += row[slot_id-1];
- }
- return rv;
-}
-
-int StatsTable::GetCounterValue(const std::string& name) {
- return GetCounterValue(name, 0);
-}
-
-int StatsTable::GetCounterValue(const std::string& name, int pid) {
- if (!internal_)
- return 0;
-
- int row = FindCounter(name);
- if (!row)
- return 0;
- return GetRowValue(row, pid);
-}
-
-int StatsTable::GetMaxCounters() const {
- if (!internal_)
- return 0;
- return internal_->max_counters();
-}
-
-int StatsTable::GetMaxThreads() const {
- if (!internal_)
- return 0;
- return internal_->max_threads();
-}
-
-int* StatsTable::FindLocation(const char* name) {
- // Get the static StatsTable
- StatsTable *table = StatsTable::current();
- if (!table)
- return NULL;
-
- // Get the slot for this thread. Try to register
- // it if none exists.
- int slot = table->GetSlot();
- if (!slot)
- slot = table->RegisterThread(std::string());
- if (!slot)
- return NULL;
-
- // Find the counter id for the counter.
- std::string str_name(name);
- int counter = table->FindCounter(str_name);
-
- // Now we can find the location in the table.
- return table->GetLocation(counter, slot);
-}
-
-void StatsTable::UnregisterThread() {
- UnregisterThread(GetTLSData());
-}
-
-void StatsTable::UnregisterThread(TLSData* data) {
- if (!data)
- return;
- DCHECK(internal_);
-
- // Mark the slot free by zeroing out the thread name.
- char* name = internal_->thread_name(data->slot);
- *name = '\0';
-
- // Remove the calling thread's TLS so that it cannot use the slot.
- tls_index_.Set(NULL);
- delete data;
-}
-
-void StatsTable::SlotReturnFunction(void* data) {
- // This is called by the TLS destructor, which on some platforms has
- // already cleared the TLS info, so use the tls_data argument
- // rather than trying to fetch it ourselves.
- TLSData* tls_data = static_cast<TLSData*>(data);
- if (tls_data) {
- DCHECK(tls_data->table);
- tls_data->table->UnregisterThread(tls_data);
- }
-}
-
-int StatsTable::FindEmptyThread() const {
- // Note: the API returns slots numbered from 1..N, although
- // internally, the array is 0..N-1. This is so that we can return
- // zero as "not found".
- //
- // The reason for doing this is because the thread 'slot' is stored
- // in TLS, which is always initialized to zero, not -1. If 0 were
- // returned as a valid slot number, it would be confused with the
- // uninitialized state.
- if (!internal_)
- return 0;
-
- int index = 1;
- for (; index <= internal_->max_threads(); index++) {
- char* name = internal_->thread_name(index);
- if (!*name)
- break;
- }
- if (index > internal_->max_threads())
- return 0; // The table is full.
- return index;
-}
-
-int StatsTable::FindCounterOrEmptyRow(const std::string& name) const {
- // Note: the API returns slots numbered from 1..N, although
- // internally, the array is 0..N-1. This is so that we can return
- // zero as "not found".
- //
- // There isn't much reason for this other than to be consistent
- // with the way we track columns for thread slots. (See comments
- // in FindEmptyThread for why it is done this way).
- if (!internal_)
- return 0;
-
- int free_slot = 0;
- for (int index = 1; index <= internal_->max_counters(); index++) {
- char* row_name = internal_->counter_name(index);
- if (!*row_name && !free_slot)
- free_slot = index; // save that we found a free slot
- else if (!strncmp(row_name, name.c_str(), kMaxCounterNameLength))
- return index;
- }
- return free_slot;
-}
-
-int StatsTable::AddCounter(const std::string& name) {
- if (!internal_)
- return 0;
-
- int counter_id = 0;
- {
- // To add a counter to the shared memory, we need the
- // shared memory lock.
- SharedMemoryAutoLockDeprecated lock(internal_->shared_memory());
-
- // We have space, so create a new counter.
- counter_id = FindCounterOrEmptyRow(name);
- if (!counter_id)
- return 0;
-
- std::string counter_name = name;
- if (name.empty())
- counter_name = kUnknownName;
- strlcpy(internal_->counter_name(counter_id), counter_name.c_str(),
- kMaxCounterNameLength);
- }
-
- // now add to our in-memory cache
- {
- AutoLock lock(counters_lock_);
- counters_[name] = counter_id;
- }
- return counter_id;
-}
-
-StatsTable::TLSData* StatsTable::GetTLSData() const {
- TLSData* data =
- static_cast<TLSData*>(tls_index_.Get());
- if (!data)
- return NULL;
-
- DCHECK(data->slot);
- DCHECK_EQ(data->table, this);
- return data;
-}
-
-#if defined(OS_POSIX)
-SharedMemoryHandle StatsTable::GetSharedMemoryHandle() const {
- if (!internal_)
- return SharedMemory::NULLHandle();
- return internal_->shared_memory()->handle();
-}
-#endif
-
-} // namespace base
diff --git a/base/metrics/stats_table.h b/base/metrics/stats_table.h
deleted file mode 100644
index 719e630..0000000
--- a/base/metrics/stats_table.h
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 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.
-//
-// A StatsTable is a table of statistics. It can be used across multiple
-// processes and threads, maintaining cheap statistics counters without
-// locking.
-//
-// The goal is to make it very cheap and easy for developers to add
-// counters to code, without having to build one-off utilities or mechanisms
-// to track the counters, and also to allow a single "view" to display
-// the contents of all counters.
-//
-// To achieve this, StatsTable creates a shared memory segment to store
-// the data for the counters. Upon creation, it has a specific size
-// which governs the maximum number of counters and concurrent
-// threads/processes which can use it.
-//
-
-#ifndef BASE_METRICS_STATS_TABLE_H_
-#define BASE_METRICS_STATS_TABLE_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#include "base/memory/shared_memory.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_local_storage.h"
-#include "build/build_config.h"
-
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#endif
-
-namespace base {
-
-class BASE_EXPORT StatsTable {
- public:
- // Identifies a StatsTable. We often want to share these between processes.
- //
- // On Windows, we use a named shared memory segment so the table identifier
- // should be a relatively unique string identifying the table to use. An
- // empty string can be used to use an anonymous shared memory segment for
- // cases where the table does not need to be shared between processes.
- //
- // Posix does not support named memory so we explicitly share file
- // descriptors. On Posix, pass a default-constructed file descriptor if a
- // handle doesn't already exist, and a new one will be created.
- //
- // If a table doesn't already exist with the given identifier, a new one will
- // be created with zeroed counters.
-#if defined(OS_POSIX)
- typedef FileDescriptor TableIdentifier;
-#elif defined(OS_WIN)
- typedef std::string TableIdentifier;
-#endif
-
- // Create a new StatsTable.
- //
- // max_threads is the maximum number of threads the table will support.
- // If the StatsTable already exists, this number is ignored.
- //
- // max_counters is the maximum number of counters the table will support.
- // If the StatsTable already exists, this number is ignored.
- StatsTable(const TableIdentifier& table,
- int max_threads,
- int max_counters);
-
- // Destroys the StatsTable. When the last StatsTable is destroyed
- // (across all processes), the StatsTable is removed from disk.
- ~StatsTable();
-
- // For convenience, we create a static table. This is generally
- // used automatically by the counters.
- static StatsTable* current();
-
- // Set the global table for use in this process.
- static void set_current(StatsTable* value);
-
- // Get the slot id for the calling thread. Returns 0 if no
- // slot is assigned.
- int GetSlot() const;
-
- // All threads that contribute data to the table must register with the
- // table first. This function will set thread local storage for the
- // thread containing the location in the table where this thread will
- // write its counter data.
- //
- // name is just a debugging tag to label the thread, and it does not
- // need to be unique. It will be truncated to kMaxThreadNameLength-1
- // characters.
- //
- // On success, returns the slot id for this thread. On failure,
- // returns 0.
- int RegisterThread(const std::string& name);
-
- // Returns the number of threads currently registered. This is really not
- // useful except for diagnostics and debugging.
- int CountThreadsRegistered() const;
-
- // Find a counter in the StatsTable.
- //
- // Returns an id for the counter which can be used to call GetLocation().
- // If the counter does not exist, attempts to create a row for the new
- // counter. If there is no space in the table for the new counter,
- // returns 0.
- int FindCounter(const std::string& name);
-
- // TODO(mbelshe): implement RemoveCounter.
-
- // Gets the location of a particular value in the table based on
- // the counter id and slot id.
- int* GetLocation(int counter_id, int slot_id) const;
-
- // Gets the counter name at a particular row. If the row is empty,
- // returns NULL.
- const char* GetRowName(int index) const;
-
- // Gets the sum of the values for a particular row.
- int GetRowValue(int index) const;
-
- // Gets the sum of the values for a particular row for a given pid.
- int GetRowValue(int index, int pid) const;
-
- // Gets the sum of the values for a particular counter. If the counter
- // does not exist, creates the counter.
- int GetCounterValue(const std::string& name);
-
- // Gets the sum of the values for a particular counter for a given pid.
- // If the counter does not exist, creates the counter.
- int GetCounterValue(const std::string& name, int pid);
-
- // The maxinum number of counters/rows in the table.
- int GetMaxCounters() const;
-
- // The maxinum number of threads/columns in the table.
- int GetMaxThreads() const;
-
-#if defined(OS_POSIX)
- // Get the underlying shared memory handle for the table.
- base::SharedMemoryHandle GetSharedMemoryHandle() const;
-#endif
-
- // The maximum length (in characters) of a Thread's name including
- // null terminator, as stored in the shared memory.
- static const int kMaxThreadNameLength = 32;
-
- // The maximum length (in characters) of a Counter's name including
- // null terminator, as stored in the shared memory.
- static const int kMaxCounterNameLength = 64;
-
- // Convenience function to lookup a counter location for a
- // counter by name for the calling thread. Will register
- // the thread if it is not already registered.
- static int* FindLocation(const char *name);
-
- private:
- class Internal;
- struct TLSData;
- typedef hash_map<std::string, int> CountersMap;
-
- // Returns the space occupied by a thread in the table. Generally used
- // if a thread terminates but the process continues. This function
- // does not zero out the thread's counters.
- // Cannot be used inside a posix tls destructor.
- void UnregisterThread();
-
- // This variant expects the tls data to be passed in, so it is safe to
- // call from inside a posix tls destructor (see doc for pthread_key_create).
- void UnregisterThread(TLSData* tls_data);
-
- // The SlotReturnFunction is called at thread exit for each thread
- // which used the StatsTable.
- static void SlotReturnFunction(void* data);
-
- // Locates a free slot in the table. Returns a number > 0 on success,
- // or 0 on failure. The caller must hold the shared_memory lock when
- // calling this function.
- int FindEmptyThread() const;
-
- // Locates a counter in the table or finds an empty row. Returns a
- // number > 0 on success, or 0 on failure. The caller must hold the
- // shared_memory_lock when calling this function.
- int FindCounterOrEmptyRow(const std::string& name) const;
-
- // Internal function to add a counter to the StatsTable. Assumes that
- // the counter does not already exist in the table.
- //
- // name is a unique identifier for this counter, and will be truncated
- // to kMaxCounterNameLength-1 characters.
- //
- // On success, returns the counter_id for the newly added counter.
- // On failure, returns 0.
- int AddCounter(const std::string& name);
-
- // Get the TLS data for the calling thread. Returns NULL if none is
- // initialized.
- TLSData* GetTLSData() const;
-
- Internal* internal_;
-
- // The counters_lock_ protects the counters_ hash table.
- base::Lock counters_lock_;
-
- // The counters_ hash map is an in-memory hash of the counters.
- // It is used for quick lookup of counters, but is cannot be used
- // as a substitute for what is in the shared memory. Even though
- // we don't have a counter in our hash table, another process may
- // have created it.
- CountersMap counters_;
- ThreadLocalStorage::Slot tls_index_;
-
- DISALLOW_COPY_AND_ASSIGN(StatsTable);
-};
-
-} // namespace base
-
-#endif // BASE_METRICS_STATS_TABLE_H_
diff --git a/base/metrics/stats_table_unittest.cc b/base/metrics/stats_table_unittest.cc
deleted file mode 100644
index 38a21cc..0000000
--- a/base/metrics/stats_table_unittest.cc
+++ /dev/null
@@ -1,402 +0,0 @@
-// 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.
-
-#include "base/memory/shared_memory.h"
-#include "base/metrics/stats_counters.h"
-#include "base/metrics/stats_table.h"
-#include "base/process/kill.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/multiprocess_test.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-
-class StatsTableTest : public MultiProcessTest {
-};
-
-// Open a StatsTable and verify that we can write to each of the
-// locations in the table.
-TEST_F(StatsTableTest, VerifySlots) {
- const int kMaxThreads = 1;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
-
- // Register a single thread.
- std::string thread_name = "mainThread";
- int slot_id = table.RegisterThread(thread_name);
- EXPECT_NE(slot_id, 0);
-
- // Fill up the table with counters.
- std::string counter_base_name = "counter";
- for (int index = 0; index < kMaxCounter; index++) {
- std::string counter_name = counter_base_name;
- base::StringAppendF(&counter_name, "counter.ctr%d", index);
- int counter_id = table.FindCounter(counter_name);
- EXPECT_GT(counter_id, 0);
- }
-
- // Try to allocate an additional thread. Verify it fails.
- slot_id = table.RegisterThread("too many threads");
- EXPECT_EQ(slot_id, 0);
-
- // Try to allocate an additional counter. Verify it fails.
- int counter_id = table.FindCounter(counter_base_name);
- EXPECT_EQ(counter_id, 0);
-}
-
-// CounterZero will continually be set to 0.
-const std::string kCounterZero = "CounterZero";
-// Counter1313 will continually be set to 1313.
-const std::string kCounter1313 = "Counter1313";
-// CounterIncrement will be incremented each time.
-const std::string kCounterIncrement = "CounterIncrement";
-// CounterDecrement will be decremented each time.
-const std::string kCounterDecrement = "CounterDecrement";
-// CounterMixed will be incremented by odd numbered threads and
-// decremented by even threads.
-const std::string kCounterMixed = "CounterMixed";
-// The number of thread loops that we will do.
-const int kThreadLoops = 100;
-
-class StatsTableThread : public SimpleThread {
- public:
- StatsTableThread(std::string name, int id)
- : SimpleThread(name),
- id_(id) {}
-
- void Run() override;
-
- private:
- int id_;
-};
-
-void StatsTableThread::Run() {
- // Each thread will open the shared memory and set counters
- // concurrently in a loop. We'll use some pauses to
- // mixup the thread scheduling.
-
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
- for (int index = 0; index < kThreadLoops; index++) {
- StatsCounter mixed_counter(kCounterMixed); // create this one in the loop
- zero_counter.Set(0);
- lucky13_counter.Set(1313);
- increment_counter.Increment();
- decrement_counter.Decrement();
- if (id_ % 2)
- mixed_counter.Decrement();
- else
- mixed_counter.Increment();
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
- }
-}
-
-// Create a few threads and have them poke on their counters.
-// See http://crbug.com/10611 for more information.
-// It is disabled on Win x64 incremental linking pending resolution of
-// http://crbug.com/251251.
-#if defined(OS_MACOSX) || defined(THREAD_SANITIZER) || \
- (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && \
- defined(INCREMENTAL_LINKING))
-#define MAYBE_MultipleThreads DISABLED_MultipleThreads
-#else
-#define MAYBE_MultipleThreads MultipleThreads
-#endif
-TEST_F(StatsTableTest, MAYBE_MultipleThreads) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- EXPECT_EQ(0, table.CountThreadsRegistered());
-
- // Spin up a set of threads to go bang on the various counters.
- // After we join the threads, we'll make sure the counters
- // contain the values we expected.
- StatsTableThread* threads[kMaxThreads];
-
- // Spawn the threads.
- for (int index = 0; index < kMaxThreads; index++) {
- threads[index] = new StatsTableThread("MultipleThreadsTest", index);
- threads[index]->Start();
- }
-
- // Wait for the threads to finish.
- for (int index = 0; index < kMaxThreads; index++) {
- threads[index]->Join();
- delete threads[index];
- }
-
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
- StatsCounter mixed_counter(kCounterMixed);
-
- // Verify the various counters are correct.
- std::string name;
- name = "c:" + kCounterZero;
- EXPECT_EQ(0, table.GetCounterValue(name));
- name = "c:" + kCounter1313;
- EXPECT_EQ(1313 * kMaxThreads,
- table.GetCounterValue(name));
- name = "c:" + kCounterIncrement;
- EXPECT_EQ(kMaxThreads * kThreadLoops,
- table.GetCounterValue(name));
- name = "c:" + kCounterDecrement;
- EXPECT_EQ(-kMaxThreads * kThreadLoops,
- table.GetCounterValue(name));
- name = "c:" + kCounterMixed;
- EXPECT_EQ((kMaxThreads % 2) * kThreadLoops,
- table.GetCounterValue(name));
- EXPECT_EQ(0, table.CountThreadsRegistered());
-}
-
-// This multiprocess test only runs on Windows. On Posix, the shared memory
-// handle is not sent between the processes properly.
-#if defined(OS_WIN)
-const std::string kMPTableName = "MultipleProcessStatTable";
-
-MULTIPROCESS_TEST_MAIN(StatsTableMultipleProcessMain) {
- // Each process will open the shared memory and set counters
- // concurrently in a loop. We'll use some pauses to
- // mixup the scheduling.
-
- StatsTable table(kMPTableName, 0, 0);
- StatsTable::set_current(&table);
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
- for (int index = 0; index < kThreadLoops; index++) {
- zero_counter.Set(0);
- lucky13_counter.Set(1313);
- increment_counter.Increment();
- decrement_counter.Decrement();
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
- }
- return 0;
-}
-
-// Create a few processes and have them poke on their counters.
-// This test is slow and flaky http://crbug.com/10611
-TEST_F(StatsTableTest, DISABLED_MultipleProcesses) {
- // Create a stats table.
- const int kMaxProcs = 20;
- const int kMaxCounter = 5;
- StatsTable table(kMPTableName, kMaxProcs, kMaxCounter);
- StatsTable::set_current(&table);
- EXPECT_EQ(0, table.CountThreadsRegistered());
-
- // Spin up a set of processes to go bang on the various counters.
- // After we join the processes, we'll make sure the counters
- // contain the values we expected.
- Process procs[kMaxProcs];
-
- // Spawn the processes.
- for (int16 index = 0; index < kMaxProcs; index++) {
- procs[index] = SpawnChild("StatsTableMultipleProcessMain");
- EXPECT_TRUE(procs[index].IsValid());
- }
-
- // Wait for the processes to finish.
- for (int index = 0; index < kMaxProcs; index++) {
- EXPECT_TRUE(WaitForSingleProcess(procs[index].Handle(),
- base::TimeDelta::FromMinutes(1)));
- procs[index].Close();
- }
-
- StatsCounter zero_counter(kCounterZero);
- StatsCounter lucky13_counter(kCounter1313);
- StatsCounter increment_counter(kCounterIncrement);
- StatsCounter decrement_counter(kCounterDecrement);
-
- // Verify the various counters are correct.
- std::string name;
- name = "c:" + kCounterZero;
- EXPECT_EQ(0, table.GetCounterValue(name));
- name = "c:" + kCounter1313;
- EXPECT_EQ(1313 * kMaxProcs,
- table.GetCounterValue(name));
- name = "c:" + kCounterIncrement;
- EXPECT_EQ(kMaxProcs * kThreadLoops,
- table.GetCounterValue(name));
- name = "c:" + kCounterDecrement;
- EXPECT_EQ(-kMaxProcs * kThreadLoops,
- table.GetCounterValue(name));
- EXPECT_EQ(0, table.CountThreadsRegistered());
-}
-#endif
-
-class MockStatsCounter : public StatsCounter {
- public:
- explicit MockStatsCounter(const std::string& name)
- : StatsCounter(name) {}
- int* Pointer() { return GetPtr(); }
-};
-
-// Test some basic StatsCounter operations
-TEST_F(StatsTableTest, StatsCounter) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- MockStatsCounter foo("foo");
-
- // Test initial state.
- EXPECT_TRUE(foo.Enabled());
- ASSERT_NE(foo.Pointer(), static_cast<int*>(0));
- EXPECT_EQ(0, *(foo.Pointer()));
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-
- // Test Increment.
- while (*(foo.Pointer()) < 123) foo.Increment();
- EXPECT_EQ(123, table.GetCounterValue("c:foo"));
- foo.Add(0);
- EXPECT_EQ(123, table.GetCounterValue("c:foo"));
- foo.Add(-1);
- EXPECT_EQ(122, table.GetCounterValue("c:foo"));
-
- // Test Set.
- foo.Set(0);
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
- foo.Set(100);
- EXPECT_EQ(100, table.GetCounterValue("c:foo"));
- foo.Set(-1);
- EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
- foo.Set(0);
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-
- // Test Decrement.
- foo.Subtract(1);
- EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
- foo.Subtract(0);
- EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
- foo.Subtract(-1);
- EXPECT_EQ(0, table.GetCounterValue("c:foo"));
-}
-
-class MockStatsCounterTimer : public StatsCounterTimer {
- public:
- explicit MockStatsCounterTimer(const std::string& name)
- : StatsCounterTimer(name) {}
-
- TimeTicks start_time() { return start_time_; }
- TimeTicks stop_time() { return stop_time_; }
-};
-
-// Test some basic StatsCounterTimer operations
-TEST_F(StatsTableTest, StatsCounterTimer) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- MockStatsCounterTimer bar("bar");
-
- // Test initial state.
- EXPECT_FALSE(bar.Running());
- EXPECT_TRUE(bar.start_time().is_null());
- EXPECT_TRUE(bar.stop_time().is_null());
-
- const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
- // Do some timing.
- bar.Start();
- PlatformThread::Sleep(kDuration);
- bar.Stop();
- EXPECT_GT(table.GetCounterValue("t:bar"), 0);
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
-
- // Verify that timing again is additive.
- bar.Start();
- PlatformThread::Sleep(kDuration);
- bar.Stop();
- EXPECT_GT(table.GetCounterValue("t:bar"), 0);
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
-}
-
-// Test some basic StatsRate operations
-TEST_F(StatsTableTest, StatsRate) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- StatsRate baz("baz");
-
- // Test initial state.
- EXPECT_FALSE(baz.Running());
- EXPECT_EQ(0, table.GetCounterValue("c:baz"));
- EXPECT_EQ(0, table.GetCounterValue("t:baz"));
-
- const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
- // Do some timing.
- baz.Start();
- PlatformThread::Sleep(kDuration);
- baz.Stop();
- EXPECT_EQ(1, table.GetCounterValue("c:baz"));
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:baz"));
-
- // Verify that timing again is additive.
- baz.Start();
- PlatformThread::Sleep(kDuration);
- baz.Stop();
- EXPECT_EQ(2, table.GetCounterValue("c:baz"));
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:baz"));
-}
-
-// Test some basic StatsScope operations
-TEST_F(StatsTableTest, StatsScope) {
- // Create a stats table.
- const int kMaxThreads = 20;
- const int kMaxCounter = 5;
- StatsTable table(StatsTable::TableIdentifier(), kMaxThreads, kMaxCounter);
- StatsTable::set_current(&table);
-
- StatsCounterTimer foo("foo");
- StatsRate bar("bar");
-
- // Test initial state.
- EXPECT_EQ(0, table.GetCounterValue("t:foo"));
- EXPECT_EQ(0, table.GetCounterValue("t:bar"));
- EXPECT_EQ(0, table.GetCounterValue("c:bar"));
-
- const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
-
- // Try a scope.
- {
- StatsScope<StatsCounterTimer> timer(foo);
- StatsScope<StatsRate> timer2(bar);
- PlatformThread::Sleep(kDuration);
- }
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:foo"));
- EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
- EXPECT_EQ(1, table.GetCounterValue("c:bar"));
-
- // Try a second scope.
- {
- StatsScope<StatsCounterTimer> timer(foo);
- StatsScope<StatsRate> timer2(bar);
- PlatformThread::Sleep(kDuration);
- }
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:foo"));
- EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
- EXPECT_EQ(2, table.GetCounterValue("c:bar"));
-}
-
-} // namespace base
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h
index b951a71..1a663337 100644
--- a/base/observer_list_threadsafe.h
+++ b/base/observer_list_threadsafe.h
@@ -168,7 +168,9 @@
// that at the completion of the Notify call that all Observers have
// been Notified. The notification may still be pending delivery.
template <class Method, class... Params>
- void Notify(Method m, const Params&... params) {
+ void Notify(const tracked_objects::Location& from_here,
+ Method m,
+ const Params&... params) {
UnboundMethod<ObserverType, Method, Tuple<Params...>> method(
m, MakeTuple(params...));
@@ -176,7 +178,7 @@
for (const auto& entry : observer_lists_) {
ObserverListContext* context = entry.second;
context->loop->PostTask(
- FROM_HERE,
+ from_here,
base::Bind(
&ObserverListThreadSafe<ObserverType>::template NotifyWrapper<
Method, Tuple<Params...>>,
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc
index 65ef934..636aa83 100644
--- a/base/observer_list_unittest.cc
+++ b/base/observer_list_unittest.cc
@@ -134,7 +134,7 @@
}
if (do_notifies_) {
- list_->Notify(&Foo::Observe, 10);
+ list_->Notify(FROM_HERE, &Foo::Observe, 10);
}
loop_->PostTask(
@@ -217,14 +217,14 @@
observer_list->AddObserver(&a);
observer_list->AddObserver(&b);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
observer_list->AddObserver(&evil);
observer_list->AddObserver(&c);
observer_list->AddObserver(&d);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(20, a.total);
@@ -247,7 +247,7 @@
observer_list->RemoveObserver(&a);
observer_list->RemoveObserver(&b);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(0, a.total);
@@ -258,7 +258,7 @@
// Should also do nothing.
observer_list->RemoveObserver(&b);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(10, a.total);
@@ -280,7 +280,7 @@
MessageLoop loop;
observer_list->AddObserver(&c);
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
EXPECT_EQ(0, a.total);
@@ -294,7 +294,7 @@
observer_list->RemoveObserver(&c);
// Notify again.
- observer_list->Notify(&Foo::Observe, 20);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
RunLoop().RunUntilIdle();
EXPECT_EQ(20, a.total);
@@ -308,7 +308,7 @@
// Notifying should not fail but should also be a no-op.
MessageLoop loop;
observer_list->AddObserver(&b);
- observer_list->Notify(&Foo::Observe, 30);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
RunLoop().RunUntilIdle();
EXPECT_EQ(20, a.total);
@@ -353,7 +353,7 @@
a.AddFooToRemove(&a);
a.AddFooToRemove(&b);
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
RunLoop().RunUntilIdle();
}
@@ -392,7 +392,7 @@
if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
break;
- observer_list->Notify(&Foo::Observe, 10);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
RunLoop().RunUntilIdle();
}
@@ -424,7 +424,7 @@
observer_list->AddObserver(&a);
delete loop;
// Test passes if we don't crash here.
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
}
TEST(ObserverListTest, Existing) {
@@ -458,7 +458,7 @@
observer_list->AddObserver(&a);
observer_list->AddObserver(&b);
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
RunLoop().RunUntilIdle();
EXPECT_TRUE(b.added);
@@ -467,7 +467,7 @@
EXPECT_EQ(0, b.adder.total);
// Notify again to make sure b's adder is notified.
- observer_list->Notify(&Foo::Observe, 1);
+ observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
RunLoop().RunUntilIdle();
EXPECT_EQ(1, b.adder.total);
}
diff --git a/base/power_monitor/power_monitor.cc b/base/power_monitor/power_monitor.cc
index 14dc4b5..98c9c68 100644
--- a/base/power_monitor/power_monitor.cc
+++ b/base/power_monitor/power_monitor.cc
@@ -45,17 +45,18 @@
void PowerMonitor::NotifyPowerStateChange(bool battery_in_use) {
DVLOG(1) << "PowerStateChange: " << (battery_in_use ? "On" : "Off")
<< " battery";
- observers_->Notify(&PowerObserver::OnPowerStateChange, battery_in_use);
+ observers_->Notify(FROM_HERE, &PowerObserver::OnPowerStateChange,
+ battery_in_use);
}
void PowerMonitor::NotifySuspend() {
DVLOG(1) << "Power Suspending";
- observers_->Notify(&PowerObserver::OnSuspend);
+ observers_->Notify(FROM_HERE, &PowerObserver::OnSuspend);
}
void PowerMonitor::NotifyResume() {
DVLOG(1) << "Power Resuming";
- observers_->Notify(&PowerObserver::OnResume);
+ observers_->Notify(FROM_HERE, &PowerObserver::OnResume);
}
} // namespace base
diff --git a/base/process/kill_win.cc b/base/process/kill_win.cc
index 4d7225f..f280c6f 100644
--- a/base/process/kill_win.cc
+++ b/base/process/kill_win.cc
@@ -182,10 +182,9 @@
}
bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
- bool success = WaitForExitCodeWithTimeout(
- handle, exit_code, base::TimeDelta::FromMilliseconds(INFINITE));
- CloseProcessHandle(handle);
- return success;
+ // TODO(rvargas) crbug.com/417532: Remove this function.
+ Process process(handle);
+ return process.WaitForExit(exit_code);
}
bool WaitForExitCodeWithTimeout(ProcessHandle handle,
diff --git a/base/process/process_handle.h b/base/process/process_handle.h
index c99ea15..77f2c58 100644
--- a/base/process/process_handle.h
+++ b/base/process/process_handle.h
@@ -40,30 +40,12 @@
// Returns the ProcessHandle of the current process.
BASE_EXPORT ProcessHandle GetCurrentProcessHandle();
-
-
-// Closes the process handle opened by OpenProcessHandle.
-BASE_EXPORT void CloseProcessHandle(ProcessHandle process);
-
// Returns the unique ID for the specified process. This is functionally the
// same as Windows' GetProcessId(), but works on versions of Windows before
// Win XP SP1 as well.
+// DEPRECATED. New code should be using Process::Pid() instead.
BASE_EXPORT ProcessId GetProcId(ProcessHandle process);
-#if defined(OS_WIN)
-enum IntegrityLevel {
- INTEGRITY_UNKNOWN,
- LOW_INTEGRITY,
- MEDIUM_INTEGRITY,
- HIGH_INTEGRITY,
-};
-// Determine the integrity level of the specified process. Returns false
-// if the system does not support integrity levels (pre-Vista) or in the case
-// of an underlying system failure.
-BASE_EXPORT bool GetProcessIntegrityLevel(ProcessHandle process,
- IntegrityLevel* level);
-#endif
-
#if defined(OS_POSIX)
// Returns the path to the executable of the given process.
BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process);
diff --git a/base/process/process_handle_posix.cc b/base/process/process_handle_posix.cc
index a661ecd..4e332df 100644
--- a/base/process/process_handle_posix.cc
+++ b/base/process/process_handle_posix.cc
@@ -16,11 +16,6 @@
return GetCurrentProcId();
}
-void CloseProcessHandle(ProcessHandle process) {
- // See OpenProcessHandle, nothing to do.
- return;
-}
-
ProcessId GetProcId(ProcessHandle process) {
return process;
}
diff --git a/base/process/process_handle_win.cc b/base/process/process_handle_win.cc
index 30b2066..f2ffff8 100644
--- a/base/process/process_handle_win.cc
+++ b/base/process/process_handle_win.cc
@@ -20,64 +20,9 @@
return ::GetCurrentProcess();
}
-void CloseProcessHandle(ProcessHandle process) {
- CloseHandle(process);
-}
-
ProcessId GetProcId(ProcessHandle process) {
// This returns 0 if we have insufficient rights to query the process handle.
return GetProcessId(process);
}
-bool GetProcessIntegrityLevel(ProcessHandle process, IntegrityLevel *level) {
- if (!level)
- return false;
-
- if (win::GetVersion() < base::win::VERSION_VISTA)
- return false;
-
- HANDLE process_token;
- if (!OpenProcessToken(process, TOKEN_QUERY | TOKEN_QUERY_SOURCE,
- &process_token))
- return false;
-
- win::ScopedHandle scoped_process_token(process_token);
-
- DWORD token_info_length = 0;
- if (GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0,
- &token_info_length) ||
- GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- return false;
-
- scoped_ptr<char[]> token_label_bytes(new char[token_info_length]);
- if (!token_label_bytes.get())
- return false;
-
- TOKEN_MANDATORY_LABEL* token_label =
- reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
- if (!token_label)
- return false;
-
- if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
- token_info_length, &token_info_length))
- return false;
-
- DWORD integrity_level = *GetSidSubAuthority(token_label->Label.Sid,
- (DWORD)(UCHAR)(*GetSidSubAuthorityCount(token_label->Label.Sid)-1));
-
- if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID) {
- *level = LOW_INTEGRITY;
- } else if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
- integrity_level < SECURITY_MANDATORY_HIGH_RID) {
- *level = MEDIUM_INTEGRITY;
- } else if (integrity_level >= SECURITY_MANDATORY_HIGH_RID) {
- *level = HIGH_INTEGRITY;
- } else {
- NOTREACHED();
- return false;
- }
-
- return true;
-}
-
} // namespace base
diff --git a/base/process/process_info.h b/base/process/process_info.h
index e9e7b4e..85f204d 100644
--- a/base/process/process_info.h
+++ b/base/process/process_info.h
@@ -2,11 +2,12 @@
// 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_INFO_H_
-#define BASE_PROCESS_PROCESS_PROCESS_INFO_H_
+#ifndef BASE_PROCESS_PROCESS_INFO_H_
+#define BASE_PROCESS_PROCESS_INFO_H_
#include "base/base_export.h"
#include "base/basictypes.h"
+#include "build/build_config.h"
namespace base {
@@ -20,6 +21,24 @@
static const Time CreationTime();
};
+#if defined(OS_WIN)
+
+enum IntegrityLevel {
+ INTEGRITY_UNKNOWN,
+ LOW_INTEGRITY,
+ MEDIUM_INTEGRITY,
+ HIGH_INTEGRITY,
+};
+
+// Returns the integrity level of the process. Returns INTEGRITY_UNKNOWN if the
+// system does not support integrity levels (pre-Vista) or in the case of an
+// underlying system failure.
+BASE_EXPORT IntegrityLevel GetCurrentProcessIntegrityLevel();
+
+#endif // defined(OS_WIN)
+
+
+
} // namespace base
-#endif // BASE_PROCESS_PROCESS_PROCESS_INFO_H_
+#endif // BASE_PROCESS_PROCESS_INFO_H_
diff --git a/base/process/process_info_win.cc b/base/process/process_info_win.cc
index b930ae6..2b9c406 100644
--- a/base/process/process_info_win.cc
+++ b/base/process/process_info_win.cc
@@ -7,11 +7,14 @@
#include <windows.h>
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
namespace base {
-//static
+// static
const Time CurrentProcessInfo::CreationTime() {
FILETIME creation_time = {};
FILETIME ignore = {};
@@ -22,4 +25,55 @@
return Time::FromFileTime(creation_time);
}
+IntegrityLevel GetCurrentProcessIntegrityLevel() {
+ if (win::GetVersion() < base::win::VERSION_VISTA)
+ return INTEGRITY_UNKNOWN;
+
+ HANDLE process_token;
+ if (!::OpenProcessToken(::GetCurrentProcess(),
+ TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
+ return INTEGRITY_UNKNOWN;
+ }
+ win::ScopedHandle scoped_process_token(process_token);
+
+ DWORD token_info_length = 0;
+ if (::GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0,
+ &token_info_length) ||
+ ::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ return INTEGRITY_UNKNOWN;
+ }
+
+ scoped_ptr<char[]> token_label_bytes(new char[token_info_length]);
+ if (!token_label_bytes.get())
+ return INTEGRITY_UNKNOWN;
+
+ TOKEN_MANDATORY_LABEL* token_label =
+ reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
+ if (!token_label)
+ return INTEGRITY_UNKNOWN;
+
+ if (!::GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
+ token_info_length, &token_info_length)) {
+ return INTEGRITY_UNKNOWN;
+ }
+
+ DWORD integrity_level = *::GetSidSubAuthority(
+ token_label->Label.Sid,
+ static_cast<DWORD>(*::GetSidSubAuthorityCount(token_label->Label.Sid)-1));
+
+ if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID)
+ return LOW_INTEGRITY;
+
+ if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
+ integrity_level < SECURITY_MANDATORY_HIGH_RID) {
+ return MEDIUM_INTEGRITY;
+ }
+
+ if (integrity_level >= SECURITY_MANDATORY_HIGH_RID)
+ return HIGH_INTEGRITY;
+
+ NOTREACHED();
+ return INTEGRITY_UNKNOWN;
+}
+
} // namespace base
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 8f334da..e084cb5 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -454,8 +454,8 @@
return DoLowerCaseEqualsASCII(a_begin, a_end, b);
}
-// TODO(jdduke): Remove guards after complete adoption of libc++ on Android.
-#if !defined(OS_ANDROID) || !defined(USE_STLPORT)
+// TODO(port): Resolve wchar_t/iterator issues that require OS_ANDROID here.
+#if !defined(OS_ANDROID)
bool LowerCaseEqualsASCII(const char* a_begin,
const char* a_end,
const char* b) {
@@ -467,7 +467,8 @@
const char* b) {
return DoLowerCaseEqualsASCII(a_begin, a_end, b);
}
-#endif // !defined(OS_ANDROID) || !defined(USE_STLPORT)
+
+#endif // !defined(OS_ANDROID)
bool EqualsASCII(const string16& a, const base::StringPiece& b) {
if (a.length() != b.length())
@@ -555,23 +556,103 @@
return base::ASCIIToUTF16(buf);
}
+// Runs in O(n) time in the length of |str|.
template<class StringType>
void DoReplaceSubstringsAfterOffset(StringType* str,
- size_t start_offset,
+ size_t offset,
const StringType& find_this,
const StringType& replace_with,
bool replace_all) {
- if ((start_offset == StringType::npos) || (start_offset >= str->length()))
+ DCHECK(!find_this.empty());
+
+ // If the find string doesn't appear, there's nothing to do.
+ offset = str->find(find_this, offset);
+ if (offset == StringType::npos)
return;
- DCHECK(!find_this.empty());
- for (size_t offs(str->find(find_this, start_offset));
- offs != StringType::npos; offs = str->find(find_this, offs)) {
- str->replace(offs, find_this.length(), replace_with);
- offs += replace_with.length();
+ // If we're only replacing one instance, there's no need to do anything
+ // complicated.
+ size_t find_length = find_this.length();
+ if (!replace_all) {
+ str->replace(offset, find_length, replace_with);
+ return;
+ }
- if (!replace_all)
- break;
+ // If the find and replace strings are the same length, we can simply use
+ // replace() on each instance, and finish the entire operation in O(n) time.
+ size_t replace_length = replace_with.length();
+ if (find_length == replace_length) {
+ do {
+ str->replace(offset, find_length, replace_with);
+ offset = str->find(find_this, offset + replace_length);
+ } while (offset != StringType::npos);
+ return;
+ }
+
+ // Since the find and replace strings aren't the same length, a loop like the
+ // one above would be O(n^2) in the worst case, as replace() will shift the
+ // entire remaining string each time. We need to be more clever to keep
+ // things O(n).
+ //
+ // If we're shortening the string, we can alternate replacements with shifting
+ // forward the intervening characters using memmove().
+ size_t str_length = str->length();
+ if (find_length > replace_length) {
+ size_t write_offset = offset;
+ do {
+ if (replace_length) {
+ str->replace(write_offset, replace_length, replace_with);
+ write_offset += replace_length;
+ }
+ size_t read_offset = offset + find_length;
+ offset = std::min(str->find(find_this, read_offset), str_length);
+ size_t length = offset - read_offset;
+ if (length) {
+ memmove(&(*str)[write_offset], &(*str)[read_offset],
+ length * sizeof(typename StringType::value_type));
+ write_offset += length;
+ }
+ } while (offset < str_length);
+ str->resize(write_offset);
+ return;
+ }
+
+ // We're lengthening the string. We can use alternating replacements and
+ // memmove() calls like above, but we need to precalculate the final string
+ // length and then expand from back-to-front to avoid overwriting the string
+ // as we're reading it, needing to shift, or having to copy to a second string
+ // temporarily.
+ size_t first_match = offset;
+
+ // First, calculate the final length and resize the string.
+ size_t final_length = str_length;
+ size_t expansion = replace_length - find_length;
+ size_t current_match;
+ do {
+ final_length += expansion;
+ // Minor optimization: save this offset into |current_match|, so that on
+ // exit from the loop, |current_match| will point at the last instance of
+ // the find string, and we won't need to find() it again immediately.
+ current_match = offset;
+ offset = str->find(find_this, offset + find_length);
+ } while (offset != StringType::npos);
+ str->resize(final_length);
+
+ // Now do the replacement loop, working backwards through the string.
+ for (size_t prev_match = str_length, write_offset = final_length; ;
+ current_match = str->rfind(find_this, current_match - 1)) {
+ size_t read_offset = current_match + find_length;
+ size_t length = prev_match - read_offset;
+ if (length) {
+ write_offset -= length;
+ memmove(&(*str)[write_offset], &(*str)[read_offset],
+ length * sizeof(typename StringType::value_type));
+ }
+ write_offset -= replace_length;
+ str->replace(write_offset, replace_length, replace_with);
+ if (current_match == first_match)
+ return;
+ prev_match = current_match;
}
}
diff --git a/base/system_monitor/system_monitor.cc b/base/system_monitor/system_monitor.cc
index 11dd000..99152ab 100644
--- a/base/system_monitor/system_monitor.cc
+++ b/base/system_monitor/system_monitor.cc
@@ -46,7 +46,7 @@
void SystemMonitor::NotifyDevicesChanged(DeviceType device_type) {
DVLOG(1) << "DevicesChanged with device type " << device_type;
devices_changed_observer_list_->Notify(
- &DevicesChangedObserver::OnDevicesChanged, device_type);
+ FROM_HERE, &DevicesChangedObserver::OnDevicesChanged, device_type);
}
} // namespace base
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java b/base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
index 09e1fd6..797585f 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
@@ -16,20 +16,41 @@
/**
* Construct the full path of a test data file.
- * @param path Pathname relative to external/chrome/testing/data
+ * @param path Pathname relative to external/chrome/test/data
*/
public static String getTestFilePath(String path) {
+ // TODO(jbudorick): Remove DATA_DIR once everything has been isolated. crbug/400499
return PathUtils.getExternalStorageDirectory() + DATA_DIR + path;
}
+ // TODO(jbudorick): Remove this function once everything has been isolated and switched back
+ // to getTestFilePath. crbug/400499
+ /**
+ * Construct the full path of a test data file.
+ * @param path Pathname relative to external/
+ */
+ public static String getIsolatedTestFilePath(String path) {
+ return PathUtils.getExternalStorageDirectory() + "/" + path;
+ }
+
/**
* Construct a suitable URL for loading a test data file.
- * @param path Pathname relative to external/chrome/testing/data
+ * @param path Pathname relative to external/chrome/test/data
*/
public static String getTestFileUrl(String path) {
return "file://" + getTestFilePath(path);
}
+ // TODO(jbudorick): Remove this function once everything has been isolated and switched back
+ // to getTestFileUrl. crbug/400499
+ /**
+ * Construct a suitable URL for loading a test data file.
+ * @param path Pathname relative to external/
+ */
+ public static String getIsolatedTestFileUrl(String path) {
+ return "file://" + getIsolatedTestFilePath(path);
+ }
+
/**
* Construct a data:text/html URI for loading from an inline HTML.
* @param html An unencoded HTML
@@ -41,8 +62,7 @@
// ' '->'+' needs to be undone and replaced with ' '->'%20'
// to match the Data URI requirements.
String encoded =
- "data:text/html;utf-8," +
- java.net.URLEncoder.encode(html, "UTF-8");
+ "data:text/html;utf-8," + java.net.URLEncoder.encode(html, "UTF-8");
encoded = encoded.replace("+", "%20");
return encoded;
} catch (java.io.UnsupportedEncodingException e) {
diff --git a/base/test/multiprocess_test.h b/base/test/multiprocess_test.h
index e419503..b1c73df 100644
--- a/base/test/multiprocess_test.h
+++ b/base/test/multiprocess_test.h
@@ -33,16 +33,15 @@
// // Maybe set some options (e.g., |start_hidden| on Windows)....
//
// // Start a child process and run |a_test_func|.
-// base::ProcessHandle test_child_handle =
+// base::Process test_child_process =
// base::SpawnMultiProcessTestChild("a_test_func", command_line,
// options);
//
-// // Do stuff involving |test_child_handle| and the child process....
+// // Do stuff involving |test_child_process| and the child process....
//
// int rv = -1;
-// ASSERT_TRUE(base::WaitForExitCodeWithTimeout(
-// test_child_handle, &rv, TestTimeouts::action_timeout()));
-// base::CloseProcessHandle(test_child_handle);
+// ASSERT_TRUE(test_child_process.WaitForExitWithTimeout(
+// TestTimeouts::action_timeout(), &rv));
// EXPECT_EQ(0, rv);
// }
//
diff --git a/base/test/test_mock_time_task_runner.cc b/base/test/test_mock_time_task_runner.cc
index 442d991..a878280 100644
--- a/base/test/test_mock_time_task_runner.cc
+++ b/base/test/test_mock_time_task_runner.cc
@@ -6,18 +6,21 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
+#include "base/time/clock.h"
+#include "base/time/tick_clock.h"
namespace base {
namespace {
-// TickClock that always returns the then-current mock time of |task_runner| as
-// the current time.
+// MockTickClock --------------------------------------------------------------
+
+// TickClock that always returns the then-current mock time ticks of
+// |task_runner| as the current time ticks.
class MockTickClock : public TickClock {
public:
explicit MockTickClock(
scoped_refptr<const TestMockTimeTaskRunner> task_runner);
- ~MockTickClock() override;
// TickClock:
TimeTicks NowTicks() override;
@@ -33,22 +36,46 @@
: task_runner_(task_runner) {
}
-MockTickClock::~MockTickClock() {
+TimeTicks MockTickClock::NowTicks() {
+ return task_runner_->NowTicks();
}
-TimeTicks MockTickClock::NowTicks() {
- return task_runner_->GetCurrentMockTime();
+// MockClock ------------------------------------------------------------------
+
+// Clock that always returns the then-current mock time of |task_runner| as the
+// current time.
+class MockClock : public Clock {
+ public:
+ explicit MockClock(scoped_refptr<const TestMockTimeTaskRunner> task_runner);
+
+ // Clock:
+ Time Now() override;
+
+ private:
+ scoped_refptr<const TestMockTimeTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockClock);
+};
+
+MockClock::MockClock(scoped_refptr<const TestMockTimeTaskRunner> task_runner)
+ : task_runner_(task_runner) {
+}
+
+Time MockClock::Now() {
+ return task_runner_->Now();
}
} // namespace
+// TestMockTimeTaskRunner -----------------------------------------------------
+
bool TestMockTimeTaskRunner::TemporalOrder::operator()(
const TestPendingTask& first_task,
const TestPendingTask& second_task) const {
return first_task.GetTimeToRun() > second_task.GetTimeToRun();
}
-TestMockTimeTaskRunner::TestMockTimeTaskRunner() {
+TestMockTimeTaskRunner::TestMockTimeTaskRunner() : now_(Time::UnixEpoch()) {
}
TestMockTimeTaskRunner::~TestMockTimeTaskRunner() {
@@ -56,42 +83,38 @@
void TestMockTimeTaskRunner::FastForwardBy(TimeDelta delta) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_GE(delta, TimeDelta());
- OnBeforeSelectingTask();
-
- const base::TimeTicks original_now = now_;
- TestPendingTask task_info;
- while (DequeueNextTask(original_now, delta, &task_info)) {
- if (task_info.GetTimeToRun() - now_ > base::TimeDelta()) {
- now_ = task_info.GetTimeToRun();
- OnAfterTimePassed();
- }
-
- task_info.task.Run();
-
- OnAfterTaskRun();
- OnBeforeSelectingTask();
- }
-
- if (!delta.is_max() && now_ - original_now < delta) {
- now_ = original_now + delta;
- OnAfterTimePassed();
- }
+ const TimeTicks original_now_ticks = now_ticks_;
+ ProcessAllTasksNoLaterThan(delta);
+ ForwardClocksUntilTickTime(original_now_ticks + delta);
}
void TestMockTimeTaskRunner::RunUntilIdle() {
- FastForwardBy(TimeDelta());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ProcessAllTasksNoLaterThan(TimeDelta());
}
void TestMockTimeTaskRunner::FastForwardUntilNoTasksRemain() {
- FastForwardBy(TimeDelta::Max());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ ProcessAllTasksNoLaterThan(TimeDelta::Max());
}
-TimeTicks TestMockTimeTaskRunner::GetCurrentMockTime() const {
+Time TestMockTimeTaskRunner::Now() const {
DCHECK(thread_checker_.CalledOnValidThread());
return now_;
}
+TimeTicks TestMockTimeTaskRunner::NowTicks() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return now_ticks_;
+}
+
+scoped_ptr<Clock> TestMockTimeTaskRunner::GetMockClock() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return make_scoped_ptr(new MockClock(this));
+}
+
scoped_ptr<TickClock> TestMockTimeTaskRunner::GetMockTickClock() const {
DCHECK(thread_checker_.CalledOnValidThread());
return make_scoped_ptr(new MockTickClock(this));
@@ -109,7 +132,8 @@
TimeDelta TestMockTimeTaskRunner::NextPendingTaskDelay() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return tasks_.empty() ? TimeDelta::Max() : tasks_.top().GetTimeToRun() - now_;
+ return tasks_.empty() ? TimeDelta::Max()
+ : tasks_.top().GetTimeToRun() - now_ticks_;
}
bool TestMockTimeTaskRunner::RunsTasksOnCurrentThread() const {
@@ -120,9 +144,9 @@
const tracked_objects::Location& from_here,
const Closure& task,
TimeDelta delay) {
- base::AutoLock scoped_lock(tasks_lock_);
- tasks_.push(
- TestPendingTask(from_here, task, now_, delay, TestPendingTask::NESTABLE));
+ AutoLock scoped_lock(tasks_lock_);
+ tasks_.push(TestPendingTask(from_here, task, now_ticks_, delay,
+ TestPendingTask::NESTABLE));
return true;
}
@@ -146,10 +170,36 @@
// Empty default implementation.
}
-bool TestMockTimeTaskRunner::DequeueNextTask(const base::TimeTicks& reference,
- const base::TimeDelta& max_delta,
+void TestMockTimeTaskRunner::ProcessAllTasksNoLaterThan(TimeDelta max_delta) {
+ DCHECK_GE(max_delta, TimeDelta());
+ const TimeTicks original_now_ticks = now_ticks_;
+ while (true) {
+ OnBeforeSelectingTask();
+ TestPendingTask task_info;
+ if (!DequeueNextTask(original_now_ticks, max_delta, &task_info))
+ break;
+ // If tasks were posted with a negative delay, task_info.GetTimeToRun() will
+ // be less than |now_ticks_|. ForwardClocksUntilTickTime() takes care of not
+ // moving the clock backwards in this case.
+ ForwardClocksUntilTickTime(task_info.GetTimeToRun());
+ task_info.task.Run();
+ OnAfterTaskRun();
+ }
+}
+
+void TestMockTimeTaskRunner::ForwardClocksUntilTickTime(TimeTicks later_ticks) {
+ if (later_ticks <= now_ticks_)
+ return;
+
+ now_ += later_ticks - now_ticks_;
+ now_ticks_ = later_ticks;
+ OnAfterTimePassed();
+}
+
+bool TestMockTimeTaskRunner::DequeueNextTask(const TimeTicks& reference,
+ const TimeDelta& max_delta,
TestPendingTask* next_task) {
- base::AutoLock scoped_lock(tasks_lock_);
+ AutoLock scoped_lock(tasks_lock_);
if (!tasks_.empty() &&
(tasks_.top().GetTimeToRun() - reference) <= max_delta) {
*next_task = tasks_.top();
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index 2f59892..1a651f6 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -14,11 +14,13 @@
#include "base/synchronization/lock.h"
#include "base/test/test_pending_task.h"
#include "base/threading/thread_checker.h"
-#include "base/time/tick_clock.h"
#include "base/time/time.h"
namespace base {
+class Clock;
+class TickClock;
+
// Runs pending tasks in the order of the tasks' post time + delay, and keeps
// track of a mock (virtual) tick clock time that can be fast-forwarded.
//
@@ -31,18 +33,26 @@
// turn call back into it (e.g., to post more tasks).
// - Tasks are stored in a priority queue, and executed in the increasing
// order of post time + delay.
+// - It does not check for overflow when doing time arithmetic. A sufficient
+// condition for preventing overflows is to make sure that the sum of all
+// posted task delays and fast-forward increments is still representable by
+// a TimeDelta, and that adding this delta to the starting values of Time
+// and TickTime is still within their respective range.
// - Non-nestable tasks are not supported.
// - Tasks aren't guaranteed to be destroyed immediately after they're run.
//
// This is a slightly more sophisticated version of TestSimpleTaskRunner, in
// that it supports running delayed tasks in the correct temporal order.
-class TestMockTimeTaskRunner : public base::SingleThreadTaskRunner {
+class TestMockTimeTaskRunner : public SingleThreadTaskRunner {
public:
+ // Constructs an instance whose virtual time will start at the Unix epoch, and
+ // whose time ticks will start at zero.
TestMockTimeTaskRunner();
// Fast-forwards virtual time by |delta|, causing all tasks with a remaining
- // delay less than or equal to |delta| to be executed.
- void FastForwardBy(base::TimeDelta delta);
+ // delay less than or equal to |delta| to be executed. |delta| must be
+ // non-negative.
+ void FastForwardBy(TimeDelta delta);
// Fast-forwards virtual time just until all tasks are executed.
void FastForwardUntilNoTasksRemain();
@@ -52,11 +62,18 @@
// elapse.
void RunUntilIdle();
- // Returns the current virtual time.
- TimeTicks GetCurrentMockTime() const;
+ // Returns the current virtual time (initially starting at the Unix epoch).
+ Time Now() const;
- // Returns a TickClock that uses the mock time of |this| as its time source.
- // The returned TickClock will hold a reference to |this|.
+ // Returns the current virtual tick time (initially starting at 0).
+ TimeTicks NowTicks() const;
+
+ // Returns a Clock that uses the virtual time of |this| as its time source.
+ // The returned Clock will hold a reference to |this|.
+ scoped_ptr<Clock> GetMockClock() const;
+
+ // Returns a TickClock that uses the virtual time ticks of |this| as its tick
+ // source. The returned TickClock will hold a reference to |this|.
scoped_ptr<TickClock> GetMockTickClock() const;
bool HasPendingTask() const;
@@ -66,12 +83,11 @@
// SingleThreadTaskRunner:
bool RunsTasksOnCurrentThread() const override;
bool PostDelayedTask(const tracked_objects::Location& from_here,
- const base::Closure& task,
- TimeDelta delay) override;
- bool PostNonNestableDelayedTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task,
- TimeDelta delay) override;
+ const Closure& task,
+ TimeDelta delay) override;
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+ const Closure& task,
+ TimeDelta delay) override;
protected:
~TestMockTimeTaskRunner() override;
@@ -100,20 +116,32 @@
std::vector<TestPendingTask>,
TemporalOrder> TaskPriorityQueue;
+ // Core of the implementation for all flavors of fast-forward methods. Given a
+ // non-negative |max_delta|, runs all tasks with a remaining delay less than
+ // or equal to |max_delta|, and moves virtual time forward as needed for each
+ // processed task. Pass in TimeDelta::Max() as |max_delta| to run all tasks.
+ void ProcessAllTasksNoLaterThan(TimeDelta max_delta);
+
+ // Forwards |now_ticks_| until it equals |later_ticks|, and forwards |now_| by
+ // the same amount. Calls OnAfterTimePassed() if |later_ticks| > |now_ticks_|.
+ // Does nothing if |later_ticks| <= |now_ticks_|.
+ void ForwardClocksUntilTickTime(TimeTicks later_ticks);
+
// Returns the |next_task| to run if there is any with a running time that is
// at most |reference| + |max_delta|. This additional complexity is required
// so that |max_delta| == TimeDelta::Max() can be supported.
- bool DequeueNextTask(const base::TimeTicks& reference,
- const base::TimeDelta& max_delta,
+ bool DequeueNextTask(const TimeTicks& reference,
+ const TimeDelta& max_delta,
TestPendingTask* next_task);
- base::ThreadChecker thread_checker_;
- base::TimeTicks now_;
+ ThreadChecker thread_checker_;
+ Time now_;
+ TimeTicks now_ticks_;
// Temporally ordered heap of pending tasks. Must only be accessed while the
// |tasks_lock_| is held.
TaskPriorityQueue tasks_;
- base::Lock tasks_lock_;
+ Lock tasks_lock_;
DISALLOW_COPY_AND_ASSIGN(TestMockTimeTaskRunner);
};
diff --git a/base/test/test_pending_task.cc b/base/test/test_pending_task.cc
index 94989de..3f2c79d 100644
--- a/base/test/test_pending_task.cc
+++ b/base/test/test_pending_task.cc
@@ -34,7 +34,7 @@
TestPendingTask::~TestPendingTask() {}
-void TestPendingTask::AsValueInto(base::debug::TracedValue* state) const {
+void TestPendingTask::AsValueInto(base::trace_event::TracedValue* state) const {
state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
state->SetString("posting_function", location.ToString());
state->SetInteger("post_time", post_time.ToInternalValue());
@@ -50,10 +50,10 @@
state->SetInteger("delay", delay.ToInternalValue());
}
-scoped_refptr<base::debug::ConvertableToTraceFormat> TestPendingTask::AsValue()
- const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+TestPendingTask::AsValue() const {
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get());
return state;
}
diff --git a/base/test/test_pending_task.h b/base/test/test_pending_task.h
index 4a2b0e7..829baa6 100644
--- a/base/test/test_pending_task.h
+++ b/base/test/test_pending_task.h
@@ -57,8 +57,8 @@
// Functions for using test pending task with tracing, useful in unit
// testing.
- void AsValueInto(base::debug::TracedValue* state) const;
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::trace_event::TracedValue* state) const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
std::string ToString() const;
};
diff --git a/base/test/trace_event_analyzer.h b/base/test/trace_event_analyzer.h
index a8be893..57ff2b5 100644
--- a/base/test/trace_event_analyzer.h
+++ b/base/test/trace_event_analyzer.h
@@ -6,7 +6,7 @@
// specific trace events that were generated by the trace_event.h API.
//
// Basic procedure:
-// - Get trace events JSON string from base::debug::TraceLog.
+// - Get trace events JSON string from base::trace_event::TraceLog.
// - Create TraceAnalyzer with JSON string.
// - Call TraceAnalyzer::AssociateBeginEndEvents (optional).
// - Call TraceAnalyzer::AssociateEvents (zero or more times).
@@ -89,7 +89,8 @@
class QueryNode;
// trace_analyzer::TraceEvent is a more convenient form of the
-// base::debug::TraceEvent class to make tracing-based tests easier to write.
+// base::trace_event::TraceEvent class to make tracing-based tests easier to
+// write.
struct TraceEvent {
// ProcessThreadID contains a Process ID and Thread ID.
struct ProcessThreadID {
diff --git a/base/test/trace_event_analyzer_unittest.cc b/base/test/trace_event_analyzer_unittest.cc
index cc1f8a3..4bdb941 100644
--- a/base/test/trace_event_analyzer_unittest.cc
+++ b/base/test/trace_event_analyzer_unittest.cc
@@ -23,12 +23,12 @@
void BeginTracing();
void EndTracing();
- base::debug::TraceResultBuffer::SimpleOutput output_;
- base::debug::TraceResultBuffer buffer_;
+ base::trace_event::TraceResultBuffer::SimpleOutput output_;
+ base::trace_event::TraceResultBuffer buffer_;
};
void TraceEventAnalyzerTest::ManualSetUp() {
- ASSERT_TRUE(base::debug::TraceLog::GetInstance());
+ ASSERT_TRUE(base::trace_event::TraceLog::GetInstance());
buffer_.SetOutputCallback(output_.GetCallback());
output_.json_output.clear();
}
@@ -45,16 +45,16 @@
void TraceEventAnalyzerTest::BeginTracing() {
output_.json_output.clear();
buffer_.Start();
- base::debug::TraceLog::GetInstance()->SetEnabled(
- base::debug::CategoryFilter("*"),
- base::debug::TraceLog::RECORDING_MODE,
- base::debug::TraceOptions());
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ base::trace_event::CategoryFilter("*"),
+ base::trace_event::TraceLog::RECORDING_MODE,
+ base::trace_event::TraceOptions());
}
void TraceEventAnalyzerTest::EndTracing() {
- base::debug::TraceLog::GetInstance()->SetDisabled();
+ base::trace_event::TraceLog::GetInstance()->SetDisabled();
base::WaitableEvent flush_complete_event(false, false);
- base::debug::TraceLog::GetInstance()->Flush(
+ base::trace_event::TraceLog::GetInstance()->Flush(
base::Bind(&TraceEventAnalyzerTest::OnTraceDataCollected,
base::Unretained(this),
base::Unretained(&flush_complete_event)));
diff --git a/base/test/trace_to_file.cc b/base/test/trace_to_file.cc
index 948a6a7..4e2a332 100644
--- a/base/test/trace_to_file.cc
+++ b/base/test/trace_to_file.cc
@@ -51,10 +51,10 @@
path_ = path;
WriteFileHeader();
- debug::TraceLog::GetInstance()->SetEnabled(
- debug::CategoryFilter(categories),
- debug::TraceLog::RECORDING_MODE,
- debug::TraceOptions(debug::RECORD_UNTIL_FULL));
+ trace_event::TraceLog::GetInstance()->SetEnabled(
+ trace_event::CategoryFilter(categories),
+ trace_event::TraceLog::RECORDING_MODE,
+ trace_event::TraceOptions(trace_event::RECORD_UNTIL_FULL));
}
void TraceToFile::WriteFileHeader() {
@@ -74,7 +74,7 @@
static void OnTraceDataCollected(
Closure quit_closure,
- debug::TraceResultBuffer* buffer,
+ trace_event::TraceResultBuffer* buffer,
const scoped_refptr<RefCountedString>& json_events_str,
bool has_more_events) {
buffer->AddFragment(json_events_str->data());
@@ -87,14 +87,14 @@
return;
started_ = false;
- debug::TraceLog::GetInstance()->SetDisabled();
+ trace_event::TraceLog::GetInstance()->SetDisabled();
- debug::TraceResultBuffer buffer;
+ trace_event::TraceResultBuffer buffer;
buffer.SetOutputCallback(
Bind(&TraceToFile::TraceOutputCallback, Unretained(this)));
RunLoop run_loop;
- debug::TraceLog::GetInstance()->Flush(
+ trace_event::TraceLog::GetInstance()->Flush(
Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
run_loop.Run();
diff --git a/base/third_party/dynamic_annotations/BUILD.gn b/base/third_party/dynamic_annotations/BUILD.gn
index 9a47867..e52938c 100644
--- a/base/third_party/dynamic_annotations/BUILD.gn
+++ b/base/third_party/dynamic_annotations/BUILD.gn
@@ -4,9 +4,9 @@
source_set("dynamic_annotations") {
sources = [
+ "../valgrind/valgrind.h",
"dynamic_annotations.c",
"dynamic_annotations.h",
- "../valgrind/valgrind.h",
]
if (is_android && !is_debug) {
configs -= [ "//build/config/compiler:optimize" ]
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.gyp b/base/third_party/dynamic_annotations/dynamic_annotations.gyp
index 12cfb65..8d2e9ec 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.gyp
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.gyp
@@ -12,9 +12,9 @@
'../../../',
],
'sources': [
+ '../valgrind/valgrind.h',
'dynamic_annotations.c',
'dynamic_annotations.h',
- '../valgrind/valgrind.h',
],
'includes': [
'../../../build/android/increase_size_for_speed.gypi',
diff --git a/base/third_party/nspr/BUILD.gn b/base/third_party/nspr/BUILD.gn
index 516ca1f..c0b2ec2 100644
--- a/base/third_party/nspr/BUILD.gn
+++ b/base/third_party/nspr/BUILD.gn
@@ -3,7 +3,10 @@
# found in the LICENSE file.
source_set("nspr") {
- visibility = [ "//base" ]
+ visibility = [
+ "//base/*",
+ ]
+
sources = [
"prtime.cc",
"prtime.h",
diff --git a/base/time/time.cc b/base/time/time.cc
index ce9d12c..951f7ba 100644
--- a/base/time/time.cc
+++ b/base/time/time.cc
@@ -274,6 +274,22 @@
return leaky_unix_epoch_singleton_instance.Get().unix_epoch();
}
+TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
+ TimeDelta tick_interval) const {
+ // |interval_offset| is the offset from |this| to the next multiple of
+ // |tick_interval| after |tick_phase|, possibly negative if in the past.
+ TimeDelta interval_offset = TimeDelta::FromInternalValue(
+ (tick_phase - *this).ToInternalValue() % tick_interval.ToInternalValue());
+ // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
+ // Otherwise, if |tick_phase| was in the past, adjust forward to the next
+ // tick after |this|.
+ if (interval_offset.ToInternalValue() != 0 && tick_phase < *this) {
+ interval_offset += tick_interval;
+ }
+
+ return *this + interval_offset;
+}
+
std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
// This function formats a TimeTicks object as "bogo-microseconds".
// The origin and granularity of the count are platform-specific, and may very
diff --git a/base/time/time.h b/base/time/time.h
index eb86693..18de085 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -680,6 +680,12 @@
return ticks_;
}
+ // Returns |this| snapped to the next tick, given a |tick_phase| and
+ // repeating |tick_interval| in both directions. |this| may be before,
+ // after, or equal to the |tick_phase|.
+ TimeTicks SnappedToNextTick(TimeTicks tick_phase,
+ TimeDelta tick_interval) const;
+
TimeTicks& operator=(TimeTicks other) {
ticks_ = other.ticks_;
return *this;
diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc
index 27f71b4..fdac59d 100644
--- a/base/time/time_unittest.cc
+++ b/base/time/time_unittest.cc
@@ -715,6 +715,62 @@
HighResClockTest(&TimeTicks::NowFromSystemTraceTime);
}
+TEST(TimeTicks, SnappedToNextTickBasic) {
+ base::TimeTicks phase = base::TimeTicks::FromInternalValue(4000);
+ base::TimeDelta interval = base::TimeDelta::FromInternalValue(1000);
+ base::TimeTicks timestamp;
+
+ // Timestamp in previous interval.
+ timestamp = base::TimeTicks::FromInternalValue(3500);
+ EXPECT_EQ(4000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp in next interval.
+ timestamp = base::TimeTicks::FromInternalValue(4500);
+ EXPECT_EQ(5000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp multiple intervals before.
+ timestamp = base::TimeTicks::FromInternalValue(2500);
+ EXPECT_EQ(3000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp multiple intervals after.
+ timestamp = base::TimeTicks::FromInternalValue(6500);
+ EXPECT_EQ(7000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp on previous interval.
+ timestamp = base::TimeTicks::FromInternalValue(3000);
+ EXPECT_EQ(3000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp on next interval.
+ timestamp = base::TimeTicks::FromInternalValue(5000);
+ EXPECT_EQ(5000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp equal to phase.
+ timestamp = base::TimeTicks::FromInternalValue(4000);
+ EXPECT_EQ(4000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+}
+
+TEST(TimeTicks, SnappedToNextTickOverflow) {
+ // int(big_timestamp / interval) < 0, so this causes a crash if the number of
+ // intervals elapsed is attempted to be stored in an int.
+ base::TimeTicks phase = base::TimeTicks::FromInternalValue(0);
+ base::TimeDelta interval = base::TimeDelta::FromInternalValue(4000);
+ base::TimeTicks big_timestamp =
+ base::TimeTicks::FromInternalValue(8635916564000);
+
+ EXPECT_EQ(8635916564000,
+ big_timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+ EXPECT_EQ(8635916564000,
+ big_timestamp.SnappedToNextTick(big_timestamp, interval)
+ .ToInternalValue());
+}
+
TEST(TimeDelta, FromAndIn) {
EXPECT_TRUE(TimeDelta::FromDays(2) == TimeDelta::FromHours(48));
EXPECT_TRUE(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180));
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
new file mode 100644
index 0000000..bf631b3
--- /dev/null
+++ b/base/trace_event/memory_dump_manager.cc
@@ -0,0 +1,135 @@
+// 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/trace_event/memory_dump_manager.h"
+
+#include <algorithm>
+
+#include "base/compiler_specific.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
+
+// TODO(primiano): in a separate CL rename DeleteTraceLogForTesting into
+// something like base::internal::TeardownSingletonForTesting so we don't have
+// to add a new friend to singleton each time.
+class DeleteTraceLogForTesting {
+ public:
+ static void Delete() {
+ Singleton<
+ base::trace_event::MemoryDumpManager,
+ LeakySingletonTraits<base::trace_event::MemoryDumpManager>>::OnExit(0);
+ }
+};
+
+namespace base {
+namespace trace_event {
+
+// TODO(primiano): this should be smarter and should do something similar to
+// trace event synthetic delays.
+const char MemoryDumpManager::kTraceCategory[] =
+ TRACE_DISABLED_BY_DEFAULT("memory-dumps");
+
+// static
+MemoryDumpManager* MemoryDumpManager::GetInstance() {
+ return Singleton<MemoryDumpManager,
+ LeakySingletonTraits<MemoryDumpManager>>::get();
+}
+
+// static
+void MemoryDumpManager::DeleteForTesting() {
+ DeleteTraceLogForTesting::Delete();
+}
+
+MemoryDumpManager::MemoryDumpManager() : memory_tracing_enabled_(0) {
+}
+
+MemoryDumpManager::~MemoryDumpManager() {
+ base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
+}
+
+void MemoryDumpManager::Initialize() {
+ TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list.
+ trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
+}
+
+void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
+ AutoLock lock(lock_);
+ if (std::find(dump_providers_registered_.begin(),
+ dump_providers_registered_.end(),
+ mdp) != dump_providers_registered_.end()) {
+ return;
+ }
+ dump_providers_registered_.push_back(mdp);
+}
+
+void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
+ AutoLock lock(lock_);
+
+ // Remove from the registered providers list.
+ auto it = std::find(dump_providers_registered_.begin(),
+ dump_providers_registered_.end(), mdp);
+ if (it != dump_providers_registered_.end())
+ dump_providers_registered_.erase(it);
+
+ // Remove from the enabled providers list. This is to deal with the case that
+ // UnregisterDumpProvider is called while the trace is enabled.
+ it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(),
+ mdp);
+ if (it != dump_providers_enabled_.end())
+ dump_providers_enabled_.erase(it);
+}
+
+void MemoryDumpManager::RequestDumpPoint(DumpPointType type) {
+ // TODO(primiano): this will have more logic, IPC broadcast & co.
+ // Bail out immediately if tracing is not enabled at all.
+ if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
+ return;
+
+ CreateLocalDumpPoint();
+}
+
+void MemoryDumpManager::BroadcastDumpRequest() {
+ NOTREACHED(); // TODO(primiano): implement IPC synchronization.
+}
+
+// Creates a dump point for the current process and appends it to the trace.
+void MemoryDumpManager::CreateLocalDumpPoint() {
+ AutoLock lock(lock_);
+ // TRACE_EVENT_* macros don't induce scoped_refptr type inference, hence we
+ // need the base ConvertableToTraceFormat and the upcast below. The
+ // alternative would be unnecessarily expensive (double Acquire/Release).
+ scoped_refptr<ConvertableToTraceFormat> pmd(new ProcessMemoryDump());
+
+ for (MemoryDumpProvider* dump_provider : dump_providers_enabled_) {
+ dump_provider->DumpInto(static_cast<ProcessMemoryDump*>(pmd.get()));
+ }
+
+ // TODO(primiano): add the dump point to the trace at this point.
+}
+
+void MemoryDumpManager::OnTraceLogEnabled() {
+ // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter
+ // to figure out (and cache) which dumpers should be enabled or not.
+ // For the moment piggy back everything on the generic "memory" category.
+ bool enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
+
+ AutoLock lock(lock_);
+ if (enabled) {
+ dump_providers_enabled_.assign(dump_providers_registered_.begin(),
+ dump_providers_registered_.end());
+ } else {
+ dump_providers_enabled_.clear();
+ }
+ subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
+}
+
+void MemoryDumpManager::OnTraceLogDisabled() {
+ AutoLock lock(lock_);
+ dump_providers_enabled_.clear();
+ subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
new file mode 100644
index 0000000..fbc71d5
--- /dev/null
+++ b/base/trace_event/memory_dump_manager.h
@@ -0,0 +1,87 @@
+// 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_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
+
+#include <vector>
+
+#include "base/atomicops.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+#include "base/trace_event/trace_event.h"
+
+namespace base {
+namespace trace_event {
+
+class MemoryDumpProvider;
+
+// Captures the reason why a dump point is being requested. This is to allow
+// selective enabling of dump points, filtering and post-processing.
+enum class DumpPointType {
+ TASK_BEGIN, // Dumping memory at the beginning of a message-loop task.
+ TASK_END, // Dumping memory at the ending of a message-loop task.
+ PERIODIC_INTERVAL, // Dumping memory at periodic intervals.
+ EXPLICITLY_TRIGGERED, // Non maskable dump request.
+};
+
+// This is the interface exposed to the rest of the codebase to deal with
+// memory tracing. The main entry point for clients is represented by
+// RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
+class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver {
+ public:
+ static MemoryDumpManager* GetInstance();
+
+ // Invoked once per process to register the TraceLog observer.
+ void Initialize();
+
+ // MemoryDumpManager does NOT take memory ownership of |mdp|, which is
+ // expected to be a singleton.
+ void RegisterDumpProvider(MemoryDumpProvider* mdp);
+ void UnregisterDumpProvider(MemoryDumpProvider* mdp);
+
+ // Requests a memory dump. The dump might happen or not depending on the
+ // filters and categories specified when enabling tracing.
+ void RequestDumpPoint(DumpPointType type);
+
+ // TraceLog::EnabledStateObserver implementation.
+ void OnTraceLogEnabled() override;
+ void OnTraceLogDisabled() override;
+
+ private:
+ friend struct DefaultSingletonTraits<MemoryDumpManager>;
+ friend class MemoryDumpManagerTest;
+
+ static const char kTraceCategory[];
+
+ MemoryDumpManager();
+ virtual ~MemoryDumpManager();
+
+ // Tears down the singleton instance.
+ static void DeleteForTesting();
+
+ // Broadcasts the dump requests to the other processes.
+ void BroadcastDumpRequest();
+
+ // Creates a dump point for the current process and appends it to the trace.
+ void CreateLocalDumpPoint();
+
+ std::vector<MemoryDumpProvider*> dump_providers_registered_; // Not owned.
+ std::vector<MemoryDumpProvider*> dump_providers_enabled_; // Not owned.
+
+ // Protects from concurrent accesses to the |dump_providers_*|, e.g., tearing
+ // down logging while creating a dump point on another thread.
+ Lock lock_;
+
+ // Optimization to avoid attempting any dump point (i.e. to not walk an empty
+ // dump_providers_enabled_ list) when tracing is not enabled.
+ subtle::AtomicWord memory_tracing_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
new file mode 100644
index 0000000..b5337e9
--- /dev/null
+++ b/base/trace_event/memory_dump_manager_unittest.cc
@@ -0,0 +1,125 @@
+// 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/trace_event/memory_dump_manager.h"
+
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace base {
+namespace trace_event {
+
+class MemoryDumpManagerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ MemoryDumpManager::GetInstance()->Initialize();
+ mdm_ = MemoryDumpManager::GetInstance();
+ }
+
+ void TearDown() override {
+ MemoryDumpManager::DeleteForTesting();
+ TraceLog::DeleteForTesting();
+ mdm_ = NULL;
+ }
+
+ protected:
+ const char* const kTraceCategory = MemoryDumpManager::kTraceCategory;
+
+ void EnableTracing(const char* category) {
+ TraceLog::GetInstance()->SetEnabled(
+ CategoryFilter(category), TraceLog::RECORDING_MODE, TraceOptions());
+ }
+
+ void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); }
+
+ MemoryDumpManager* mdm_;
+
+ private:
+ // We want our singleton torn down after each test.
+ ShadowingAtExitManager at_exit_manager_;
+};
+
+class MockDumpProvider : public MemoryDumpProvider {
+ public:
+ MOCK_METHOD1(DumpInto, void(ProcessMemoryDump* pmd));
+};
+
+TEST_F(MemoryDumpManagerTest, SingleDumper) {
+ MockDumpProvider mdp;
+ mdm_->RegisterDumpProvider(&mdp);
+
+ // Check that the dumper is not called if the memory category is not enabled.
+ EnableTracing("foo-and-bar-but-not-memory");
+ EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ // Now repeat enabling the memory category and check that the dumper is
+ // invoked this time.
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(3);
+ for (int i = 0; i < 3; ++i)
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ mdm_->UnregisterDumpProvider(&mdp);
+
+ // Finally check the unregister logic (no calls to the mdp after unregister).
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ TraceLog::GetInstance()->SetDisabled();
+}
+
+TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileTracing) {
+ MockDumpProvider mdp;
+ mdm_->RegisterDumpProvider(&mdp);
+
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(1);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+ mdm_->UnregisterDumpProvider(&mdp);
+ EXPECT_CALL(mdp, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+
+ DisableTracing();
+}
+
+TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
+ MockDumpProvider mdp1;
+ MockDumpProvider mdp2;
+
+ // Enable only mdp1.
+ mdm_->RegisterDumpProvider(&mdp1);
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
+ EXPECT_CALL(mdp2, DumpInto(_)).Times(0);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ // Invert: enable mdp1 and disable mdp2.
+ mdm_->UnregisterDumpProvider(&mdp1);
+ mdm_->RegisterDumpProvider(&mdp2);
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
+ EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+
+ // Enable both mdp1 and mdp2.
+ mdm_->RegisterDumpProvider(&mdp1);
+ EnableTracing(kTraceCategory);
+ EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
+ EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
+ mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
+ DisableTracing();
+}
+
+} // namespace trace_Event
+} // namespace base
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h
new file mode 100644
index 0000000..18363c5
--- /dev/null
+++ b/base/trace_event/memory_dump_provider.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 BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
+#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+namespace base {
+namespace trace_event {
+
+class ProcessMemoryDump;
+
+// The contract interface that memory dump providers must implement.
+class BASE_EXPORT MemoryDumpProvider {
+ public:
+ // Called by the MemoryDumpManager when generating dump points.
+ virtual void DumpInto(ProcessMemoryDump* pmd) = 0;
+
+ protected:
+ MemoryDumpProvider() {}
+ virtual ~MemoryDumpProvider() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc
new file mode 100644
index 0000000..0a3e096
--- /dev/null
+++ b/base/trace_event/process_memory_dump.cc
@@ -0,0 +1,29 @@
+// 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/trace_event/process_memory_dump.h"
+
+#include "base/json/json_writer.h"
+#include "base/values.h"
+
+namespace base {
+namespace trace_event {
+
+ProcessMemoryDump::ProcessMemoryDump() {
+}
+
+ProcessMemoryDump::~ProcessMemoryDump() {
+}
+
+void ProcessMemoryDump::AppendAsTraceFormat(std::string* out) const {
+ // Build up the [dumper name] -> [serialized snapshot] JSON dictionary.
+ DictionaryValue dict;
+ std::string json_dict;
+ // TODO(primiano): this will append here the actual dumps from the dumpers.
+ base::JSONWriter::Write(&dict, &json_dict);
+ *out += json_dict;
+}
+
+} // namespace trace_event
+} // namespace base
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h
new file mode 100644
index 0000000..ae42987
--- /dev/null
+++ b/base/trace_event/process_memory_dump.h
@@ -0,0 +1,37 @@
+// 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_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
+#define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/trace_event/trace_event_impl.h"
+
+namespace base {
+namespace trace_event {
+
+// A container which holds the dumps produced by the MemoryDumpProvider(s)
+// for a specific process. ProcessMemoryDump is as a strongly typed container
+// which enforces the data model for each memory dump point.
+// At trace generation time (i.e. when AppendAsTraceFormat is called) the
+// ProcessMemoryDump will compose a key-value dictionary of the various dumps
+// obtained during at trace dump point time.
+class BASE_EXPORT ProcessMemoryDump : public ConvertableToTraceFormat {
+ public:
+ ProcessMemoryDump();
+
+ // ConvertableToTraceFormat implementation.
+ void AppendAsTraceFormat(std::string* out) const override;
+
+ private:
+ ~ProcessMemoryDump() override;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
+};
+
+} // namespace trace_event
+} // namespace base
+
+#endif // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index c8583d7..07a2afa 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -1603,12 +1603,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::TraceScopedTrackableObject;
-} // namespace debug
-} // namespace base
-
#endif /* BASE_TRACE_EVENT_TRACE_EVENT_H_ */
diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h
index 43a0f38..78d37d4 100644
--- a/base/trace_event/trace_event_argument.h
+++ b/base/trace_event/trace_event_argument.h
@@ -56,12 +56,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::TracedValue;
-} // namespace debug
-} // namespace base
-
#endif // BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 95cf06d..9ca0ddc 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -1908,11 +1908,13 @@
AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
DCHECK(name);
+ DCHECK(!timestamp.is_null());
if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
id ^= process_id_hash_;
- TimeTicks now = OffsetTimestamp(timestamp);
+ TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp);
+ TimeTicks now = OffsetNow();
TimeTicks thread_now = ThreadNow();
ThreadLocalEventBuffer* thread_local_event_buffer = NULL;
@@ -1985,8 +1987,8 @@
}
if (trace_event) {
- trace_event->Initialize(thread_id, now, thread_now, phase,
- category_group_enabled, name, id,
+ trace_event->Initialize(thread_id, offset_event_timestamp, thread_now,
+ phase, category_group_enabled, name, id,
num_args, arg_names, arg_types, arg_values,
convertable_values, flags);
@@ -2024,7 +2026,7 @@
EventCallback event_callback = reinterpret_cast<EventCallback>(
subtle::NoBarrier_Load(&event_callback_));
if (event_callback) {
- event_callback(now,
+ event_callback(offset_event_timestamp,
phase == TRACE_EVENT_PHASE_COMPLETE ?
TRACE_EVENT_PHASE_BEGIN : phase,
category_group_enabled, name, id,
@@ -2033,6 +2035,9 @@
}
}
+ // Use |now| instead of |offset_event_timestamp| to compute overhead, because
+ // event timestamp may be not the real time that we started to add the event
+ // (e.g. event with zero timestamp or that was generated some time ago).
if (thread_local_event_buffer)
thread_local_event_buffer->ReportOverhead(now, thread_now);
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
index 742f6b6..efa20c4 100644
--- a/base/trace_event/trace_event_impl.h
+++ b/base/trace_event/trace_event_impl.h
@@ -810,21 +810,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::CategoryFilter;
-using base::trace_event::ConvertableToTraceFormat;
-using base::trace_event::RECORD_UNTIL_FULL;
-using base::trace_event::RECORD_CONTINUOUSLY;
-using base::trace_event::RECORD_AS_MUCH_AS_POSSIBLE;
-using base::trace_event::TraceEventHandle;
-using base::trace_event::TraceLog;
-using base::trace_event::TraceLogStatus;
-using base::trace_event::TraceOptions;
-using base::trace_event::TraceResultBuffer;
-} // namespace debug
-} // namespace base
-
#endif // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
diff --git a/base/trace_event/trace_event_win.h b/base/trace_event/trace_event_win.h
index dcb5aac..4161361 100644
--- a/base/trace_event/trace_event_win.h
+++ b/base/trace_event/trace_event_win.h
@@ -122,18 +122,4 @@
} // namespace trace_event
} // namespace base
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace base {
-namespace debug {
-using base::trace_event::kChromeTraceProviderName;
-using base::trace_event::kTraceEventClass32;
-using base::trace_event::kTraceEventClass64;
-using base::trace_event::kTraceEventTypeBegin;
-using base::trace_event::kTraceEventTypeEnd;
-using base::trace_event::kTraceEventTypeInstant;
-using base::trace_event::TraceEventETWProvider;
-} // namespace debug
-} // namespace base
-
#endif // BASE_TRACE_EVENT_TRACE_EVENT_WIN_H_
diff --git a/build/all.gyp b/build/all.gyp
index 8556aa7..93cac8c 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -59,7 +59,6 @@
'../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
'../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/mojo/mojo_edk_tests.gyp:mojo_system_unittests',
@@ -230,6 +229,7 @@
['use_aura==1', {
'dependencies': [
'../ui/aura/aura.gyp:*',
+ '../ui/aura_extra/aura_extra.gyp:*',
],
}],
['use_ash==1', {
@@ -1191,13 +1191,6 @@
'../url/url.gyp:url_unittests',
],
},
- {
- 'target_name': 'webkit_builder_win',
- 'type': 'none',
- 'dependencies': [
- 'blink_tests',
- ],
- },
], # targets
'conditions': [
['branding=="Chrome"', {
@@ -1272,6 +1265,7 @@
'../skia/skia_tests.gyp:skia_unittests',
'../ui/app_list/app_list.gyp:*',
'../ui/aura/aura.gyp:*',
+ '../ui/aura_extra/aura_extra.gyp:*',
'../ui/base/ui_base_tests.gyp:ui_base_unittests',
'../ui/compositor/compositor.gyp:*',
'../ui/display/display.gyp:display_unittests',
@@ -1328,21 +1322,6 @@
],
},
], # targets
- }, {
- 'conditions': [
- ['OS=="linux"', {
- # TODO(thakis): Remove this once the linux gtk bot no longer references
- # it (probably after the first aura release on linux), see r249162
- 'targets': [
- {
- 'target_name': 'aura_builder',
- 'type': 'none',
- 'dependencies': [
- '../chrome/chrome.gyp:chrome',
- ],
- },
- ], # targets
- }]], # OS=="linux"
}], # "use_aura==1"
['test_isolation_mode != "noop"', {
'targets': [
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index 69c17f8..6de2723 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -336,6 +336,13 @@
types, builds, batteries, reports, errors, fail_step_lst, json_data = (
zip(*[DeviceInfo(dev, options) for dev in devices]))
+ # Write device info to file for buildbot info display.
+ with open('/home/chrome-bot/.adb_device_info', 'w') as f:
+ for device in json_data:
+ f.write('%s %s %s %.1fC %s%%\n' % (device['serial'], device['type'],
+ device['build'], float(device['battery']['temperature']) / 10,
+ device['battery']['level']))
+
err_msg = CheckForMissingDevices(options, devices) or []
unique_types = list(set(types))
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index e1858ce..a53bb56 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -43,36 +43,40 @@
# annotation: Annotation of the tests to include.
# exclude_annotation: The annotation of the tests to exclude.
I_TEST = collections.namedtuple('InstrumentationTest', [
- 'name', 'apk', 'apk_package', 'test_apk', 'test_data', 'host_driven_root',
- 'annotation', 'exclude_annotation', 'extra_flags'])
+ 'name', 'apk', 'apk_package', 'test_apk', 'test_data', 'isolate_file_path',
+ 'host_driven_root', 'annotation', 'exclude_annotation', 'extra_flags'])
def SrcPath(*path):
return os.path.join(CHROME_SRC_DIR, *path)
-def I(name, apk, apk_package, test_apk, test_data, host_driven_root=None,
- annotation=None, exclude_annotation=None, extra_flags=None):
- return I_TEST(name, apk, apk_package, test_apk, test_data, host_driven_root,
- annotation, exclude_annotation, extra_flags)
+def I(name, apk, apk_package, test_apk, test_data, isolate_file_path=None,
+ host_driven_root=None, annotation=None, exclude_annotation=None,
+ extra_flags=None):
+ return I_TEST(name, apk, apk_package, test_apk, test_data, isolate_file_path,
+ host_driven_root, annotation, exclude_annotation, extra_flags)
INSTRUMENTATION_TESTS = dict((suite.name, suite) for suite in [
I('ContentShell',
'ContentShell.apk',
'org.chromium.content_shell_apk',
'ContentShellTest',
- 'content:content/test/data/android/device_files'),
+ 'content:content/test/data/android/device_files',
+ isolate_file_path='content/content_shell_test_apk.isolate'),
I('ChromeShell',
'ChromeShell.apk',
'org.chromium.chrome.shell',
'ChromeShellTest',
'chrome:chrome/test/data/android/device_files',
- constants.CHROME_SHELL_HOST_DRIVEN_DIR),
+ isolate_file_path='chrome/chrome_shell_test_apk.isolate',
+ host_driven_root=constants.CHROME_SHELL_HOST_DRIVEN_DIR),
I('AndroidWebView',
'AndroidWebView.apk',
'org.chromium.android_webview.shell',
'AndroidWebViewTest',
- 'webview:android_webview/test/data/device_files'),
+ 'webview:android_webview/test/data/device_files',
+ isolate_file_path='android_webview/android_webview_test_apk.isolate'),
I('ChromeSyncShell',
'ChromeSyncShell.apk',
'org.chromium.chrome.browser.sync',
@@ -265,6 +269,8 @@
options.flakiness_server)
if options.coverage_bucket:
args.append('--coverage-dir=%s' % options.coverage_dir)
+ if test.isolate_file_path:
+ args.append('--isolate-file-path=%s' % test.isolate_file_path)
if test.host_driven_root:
args.append('--host-driven-root=%s' % test.host_driven_root)
if test.annotation:
@@ -340,13 +346,13 @@
unexpected_passes, unexpected_failures, unexpected_flakes = (
_ParseLayoutTestResults(full_results))
if unexpected_failures:
- _PrintDashboardLink('failed', unexpected_failures,
+ _PrintDashboardLink('failed', unexpected_failures.keys(),
max_tests=25)
elif unexpected_passes:
- _PrintDashboardLink('unexpected passes', unexpected_passes,
+ _PrintDashboardLink('unexpected passes', unexpected_passes.keys(),
max_tests=10)
if unexpected_flakes:
- _PrintDashboardLink('unexpected flakes', unexpected_flakes,
+ _PrintDashboardLink('unexpected flakes', unexpected_flakes.keys(),
max_tests=10)
if exit_code == 0 and (unexpected_passes or unexpected_flakes):
diff --git a/build/android/developer_recommended_flags.gypi b/build/android/developer_recommended_flags.gypi
index 3a3db0a..79c201d 100644
--- a/build/android/developer_recommended_flags.gypi
+++ b/build/android/developer_recommended_flags.gypi
@@ -38,6 +38,7 @@
# This comes with some caveats:
# Only works with a single device connected (it will print a warning if
# zero or multiple devices are attached).
+ # Device must be flashed with a user-debug unsigned Android build.
# Some actions are always run (i.e. ninja will never say "no work to do").
'gyp_managed_install%': 1,
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index 15fe73d..3738062 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -106,7 +106,8 @@
_MAX_MANIFEST_LINE_LEN = 72
-def CreateManifest(manifest_path, classpath, main_class=None):
+def CreateManifest(manifest_path, classpath, main_class=None,
+ manifest_entries=None):
"""Creates a manifest file with the given parameters.
This generates a manifest file that compiles with the spec found at
@@ -117,11 +118,16 @@
classpath: The JAR files that should be listed on the manifest file's
classpath.
main_class: If present, the class containing the main() function.
+ manifest_entries: If present, a list of (key, value) pairs to add to
+ the manifest.
"""
output = ['Manifest-Version: 1.0']
if main_class:
output.append('Main-Class: %s' % main_class)
+ if manifest_entries:
+ for k, v in manifest_entries:
+ output.append('%s: %s' % (k, v))
if classpath:
sanitized_paths = []
for path in classpath:
@@ -183,6 +189,10 @@
parser.add_option(
'--main-class',
help='The class containing the main method.')
+ parser.add_option(
+ '--manifest-entry',
+ action='append',
+ help='Key:value pairs to add to the .jar manifest.')
parser.add_option('--stamp', help='Path to touch on success.')
@@ -232,10 +242,13 @@
java_files)
if options.jar_path:
- if options.main_class:
+ if options.main_class or options.manifest_entry:
+ if options.manifest_entry:
+ entries = map(lambda e: e.split(":"), options.manifest_entry)
+ else:
+ entries = []
manifest_file = os.path.join(temp_dir, 'manifest')
- CreateManifest(manifest_file, classpath,
- options.main_class)
+ CreateManifest(manifest_file, classpath, options.main_class, entries)
else:
manifest_file = None
jar.JarDirectory(classes_dir,
diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py
index d6f9d32..1ed1877 100644
--- a/build/android/pylib/android_commands.py
+++ b/build/android/pylib/android_commands.py
@@ -694,8 +694,8 @@
assert os.path.exists(run_pie_dist_path), 'Please build run_pie'
# The PIE loader must be pushed manually (i.e. no PushIfNeeded) because
# PushIfNeeded requires md5sum and md5sum requires the wrapper as well.
- command = 'push %s %s' % (run_pie_dist_path, PIE_WRAPPER_PATH)
- assert _HasAdbPushSucceeded(self._adb.SendCommand(command))
+ adb_command = 'push %s %s' % (run_pie_dist_path, PIE_WRAPPER_PATH)
+ assert _HasAdbPushSucceeded(self._adb.SendCommand(adb_command))
self._pie_wrapper = PIE_WRAPPER_PATH
if self._pie_wrapper:
diff --git a/build/android/pylib/device/OWNERS b/build/android/pylib/device/OWNERS
index 65ce0dc..c35d7ac 100644
--- a/build/android/pylib/device/OWNERS
+++ b/build/android/pylib/device/OWNERS
@@ -1,3 +1,2 @@
-set noparent
jbudorick@chromium.org
perezju@chromium.org
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index 7d11671..f29f5c7 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -253,6 +253,20 @@
command, output, status=status, device_serial=self._device_serial)
return output
+ def IterShell(self, command, timeout):
+ """Runs a shell command and returns an iterator over its output lines.
+
+ Args:
+ command: A string with the shell command to run.
+ timeout: Timeout in seconds.
+
+ Yields:
+ The output of the command line by line.
+ """
+ args = ['shell', command]
+ return cmd_helper.IterCmdOutputLines(
+ self._BuildAdbCmd(args, self._device_serial), timeout=timeout)
+
def Ls(self, path, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
"""List the contents of a directory on the device.
@@ -286,26 +300,42 @@
device_serial=self._device_serial)
def Logcat(self, clear=False, dump=False, filter_spec=None,
- logcat_format=None, timeout=None):
- """Get an iterator over the logcat output.
+ logcat_format=None, timeout=None, retries=_DEFAULT_RETRIES):
+ """Get an iterable over the logcat output.
Args:
- filter_spec: (optional) Spec to filter the logcat.
- timeout: (optional) Timeout per try in seconds.
+ clear: If true, clear the logcat.
+ dump: If true, dump the current logcat contents.
+ filter_spec: If set, spec to filter the logcat.
+ logcat_format: If set, the format in which the logcat should be output.
+ Options include "brief", "process", "tag", "thread", "raw", "time",
+ "threadtime", and "long"
+ timeout: (optional) If set, timeout per try in seconds. If clear or dump
+ is set, defaults to _DEFAULT_TIMEOUT.
+ retries: (optional) If clear or dump is set, the number of retries to
+ attempt. Otherwise, does nothing.
Yields:
logcat output line by line.
"""
cmd = ['logcat']
+ use_iter = True
if clear:
cmd.append('-c')
+ use_iter = False
if dump:
cmd.append('-d')
+ use_iter = False
if logcat_format:
cmd.extend(['-v', logcat_format])
if filter_spec is not None:
cmd.append(filter_spec)
- return self._IterRunDeviceAdbCmd(cmd, timeout)
+
+ if use_iter:
+ return self._IterRunDeviceAdbCmd(cmd, timeout)
+ else:
+ timeout = timeout if timeout is not None else _DEFAULT_TIMEOUT
+ return self._RunDeviceAdbCmd(cmd, timeout, retries)
def Forward(self, local, remote, timeout=_DEFAULT_TIMEOUT,
retries=_DEFAULT_RETRIES):
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
index a1b4117..eba5e02 100644
--- a/build/android/pylib/device/device_utils.py
+++ b/build/android/pylib/device/device_utils.py
@@ -412,8 +412,8 @@
@decorators.WithTimeoutAndRetriesFromInstance()
def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None,
- as_root=False, single_line=False,
- timeout=None, retries=None):
+ as_root=False, single_line=False, timeout=None,
+ retries=None):
"""Run an ADB shell command.
The command to run |cmd| should be a sequence of program arguments or else
@@ -847,7 +847,7 @@
self.RunShellCommand(
['unzip', zip_on_device],
as_root=True,
- env={'PATH': '$PATH:%s' % install_commands.BIN_DIR},
+ env={'PATH': '%s:$PATH' % install_commands.BIN_DIR},
check_return=True)
finally:
if zip_proc.is_alive():
@@ -1297,23 +1297,6 @@
return host_path
@decorators.WithTimeoutAndRetriesFromInstance()
- def GetIOStats(self, timeout=None, retries=None):
- """Gets cumulative disk IO stats since boot for all processes.
-
- Args:
- timeout: timeout in seconds
- retries: number of retries
-
- Returns:
- A dict containing |num_reads|, |num_writes|, |read_ms|, and |write_ms|.
-
- Raises:
- CommandTimeoutError on timeout.
- DeviceUnreachableError on missing device.
- """
- return self.old_interface.GetIoStats()
-
- @decorators.WithTimeoutAndRetriesFromInstance()
def GetMemoryUsageForPid(self, pid, timeout=None, retries=None):
"""Gets the memory usage for the given PID.
@@ -1349,6 +1332,41 @@
"""Returns the device serial."""
return self.adb.GetDeviceSerial()
+ @decorators.WithTimeoutAndRetriesFromInstance()
+ def GetDevicePieWrapper(self, timeout=None, retries=None):
+ """Gets the absolute path to the run_pie wrapper on the device.
+
+ We have to build our device executables to be PIE, but they need to be able
+ to run on versions of android that don't support PIE (i.e. ICS and below).
+ To do so, we push a wrapper to the device that lets older android versions
+ run PIE executables. This method pushes that wrapper to the device if
+ necessary and returns the path to it.
+
+ This is exposed publicly to allow clients to write scripts using run_pie
+ (e.g. md5sum.CalculateDeviceMd5Sum).
+
+ Args:
+ timeout: timeout in seconds
+ retries: number of retries
+
+ Returns:
+ The path to the PIE wrapper on the device, or an empty string if the
+ device does not require the wrapper.
+ """
+ if 'run_pie' not in self._cache:
+ pie = ''
+ if (self.build_version_sdk <
+ constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN):
+ host_pie_path = os.path.join(constants.GetOutDirectory(), 'run_pie')
+ if not os.path.exists(host_pie_path):
+ raise device_errors.CommandFailedError('Please build run_pie')
+ pie = '%s/run_pie' % constants.TEST_EXECUTABLE_DIR
+ self.adb.Push(host_pie_path, pie)
+
+ self._cache['run_pie'] = pie
+
+ return self._cache['run_pie']
+
@classmethod
def parallel(cls, devices=None, async=False):
"""Creates a Parallelizer to operate over the provided list of devices.
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 6071fd5..8a25f25 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -656,6 +656,24 @@
self.device.RunShellCommand(cmd, check_return=False))
+class DeviceUtilsGetDevicePieWrapper(DeviceUtilsNewImplTest):
+
+ def testGetDevicePieWrapper_jb(self):
+ with self.assertCall(
+ self.call.device.build_version_sdk(),
+ constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN):
+ self.assertEqual('', self.device.GetDevicePieWrapper())
+
+ def testGetDevicePieWrapper_ics(self):
+ with self.assertCalls(
+ (self.call.device.build_version_sdk(),
+ constants.ANDROID_SDK_VERSION_CODES.ICE_CREAM_SANDWICH),
+ (mock.call.pylib.constants.GetOutDirectory(), '/foo/bar'),
+ (mock.call.os.path.exists(mock.ANY), True),
+ (self.call.adb.Push(mock.ANY, mock.ANY), '')):
+ self.assertNotEqual('', self.device.GetDevicePieWrapper())
+
+
@mock.patch('time.sleep', mock.Mock())
class DeviceUtilsKillAllTest(DeviceUtilsNewImplTest):
@@ -1045,7 +1063,7 @@
self.call.device.RunShellCommand(
['unzip', '/test/device/external_dir/tmp.zip'],
as_root=True,
- env={'PATH': '$PATH:/data/local/tmp/bin'},
+ env={'PATH': '/data/local/tmp/bin:$PATH'},
check_return=True),
(self.call.device.IsOnline(), True),
self.call.device.RunShellCommand(
@@ -1383,22 +1401,6 @@
self.device.TakeScreenshot('/test/host/screenshot.png')
-class DeviceUtilsGetIOStatsTest(DeviceUtilsOldImplTest):
-
- def testGetIOStats(self):
- with self.assertCalls(
- "adb -s 0123456789abcdef shell 'cat \"/proc/diskstats\" 2>/dev/null'",
- '179 0 mmcblk0 1 2 3 4 5 6 7 8 9 10 11\r\n'):
- self.assertEqual(
- {
- 'num_reads': 1,
- 'num_writes': 5,
- 'read_ms': 4,
- 'write_ms': 8,
- },
- self.device.GetIOStats())
-
-
class DeviceUtilsGetMemoryUsageForPidTest(DeviceUtilsOldImplTest):
def setUp(self):
diff --git a/build/android/pylib/gtest/setup.py b/build/android/pylib/gtest/setup.py
index 72c4b05..1b882ca 100644
--- a/build/android/pylib/gtest/setup.py
+++ b/build/android/pylib/gtest/setup.py
@@ -38,6 +38,7 @@
'media_unittests': 'media/media_unittests.isolate',
'net_unittests': 'net/net_unittests.isolate',
'sql_unittests': 'sql/sql_unittests.isolate',
+ 'sync_unit_tests': 'sync/sync_unit_tests.isolate',
'ui_base_unittests': 'ui/base/ui_base_tests.isolate',
'unit_tests': 'chrome/unit_tests.isolate',
'webkit_unit_tests':
diff --git a/build/android/pylib/instrumentation/instrumentation_parser.py b/build/android/pylib/instrumentation/instrumentation_parser.py
new file mode 100644
index 0000000..1859f14
--- /dev/null
+++ b/build/android/pylib/instrumentation/instrumentation_parser.py
@@ -0,0 +1,96 @@
+# 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.
+
+import logging
+import re
+
+# http://developer.android.com/reference/android/test/InstrumentationTestRunner.html
+STATUS_CODE_START = 1
+STATUS_CODE_OK = 0
+STATUS_CODE_ERROR = -1
+STATUS_CODE_FAILURE = -2
+
+# http://developer.android.com/reference/android/app/Activity.html
+RESULT_CODE_OK = -1
+RESULT_CODE_CANCELED = 0
+
+_INSTR_LINE_RE = re.compile('^\s*INSTRUMENTATION_([A-Z_]+): (.*)$')
+
+
+class InstrumentationParser(object):
+
+ def __init__(self, stream):
+ """An incremental parser for the output of Android instrumentation tests.
+
+ Example:
+
+ stream = adb.IterShell('am instrument -r ...')
+ parser = InstrumentationParser(stream)
+
+ for code, bundle in parser.IterStatus():
+ # do something with each instrumentation status
+ print 'status:', code, bundle
+
+ # do something with the final instrumentation result
+ code, bundle = parser.GetResult()
+ print 'result:', code, bundle
+
+ Args:
+ stream: a sequence of lines as produced by the raw output of an
+ instrumentation test (e.g. by |am instrument -r| or |uiautomator|).
+ """
+ self._stream = stream
+ self._code = None
+ self._bundle = None
+
+ def IterStatus(self):
+ """Iterate over statuses as they are produced by the instrumentation test.
+
+ Yields:
+ A tuple (code, bundle) for each instrumentation status found in the
+ output.
+ """
+ def join_bundle_values(bundle):
+ for key in bundle:
+ bundle[key] = '\n'.join(bundle[key])
+ return bundle
+
+ bundle = {'STATUS': {}, 'RESULT': {}}
+ header = None
+ key = None
+ for line in self._stream:
+ m = _INSTR_LINE_RE.match(line)
+ if m:
+ header, value = m.groups()
+ key = None
+ if header in ['STATUS', 'RESULT'] and '=' in value:
+ key, value = value.split('=', 1)
+ bundle[header][key] = [value]
+ elif header == 'STATUS_CODE':
+ yield int(value), join_bundle_values(bundle['STATUS'])
+ bundle['STATUS'] = {}
+ elif header == 'CODE':
+ self._code = int(value)
+ else:
+ logging.warning('Unknown INSTRUMENTATION_%s line: %s', header, value)
+ elif key is not None:
+ bundle[header][key].append(line)
+
+ self._bundle = join_bundle_values(bundle['RESULT'])
+
+ def GetResult(self):
+ """Return the final instrumentation result.
+
+ Returns:
+ A pair (code, bundle) with the final instrumentation result. The |code|
+ may be None if no instrumentation result was found in the output.
+
+ Raises:
+ AssertionError if attempting to get the instrumentation result before
+ exhausting |IterStatus| first.
+ """
+ assert self._bundle is not None, (
+ 'The IterStatus generator must be exhausted before reading the final'
+ ' instrumentation result.')
+ return self._code, self._bundle
diff --git a/build/android/pylib/instrumentation/instrumentation_parser_test.py b/build/android/pylib/instrumentation/instrumentation_parser_test.py
new file mode 100755
index 0000000..092d10f
--- /dev/null
+++ b/build/android/pylib/instrumentation/instrumentation_parser_test.py
@@ -0,0 +1,134 @@
+#!/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.
+
+
+"""Unit tests for instrumentation.InstrumentationParser."""
+
+import unittest
+
+from pylib.instrumentation import instrumentation_parser
+
+
+class InstrumentationParserTest(unittest.TestCase):
+
+ def testInstrumentationParser_nothing(self):
+ parser = instrumentation_parser.InstrumentationParser([''])
+ statuses = list(parser.IterStatus())
+ code, bundle = parser.GetResult()
+ self.assertEqual(None, code)
+ self.assertEqual({}, bundle)
+ self.assertEqual([], statuses)
+
+ def testInstrumentationParser_noMatchingStarts(self):
+ raw_output = [
+ '',
+ 'this.is.a.test.package.TestClass:.',
+ 'Test result for =.',
+ 'Time: 1.234',
+ '',
+ 'OK (1 test)',
+ ]
+
+ parser = instrumentation_parser.InstrumentationParser(raw_output)
+ statuses = list(parser.IterStatus())
+ code, bundle = parser.GetResult()
+ self.assertEqual(None, code)
+ self.assertEqual({}, bundle)
+ self.assertEqual([], statuses)
+
+ def testInstrumentationParser_resultAndCode(self):
+ raw_output = [
+ 'INSTRUMENTATION_RESULT: shortMsg=foo bar',
+ 'INSTRUMENTATION_RESULT: longMsg=a foo',
+ 'walked into',
+ 'a bar',
+ 'INSTRUMENTATION_CODE: -1',
+ ]
+
+ parser = instrumentation_parser.InstrumentationParser(raw_output)
+ statuses = list(parser.IterStatus())
+ code, bundle = parser.GetResult()
+ self.assertEqual(-1, code)
+ self.assertEqual(
+ {'shortMsg': 'foo bar', 'longMsg': 'a foo\nwalked into\na bar'}, bundle)
+ self.assertEqual([], statuses)
+
+ def testInstrumentationParser_oneStatus(self):
+ raw_output = [
+ 'INSTRUMENTATION_STATUS: foo=1',
+ 'INSTRUMENTATION_STATUS: bar=hello',
+ 'INSTRUMENTATION_STATUS: world=false',
+ 'INSTRUMENTATION_STATUS: class=this.is.a.test.package.TestClass',
+ 'INSTRUMENTATION_STATUS: test=testMethod',
+ 'INSTRUMENTATION_STATUS_CODE: 0',
+ ]
+
+ parser = instrumentation_parser.InstrumentationParser(raw_output)
+ statuses = list(parser.IterStatus())
+
+ expected = [
+ (0, {
+ 'foo': '1',
+ 'bar': 'hello',
+ 'world': 'false',
+ 'class': 'this.is.a.test.package.TestClass',
+ 'test': 'testMethod',
+ })
+ ]
+ self.assertEqual(expected, statuses)
+
+ def testInstrumentationParser_multiStatus(self):
+ raw_output = [
+ 'INSTRUMENTATION_STATUS: class=foo',
+ 'INSTRUMENTATION_STATUS: test=bar',
+ 'INSTRUMENTATION_STATUS_CODE: 1',
+ 'INSTRUMENTATION_STATUS: test_skipped=true',
+ 'INSTRUMENTATION_STATUS_CODE: 0',
+ 'INSTRUMENTATION_STATUS: class=hello',
+ 'INSTRUMENTATION_STATUS: test=world',
+ 'INSTRUMENTATION_STATUS: stack=',
+ 'foo/bar.py (27)',
+ 'hello/world.py (42)',
+ 'test/file.py (1)',
+ 'INSTRUMENTATION_STATUS_CODE: -1',
+ ]
+
+ parser = instrumentation_parser.InstrumentationParser(raw_output)
+ statuses = list(parser.IterStatus())
+
+ expected = [
+ (1, {'class': 'foo', 'test': 'bar',}),
+ (0, {'test_skipped': 'true'}),
+ (-1, {
+ 'class': 'hello',
+ 'test': 'world',
+ 'stack': '\nfoo/bar.py (27)\nhello/world.py (42)\ntest/file.py (1)',
+ }),
+ ]
+ self.assertEqual(expected, statuses)
+
+ def testInstrumentationParser_statusResultAndCode(self):
+ raw_output = [
+ 'INSTRUMENTATION_STATUS: class=foo',
+ 'INSTRUMENTATION_STATUS: test=bar',
+ 'INSTRUMENTATION_STATUS_CODE: 1',
+ 'INSTRUMENTATION_RESULT: result=hello',
+ 'world',
+ '',
+ '',
+ 'INSTRUMENTATION_CODE: 0',
+ ]
+
+ parser = instrumentation_parser.InstrumentationParser(raw_output)
+ statuses = list(parser.IterStatus())
+ code, bundle = parser.GetResult()
+
+ self.assertEqual(0, code)
+ self.assertEqual({'result': 'hello\nworld\n\n'}, bundle)
+ self.assertEqual([(1, {'class': 'foo', 'test': 'bar'})], statuses)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 0c4f566..45e6ee4 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -14,6 +14,7 @@
from pylib.base import base_test_result
from pylib.base import test_instance
from pylib.instrumentation import test_result
+from pylib.instrumentation import instrumentation_parser
from pylib.utils import apk_helper
from pylib.utils import md5sum
from pylib.utils import proguard
@@ -47,48 +48,10 @@
- the bundle dump as a dict mapping string keys to a list of
strings, one for each line.
"""
- INSTR_STATUS = 'INSTRUMENTATION_STATUS: '
- INSTR_STATUS_CODE = 'INSTRUMENTATION_STATUS_CODE: '
- INSTR_RESULT = 'INSTRUMENTATION_RESULT: '
- INSTR_CODE = 'INSTRUMENTATION_CODE: '
-
- last = None
- instr_code = None
- instr_result = []
- instr_statuses = []
- bundle = {}
- for line in raw_output:
- if line.startswith(INSTR_STATUS):
- instr_var = line[len(INSTR_STATUS):]
- if '=' in instr_var:
- k, v = instr_var.split('=', 1)
- bundle[k] = [v]
- last = INSTR_STATUS
- last_key = k
- else:
- logging.debug('Unknown "%s" line: %s' % (INSTR_STATUS, line))
-
- elif line.startswith(INSTR_STATUS_CODE):
- instr_status = line[len(INSTR_STATUS_CODE):]
- instr_statuses.append((int(instr_status), bundle))
- bundle = {}
- last = INSTR_STATUS_CODE
-
- elif line.startswith(INSTR_RESULT):
- instr_result.append(line[len(INSTR_RESULT):])
- last = INSTR_RESULT
-
- elif line.startswith(INSTR_CODE):
- instr_code = int(line[len(INSTR_CODE):])
- last = INSTR_CODE
-
- elif last == INSTR_STATUS:
- bundle[last_key].append(line)
-
- elif last == INSTR_RESULT:
- instr_result.append(line)
-
- return (instr_code, instr_result, instr_statuses)
+ parser = instrumentation_parser.InstrumentationParser(raw_output)
+ statuses = list(parser.IterStatus())
+ code, bundle = parser.GetResult()
+ return (code, bundle, statuses)
def GenerateTestResult(test_name, instr_statuses, start_ms, duration_ms):
@@ -106,22 +69,15 @@
Returns:
An InstrumentationTestResult object.
"""
- INSTR_STATUS_CODE_START = 1
- INSTR_STATUS_CODE_OK = 0
- INSTR_STATUS_CODE_ERROR = -1
- INSTR_STATUS_CODE_FAIL = -2
-
log = ''
result_type = base_test_result.ResultType.UNKNOWN
for status_code, bundle in instr_statuses:
- if status_code == INSTR_STATUS_CODE_START:
+ if status_code == instrumentation_parser.STATUS_CODE_START:
pass
- elif status_code == INSTR_STATUS_CODE_OK:
- bundle_test = '%s#%s' % (
- ''.join(bundle.get('class', [''])),
- ''.join(bundle.get('test', [''])))
- skipped = ''.join(bundle.get('test_skipped', ['']))
+ elif status_code == instrumentation_parser.STATUS_CODE_OK:
+ bundle_test = '%s#%s' % (bundle.get('class', ''), bundle.get('test', ''))
+ skipped = bundle.get('test_skipped', '')
if (test_name == bundle_test and
result_type == base_test_result.ResultType.UNKNOWN):
@@ -130,13 +86,13 @@
result_type = base_test_result.ResultType.SKIP
logging.info('Skipped ' + test_name)
else:
- if status_code not in (INSTR_STATUS_CODE_ERROR,
- INSTR_STATUS_CODE_FAIL):
+ if status_code not in (instrumentation_parser.STATUS_CODE_ERROR,
+ instrumentation_parser.STATUS_CODE_FAILURE):
logging.error('Unrecognized status code %d. Handling as an error.',
status_code)
result_type = base_test_result.ResultType.FAIL
if 'stack' in bundle:
- log = '\n'.join(bundle['stack'])
+ log = bundle['stack']
return test_result.InstrumentationTestResult(
test_name, result_type, start_ms, duration_ms, log=log)
@@ -466,24 +422,22 @@
@staticmethod
def GenerateMultiTestResult(errors, statuses):
- INSTR_STATUS_CODE_START = 1
results = []
skip_counter = 1
for status_code, bundle in statuses:
- if status_code != INSTR_STATUS_CODE_START:
+ if status_code != instrumentation_parser.STATUS_CODE_START:
# TODO(rnephew): Make skipped tests still output test name. This is only
# there to give skipped tests a unique name so they are counted
if 'test_skipped' in bundle:
test_name = str(skip_counter)
skip_counter += 1
else:
- test_name = '%s#%s' % (
- ''.join(bundle.get('class', [''])),
- ''.join(bundle.get('test', [''])))
+ test_name = '%s#%s' % (bundle.get('class', ''),
+ bundle.get('test', ''))
results.append(
GenerateTestResult(test_name, [(status_code, bundle)], 0, 0))
- for error in errors:
+ for error in errors.itervalues():
if _NATIVE_CRASH_RE.search(error):
results.append(
base_test_result.BaseTestResult(
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance_test.py b/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
index 3bf3939..693f175 100755
--- a/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
@@ -27,115 +27,6 @@
options = mock.Mock()
options.tool = ''
- def testParseAmInstrumentRawOutput_nothing(self):
- code, result, statuses = (
- instrumentation_test_instance.ParseAmInstrumentRawOutput(['']))
- self.assertEqual(None, code)
- self.assertEqual([], result)
- self.assertEqual([], statuses)
-
- def testParseAmInstrumentRawOutput_noMatchingStarts(self):
- raw_output = [
- '',
- 'this.is.a.test.package.TestClass:.',
- 'Test result for =.',
- 'Time: 1.234',
- '',
- 'OK (1 test)',
- ]
-
- code, result, statuses = (
- instrumentation_test_instance.ParseAmInstrumentRawOutput(raw_output))
- self.assertEqual(None, code)
- self.assertEqual([], result)
- self.assertEqual([], statuses)
-
- def testParseAmInstrumentRawOutput_resultAndCode(self):
- raw_output = [
- 'INSTRUMENTATION_RESULT: foo',
- 'bar',
- 'INSTRUMENTATION_CODE: -1',
- ]
-
- code, result, _ = (
- instrumentation_test_instance.ParseAmInstrumentRawOutput(raw_output))
- self.assertEqual(-1, code)
- self.assertEqual(['foo', 'bar'], result)
-
- def testParseAmInstrumentRawOutput_oneStatus(self):
- raw_output = [
- 'INSTRUMENTATION_STATUS: foo=1',
- 'INSTRUMENTATION_STATUS: bar=hello',
- 'INSTRUMENTATION_STATUS: world=false',
- 'INSTRUMENTATION_STATUS: class=this.is.a.test.package.TestClass',
- 'INSTRUMENTATION_STATUS: test=testMethod',
- 'INSTRUMENTATION_STATUS_CODE: 0',
- ]
-
- _, _, statuses = (
- instrumentation_test_instance.ParseAmInstrumentRawOutput(raw_output))
-
- expected = [
- (0, {
- 'foo': ['1'],
- 'bar': ['hello'],
- 'world': ['false'],
- 'class': ['this.is.a.test.package.TestClass'],
- 'test': ['testMethod'],
- })
- ]
- self.assertEqual(expected, statuses)
-
- def testParseAmInstrumentRawOutput_multiStatus(self):
- raw_output = [
- 'INSTRUMENTATION_STATUS: class=foo',
- 'INSTRUMENTATION_STATUS: test=bar',
- 'INSTRUMENTATION_STATUS_CODE: 1',
- 'INSTRUMENTATION_STATUS: test_skipped=true',
- 'INSTRUMENTATION_STATUS_CODE: 0',
- 'INSTRUMENTATION_STATUS: class=hello',
- 'INSTRUMENTATION_STATUS: test=world',
- 'INSTRUMENTATION_STATUS: stack=',
- 'foo/bar.py (27)',
- 'hello/world.py (42)',
- 'test/file.py (1)',
- 'INSTRUMENTATION_STATUS_CODE: -1',
- ]
-
- _, _, statuses = (
- instrumentation_test_instance.ParseAmInstrumentRawOutput(raw_output))
-
- expected = [
- (1, {'class': ['foo'], 'test': ['bar'],}),
- (0, {'test_skipped': ['true']}),
- (-1, {
- 'class': ['hello'],
- 'test': ['world'],
- 'stack': ['', 'foo/bar.py (27)', 'hello/world.py (42)',
- 'test/file.py (1)'],
- }),
- ]
- self.assertEqual(expected, statuses)
-
- def testParseAmInstrumentRawOutput_statusResultAndCode(self):
- raw_output = [
- 'INSTRUMENTATION_STATUS: class=foo',
- 'INSTRUMENTATION_STATUS: test=bar',
- 'INSTRUMENTATION_STATUS_CODE: 1',
- 'INSTRUMENTATION_RESULT: hello',
- 'world',
- '',
- '',
- 'INSTRUMENTATION_CODE: 0',
- ]
-
- code, result, statuses = (
- instrumentation_test_instance.ParseAmInstrumentRawOutput(raw_output))
-
- self.assertEqual(0, code)
- self.assertEqual(['hello', 'world', '', ''], result)
- self.assertEqual([(1, {'class': ['foo'], 'test': ['bar']})], statuses)
-
def testGenerateTestResult_noStatus(self):
result = instrumentation_test_instance.GenerateTestResult(
'test.package.TestClass#testMethod', [], 0, 1000)
@@ -147,12 +38,12 @@
def testGenerateTestResult_testPassed(self):
statuses = [
(1, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
(0, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
]
result = instrumentation_test_instance.GenerateTestResult(
@@ -162,15 +53,15 @@
def testGenerateTestResult_testSkipped_first(self):
statuses = [
(0, {
- 'test_skipped': ['true'],
+ 'test_skipped': 'true',
}),
(1, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
(0, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
]
result = instrumentation_test_instance.GenerateTestResult(
@@ -180,15 +71,15 @@
def testGenerateTestResult_testSkipped_last(self):
statuses = [
(1, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
(0, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
(0, {
- 'test_skipped': ['true'],
+ 'test_skipped': 'true',
}),
]
result = instrumentation_test_instance.GenerateTestResult(
@@ -198,15 +89,15 @@
def testGenerateTestResult_testSkipped_false(self):
statuses = [
(0, {
- 'test_skipped': ['false'],
+ 'test_skipped': 'false',
}),
(1, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
(0, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
]
result = instrumentation_test_instance.GenerateTestResult(
@@ -216,12 +107,12 @@
def testGenerateTestResult_testFailed(self):
statuses = [
(1, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
(-2, {
- 'class': ['test.package.TestClass'],
- 'test': ['testMethod'],
+ 'class': 'test.package.TestClass',
+ 'test': 'testMethod',
}),
]
result = instrumentation_test_instance.GenerateTestResult(
diff --git a/build/android/pylib/instrumentation/setup.py b/build/android/pylib/instrumentation/setup.py
index 8dacc3d..bdde80d 100644
--- a/build/android/pylib/instrumentation/setup.py
+++ b/build/android/pylib/instrumentation/setup.py
@@ -89,15 +89,15 @@
if test_options.test_data:
device_utils.DeviceUtils.parallel(devices).pMap(
_PushDataDeps, test_options)
- else:
+
+ if test_options.isolate_file_path:
base_setup.GenerateDepsDirUsingIsolate(test_options.test_apk,
test_options.isolate_file_path,
ISOLATE_FILE_PATHS,
DEPS_EXCLUSION_LIST)
def push_data_deps_to_device_dir(device):
- device_dir = os.path.join(device.GetExternalStoragePath(),
- DEVICE_DATA_DIR)
- base_setup.PushDataDeps(device, device_dir, test_options)
+ base_setup.PushDataDeps(device, device.GetExternalStoragePath(),
+ test_options)
device_utils.DeviceUtils.parallel(devices).pMap(
push_data_deps_to_device_dir)
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py
index fb9557e..5f095a5 100644
--- a/build/android/pylib/instrumentation/test_runner.py
+++ b/build/android/pylib/instrumentation/test_runner.py
@@ -318,7 +318,7 @@
extras['class'] = test
return self.device.StartInstrumentation(
'%s/%s' % (self.test_pkg.GetPackageName(), self.options.test_runner),
- raw=True, extras=extras, timeout=timeout, retries=0)
+ raw=True, extras=extras, timeout=timeout, retries=3)
def _GenerateTestResult(self, test, instr_statuses, start_ms, duration_ms):
return instrumentation_test_instance.GenerateTestResult(
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py
index 1f1686b..8c322cb 100644
--- a/build/android/pylib/local/device/local_device_test_run.py
+++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -61,7 +61,7 @@
tests = [t for t in tests if self._GetTestName(t) not in results_names]
tries += 1
- all_unknown_test_names = set(self._GetTestName(t) for f in tests)
+ all_unknown_test_names = set(self._GetTestName(t) for t in tests)
all_failed_test_names = set(all_fail_results.iterkeys())
unknown_tests = all_unknown_test_names.difference(all_failed_test_names)
diff --git a/build/android/pylib/perf/test_runner.py b/build/android/pylib/perf/test_runner.py
index b7fadd2..d9227a5 100644
--- a/build/android/pylib/perf/test_runner.py
+++ b/build/android/pylib/perf/test_runner.py
@@ -69,9 +69,10 @@
def OutputJsonList(json_input, json_output):
with file(json_input, 'r') as i:
all_steps = json.load(i)
- step_names = all_steps['steps'].keys()
+ step_values = [{'test': k, 'device_affinity': v['device_affinity']}
+ for k, v in all_steps['steps'].iteritems()]
with file(json_output, 'w') as o:
- o.write(json.dumps(step_names))
+ o.write(json.dumps(step_values))
return 0
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py
index cc39112..2561180 100644
--- a/build/android/pylib/remote/device/remote_device_environment.py
+++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -15,12 +15,15 @@
from pylib.base import environment
from pylib.remote.device import appurify_sanitized
from pylib.remote.device import remote_device_helper
+from pylib.utils import timeout_retry
+from pylib.utils import reraiser_thread
class RemoteDeviceEnvironment(environment.Environment):
"""An environment for running on remote devices."""
_ENV_KEY = 'env'
_DEVICE_KEY = 'device'
+ _DEFAULT_RETRIES = 0
def __init__(self, args, error_func):
"""Constructor.
@@ -74,6 +77,7 @@
self._remote_device_minimum_os = device_json.get(
'remote_device_minimum_os', None)
self._remote_device_os = device_json.get('remote_device_os', None)
+ self._remote_device_timeout = device_json.get('remote_device_timeout', None)
self._results_path = device_json.get('results_path', None)
self._runner_package = device_json.get('runner_package', None)
self._runner_type = device_json.get('runner_type', None)
@@ -110,6 +114,9 @@
'remote_device_minimum_os')
self._remote_device_os = command_line_override(
self._remote_device_os, args.remote_device_os, 'remote_device_os')
+ self._remote_device_timeout = command_line_override(
+ self._remote_device_timeout, args.remote_device_timeout,
+ 'remote_device_timeout')
self._results_path = command_line_override(
self._results_path, args.results_path, 'results_path')
self._runner_package = command_line_override(
@@ -158,6 +165,7 @@
logging.info('Remote device OS: %s', self._remote_device_os)
logging.info('Remote device OEM: %s', self._device_oem)
logging.info('Remote device type: %s', self._device_type)
+ logging.info('Remote device timout: %s', self._remote_device_timeout)
logging.info('Results Path: %s', self._results_path)
logging.info('Runner package: %s', self._runner_package)
logging.info('Runner type: %s', self._runner_type)
@@ -177,7 +185,7 @@
os.environ['APPURIFY_API_PORT'] = self._api_port
self._GetAccessToken()
if self._trigger:
- self._device = self._SelectDevice()
+ self._SelectDevice()
def TearDown(self):
"""Teardown the test environment."""
@@ -228,14 +236,20 @@
'Unable to revoke access token.')
def _SelectDevice(self):
- """Select which device to use."""
+ if self._remote_device_timeout:
+ try:
+ timeout_retry.Run(self._FindDeviceWithTimeout,
+ self._remote_device_timeout, self._DEFAULT_RETRIES)
+ except reraiser_thread.TimeoutError:
+ self._NoDeviceFound()
+ else:
+ if not self._FindDevice():
+ self._NoDeviceFound()
+
+ def _FindDevice(self):
+ """Find which device to use."""
logging.info('Finding device to run tests on.')
- with appurify_sanitized.SanitizeLogging(self._verbose_count,
- logging.WARNING):
- dev_list_res = appurify_sanitized.api.devices_list(self._access_token)
- remote_device_helper.TestHttpResponse(dev_list_res,
- 'Unable to generate access token.')
- device_list = dev_list_res.json()['response']
+ device_list = self._GetDeviceList()
random.shuffle(device_list)
for device in device_list:
if device['os_name'] != self._device_type:
@@ -251,12 +265,16 @@
and distutils.version.LooseVersion(device['os_version'])
< distutils.version.LooseVersion(self._remote_device_minimum_os)):
continue
- if ((self._remote_device and self._remote_device_os)
- or device['available_devices_count']):
+ if device['has_available_device']:
logging.info('Found device: %s %s',
device['name'], device['os_version'])
- return device
- self._NoDeviceFound(device_list)
+ self._device = device
+ return True
+ return False
+
+ def _FindDeviceWithTimeout(self):
+ """Find which device to use with timeout."""
+ timeout_retry.WaitFor(self._FindDevice, wait_period=1)
def _PrintAvailableDevices(self, device_list):
def compare_devices(a,b):
@@ -267,12 +285,23 @@
return 0
logging.critical('Available %s Devices:', self._device_type)
+ logging.critical(' %s %s %s', 'OS'.ljust(7),
+ 'Device Name'.ljust(20), '# Available')
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', d['os_version'].ljust(7), d['name'])
+ logging.critical(' %s %s %s', d['os_version'].ljust(7),
+ d['name'].ljust(20), d['available_devices_count'])
- def _NoDeviceFound(self, device_list):
- self._PrintAvailableDevices(device_list)
+ def _GetDeviceList(self):
+ with appurify_sanitized.SanitizeLogging(self._verbose_count,
+ logging.WARNING):
+ dev_list_res = appurify_sanitized.api.devices_list(self._access_token)
+ remote_device_helper.TestHttpResponse(dev_list_res,
+ 'Unable to generate access token.')
+ return dev_list_res.json()['response']
+
+ def _NoDeviceFound(self):
+ self._PrintAvailableDevices(self._GetDeviceList())
raise remote_device_helper.RemoteDeviceError('No device found.')
@property
diff --git a/build/android/pylib/remote/device/remote_device_test_run.py b/build/android/pylib/remote/device/remote_device_test_run.py
index 91701b0..43a7399 100644
--- a/build/android/pylib/remote/device/remote_device_test_run.py
+++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -170,12 +170,12 @@
"""
if results_path:
logging.info('Downloading results to %s.' % results_path)
- if not os.path.exists(os.path.basename(results_path)):
- os.makedirs(os.path.basename(results_path))
- with appurify_sanitized.SanitizeLogging(self._env.verbose_count,
- logging.WARNING):
- appurify_sanitized.utils.wget(self._results['results']['url'],
- results_path)
+ if not os.path.exists(os.path.dirname(results_path)):
+ os.makedirs(os.path.dirname(results_path))
+ with appurify_sanitized.SanitizeLogging(self._env.verbose_count,
+ logging.WARNING):
+ appurify_sanitized.utils.wget(self._results['results']['url'],
+ results_path)
def _GetTestStatus(self, test_run_id):
"""Checks the state of the test, and sets self._results
diff --git a/build/android/pylib/utils/md5sum.py b/build/android/pylib/utils/md5sum.py
index 4d0d703..da3cd15 100644
--- a/build/android/pylib/utils/md5sum.py
+++ b/build/android/pylib/utils/md5sum.py
@@ -19,7 +19,7 @@
MD5SUM_DEVICE_SCRIPT_FORMAT = (
'test -f {path} -o -d {path} '
- '&& LD_LIBRARY_PATH={md5sum_lib} {md5sum_bin} {path}')
+ '&& LD_LIBRARY_PATH={md5sum_lib} {device_pie_wrapper} {md5sum_bin} {path}')
def CalculateHostMd5Sums(paths):
@@ -56,12 +56,15 @@
MD5SUM_DEVICE_LIB_PATH)
out = []
+
with tempfile.NamedTemporaryFile() as md5sum_script_file:
with device_temp_file.DeviceTempFile(
device.adb) as md5sum_device_script_file:
+ device_pie_wrapper = device.GetDevicePieWrapper()
md5sum_script = (
MD5SUM_DEVICE_SCRIPT_FORMAT.format(
path=p, md5sum_lib=MD5SUM_DEVICE_LIB_PATH,
+ device_pie_wrapper=device_pie_wrapper,
md5sum_bin=MD5SUM_DEVICE_BIN_PATH)
for p in paths)
md5sum_script_file.write('; '.join(md5sum_script))
@@ -69,5 +72,5 @@
device.adb.Push(md5sum_script_file.name, md5sum_device_script_file.name)
out = device.RunShellCommand(['sh', md5sum_device_script_file.name])
- return [HashAndPath(*l.split(None, 1)) for l in out]
+ return [HashAndPath(*l.split(None, 1)) for l in out if l]
diff --git a/build/android/pylib/utils/mock_calls.py b/build/android/pylib/utils/mock_calls.py
index fab9f2b..3052b0d 100644
--- a/build/android/pylib/utils/mock_calls.py
+++ b/build/android/pylib/utils/mock_calls.py
@@ -110,7 +110,12 @@
if call.name.startswith('self.'):
target = self.call_target(call.parent)
_, attribute = call.name.rsplit('.', 1)
- return mock.patch.object(target, attribute, **kwargs)
+ if (hasattr(type(target), attribute)
+ and isinstance(getattr(type(target), attribute), property)):
+ return mock.patch.object(
+ type(target), attribute, new_callable=mock.PropertyMock, **kwargs)
+ else:
+ return mock.patch.object(target, attribute, **kwargs)
else:
return mock.patch(call.name, **kwargs)
diff --git a/build/android/pylib/utils/mock_calls_test.py b/build/android/pylib/utils/mock_calls_test.py
index 1b474af..4dbafd4 100755
--- a/build/android/pylib/utils/mock_calls_test.py
+++ b/build/android/pylib/utils/mock_calls_test.py
@@ -38,6 +38,11 @@
def Reboot(self):
logging.debug('(device %s) rebooted!', self)
+ @property
+ def build_version_sdk(self):
+ logging.debug('(device %s) getting build_version_sdk', self)
+ return constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP
+
class TestCaseWithAssertCallsTest(mock_calls.TestCase):
def setUp(self):
@@ -91,6 +96,17 @@
with self.assertRaises(ValueError):
self.adb.Shell('echo hello')
+ def testPatchCall_property(self):
+ self.assertEquals(constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP,
+ self.adb.build_version_sdk)
+ with self.patch_call(
+ self.call.adb.build_version_sdk,
+ return_value=constants.ANDROID_SDK_VERSION_CODES.KITKAT):
+ self.assertEquals(constants.ANDROID_SDK_VERSION_CODES.KITKAT,
+ self.adb.build_version_sdk)
+ self.assertEquals(constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP,
+ self.adb.build_version_sdk)
+
def testAssertCalls_succeeds_simple(self):
self.assertEquals(42, self.get_answer())
with self.assertCall(self.call.get_answer(), 123):
diff --git a/build/android/setup.gyp b/build/android/setup.gyp
index b3c3422..7dce19d 100644
--- a/build/android/setup.gyp
+++ b/build/android/setup.gyp
@@ -16,7 +16,7 @@
{
'destination': '<(SHARED_LIB_DIR)/',
'files': [
- '<(android_libcpp_libs_dir)/libc++_shared.so',
+ '<(android_stlport_libs_dir)/libstlport_shared.so',
],
},
],
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index cc7bbee..f79e13e 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -149,6 +149,8 @@
group.add_argument('--remote-device-file',
help=('File with JSON to select remote device. '
'Overrides all other flags.'))
+ group.add_argument('--remote-device-timeout', type=int,
+ help='Times to retry finding remote device')
device_os_group = group.add_mutually_exclusive_group()
device_os_group.add_argument('--remote-device-minimum-os',
@@ -529,7 +531,7 @@
help='APK to run tests on.')
group.add_argument(
'--minutes', default=5, type=int,
- help='Number of minutes to run uirobot test [default: %default].')
+ help='Number of minutes to run uirobot test [default: %(default)s].')
AddCommonOptions(parser)
AddDeviceOptions(parser)
diff --git a/build/common.gypi b/build/common.gypi
index 153a500..3a071c8 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -391,9 +391,12 @@
# See https://sites.google.com/a/chromium.org/dev/developers/testing/addresssanitizer
'asan%': 0,
'asan_blacklist%': '<(PRODUCT_DIR)/../../tools/memory/asan/blacklist.txt',
- # Enable coverage gathering instrumentation in ASan. This flag also
- # controls coverage granularity (1 for function-level coverage, 2 for
- # block-level coverage).
+ # Enable coverage gathering instrumentation in sanitizer tools. This flag
+ # also controls coverage granularity (1 for function-level coverage, 2
+ # for block-level coverage).
+ 'sanitizer_coverage%': 0,
+ # Deprecated, only works if |sanitizer_coverage| isn't set.
+ # TODO(glider): remove this flag.
'asan_coverage%': 0,
# Enable intra-object-overflow detection in ASan (experimental).
'asan_field_padding%': 0,
@@ -1119,6 +1122,7 @@
'asan%': '<(asan)',
'asan_blacklist%': '<(asan_blacklist)',
'asan_coverage%': '<(asan_coverage)',
+ 'sanitizer_coverage%': '<(sanitizer_coverage)',
'asan_field_padding%': '<(asan_field_padding)',
'use_sanitizer_options%': '<(use_sanitizer_options)',
'syzyasan%': '<(syzyasan)',
@@ -1668,7 +1672,7 @@
'android_ndk_root%': '<(android_ndk_root)',
'android_sdk_root%': '<(android_sdk_root)',
'android_sdk_version%': '<(android_sdk_version)',
- 'android_libcpp_root': '<(android_ndk_root)/sources/cxx-stl/llvm-libc++',
+ 'android_stlport_root': '<(android_ndk_root)/sources/cxx-stl/stlport',
'host_os%': '<(host_os)',
'android_sdk%': '<(android_sdk_root)/platforms/android-<(android_sdk_version)',
@@ -1745,10 +1749,9 @@
'android_sdk%': '<(android_sdk)',
'android_sdk_jar%': '<(android_sdk)/android.jar',
- 'android_libcpp_root': '<(android_libcpp_root)',
- 'android_libcpp_include': '<(android_libcpp_root)/libcxx/include',
- 'android_libcpp_libs_dir': '<(android_libcpp_root)/libs/<(android_app_abi)',
-
+ 'android_stlport_root': '<(android_stlport_root)',
+ 'android_stlport_include': '<(android_stlport_root)/stlport',
+ 'android_stlport_libs_dir': '<(android_stlport_root)/libs/<(android_app_abi)',
'host_os%': '<(host_os)',
# Location of the "objcopy" binary, used by both gyp and scripts.
@@ -2066,10 +2069,10 @@
},
'grit_defines': [
'-t', 'ios',
- # iOS uses a whitelist to filter resources.
- '-w', '<(DEPTH)/build/ios/grit_whitelist.txt',
'--no-output-all-resource-defines',
],
+ # iOS uses a whitelist to filter resources.
+ 'grit_whitelist%': '<(DEPTH)/build/ios/grit_whitelist.txt',
# Enable host builds when generating with ninja-ios.
'conditions': [
@@ -2077,12 +2080,10 @@
'host_os%': "mac",
}],
- # TODO(sdefresne): Remove the target_subarch check once Apple has
- # upstreamed the support for "arm64". http://crbug.com/341453
# TODO(eugenebut): Remove enable_coverage check once
# libclang_rt.profile_ios.a is bundled with Chromium's clang.
# http://crbug.com/450379
- ['target_subarch!="arm32" or enable_coverage or "<(GENERATOR)"=="xcode"', {
+ ['enable_coverage or "<(GENERATOR)"=="xcode"', {
'clang_xcode%': 1,
}],
],
@@ -2688,74 +2689,47 @@
'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO',
},
'conditions': [
- ['clang==1 and asan==0 and msan==0 and tsan==0 and ubsan_vptr==0', {
- # Clang creates chubby debug information, which makes linking very
- # slow. For now, don't create debug information with clang. See
- # http://crbug.com/70000
- 'conditions': [
- ['OS=="linux"', {
- 'variables': {
- 'debug_extra_cflags': '-g0',
- },
- }],
- # Android builds symbols on release by default, disable them.
- ['OS=="android"', {
- 'variables': {
- 'debug_extra_cflags': '-g0',
- 'release_extra_cflags': '-g0',
- },
- }],
- ],
- }, { # else clang!=1
- 'conditions': [
- ['OS=="win" and fastbuild==2', {
- # Completely disable debug information.
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'GenerateDebugInformation': 'false',
- },
- 'VCCLCompilerTool': {
- 'DebugInformationFormat': '0',
- },
- },
- }],
- ['OS=="win" and fastbuild==1', {
- 'msvs_settings': {
- 'VCLinkerTool': {
- # This tells the linker to generate .pdbs, so that
- # we can get meaningful stack traces.
- 'GenerateDebugInformation': 'true',
- },
- 'VCCLCompilerTool': {
- # No debug info to be generated by compiler.
- 'DebugInformationFormat': '0',
- },
- },
- }],
- ['OS=="linux" and fastbuild==2', {
- 'variables': {
- 'debug_extra_cflags': '-g0',
- },
- }],
- ['OS=="linux" and fastbuild==1', {
- 'variables': {
- 'debug_extra_cflags': '-g1',
- },
- }],
- ['OS=="android" and fastbuild==2', {
- 'variables': {
- 'debug_extra_cflags': '-g0',
- 'release_extra_cflags': '-g0',
- },
- }],
- ['OS=="android" and fastbuild==1', {
- 'variables': {
- 'debug_extra_cflags': '-g1',
- 'release_extra_cflags': '-g1',
- },
- }],
- ],
- }], # clang!=1
+ ['OS=="win" and fastbuild==2', {
+ # Completely disable debug information.
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'false',
+ },
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '0',
+ },
+ },
+ }],
+ ['OS=="win" and fastbuild==1', {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ # This tells the linker to generate .pdbs, so that
+ # we can get meaningful stack traces.
+ 'GenerateDebugInformation': 'true',
+ },
+ 'VCCLCompilerTool': {
+ # No debug info to be generated by compiler.
+ 'DebugInformationFormat': '0',
+ },
+ },
+ }],
+ ['(OS=="android" or OS=="linux") and fastbuild==2', {
+ 'variables': { 'debug_extra_cflags': '-g0', },
+ }],
+ ['(OS=="android" or OS=="linux") and fastbuild==1', {
+ # TODO(thakis): Change this to -g1 once http://crbug.com/456947 is
+ # fixed.
+ 'variables': { 'debug_extra_cflags': '-g0', },
+ }],
+ # Android builds symbols on release by default, disable them.
+ ['OS=="android" and fastbuild==2', {
+ 'variables': { 'release_extra_cflags': '-g0', },
+ }],
+ ['OS=="android" and fastbuild==1', {
+ # TODO(thakis): Change this to -g1 once http://crbug.com/456947 is
+ # fixed.
+ 'variables': { 'release_extra_cflags': '-g0', },
+ }],
],
}], # fastbuild!=0
['dont_embed_build_metadata==1', {
@@ -3544,7 +3518,7 @@
},
}],
# TODO(thakis): Enable this everywhere. http://crbug.com/371125
- ['(OS=="linux" or OS=="android") and asan==0 and msan==0 and tsan==0 and ubsan==0 and ubsan_vptr==0 and use_ozone!=1', {
+ ['(OS=="linux" or OS=="android") and asan==0 and msan==0 and tsan==0 and ubsan==0 and ubsan_vptr==0', {
'target_defaults': {
'ldflags': [
'-Wl,-z,defs',
@@ -4047,6 +4021,13 @@
'-fstack-protector', # stack protector is always enabled on arm64.
],
}],
+ # TODO: Remove webview test once webview fully compiles from
+ # Chromium. crbug.com/440793
+ ['OS=="android" and android_webview_build==0', {
+ 'ldflags': [
+ '-fuse-ld=gold',
+ ],
+ }],
],
}],
],
@@ -4272,12 +4253,27 @@
}],
],
}],
- ['asan_coverage!=0', {
+ ['asan_coverage!=0 and sanitizer_coverage==0', {
'target_conditions': [
['_toolset=="target"', {
'cflags': [
'-fsanitize-coverage=<(asan_coverage)',
],
+ 'defines': [
+ 'SANITIZER_COVERAGE',
+ ],
+ }],
+ ],
+ }],
+ ['sanitizer_coverage!=0', {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags': [
+ '-fsanitize-coverage=<(sanitizer_coverage)',
+ ],
+ 'defines': [
+ 'SANITIZER_COVERAGE',
+ ],
}],
],
}],
@@ -4406,8 +4402,10 @@
# https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
# Only apply this to the target linker, since the host
# linker might not be gold, but isn't used much anyway.
- '-Wl,--threads',
- '-Wl,--thread-count=4',
+ # TODO(raymes): Disable threading because gold is frequently
+ # crashing on the bots: crbug.com/161942.
+ # '-Wl,--threads',
+ # '-Wl,--thread-count=4',
],
}],
],
@@ -4499,9 +4497,9 @@
# Figure this out early since it needs symbols from libgcc.a, so it
# has to be before that in the set of libraries.
['component=="shared_library"', {
- 'android_libcpp_library': 'c++_shared',
+ 'android_stlport_library': 'stlport_shared',
}, {
- 'android_libcpp_library': 'c++_static',
+ 'android_stlport_library': 'stlport_static',
}],
],
@@ -4585,6 +4583,8 @@
'defines': [
'ANDROID',
'__GNU_SOURCE=1', # Necessary for clone()
+ 'USE_STLPORT=1',
+ '_STLP_USE_PTR_SPECIALIZATIONS=1',
'CHROME_BUILD_ID="<(chrome_build_id)"',
],
'ldflags!': [
@@ -4658,13 +4658,12 @@
'-nostdlib',
],
'libraries': [
- '-l<(android_libcpp_library)',
- '-latomic',
+ '-l<(android_stlport_library)',
# Manually link the libgcc.a that the cross compiler uses.
'<!(<(android_toolchain)/*-gcc -print-libgcc-file-name)',
- '-lm',
'-lc',
'-ldl',
+ '-lm',
],
}],
['android_webview_build==1', {
@@ -4716,20 +4715,20 @@
'-Wl,--icf=safe',
],
}],
+ # NOTE: The stlport header include paths below are specified in
+ # cflags rather than include_dirs because they need to come
+ # after include_dirs. Think of them like system headers, but
+ # don't use '-isystem' because the arm-linux-androideabi-4.4.3
+ # toolchain (circa Gingerbread) will exhibit strange errors.
+ # The include ordering here is important; change with caution.
['android_webview_build==0', {
'cflags': [
- '-isystem<(android_libcpp_include)',
- '-isystem<(android_ndk_root)/sources/cxx-stl/llvm-libc++abi/libcxxabi/include',
- '-isystem<(android_ndk_root)/sources/android/support/include',
+ '-isystem<(android_stlport_include)',
],
'ldflags': [
- '-L<(android_libcpp_libs_dir)',
+ '-L<(android_stlport_libs_dir)',
],
}, { # else: android_webview_build!=0
- 'defines': [
- 'USE_STLPORT=1',
- '_STLP_USE_PTR_SPECIALIZATIONS=1',
- ],
'aosp_build_settings': {
# Specify that we want to statically link stlport from the
# NDK. This will provide all the include and library paths
@@ -4933,12 +4932,27 @@
],
},
}],
- ['asan_coverage!=0', {
+ ['asan_coverage!=0 and sanitizer_coverage==0', {
'target_conditions': [
['_toolset=="target"', {
'cflags': [
'-fsanitize-coverage=<(asan_coverage)',
],
+ 'defines': [
+ 'SANITIZER_COVERAGE',
+ ],
+ }],
+ ],
+ }],
+ ['sanitizer_coverage!=0', {
+ 'target_conditions': [
+ ['_toolset=="target"', {
+ 'cflags': [
+ '-fsanitize-coverage=<(sanitizer_coverage)',
+ ],
+ 'defines': [
+ 'SANITIZER_COVERAGE',
+ ],
}],
],
}],
@@ -5498,15 +5512,12 @@
}],
],
'conditions': [
+ # Building with Clang on Windows is a work in progress and very
+ # experimental. See crbug.com/82385.
['clang==1', {
- # Building with Clang on Windows is a work in progress and very
- # experimental. See crbug.com/82385.
'VCCLCompilerTool': {
- 'WarnAsError': 'false',
- 'RuntimeTypeInfo': 'false',
'AdditionalOptions': [
'-fmsc-version=1800',
- '/fallback',
# Many files use intrinsics without including this header.
# TODO(hans): Fix those files, or move this to sub-GYPs.
@@ -5549,6 +5560,14 @@
],
},
}],
+ ['clang==1 and target_arch=="ia32"', {
+ 'VCCLCompilerTool': {
+ 'WarnAsError': 'false',
+ 'AdditionalOptions': [
+ '/fallback',
+ ],
+ },
+ }],
],
},
},
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 33449ef..d806a17 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -80,7 +80,7 @@
# TODO(brettw) remove this flag (and therefore enable linking all targets) on
# Windows when we have sufficient bot capacity. In the meantime, you can
# enable linking for local compiles.
- link_chrome_on_windows = false
+ link_chrome_on_windows = true
}
# =============================================================================
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index c6202d4..0105a64 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -20,6 +20,11 @@
default_android_sdk_build_tools_version = "21.0.1"
}
+ if (!defined(google_play_services_library)) {
+ google_play_services_library =
+ "//third_party/android_tools:google_play_services_default_java"
+ }
+
declare_args() {
android_sdk_root = default_android_sdk_root
android_sdk_version = default_android_sdk_version
@@ -93,6 +98,13 @@
"platforms/android-${_android_api_level}/arch-arm"
mips_android_sysroot_subdir =
"platforms/android-${_android_api_level}/arch-mips"
+ _android64_api_level = 21
+ x86_64_android_sysroot_subdir =
+ "platforms/android-${_android64_api_level}/arch-x86_64"
+ arm64_android_sysroot_subdir =
+ "platforms/android-${_android64_api_level}/arch-arm64"
+ mips64_android_sysroot_subdir =
+ "platforms/android-${_android64_api_level}/arch-mips64"
# Toolchain root directory for each build. The actual binaries are inside
# a "bin" directory inside of these.
@@ -100,6 +112,9 @@
x86_android_toolchain_root = "$android_ndk_root/toolchains/x86-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
arm_android_toolchain_root = "$android_ndk_root/toolchains/arm-linux-androideabi-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
mips_android_toolchain_root = "$android_ndk_root/toolchains/mipsel-linux-android-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
+ x86_64_android_toolchain_root = "$android_ndk_root/toolchains/x86_64-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
+ arm64_android_toolchain_root = "$android_ndk_root/toolchains/aarch64-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
+ mips64_android_toolchain_root = "$android_ndk_root/toolchains/mips64el-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}"
# Location of libgcc. This is only needed for the current GN toolchain, so we
# only need to define the current one, rather than one for every platform
@@ -119,6 +134,21 @@
_binary_prefix = "mipsel-linux-android"
android_toolchain_root = "$mips_android_toolchain_root"
android_libgcc_file = "$android_toolchain_root/lib/gcc/mipsel-linux-android/${_android_toolchain_version}/libgcc.a"
+ } else if (cpu_arch == "x64") {
+ android_prebuilt_arch = "android-x86_64"
+ _binary_prefix = "x86_64-linux-android"
+ android_toolchain_root = "$x86_64_android_toolchain_root"
+ android_libgcc_file = "$android_toolchain_root/lib/gcc/x86_64-linux-android/${_android_toolchain_version}/libgcc.a"
+ } else if (cpu_arch == "arm64") {
+ android_prebuilt_arch = "android-arm64"
+ _binary_prefix = "aarch64-linux-android"
+ android_toolchain_root = "$arm64_android_toolchain_root"
+ android_libgcc_file = "$android_toolchain_root/lib/gcc/aarch64-linux-android/${_android_toolchain_version}/libgcc.a"
+ } else if (cpu_arch == "mips64el") {
+ android_prebuilt_arch = "android-mips64"
+ _binary_prefix = "mips64el-linux-android"
+ android_toolchain_root = "$mips64_android_toolchain_root"
+ android_libgcc_file = "$android_toolchain_root/lib/gcc/mips64el-linux-android/${_android_toolchain_version}/libgcc.a"
} else {
assert(false, "Need android libgcc support for your target arch.")
}
@@ -129,6 +159,14 @@
android_gdbserver =
"$android_ndk_root/prebuilt/$android_prebuilt_arch/gdbserver/gdbserver"
+ # stlport stuff --------------------------------------------------------------
+
+ if (component_mode == "shared_library") {
+ android_stlport_library = "stlport_shared"
+ } else {
+ android_stlport_library = "stlport_static"
+ }
+
# ABI ------------------------------------------------------------------------
if (cpu_arch == "x86") {
@@ -142,6 +180,12 @@
}
} else if (cpu_arch == "mipsel") {
android_app_abi = "mips"
+ } else if (cpu_arch == "x64") {
+ android_app_abi = "x86_64"
+ } else if (cpu_arch == "arm64") {
+ android_app_abi = "arm64-v8a"
+ } else if (cpu_arch == "mips64el") {
+ android_app_abi = "mips64"
} else {
assert(false, "Unknown Android ABI: " + cpu_arch)
}
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 125aa2c..c31d40e 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -665,6 +665,10 @@
if (defined(invoker.chromium_code)) {
_chromium_code = invoker.chromium_code
}
+ _manifest_entries = []
+ if (defined(invoker.manifest_entries)) {
+ _manifest_entries = invoker.manifest_entries
+ }
_srcjar_deps = []
if (defined(invoker.srcjar_deps)) {
@@ -718,6 +722,9 @@
"--java-srcjars=@FileArg($_rebased_build_config:javac:srcjars)",
"--jar-excluded-classes=$_jar_excluded_patterns",
]
+ foreach(e, _manifest_entries) {
+ args += [ "--manifest-entry=" + e ]
+ }
if (_chromium_code) {
args += [ "--chromium-code=1" ]
}
@@ -861,6 +868,9 @@
if (defined(invoker.dist_jar_path)) {
dist_jar_path = invoker.dist_jar_path
}
+ if (defined(invoker.manifest_entries)) {
+ manifest_entries = invoker.manifest_entries
+ }
}
if (defined(invoker.main_class)) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 021a7a0..33dfa37 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -345,6 +345,11 @@
assert(defined(invoker.outputs))
action("${target_name}__generate_enum") {
+ # The sources aren't compiled so don't check their dependencies.
+ # TODO(brettw) uncomment after GN binary rolled pas 314974 (which added
+ # support for this value on actions).
+ #check_includes = false
+
sources = invoker.sources
script = "//build/android/gyp/java_cpp_enum.py"
gen_dir = "${target_gen_dir}/${target_name}/enums"
@@ -998,6 +1003,9 @@
if (defined(invoker.dex_path)) {
dex_path = invoker.dex_path
}
+ if (defined(invoker.manifest_entries)) {
+ manifest_entries = invoker.manifest_entries
+ }
supports_android = true
requires_android = true
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b50a64c..164b97d 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -380,8 +380,10 @@
# https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
# Only apply this to the target linker, since the host
# linker might not be gold, but isn't used much anyway.
- "-Wl,--threads",
- "-Wl,--thread-count=4",
+ # TODO(raymes): Disable threading because gold is frequently
+ # crashing on the bots: crbug.com/161942.
+ #"-Wl,--threads",
+ #"-Wl,--thread-count=4",
]
}
@@ -529,7 +531,7 @@
]
}
- # Android standard library setup.
+ # Stlport setup. Android uses a different (smaller) version of the STL.
if (is_android) {
if (is_clang) {
# Work around incompatibilities between bionic and clang headers.
@@ -539,44 +541,55 @@
]
}
- defines += [ "__GNU_SOURCE=1" ] # Necessary for clone().
+ defines += [
+ "USE_STLPORT=1",
+ "_STLP_USE_PTR_SPECIALIZATIONS=1",
+ "__GNU_SOURCE=1", # Necessary for clone().
+ ]
ldflags += [
"-Wl,--warn-shared-textrel",
"-nostdlib",
]
- android_libcpp_root = "$android_ndk_root/sources/cxx-stl/llvm-libc++"
+ # NOTE: The stlport header include paths below are specified in cflags
+ # rather than include_dirs because they need to come after include_dirs.
+ # Think of them like system headers, but don't use '-isystem' because the
+ # arm-linux-androideabi-4.4.3 toolchain (circa Gingerbread) will exhibit
+ # strange errors. The include ordering here is important; change with
+ # caution.
+ android_stlport_root = "$android_ndk_root/sources/cxx-stl/stlport"
- cflags += [
- "-isystem" +
- rebase_path("$android_libcpp_root/libcxx/include", root_build_dir),
- "-isystem" + rebase_path(
- "$android_ndk_root/sources/cxx-stl/llvm-libc++abi/libcxxabi/include",
- root_build_dir),
- "-isystem" +
- rebase_path("$android_ndk_root/sources/android/support/include",
- root_build_dir),
- ]
-
- lib_dirs += [ "$android_libcpp_root/libs/$android_app_abi" ]
+ cflags += [ "-isystem" +
+ rebase_path("$android_stlport_root/stlport", root_build_dir) ]
+ lib_dirs += [ "$android_stlport_root/libs/$android_app_abi" ]
if (component_mode == "shared_library") {
- android_libcpp_library = "c++_shared"
+ libs += [ "stlport_shared" ]
} else {
- android_libcpp_library = "c++_static"
+ libs += [ "stlport_static" ]
+ }
+
+ if (cpu_arch == "mipsel") {
+ libs += [
+ # ld linker is used for mips Android, and ld does not accept library
+ # absolute path prefixed by "-l"; Since libgcc does not exist in mips
+ # sysroot the proper library will be linked.
+ # TODO(gordanac): Remove once gold linker is used for mips Android.
+ "gcc",
+ ]
+ } else {
+ libs += [
+ # Manually link the libgcc.a that the cross compiler uses. This is
+ # absolute because the linker will look inside the sysroot if it's not.
+ rebase_path(android_libgcc_file),
+ ]
}
libs += [
- "$android_libcpp_library",
- "atomic",
-
- # Manually link the libgcc.a that the cross compiler uses. This is
- # absolute because the linker will look inside the sysroot if it's not.
- rebase_path(android_libgcc_file),
- "m",
"c",
"dl",
+ "m",
]
}
}
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index 77032f7..a9b250c 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -22,6 +22,12 @@
sysroot = rebase_path("$android_ndk_root/$arm_android_sysroot_subdir")
} else if (cpu_arch == "mipsel") {
sysroot = rebase_path("$android_ndk_root/$mips_android_sysroot_subdir")
+ } else if (cpu_arch == "x64") {
+ sysroot = rebase_path("$android_ndk_root/$x86_64_android_sysroot_subdir")
+ } else if (cpu_arch == "arm64") {
+ sysroot = rebase_path("$android_ndk_root/$arm64_android_sysroot_subdir")
+ } else if (cpu_arch == "mips64") {
+ sysroot = rebase_path("$android_ndk_root/$mips64_android_sysroot_subdir")
} else {
sysroot = ""
}
diff --git a/build/download_sdk_extras.py b/build/download_sdk_extras.py
index d38ee86..45e7199 100755
--- a/build/download_sdk_extras.py
+++ b/build/download_sdk_extras.py
@@ -7,7 +7,8 @@
The script expects arguments that specify zips file in the google storage
bucket named: <dir in SDK extras>_<package name>_<version>.zip. The file will
-be extracted in the android_tools/sdk/extras directory.
+be extracted in the android_tools/sdk/extras directory on the test bots. This
+script will not do anything for developers.
"""
import json
@@ -17,11 +18,16 @@
import sys
import zipfile
-sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'android'))
-from pylib import constants
+SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
+CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
+sys.path.insert(0, os.path.join(SCRIPT_DIR, 'android'))
+sys.path.insert(1, os.path.join(CHROME_SRC, 'tools'))
-GSUTIL_PATH = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
- os.pardir, os.pardir, os.pardir, os.pardir, 'depot_tools', 'gsutil.py')
+from pylib import constants
+import find_depot_tools
+
+DEPOT_PATH = find_depot_tools.add_depot_tools_to_path()
+GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py')
SDK_EXTRAS_BUCKET = 'gs://chrome-sdk-extras'
SDK_EXTRAS_PATH = os.path.join(constants.ANDROID_SDK_ROOT, 'extras')
SDK_EXTRAS_JSON_FILE = os.path.join(os.path.dirname(__file__),
@@ -38,7 +44,7 @@
def main():
- if not os.path.exists(GSUTIL_PATH) or not os.path.exists(SDK_EXTRAS_PATH):
+ if not os.environ.get('CHROME_HEADLESS'):
# This is not a buildbot checkout.
return 0
# Update the android_sdk_extras.json file to update downloaded packages.
@@ -48,8 +54,8 @@
local_zip = '%s/%s' % (SDK_EXTRAS_PATH, package['zip'])
if not os.path.exists(local_zip):
package_zip = '%s/%s' % (SDK_EXTRAS_BUCKET, package['zip'])
- subprocess.check_call([GSUTIL_PATH, '--force-version', '4.7', 'cp',
- package_zip, local_zip])
+ subprocess.check_call(['python', GSUTIL_PATH, '--force-version', '4.7',
+ 'cp', package_zip, local_zip])
# Always clean dir and extract zip to ensure correct contents.
clean_and_extract(package['dir_name'], package['package'], package['zip'])
diff --git a/build/filename_rules.gypi b/build/filename_rules.gypi
index 1bef75f..bc657d8 100644
--- a/build/filename_rules.gypi
+++ b/build/filename_rules.gypi
@@ -37,7 +37,7 @@
}],
['OS!="android" or _toolset=="host" or >(nacl_untrusted_build)==1', {
'sources/': [
- ['exclude', '_android(_unittest)?\\.cc$'],
+ ['exclude', '_android(_unittest)?\\.(h|cc)$'],
['exclude', '(^|/)android/'],
],
}],
diff --git a/build/get_landmines.py b/build/get_landmines.py
index ac3d7d6..7a918c8 100755
--- a/build/get_landmines.py
+++ b/build/get_landmines.py
@@ -29,6 +29,7 @@
print 'Need to clobber winja goma due to backend cwd cache fix.'
if platform() == 'android':
print 'Clobber: to handle new way of suppressing findbugs failures.'
+ print 'Clobber to fix gyp not rename package name (crbug.com/457038)'
if platform() == 'win' and builder() == 'ninja':
print 'Compile on cc_unittests fails due to symbols removed in r185063.'
if platform() == 'linux' and builder() == 'ninja':
diff --git a/build/grit_action.gypi b/build/grit_action.gypi
index 15ead28..462fb4c 100644
--- a/build/grit_action.gypi
+++ b/build/grit_action.gypi
@@ -21,6 +21,7 @@
# instead of build/common.gypi .
'grit_additional_defines%': [],
'grit_rc_header_format%': [],
+ 'grit_whitelist%': '',
'conditions': [
# These scripts can skip writing generated files if they are identical
@@ -36,6 +37,17 @@
}],
],
},
+ 'conditions': [
+ ['"<(grit_whitelist)"==""', {
+ 'variables': {
+ 'grit_whitelist_flag': [],
+ }
+ }, {
+ 'variables': {
+ 'grit_whitelist_flag': ['-w', '<(grit_whitelist)'],
+ }
+ }]
+ ],
'inputs': [
'<!@pymod_do_main(grit_info <@(grit_defines) <@(grit_additional_defines) '
'--inputs <(grit_grd_file) -f "<(grit_resource_ids)")',
@@ -51,6 +63,7 @@
'-o', '<(grit_out_dir)',
'--write-only-new=<(write_only_new)',
'<@(grit_defines)',
+ '<@(grit_whitelist_flag)',
'<@(grit_additional_defines)',
'<@(grit_rc_header_format)'],
'message': 'Generating resources from <(grit_grd_file)',
diff --git a/build/install-android-sdks.sh b/build/install-android-sdks.sh
new file mode 100755
index 0000000..5c4edaf
--- /dev/null
+++ b/build/install-android-sdks.sh
@@ -0,0 +1,25 @@
+#!/bin/bash -e
+
+# 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.
+
+# Script to install SDKs needed to build chromium on android.
+# See http://code.google.com/p/chromium/wiki/AndroidBuildInstructions
+
+echo 'checking for sdk packages install'
+# Use absolute path to call 'android' so script can be run from any directory.
+cwd=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+# Get the SDK extras packages to install from the DEPS file 'sdkextras' hook.
+packages="$(python ${cwd}/get_sdk_extras_packages.py)"
+for package in "${packages}"; do
+ pkg_id=$(${cwd}/../third_party/android_tools/sdk/tools/android list sdk | \
+ grep -i "$package," | \
+ awk '/^[ ]*[0-9]*- / {gsub("-",""); print $1}')
+ if [[ -n ${pkg_id} ]]; then
+ ${cwd}/../third_party/android_tools/sdk/tools/android update sdk --no-ui \
+ --filter ${pkg_id}
+ fi
+done
+
+echo "install-android-sdks.sh complete."
diff --git a/build/install-build-deps-android.sh b/build/install-build-deps-android.sh
index 5d95ed5..cf87381 100755
--- a/build/install-build-deps-android.sh
+++ b/build/install-build-deps-android.sh
@@ -4,8 +4,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# Script to install everything needed to build chromium on android that
-# requires sudo privileges.
+# Script to install everything needed to build chromium on android, including
+# items requiring sudo privileges.
# See http://code.google.com/p/chromium/wiki/AndroidBuildInstructions
# This script installs the sun-java6 packages (bin, jre and jdk). Sun requires
@@ -92,21 +92,9 @@
fi
fi
+# Install SDK packages for android
if test "$skip_inst_sdk_packages" != 1; then
- echo 'checking for sdk packages install'
- # Use absolute path to call 'android' so script can be run from any directory.
- cwd=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
- # Get the SDK extras packages to install from the DEPS file 'sdkextras' hook.
- packages="$(python ${cwd}/get_sdk_extras_packages.py)"
- for package in "${packages}"; do
- pkg_id=$(${cwd}/../third_party/android_tools/sdk/tools/android list sdk | \
- grep -i "$package," | \
- awk '/^[ ]*[0-9]*- / {gsub("-",""); print $1}')
- if [[ -n ${pkg_id} ]]; then
- ${cwd}/../third_party/android_tools/sdk/tools/android update sdk --no-ui \
- --filter ${pkg_id}
- fi
- done
+ "$(dirname "${BASH_SOURCE[0]}")/install-android-sdks.sh"
fi
echo "install-build-deps-android.sh complete."
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh
index cded452..43b5545 100755
--- a/build/install-build-deps.sh
+++ b/build/install-build-deps.sh
@@ -155,7 +155,7 @@
libfontconfig1:i386 libgconf-2-4:i386 libglib2.0-0:i386 libgpm2:i386
libgtk2.0-0:i386 libncurses5:i386 lib32ncurses5-dev
libnss3:i386 libpango1.0-0:i386
- libssl0.9.8:i386 libtinfo-dev libtinfo-dev:i386 libtool
+ libssl1.0.0:i386 libtinfo-dev libtinfo-dev:i386 libtool
libxcomposite1:i386 libxcursor1:i386 libxdamage1:i386 libxi6:i386
libxrandr2:i386 libxss1:i386 libxtst6:i386 texinfo xvfb
${naclports_list}"
@@ -352,7 +352,7 @@
sudo dpkg --add-architecture i386
fi
fi
-sudo apt-get update
+#sudo apt-get update
# We initially run "apt-get" with the --reinstall option and parse its output.
# This way, we can find all the packages that need to be newly installed
@@ -416,14 +416,32 @@
echo "Skipping installation of Chrome OS fonts."
fi
+# $1 - target name
+# $2 - link name
+create_library_symlink() {
+ target=$1
+ linkname=$2
+ if [ -L $linkname ]; then
+ if [ "$(basename $(readlink $linkname))" != "$(basename $target)" ]; then
+ sudo rm $linkname
+ fi
+ fi
+ if [ ! -r $linkname ]; then
+ echo "Creating link: $linkname"
+ sudo ln -fs $target $linkname
+ fi
+}
+
if test "$do_inst_nacl" = "1"; then
echo "Installing symbolic links for NaCl."
- if [ ! -r /usr/lib/i386-linux-gnu/libcrypto.so ]; then
- sudo ln -fs libcrypto.so.0.9.8 /usr/lib/i386-linux-gnu/libcrypto.so
- fi
- if [ ! -r /usr/lib/i386-linux-gnu/libssl.so ]; then
- sudo ln -fs libssl.so.0.9.8 /usr/lib/i386-linux-gnu/libssl.so
- fi
+ # naclports needs to cross build python for i386, but libssl1.0.0:i386
+ # only contains libcrypto.so.1.0.0 and not the symlink needed for
+ # linking (libcrypto.so).
+ create_library_symlink /lib/i386-linux-gnu/libcrypto.so.1.0.0 \
+ /usr/lib/i386-linux-gnu/libcrypto.so
+
+ create_library_symlink /lib/i386-linux-gnu/libssl.so.1.0.0 \
+ /usr/lib/i386-linux-gnu/libssl.so
else
echo "Skipping symbolic links for NaCl."
fi
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 7fc4e1d..c1edfdf 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -12,6 +12,7 @@
IDR_CRASHES_JS
IDR_CREDITS_HTML
IDR_CREDITS_JS
+IDR_DATA_REDUCTION_PROXY_INTERSTITIAL_HTML
IDR_DEFAULT_FAVICON
IDR_DEFAULT_FAVICON_32
IDR_DEFAULT_FAVICON_64
@@ -176,6 +177,7 @@
IDS_BOOKMARK_BAR_REDO_EDIT
IDS_BOOKMARK_BAR_REDO_MOVE
IDS_BOOKMARK_BAR_REDO_REORDER
+IDS_BOOKMARK_BAR_SUPERVISED_FOLDER_DEFAULT_NAME
IDS_BOOKMARK_BAR_UNDO
IDS_BOOKMARK_BAR_UNDO_ADD
IDS_BOOKMARK_BAR_UNDO_DELETE
@@ -270,6 +272,12 @@
IDS_CRASHES_TITLE
IDS_CRASHES_UPLOAD_MESSAGE
IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT
+IDS_DATA_REDUCTION_PROXY_BACK_BUTTON
+IDS_DATA_REDUCTION_PROXY_CANNOT_PROXY_HEADING
+IDS_DATA_REDUCTION_PROXY_CANNOT_PROXY_PRIMARY_PARAGRAPH
+IDS_DATA_REDUCTION_PROXY_CANNOT_PROXY_SECONDARY_PARAGRAPH
+IDS_DATA_REDUCTION_PROXY_CONTINUE_BUTTON
+IDS_DATA_REDUCTION_PROXY_TITLE
IDS_DEFAULT_AVATAR_NAME_10
IDS_DEFAULT_AVATAR_NAME_11
IDS_DEFAULT_AVATAR_NAME_12
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index 4243554..8d55307 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -24,9 +24,8 @@
# Optional/automatic variables:
# additional_input_paths - These paths will be included in the 'inputs' list to
# ensure that this target is rebuilt when one of these paths changes.
-# additional_res_dirs - Additional directories containing Android resources.
-# additional_res_packages - Package names of the R.java files corresponding to
-# each directory in additional_res_dirs.
+# additional_res_packages - Package names of R.java files generated in addition
+# to the default package name defined in AndroidManifest.xml.
# additional_src_dirs - Additional directories with .java files to be compiled
# and included in the output of this target.
# additional_bundled_libs - Additional libraries what will be stripped and
diff --git a/build/sanitizers/OWNERS b/build/sanitizers/OWNERS
index 10a3e3b..0be2be8 100644
--- a/build/sanitizers/OWNERS
+++ b/build/sanitizers/OWNERS
@@ -1,2 +1,4 @@
glider@chromium.org
+earthdok@chromium.org
per-file tsan_suppressions.cc=*
+per-file lsan_suppressions.cc=*
diff --git a/build/sanitizers/lsan_suppressions.cc b/build/sanitizers/lsan_suppressions.cc
new file mode 100644
index 0000000..a076ba0
--- /dev/null
+++ b/build/sanitizers/lsan_suppressions.cc
@@ -0,0 +1,100 @@
+// 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 file contains the default suppressions for LeakSanitizer.
+// You can also pass additional suppressions via LSAN_OPTIONS:
+// LSAN_OPTIONS=suppressions=/path/to/suppressions. Please refer to
+// http://dev.chromium.org/developers/testing/leaksanitizer for more info.
+
+#if defined(LEAK_SANITIZER)
+
+// Please make sure the code below declares a single string variable
+// kLSanDefaultSuppressions which contains LSan suppressions delimited by
+// newlines. See http://dev.chromium.org/developers/testing/leaksanitizer
+// for the instructions on writing suppressions.
+char kLSanDefaultSuppressions[] =
+// Intentional leak used as sanity test for Valgrind/memcheck.
+"leak:base::ToolsSanityTest_MemoryLeak_Test::TestBody\n"
+
+// ================ Leaks in third-party code ================
+
+// False positives in libfontconfig. http://crbug.com/39050
+"leak:libfontconfig\n"
+
+// Leaks in Nvidia's libGL.
+"leak:libGL.so\n"
+
+// A small leak in V8. http://crbug.com/46571#c9
+"leak:blink::V8GCController::collectGarbage\n"
+
+// TODO(earthdok): revisit NSS suppressions after the switch to BoringSSL
+// NSS leaks in CertDatabaseNSSTest tests. http://crbug.com/51988
+"leak:net::NSSCertDatabase::ImportFromPKCS12\n"
+"leak:net::NSSCertDatabase::ListCerts\n"
+"leak:net::NSSCertDatabase::DeleteCertAndKey\n"
+"leak:crypto::ScopedTestNSSDB::ScopedTestNSSDB\n"
+// Another leak due to not shutting down NSS properly. http://crbug.com/124445
+"leak:error_get_my_stack\n"
+// The NSS suppressions above will not fire when the fast stack unwinder is
+// used, because it can't unwind through NSS libraries. Apply blanket
+// suppressions for now.
+"leak:libnssutil3\n"
+"leak:libnspr4\n"
+"leak:libnss3\n"
+"leak:libplds4\n"
+"leak:libnssckbi\n"
+
+// XRandR has several one time leaks.
+"leak:libxrandr\n"
+
+// xrandr leak. http://crbug.com/119677
+"leak:XRRFindDisplay\n"
+
+// Suppressions for objects which can be owned by the V8 heap. This is a
+// temporary workaround until LeakSanitizer supports the V8 heap.
+// Those should only fire in (browser)tests. If you see one of them in Chrome,
+// then it's a real leak.
+// http://crbug.com/328552
+"leak:WTF::StringImpl::createUninitialized\n"
+"leak:WTF::StringImpl::create8BitIfPossible\n"
+"leak:blink::MouseEvent::create\n"
+"leak:blink::WindowProxy::initializeIfNeeded\n"
+"leak:blink::*::*GetterCallback\n"
+"leak:blink::CSSComputedStyleDeclaration::create\n"
+"leak:blink::V8PerIsolateData::ensureDomInJSContext\n"
+"leak:gin/object_template_builder.h\n"
+"leak:gin::internal::Dispatcher\n"
+"leak:blink::LocalDOMWindow::getComputedStyle\n"
+
+// http://crbug.com/356785
+"leak:content::RenderViewImplTest_DecideNavigationPolicyForWebUI_Test::TestBody\n"
+
+// ================ Leaks in Chromium code ================
+// PLEASE DO NOT ADD SUPPRESSIONS FOR NEW LEAKS.
+// Instead, commits that introduce memory leaks should be reverted. Suppressing
+// the leak is acceptable in some cases when reverting is impossible, i.e. when
+// enabling leak detection for the first time for a test target with
+// pre-existing leaks.
+
+// Small test-only leak in ppapi_unittests. http://crbug.com/258113
+"leak:ppapi::proxy::PPP_Instance_Private_ProxyTest_PPPInstancePrivate_Test\n"
+
+// http://crbug.com/322671
+"leak:content::SpeechRecognitionBrowserTest::SetUpOnMainThread\n"
+
+// http://crbug.com/355641
+"leak:TrayAccessibilityTest\n"
+
+// http://crbug.com/354644
+"leak:CertificateViewerUITest::ShowModalCertificateViewer\n"
+
+// http://crbug.com/356306
+"leak:content::SetProcessTitleFromCommandLine\n"
+
+// PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS.
+
+// End of suppressions.
+; // Please keep this semicolon.
+
+#endif // LEAK_SANITIZER
diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc
index af78bf8..6668c1e 100644
--- a/build/sanitizers/sanitizer_options.cc
+++ b/build/sanitizers/sanitizer_options.cc
@@ -12,6 +12,8 @@
#include <string.h>
#endif // ADDRESS_SANITIZER && OS_MACOSX
+#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER)
// Functions returning default options are declared weak in the tools' runtime
// libraries. To make the linker pick the strong replacements for those
// functions from this module, we explicitly force its inclusion by passing
@@ -19,6 +21,19 @@
extern "C"
void _sanitizer_options_link_helper() { }
+// The callbacks we define here will be called from the sanitizer runtime, but
+// aren't referenced from the Chrome executable. We must ensure that those
+// callbacks are not sanitizer-instrumented, and that they aren't stripped by
+// the linker.
+#define SANITIZER_HOOK_ATTRIBUTE \
+ extern "C" \
+ __attribute__((no_sanitize_address)) \
+ __attribute__((no_sanitize_memory)) \
+ __attribute__((no_sanitize_thread)) \
+ __attribute__((visibility("default"))) \
+ __attribute__((used))
+#endif
+
#if defined(ADDRESS_SANITIZER)
// Default options for AddressSanitizer in various configurations:
// strict_memcmp=1 - disable the strict memcmp() checking
@@ -78,13 +93,7 @@
#endif // OS_LINUX
#if defined(OS_LINUX) || defined(OS_MACOSX)
-extern "C"
-__attribute__((no_sanitize_address))
-__attribute__((visibility("default")))
-// The function isn't referenced from the executable itself. Make sure it isn't
-// stripped by the linker.
-__attribute__((used))
-const char *__asan_default_options() {
+SANITIZER_HOOK_ATTRIBUTE const char *__asan_default_options() {
#if defined(OS_MACOSX)
char*** argvp = _NSGetArgv();
int* argcp = _NSGetArgc();
@@ -120,26 +129,34 @@
"report_thread_leaks=0 print_suppressions=1 history_size=7 "
"strip_path_prefix=Release/../../ ";
-extern "C"
-__attribute__((no_sanitize_thread))
-__attribute__((visibility("default")))
-// The function isn't referenced from the executable itself. Make sure it isn't
-// stripped by the linker.
-__attribute__((used))
-const char *__tsan_default_options() {
+SANITIZER_HOOK_ATTRIBUTE const char *__tsan_default_options() {
return kTsanDefaultOptions;
}
extern "C" char kTSanDefaultSuppressions[];
-extern "C"
-__attribute__((no_sanitize_thread))
-__attribute__((visibility("default")))
-// The function isn't referenced from the executable itself. Make sure it isn't
-// stripped by the linker.
-__attribute__((used))
-const char *__tsan_default_suppressions() {
+SANITIZER_HOOK_ATTRIBUTE const char *__tsan_default_suppressions() {
return kTSanDefaultSuppressions;
}
#endif // THREAD_SANITIZER && OS_LINUX
+
+#if defined(LEAK_SANITIZER)
+// Default options for LeakSanitizer:
+// print_suppressions=1 - print the list of matched suppressions.
+// strip_path_prefix=Release/../../ - prefixes up to and including this
+// substring will be stripped from source file paths in symbolized reports.
+const char kLsanDefaultOptions[] =
+ "print_suppressions=1 strip_path_prefix=Release/../../ ";
+
+SANITIZER_HOOK_ATTRIBUTE const char *__lsan_default_options() {
+ return kLsanDefaultOptions;
+}
+
+extern "C" char kLSanDefaultSuppressions[];
+
+SANITIZER_HOOK_ATTRIBUTE const char *__lsan_default_suppressions() {
+ return kLSanDefaultSuppressions;
+}
+
+#endif // LEAK_SANITIZER
diff --git a/build/sanitizers/sanitizers.gyp b/build/sanitizers/sanitizers.gyp
index 53cc298..4126d22 100644
--- a/build/sanitizers/sanitizers.gyp
+++ b/build/sanitizers/sanitizers.gyp
@@ -36,6 +36,11 @@
'tsan_suppressions.cc',
],
}],
+ ['lsan==1', {
+ 'sources': [
+ 'lsan_suppressions.cc',
+ ],
+ }],
],
'cflags/': [
['exclude', '-fsanitize='],
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc
index a15cba1..5704f2d 100644
--- a/build/sanitizers/tsan_suppressions.cc
+++ b/build/sanitizers/tsan_suppressions.cc
@@ -316,15 +316,15 @@
// https://crbug.com/448203
"race:blink::RemoteFrame::detach\n"
+// https://crbug.com/454652
+"race:net::NetworkChangeNotifier::SetTestNotificationsOnly\n"
+
// https://crbug.com/455638
"deadlock:dbus::Bus::ShutdownAndBlock\n"
// https://crbug.com/455665
"race:mojo::common::*::tick_clock\n"
-// https://crbug.com/456095
-"race:blink::Scheduler\n"
-
// End of suppressions.
; // Please keep this semicolon.
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index fc1ecbf..92a088a 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -64,3 +64,16 @@
]
jar_path = "$android_sdk_root/extras/android/support/v7/mediarouter/libs/android-support-v7-mediarouter.jar"
}
+
+android_resources("google_play_services_default_resources") {
+ v14_verify_only = true
+ resource_dirs = [ "$android_sdk_root/extras/google/google_play_services/libproject/google-play-services_lib/res" ]
+ custom_package = "com.google.android.gms"
+}
+android_java_prebuilt("google_play_services_default_java") {
+ deps = [
+ ":android_support_v13_java",
+ ":google_play_services_default_resources",
+ ]
+ jar_path = "$android_sdk_root/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar"
+}
diff --git a/build/toolchain/android/BUILD.gn b/build/toolchain/android/BUILD.gn
index d21ed27..e3d950a 100644
--- a/build/toolchain/android/BUILD.gn
+++ b/build/toolchain/android/BUILD.gn
@@ -103,3 +103,27 @@
tool_prefix = "$mips_android_toolchain_root/bin/mipsel-linux-android-"
toolchain_cpu_arch = "mipsel"
}
+
+android_gcc_toolchain("x64") {
+ android_ndk_sysroot = "$android_ndk_root/$x86_64_android_sysroot_subdir"
+ android_ndk_lib_dir = "usr/lib64"
+
+ tool_prefix = "$x86_64_android_toolchain_root/bin/x86_64-linux-android-"
+ toolchain_cpu_arch = "x86_64"
+}
+
+android_gcc_toolchain("arm64") {
+ android_ndk_sysroot = "$android_ndk_root/$arm64_android_sysroot_subdir"
+ android_ndk_lib_dir = "usr/lib"
+
+ tool_prefix = "$arm64_android_toolchain_root/bin/arm-linux-androideabi-"
+ toolchain_cpu_arch = "aarch64"
+}
+
+android_gcc_toolchain("mips64el") {
+ android_ndk_sysroot = "$android_ndk_root/$mips64_android_sysroot_subdir"
+ android_ndk_lib_dir = "usr/lib64"
+
+ tool_prefix = "$mips64_android_toolchain_root/bin/mipsel-linux-android-"
+ toolchain_cpu_arch = "mipsel64el"
+}
diff --git a/build/toolchain/get_concurrent_links.py b/build/toolchain/get_concurrent_links.py
index 629d67d..6a40101 100644
--- a/build/toolchain/get_concurrent_links.py
+++ b/build/toolchain/get_concurrent_links.py
@@ -7,6 +7,7 @@
import os
import re
+import subprocess
import sys
def GetDefaultConcurrentLinks():
@@ -31,8 +32,7 @@
("sullAvailExtendedVirtual", ctypes.c_ulonglong),
]
- stat = MEMORYSTATUSEX()
- stat.dwLength = ctypes.sizeof(stat)
+ stat = MEMORYSTATUSEX(dwLength=ctypes.sizeof(MEMORYSTATUSEX))
ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))
mem_limit = max(1, stat.ullTotalPhys / (4 * (2 ** 30))) # total / 4GB
@@ -55,7 +55,7 @@
# A static library debug build of Chromium's unit_tests takes ~2.7GB, so
# 4GB per ld process allows for some more bloat.
return max(1, avail_bytes / (4 * (2 ** 30))) # total / 4GB
- except:
+ except Exception:
return 1
else:
# TODO(scottmg): Implement this for other platforms.
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index 26ad865..0560714 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -14,6 +14,12 @@
import("//build/toolchain/clang.gni")
import("//build/toolchain/goma.gni")
+if (use_goma) {
+ goma_prefix = "$goma_dir/gomacc "
+} else {
+ goma_prefix = ""
+}
+
if (is_clang) {
cc = rebase_path("//third_party/llvm-build/Release+Asserts/bin/clang",
root_build_dir)
@@ -23,6 +29,8 @@
cc = "gcc"
cxx = "g++"
}
+cc = goma_prefix + cc
+cxx = goma_prefix + cxx
ld = cxx
# This will copy the gyp-mac-tool to the build directory. We pass in the source
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
index 569f4da..cc89638 100644
--- a/build/toolchain/win/setup_toolchain.py
+++ b/build/toolchain/win/setup_toolchain.py
@@ -1,6 +1,14 @@
# 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.
+#
+# Copies the given "win tool" (which the toolchain uses to wrap compiler
+# invocations) and the environment blocks for the 32-bit and 64-bit builds on
+# Windows to the build directory.
+#
+# The arguments are the visual studio install location and the location of the
+# win tool. The script assumes that the root build directory is the current dir
+# and the files will be written to the current directory.
import errno
import os
@@ -8,16 +16,6 @@
import subprocess
import sys
-"""
-Copies the given "win tool" (which the toolchain uses to wrap compiler
-invocations) and the environment blocks for the 32-bit and 64-bit builds on
-Windows to the build directory.
-
-The arguments are the visual studio install location and the location of the
-win tool. The script assumes that the root build directory is the current dir
-and the files will be written to the current directory.
-"""
-
def _ExtractImportantEnvironment(output_of_set):
"""Extracts environment variables required for the toolchain to run from
@@ -104,7 +102,6 @@
'<visual studio path> <win tool path> <win sdk path> '
'<runtime dirs> <cpu_arch>')
sys.exit(2)
- vs_path = sys.argv[1]
tool_source = sys.argv[2]
win_sdk_path = sys.argv[3]
runtime_dirs = sys.argv[4]
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 5373f03..6f49e7c 100644
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -37,7 +37,6 @@
toolchain = toolchain_data['path']
version = toolchain_data['version']
- version_is_pro = version[-1] != 'e'
win8sdk = toolchain_data['win8sdk']
wdk = toolchain_data['wdk']
# TODO(scottmg): The order unfortunately matters in these. They should be
@@ -168,7 +167,6 @@
if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
import find_depot_tools
depot_tools_path = find_depot_tools.add_depot_tools_to_path()
- json_data_file = os.path.join(script_dir, 'win_toolchain.json')
get_toolchain_args = [
sys.executable,
os.path.join(depot_tools_path,
diff --git a/cc/base/math_util.cc b/cc/base/math_util.cc
index 70090d9..e2fd565 100644
--- a/cc/base/math_util.cc
+++ b/cc/base/math_util.cc
@@ -735,7 +735,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::Size& s,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginDictionary(name);
res->SetDouble("width", s.width());
res->SetDouble("height", s.height());
@@ -744,7 +744,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::SizeF& s,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginDictionary(name);
res->SetDouble("width", s.width());
res->SetDouble("height", s.height());
@@ -753,7 +753,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::Rect& r,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendInteger(r.x());
res->AppendInteger(r.y());
@@ -764,7 +764,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::PointF& pt,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendDouble(pt.x());
res->AppendDouble(pt.y());
@@ -773,7 +773,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::Point3F& pt,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendDouble(pt.x());
res->AppendDouble(pt.y());
@@ -783,7 +783,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::Vector2d& v,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendInteger(v.x());
res->AppendInteger(v.y());
@@ -792,7 +792,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::Vector2dF& v,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendDouble(v.x());
res->AppendDouble(v.y());
@@ -801,7 +801,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::ScrollOffset& v,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendDouble(v.x());
res->AppendDouble(v.y());
@@ -810,7 +810,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::QuadF& q,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendDouble(q.p1().x());
res->AppendDouble(q.p1().y());
@@ -825,7 +825,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::RectF& rect,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendDouble(rect.x());
res->AppendDouble(rect.y());
@@ -836,7 +836,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::Transform& transform,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
const SkMatrix44& m = transform.matrix();
for (int row = 0; row < 4; ++row) {
@@ -848,7 +848,7 @@
void MathUtil::AddToTracedValue(const char* name,
const gfx::BoxF& box,
- base::debug::TracedValue* res) {
+ base::trace_event::TracedValue* res) {
res->BeginArray(name);
res->AppendInteger(box.x());
res->AppendInteger(box.y());
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index ddc8955..56fdd17 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -24,12 +24,6 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace debug {
-using ::base::trace_event::TracedValue;
-}
} // namespace base
namespace gfx {
@@ -207,40 +201,40 @@
static void AddToTracedValue(const char* name,
const gfx::Size& s,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::SizeF& s,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::Rect& r,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::PointF& q,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::Point3F&,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::Vector2d& v,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::Vector2dF& v,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::ScrollOffset& v,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::QuadF& q,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::RectF& rect,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::Transform& transform,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
static void AddToTracedValue(const char* name,
const gfx::BoxF& box,
- base::debug::TracedValue* res);
+ base::trace_event::TracedValue* res);
// Returns a base::Value representation of the floating point value.
// If the value is inf, returns max double/float representation.
diff --git a/cc/base/region.cc b/cc/base/region.cc
index 22d9585..c048c89 100644
--- a/cc/base/region.cc
+++ b/cc/base/region.cc
@@ -130,7 +130,7 @@
return result.Pass();
}
-void Region::AsValueInto(base::debug::TracedValue* result) const {
+void Region::AsValueInto(base::trace_event::TracedValue* result) const {
for (Iterator it(*this); it.has_rect(); it.next()) {
gfx::Rect rect(it.rect());
result->AppendInteger(rect.x());
diff --git a/cc/base/region.h b/cc/base/region.h
index b84dbd5..583311e 100644
--- a/cc/base/region.h
+++ b/cc/base/region.h
@@ -18,13 +18,7 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace debug {
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
class SimpleEnclosedRegion;
@@ -69,7 +63,7 @@
std::string ToString() const;
scoped_ptr<base::Value> AsValue() const;
- void AsValueInto(base::debug::TracedValue* array) const;
+ void AsValueInto(base::trace_event::TracedValue* array) const;
class CC_EXPORT Iterator {
public:
diff --git a/cc/base/switches.cc b/cc/base/switches.cc
index d34821e..c3fad97 100644
--- a/cc/base/switches.cc
+++ b/cc/base/switches.cc
@@ -99,16 +99,6 @@
const char kUIShowReplicaScreenSpaceRects[] =
"ui-show-replica-screenspace-rects";
-// Show rects in the HUD wherever something is known to be drawn opaque and is
-// considered occluding the pixels behind it.
-const char kShowOccludingRects[] = "show-occluding-rects";
-const char kUIShowOccludingRects[] = "ui-show-occluding-rects";
-
-// Show rects in the HUD wherever something is not known to be drawn opaque and
-// is not considered to be occluding the pixels behind it.
-const char kShowNonOccludingRects[] = "show-nonoccluding-rects";
-const char kUIShowNonOccludingRects[] = "ui-show-nonoccluding-rects";
-
// Prevents the layer tree unit tests from timing out.
const char kCCLayerTreeTestNoTimeout[] = "cc-layer-tree-test-no-timeout";
diff --git a/cc/base/switches.h b/cc/base/switches.h
index 611f0da..5b7c92e 100644
--- a/cc/base/switches.h
+++ b/cc/base/switches.h
@@ -51,10 +51,6 @@
CC_EXPORT extern const char kUIShowScreenSpaceRects[];
CC_EXPORT extern const char kShowReplicaScreenSpaceRects[];
CC_EXPORT extern const char kUIShowReplicaScreenSpaceRects[];
-CC_EXPORT extern const char kShowOccludingRects[];
-CC_EXPORT extern const char kUIShowOccludingRects[];
-CC_EXPORT extern const char kShowNonOccludingRects[];
-CC_EXPORT extern const char kUIShowNonOccludingRects[];
// Unit test related.
CC_EXPORT extern const char kCCLayerTreeTestNoTimeout[];
diff --git a/cc/blink/web_display_item_list_impl.cc b/cc/blink/web_display_item_list_impl.cc
index fdd05df..dc1d430 100644
--- a/cc/blink/web_display_item_list_impl.cc
+++ b/cc/blink/web_display_item_list_impl.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "cc/blink/web_blend_mode.h"
+#include "cc/blink/web_filter_operations_impl.h"
#include "cc/resources/clip_display_item.h"
#include "cc/resources/clip_path_display_item.h"
#include "cc/resources/drawing_display_item.h"
@@ -32,6 +33,11 @@
return display_item_list_;
}
+void WebDisplayItemListImpl::appendDrawingItem(const SkPicture* picture) {
+ display_item_list_->AppendItem(cc::DrawingDisplayItem::Create(
+ skia::SharePtr(const_cast<SkPicture*>(picture)), gfx::PointF(0, 0)));
+}
+
void WebDisplayItemListImpl::appendDrawingItem(
SkPicture* picture,
const blink::WebFloatPoint& location) {
@@ -95,12 +101,26 @@
display_item_list_->AppendItem(cc::EndTransparencyDisplayItem::Create());
}
+#if FILTER_DISPLAY_ITEM_USES_FILTER_OPERATIONS
+void WebDisplayItemListImpl::appendFilterItem(
+ const blink::WebFilterOperations& filters,
+ const blink::WebFloatRect& bounds) {
+ const WebFilterOperationsImpl& filters_impl =
+ static_cast<const WebFilterOperationsImpl&>(filters);
+ display_item_list_->AppendItem(
+ cc::FilterDisplayItem::Create(filters_impl.AsFilterOperations(), bounds));
+}
+#else
void WebDisplayItemListImpl::appendFilterItem(
SkImageFilter* filter,
const blink::WebFloatRect& bounds) {
+ cc::FilterOperations filter_operations;
+ filter_operations.Append(
+ cc::FilterOperation::CreateReferenceFilter(skia::SharePtr(filter)));
display_item_list_->AppendItem(
- cc::FilterDisplayItem::Create(skia::SharePtr(filter), bounds));
+ cc::FilterDisplayItem::Create(filter_operations, bounds));
}
+#endif
void WebDisplayItemListImpl::appendEndFilterItem() {
display_item_list_->AppendItem(cc::EndFilterDisplayItem::Create());
diff --git a/cc/blink/web_display_item_list_impl.h b/cc/blink/web_display_item_list_impl.h
index cd35975..f2ff8c6 100644
--- a/cc/blink/web_display_item_list_impl.h
+++ b/cc/blink/web_display_item_list_impl.h
@@ -14,6 +14,7 @@
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/skia/include/core/SkRegion.h"
+#include "ui/gfx/geometry/point_f.h"
class SkImageFilter;
class SkMatrix44;
@@ -31,7 +32,8 @@
scoped_refptr<cc::DisplayItemList> ToDisplayItemList();
// blink::WebDisplayItemList implementation.
- virtual void appendDrawingItem(SkPicture* picture,
+ virtual void appendDrawingItem(const SkPicture*);
+ virtual void appendDrawingItem(SkPicture*,
const blink::WebFloatPoint& location);
virtual void appendClipItem(
const blink::WebRect& clip_rect,
@@ -48,8 +50,13 @@
virtual void appendTransparencyItem(float opacity,
blink::WebBlendMode blend_mode);
virtual void appendEndTransparencyItem();
+#if FILTER_DISPLAY_ITEM_USES_FILTER_OPERATIONS
+ virtual void appendFilterItem(const blink::WebFilterOperations& filters,
+ const blink::WebFloatRect& bounds);
+#else
virtual void appendFilterItem(SkImageFilter* filter,
const blink::WebFloatRect& bounds);
+#endif
virtual void appendEndFilterItem();
private:
diff --git a/cc/blink/web_layer_impl.cc b/cc/blink/web_layer_impl.cc
index bcebfec..2d5e459 100644
--- a/cc/blink/web_layer_impl.cc
+++ b/cc/blink/web_layer_impl.cc
@@ -4,6 +4,9 @@
#include "cc/blink/web_layer_impl.h"
+#include <utility>
+#include <vector>
+
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/strings/string_util.h"
@@ -358,6 +361,16 @@
return result;
}
+void WebLayerImpl::setFrameTimingRequests(
+ const WebVector<std::pair<int64_t, WebRect>>& requests) {
+ std::vector<cc::FrameTimingRequest> frame_timing_requests(requests.size());
+ for (size_t i = 0; i < requests.size(); ++i) {
+ frame_timing_requests.push_back(cc::FrameTimingRequest(
+ requests[i].first, gfx::Rect(requests[i].second)));
+ }
+ layer_->SetFrameTimingRequests(frame_timing_requests);
+}
+
void WebLayerImpl::setTouchEventHandlerRegion(const WebVector<WebRect>& rects) {
cc::Region region;
for (size_t i = 0; i < rects.size(); ++i)
@@ -458,7 +471,7 @@
web_layer_client_ = client;
}
-class TracedDebugInfo : public base::debug::ConvertableToTraceFormat {
+class TracedDebugInfo : public base::trace_event::ConvertableToTraceFormat {
public:
// This object takes ownership of the debug_info object.
explicit TracedDebugInfo(blink::WebGraphicsLayerDebugInfo* debug_info)
@@ -476,7 +489,7 @@
base::ThreadChecker thread_checker_;
};
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
WebLayerImpl::TakeDebugInfo() {
if (!web_layer_client_)
return nullptr;
diff --git a/cc/blink/web_layer_impl.h b/cc/blink/web_layer_impl.h
index 787f632..0560bed 100644
--- a/cc/blink/web_layer_impl.h
+++ b/cc/blink/web_layer_impl.h
@@ -6,6 +6,7 @@
#define CC_BLINK_WEB_LAYER_IMPL_H_
#include <string>
+#include <utility>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -34,13 +35,7 @@
namespace trace_event {
class ConvertableToTraceFormat;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
}
-} // namespace base
namespace cc {
class Layer;
@@ -131,6 +126,8 @@
virtual blink::WebVector<blink::WebRect> touchEventHandlerRegion() const;
virtual void setScrollBlocksOn(blink::WebScrollBlocksOn);
virtual blink::WebScrollBlocksOn scrollBlocksOn() const;
+ virtual void setFrameTimingRequests(
+ const blink::WebVector<std::pair<int64_t, blink::WebRect>>& requests);
virtual void setIsContainerForFixedPositionLayers(bool is_container);
virtual bool isContainerForFixedPositionLayers() const;
virtual void setPositionConstraint(
@@ -141,7 +138,8 @@
virtual void setWebLayerClient(blink::WebLayerClient* client);
// LayerClient implementation.
- scoped_refptr<base::debug::ConvertableToTraceFormat> TakeDebugInfo() override;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo()
+ override;
virtual void setScrollParent(blink::WebLayer* parent);
virtual void setClipParent(blink::WebLayer* parent);
diff --git a/cc/cc_unittests.isolate b/cc/cc_unittests.isolate
index 5d652d9..db47aab 100644
--- a/cc/cc_unittests.isolate
+++ b/cc/cc_unittests.isolate
@@ -82,6 +82,13 @@
],
},
}],
+ ['OS=="mac" and asan==1 and fastbuild==0', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/cc_unittests.dSYM/',
+ ],
+ },
+ }],
],
'includes': [
'../base/base.isolate',
diff --git a/cc/debug/benchmark_instrumentation.cc b/cc/debug/benchmark_instrumentation.cc
index bf8ec00..5a04e21 100644
--- a/cc/debug/benchmark_instrumentation.cc
+++ b/cc/debug/benchmark_instrumentation.cc
@@ -20,15 +20,15 @@
}
void IssueDisplayRenderingStatsEvent() {
- scoped_refptr<base::debug::TracedValue> record_data =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> record_data =
+ new base::trace_event::TracedValue();
record_data->SetInteger("frame_count", 1);
TRACE_EVENT_INSTANT1(
"benchmark",
"BenchmarkInstrumentation::DisplayRenderingStats",
TRACE_EVENT_SCOPE_THREAD,
"data",
- scoped_refptr<base::debug::ConvertableToTraceFormat>(record_data));
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>(record_data));
}
} // namespace benchmark_instrumentation
diff --git a/cc/debug/debug_colors.cc b/cc/debug/debug_colors.cc
index 6cbbfe9..daec5cc 100644
--- a/cc/debug/debug_colors.cc
+++ b/cc/debug/debug_colors.cc
@@ -216,24 +216,6 @@
return SkColorSetARGB(10, 100, 0, 200);
}
-// Occluding rects in pink.
-SkColor DebugColors::OccludingRectBorderColor() {
- return SkColorSetARGB(255, 245, 136, 255);
-}
-int DebugColors::OccludingRectBorderWidth() { return 2; }
-SkColor DebugColors::OccludingRectFillColor() {
- return SkColorSetARGB(10, 245, 136, 255);
-}
-
-// Non-Occluding rects in a reddish color.
-SkColor DebugColors::NonOccludingRectBorderColor() {
- return SkColorSetARGB(255, 200, 0, 100);
-}
-int DebugColors::NonOccludingRectBorderWidth() { return 2; }
-SkColor DebugColors::NonOccludingRectFillColor() {
- return SkColorSetARGB(10, 200, 0, 100);
-}
-
// Touch-event-handler rects in yellow.
SkColor DebugColors::TouchEventHandlerRectBorderColor() {
return SkColorSetARGB(255, 239, 229, 60);
diff --git a/cc/debug/debug_colors.h b/cc/debug/debug_colors.h
index 3b00d84..52dab85 100644
--- a/cc/debug/debug_colors.h
+++ b/cc/debug/debug_colors.h
@@ -87,14 +87,6 @@
static int ScreenSpaceSurfaceReplicaRectBorderWidth();
static SkColor ScreenSpaceSurfaceReplicaRectFillColor();
- static SkColor OccludingRectBorderColor();
- static int OccludingRectBorderWidth();
- static SkColor OccludingRectFillColor();
-
- static SkColor NonOccludingRectBorderColor();
- static int NonOccludingRectBorderWidth();
- static SkColor NonOccludingRectFillColor();
-
static SkColor TouchEventHandlerRectBorderColor();
static int TouchEventHandlerRectBorderWidth();
static SkColor TouchEventHandlerRectFillColor();
diff --git a/cc/debug/debug_rect_history.cc b/cc/debug/debug_rect_history.cc
index a8c5030..cde7765 100644
--- a/cc/debug/debug_rect_history.cc
+++ b/cc/debug/debug_rect_history.cc
@@ -29,8 +29,6 @@
LayerImpl* root_layer,
LayerImpl* hud_layer,
const LayerImplList& render_surface_layer_list,
- const std::vector<gfx::Rect>& occluding_screen_space_rects,
- const std::vector<gfx::Rect>& non_occluding_screen_space_rects,
const LayerTreeDebugState& debug_state) {
// For now, clear all rects from previous frames. In the future we may want to
// store all debug rects for a history of many frames.
@@ -60,12 +58,6 @@
if (debug_state.show_screen_space_rects)
SaveScreenSpaceRects(render_surface_layer_list);
- if (debug_state.show_occluding_rects)
- SaveOccludingRects(occluding_screen_space_rects);
-
- if (debug_state.show_non_occluding_rects)
- SaveNonOccludingRects(non_occluding_screen_space_rects);
-
if (debug_state.show_layer_animation_bounds_rects)
SaveLayerAnimationBoundsRects(render_surface_layer_list);
}
@@ -170,20 +162,6 @@
}
}
-void DebugRectHistory::SaveOccludingRects(
- const std::vector<gfx::Rect>& occluding_rects) {
- for (size_t i = 0; i < occluding_rects.size(); ++i)
- debug_rects_.push_back(DebugRect(OCCLUDING_RECT_TYPE, occluding_rects[i]));
-}
-
-void DebugRectHistory::SaveNonOccludingRects(
- const std::vector<gfx::Rect>& non_occluding_rects) {
- for (size_t i = 0; i < non_occluding_rects.size(); ++i) {
- debug_rects_.push_back(
- DebugRect(NONOCCLUDING_RECT_TYPE, non_occluding_rects[i]));
- }
-}
-
void DebugRectHistory::SaveTouchEventHandlerRects(LayerImpl* layer) {
LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
layer,
diff --git a/cc/debug/debug_rect_history.h b/cc/debug/debug_rect_history.h
index 6d25b29..6bcf438 100644
--- a/cc/debug/debug_rect_history.h
+++ b/cc/debug/debug_rect_history.h
@@ -34,21 +34,12 @@
//
// - Replica screen space rects: this is the region the replica's contents
// occupy in screen space.
-//
-// - Occluding rects: these are the regions that contribute to the occluded
-// region.
-//
-// - Non-Occluding rects: these are the regions of composited layers that do not
-// contribute to the occluded region.
-//
enum DebugRectType {
PAINT_RECT_TYPE,
PROPERTY_CHANGED_RECT_TYPE,
SURFACE_DAMAGE_RECT_TYPE,
SCREEN_SPACE_RECT_TYPE,
REPLICA_SCREEN_SPACE_RECT_TYPE,
- OCCLUDING_RECT_TYPE,
- NONOCCLUDING_RECT_TYPE,
TOUCH_EVENT_HANDLER_RECT_TYPE,
WHEEL_EVENT_HANDLER_RECT_TYPE,
SCROLL_EVENT_HANDLER_RECT_TYPE,
@@ -79,8 +70,6 @@
LayerImpl* root_layer,
LayerImpl* hud_layer,
const LayerImplList& render_surface_layer_list,
- const std::vector<gfx::Rect>& occluding_screen_space_rects,
- const std::vector<gfx::Rect>& non_occluding_screen_space_rects,
const LayerTreeDebugState& debug_state);
const std::vector<DebugRect>& debug_rects() { return debug_rects_; }
@@ -95,10 +84,6 @@
const LayerImplList& render_surface_layer_list);
void SaveScreenSpaceRects(
const LayerImplList& render_surface_layer_list);
- void SaveOccludingRects(
- const std::vector<gfx::Rect>& occluding_screen_space_rects);
- void SaveNonOccludingRects(
- const std::vector<gfx::Rect>& non_occluding_screen_space_rects);
void SaveTouchEventHandlerRects(LayerImpl* layer);
void SaveTouchEventHandlerRectsCallback(LayerImpl* layer);
void SaveWheelEventHandlerRects(LayerImpl* layer);
diff --git a/cc/debug/devtools_instrumentation.h b/cc/debug/devtools_instrumentation.h
index 73788a5..f1faf6f 100644
--- a/cc/debug/devtools_instrumentation.h
+++ b/cc/debug/devtools_instrumentation.h
@@ -96,9 +96,9 @@
};
struct ScopedLayerObjectTracker
- : public base::debug::TraceScopedTrackableObject<int> {
+ : public base::trace_event::TraceScopedTrackableObject<int> {
explicit ScopedLayerObjectTracker(int layer_id)
- : base::debug::TraceScopedTrackableObject<int>(
+ : base::trace_event::TraceScopedTrackableObject<int>(
internal::kCategory,
internal::kLayerId,
layer_id) {
@@ -142,10 +142,10 @@
layer_tree_host_id);
}
-inline scoped_refptr<base::debug::ConvertableToTraceFormat>
+inline scoped_refptr<base::trace_event::ConvertableToTraceFormat>
BeginMainThreadFrameData(int frame_id) {
- scoped_refptr<base::debug::TracedValue> value =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> value =
+ new base::trace_event::TracedValue();
value->SetInteger("frameId", frame_id);
return value;
}
diff --git a/cc/debug/frame_timing_tracker_unittest.cc b/cc/debug/frame_timing_tracker_unittest.cc
index ed862c5..85f5716 100644
--- a/cc/debug/frame_timing_tracker_unittest.cc
+++ b/cc/debug/frame_timing_tracker_unittest.cc
@@ -15,8 +15,8 @@
static std::string ToString(
scoped_ptr<FrameTimingTracker::CompositeTimingSet> timingset) {
- scoped_refptr<base::debug::TracedValue> value =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> value =
+ new base::trace_event::TracedValue();
value->BeginArray("values");
for (const auto& it : *timingset) {
value->BeginDictionary();
diff --git a/cc/debug/frame_viewer_instrumentation.cc b/cc/debug/frame_viewer_instrumentation.cc
index bd0fbdc..53c1551 100644
--- a/cc/debug/frame_viewer_instrumentation.cc
+++ b/cc/debug/frame_viewer_instrumentation.cc
@@ -18,12 +18,13 @@
const char kAnalyzeTask[] = "AnalyzeTask";
const char kRasterTask[] = "RasterTask";
-scoped_refptr<base::debug::ConvertableToTraceFormat> TileDataAsValue(
+scoped_refptr<base::trace_event::ConvertableToTraceFormat> TileDataAsValue(
const void* tile_id,
TileResolution tile_resolution,
int source_frame_number,
int layer_id) {
- scoped_refptr<base::debug::TracedValue> res(new base::debug::TracedValue());
+ scoped_refptr<base::trace_event::TracedValue> res(
+ new base::trace_event::TracedValue());
TracedValue::SetIDRef(tile_id, res.get(), kTileId);
res->SetString(kTileResolution, TileResolutionToString(tile_resolution));
res->SetInteger(kSourceFrameNumber, source_frame_number);
diff --git a/cc/debug/layer_tree_debug_state.cc b/cc/debug/layer_tree_debug_state.cc
index d89bca3..e840220 100644
--- a/cc/debug/layer_tree_debug_state.cc
+++ b/cc/debug/layer_tree_debug_state.cc
@@ -18,8 +18,6 @@
show_surface_damage_rects(false),
show_screen_space_rects(false),
show_replica_screen_space_rects(false),
- show_occluding_rects(false),
- show_non_occluding_rects(false),
show_touch_event_handler_rects(false),
show_wheel_event_handler_rects(false),
show_scroll_event_handler_rects(false),
@@ -48,8 +46,7 @@
bool LayerTreeDebugState::ShowHudRects() const {
return show_paint_rects || show_property_changed_rects ||
show_surface_damage_rects || show_screen_space_rects ||
- show_replica_screen_space_rects || show_occluding_rects ||
- show_non_occluding_rects || show_touch_event_handler_rects ||
+ show_replica_screen_space_rects || show_touch_event_handler_rects ||
show_wheel_event_handler_rects || show_scroll_event_handler_rects ||
show_non_fast_scrollable_rects || show_layer_animation_bounds_rects;
}
@@ -69,8 +66,6 @@
a.show_surface_damage_rects == b.show_surface_damage_rects &&
a.show_screen_space_rects == b.show_screen_space_rects &&
a.show_replica_screen_space_rects == b.show_replica_screen_space_rects &&
- a.show_occluding_rects == b.show_occluding_rects &&
- a.show_non_occluding_rects == b.show_non_occluding_rects &&
a.show_touch_event_handler_rects == b.show_touch_event_handler_rects &&
a.show_wheel_event_handler_rects == b.show_wheel_event_handler_rects &&
a.show_scroll_event_handler_rects == b.show_scroll_event_handler_rects &&
@@ -96,8 +91,6 @@
r.show_surface_damage_rects |= b.show_surface_damage_rects;
r.show_screen_space_rects |= b.show_screen_space_rects;
r.show_replica_screen_space_rects |= b.show_replica_screen_space_rects;
- r.show_occluding_rects |= b.show_occluding_rects;
- r.show_non_occluding_rects |= b.show_non_occluding_rects;
r.show_touch_event_handler_rects |= b.show_touch_event_handler_rects;
r.show_wheel_event_handler_rects |= b.show_wheel_event_handler_rects;
r.show_scroll_event_handler_rects |= b.show_scroll_event_handler_rects;
diff --git a/cc/debug/layer_tree_debug_state.h b/cc/debug/layer_tree_debug_state.h
index c3970e1..4b71cd9 100644
--- a/cc/debug/layer_tree_debug_state.h
+++ b/cc/debug/layer_tree_debug_state.h
@@ -24,8 +24,6 @@
bool show_surface_damage_rects;
bool show_screen_space_rects;
bool show_replica_screen_space_rects;
- bool show_occluding_rects;
- bool show_non_occluding_rects;
bool show_touch_event_handler_rects;
bool show_wheel_event_handler_rects;
bool show_scroll_event_handler_rects;
diff --git a/cc/debug/rendering_stats.cc b/cc/debug/rendering_stats.cc
index 2247b3a..3a27c1d 100644
--- a/cc/debug/rendering_stats.cc
+++ b/cc/debug/rendering_stats.cc
@@ -18,7 +18,7 @@
void RenderingStats::TimeDeltaList::AddToTracedValue(
const char* name,
- base::debug::TracedValue* list_value) const {
+ base::trace_event::TracedValue* list_value) const {
list_value->BeginArray(name);
for (const auto& value : values) {
list_value->AppendDouble(value.InMillisecondsF());
@@ -43,10 +43,10 @@
RenderingStats::~RenderingStats() {
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
RenderingStats::AsTraceableData() const {
- scoped_refptr<base::debug::TracedValue> record_data =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> record_data =
+ new base::trace_event::TracedValue();
record_data->SetInteger("frame_count", frame_count);
record_data->SetInteger("visible_content_area", visible_content_area);
record_data->SetInteger("approximated_visible_content_area",
diff --git a/cc/debug/rendering_stats.h b/cc/debug/rendering_stats.h
index 3a72371..1e97be1 100644
--- a/cc/debug/rendering_stats.h
+++ b/cc/debug/rendering_stats.h
@@ -25,7 +25,7 @@
void Append(base::TimeDelta value);
void AddToTracedValue(const char* name,
- base::debug::TracedValue* list_value) const;
+ base::trace_event::TracedValue* list_value) const;
void Add(const TimeDeltaList& other);
@@ -52,7 +52,8 @@
TimeDeltaList commit_to_activate_duration;
TimeDeltaList commit_to_activate_duration_estimate;
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsTraceableData() const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsTraceableData()
+ const;
void Add(const RenderingStats& other);
};
diff --git a/cc/debug/rendering_stats_unittest.cc b/cc/debug/rendering_stats_unittest.cc
index c1e189a..6784e09 100644
--- a/cc/debug/rendering_stats_unittest.cc
+++ b/cc/debug/rendering_stats_unittest.cc
@@ -13,8 +13,8 @@
namespace {
static std::string ToString(const RenderingStats::TimeDeltaList& list) {
- scoped_refptr<base::debug::TracedValue> value =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> value =
+ new base::trace_event::TracedValue();
list.AddToTracedValue("list_value", value.get());
return value->ToString();
}
diff --git a/cc/debug/traced_picture.cc b/cc/debug/traced_picture.cc
index 2db5492..2c7622b 100644
--- a/cc/debug/traced_picture.cc
+++ b/cc/debug/traced_picture.cc
@@ -16,17 +16,17 @@
TracedPicture::~TracedPicture() {
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
TracedPicture::AsTraceablePicture(const Picture* picture) {
- return scoped_refptr<base::debug::ConvertableToTraceFormat>(
+ return scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
new TracedPicture(picture));
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
TracedPicture::AsTraceablePictureAlias(const Picture* original) {
scoped_refptr<TracedPicture> ptr = new TracedPicture(original);
ptr->is_alias_ = true;
- return scoped_refptr<base::debug::ConvertableToTraceFormat>(ptr);
+ return scoped_refptr<base::trace_event::ConvertableToTraceFormat>(ptr);
}
void TracedPicture::AppendAsTraceFormat(std::string* out) const {
diff --git a/cc/debug/traced_picture.h b/cc/debug/traced_picture.h
index 7212277..b9d232d 100644
--- a/cc/debug/traced_picture.h
+++ b/cc/debug/traced_picture.h
@@ -13,14 +13,14 @@
namespace cc {
-class TracedPicture : public base::debug::ConvertableToTraceFormat {
+class TracedPicture : public base::trace_event::ConvertableToTraceFormat {
public:
explicit TracedPicture(scoped_refptr<const Picture>);
- static scoped_refptr<base::debug::ConvertableToTraceFormat>
+ static scoped_refptr<base::trace_event::ConvertableToTraceFormat>
AsTraceablePicture(const Picture* picture);
- static scoped_refptr<base::debug::ConvertableToTraceFormat>
+ static scoped_refptr<base::trace_event::ConvertableToTraceFormat>
AsTraceablePictureAlias(const Picture* original);
void AppendAsTraceFormat(std::string* out) const override;
diff --git a/cc/debug/traced_value.cc b/cc/debug/traced_value.cc
index 72b7ff3..c2ac7f5 100644
--- a/cc/debug/traced_value.cc
+++ b/cc/debug/traced_value.cc
@@ -9,29 +9,31 @@
namespace cc {
-void TracedValue::AppendIDRef(const void* id, base::debug::TracedValue* state) {
+void TracedValue::AppendIDRef(const void* id,
+ base::trace_event::TracedValue* state) {
state->BeginDictionary();
state->SetString("id_ref", base::StringPrintf("%p", id));
state->EndDictionary();
}
void TracedValue::SetIDRef(const void* id,
- base::debug::TracedValue* state,
+ base::trace_event::TracedValue* state,
const char* name) {
state->BeginDictionary(name);
state->SetString("id_ref", base::StringPrintf("%p", id));
state->EndDictionary();
}
-void TracedValue::MakeDictIntoImplicitSnapshot(base::debug::TracedValue* dict,
- const char* object_name,
- const void* id) {
+void TracedValue::MakeDictIntoImplicitSnapshot(
+ base::trace_event::TracedValue* dict,
+ const char* object_name,
+ const void* id) {
dict->SetString("id", base::StringPrintf("%s/%p", object_name, id));
}
void TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
const char* category,
- base::debug::TracedValue* dict,
+ base::trace_event::TracedValue* dict,
const char* object_name,
const void* id) {
dict->SetString("cat", category);
@@ -40,7 +42,7 @@
void TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
const char* category,
- base::debug::TracedValue* dict,
+ base::trace_event::TracedValue* dict,
const char* object_base_type_name,
const char* object_name,
const void* id) {
diff --git a/cc/debug/traced_value.h b/cc/debug/traced_value.h
index db0a08a..34e79a7 100644
--- a/cc/debug/traced_value.h
+++ b/cc/debug/traced_value.h
@@ -9,33 +9,28 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015.
-namespace debug {
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
class TracedValue {
public:
- static void AppendIDRef(const void* id, base::debug::TracedValue* array);
+ static void AppendIDRef(const void* id,
+ base::trace_event::TracedValue* array);
static void SetIDRef(const void* id,
- base::debug::TracedValue* dict,
+ base::trace_event::TracedValue* dict,
const char* name);
- static void MakeDictIntoImplicitSnapshot(base::debug::TracedValue* dict,
+ static void MakeDictIntoImplicitSnapshot(base::trace_event::TracedValue* dict,
const char* object_name,
const void* id);
static void MakeDictIntoImplicitSnapshotWithCategory(
const char* category,
- base::debug::TracedValue* dict,
+ base::trace_event::TracedValue* dict,
const char* object_name,
const void* id);
static void MakeDictIntoImplicitSnapshotWithCategory(
const char* category,
- base::debug::TracedValue* dict,
+ base::trace_event::TracedValue* dict,
const char* object_base_type_name,
const char* object_name,
const void* id);
diff --git a/cc/input/top_controls_manager.cc b/cc/input/top_controls_manager.cc
index 1615d7f..615afb0 100644
--- a/cc/input/top_controls_manager.cc
+++ b/cc/input/top_controls_manager.cc
@@ -39,7 +39,6 @@
: client_(client),
animation_direction_(NO_ANIMATION),
permitted_state_(BOTH),
- top_controls_height_(0.f),
current_scroll_delta_(0.f),
controls_scroll_begin_offset_(0.f),
top_controls_show_threshold_(top_controls_hide_threshold),
@@ -51,12 +50,20 @@
TopControlsManager::~TopControlsManager() {
}
-float TopControlsManager::ControlsTopOffset() {
- return client_->ControlsTopOffset();
+float TopControlsManager::ControlsTopOffset() const {
+ return ContentTopOffset() - TopControlsHeight();
}
-float TopControlsManager::ContentTopOffset() {
- return client_->ControlsTopOffset() + top_controls_height_;
+float TopControlsManager::ContentTopOffset() const {
+ return TopControlsShownRatio() * TopControlsHeight();
+}
+
+float TopControlsManager::TopControlsShownRatio() const {
+ return client_->CurrentTopControlsShownRatio();
+}
+
+float TopControlsManager::TopControlsHeight() const {
+ return client_->TopControlsHeight();
}
void TopControlsManager::UpdateTopControlsState(TopControlsState constraints,
@@ -72,31 +79,25 @@
return;
// Don't do anything if there is no change in offset.
- float final_controls_position = 0.f;
- if (constraints == HIDDEN || current == HIDDEN) {
- final_controls_position = -top_controls_height_;
- }
- if (final_controls_position == client_->ControlsTopOffset()) {
- return;
- }
-
- AnimationDirection animation_direction = SHOWING_CONTROLS;
+ float final_shown_ratio = 1.f;
if (constraints == HIDDEN || current == HIDDEN)
- animation_direction = HIDING_CONTROLS;
- ResetAnimations();
+ final_shown_ratio = 0.f;
+ if (final_shown_ratio == TopControlsShownRatio())
+ return;
+
if (animate) {
- SetupAnimation(animation_direction);
+ SetupAnimation(final_shown_ratio ? SHOWING_CONTROLS : HIDING_CONTROLS);
} else {
- client_->SetControlsTopOffset(final_controls_position);
+ ResetAnimations();
+ client_->SetCurrentTopControlsShownRatio(final_shown_ratio);
}
- client_->DidChangeTopControlsPosition();
}
void TopControlsManager::ScrollBegin() {
DCHECK(!pinch_gesture_active_);
ResetAnimations();
current_scroll_delta_ = 0.f;
- controls_scroll_begin_offset_ = client_->ControlsTopOffset();
+ controls_scroll_begin_offset_ = ContentTopOffset();
}
gfx::Vector2dF TopControlsManager::ScrollBy(
@@ -111,19 +112,21 @@
current_scroll_delta_ += pending_delta.y();
- float old_offset = client_->ControlsTopOffset();
- SetControlsTopOffset(controls_scroll_begin_offset_ - current_scroll_delta_);
+ float old_offset = ContentTopOffset();
+ client_->SetCurrentTopControlsShownRatio(
+ (controls_scroll_begin_offset_ - current_scroll_delta_) /
+ TopControlsHeight());
// If the controls are fully visible, treat the current position as the
// new baseline even if the gesture didn't end.
- if (client_->ControlsTopOffset() == 0.f) {
+ if (TopControlsShownRatio() == 1.f) {
current_scroll_delta_ = 0.f;
- controls_scroll_begin_offset_ = 0.f;
+ controls_scroll_begin_offset_ = ContentTopOffset();
}
ResetAnimations();
- gfx::Vector2dF applied_delta(0.f, old_offset - client_->ControlsTopOffset());
+ gfx::Vector2dF applied_delta(0.f, old_offset - ContentTopOffset());
return pending_delta - applied_delta;
}
@@ -146,44 +149,20 @@
ScrollBegin();
}
-void TopControlsManager::SetControlsTopOffset(float controls_top_offset) {
- controls_top_offset = std::max(controls_top_offset, -top_controls_height_);
- controls_top_offset = std::min(controls_top_offset, 0.f);
-
- if (client_->ControlsTopOffset() == controls_top_offset)
- return;
-
- client_->SetControlsTopOffset(controls_top_offset);
-
- client_->DidChangeTopControlsPosition();
-}
-
-void TopControlsManager::SetTopControlsHeight(float top_controls_height) {
- DCHECK_GE(top_controls_height, 0);
-
- if (top_controls_height == top_controls_height_)
- return;
-
- ResetAnimations();
- float top_controls_offset = client_->ControlsTopOffset();
- top_controls_height_ = top_controls_height;
- SetControlsTopOffset(top_controls_offset);
- StartAnimationIfNecessary();
-}
-
gfx::Vector2dF TopControlsManager::Animate(base::TimeTicks monotonic_time) {
if (!top_controls_animation_ || !client_->HaveRootScrollLayer())
return gfx::Vector2dF();
base::TimeDelta time = monotonic_time - base::TimeTicks();
- float old_offset = client_->ControlsTopOffset();
- SetControlsTopOffset(top_controls_animation_->GetValue(time));
+ float old_offset = ContentTopOffset();
+ client_->SetCurrentTopControlsShownRatio(
+ top_controls_animation_->GetValue(time));
if (IsAnimationCompleteAtTime(monotonic_time))
ResetAnimations();
- gfx::Vector2dF scroll_delta(0.f, client_->ControlsTopOffset() - old_offset);
+ gfx::Vector2dF scroll_delta(0.f, ContentTopOffset() - old_offset);
return scroll_delta;
}
@@ -193,15 +172,9 @@
}
void TopControlsManager::SetupAnimation(AnimationDirection direction) {
- DCHECK(direction != NO_ANIMATION);
-
- if (direction == SHOWING_CONTROLS && client_->ControlsTopOffset() == 0)
- return;
-
- if (direction == HIDING_CONTROLS &&
- client_->ControlsTopOffset() == -top_controls_height_) {
- return;
- }
+ DCHECK_NE(NO_ANIMATION, direction);
+ DCHECK_IMPLIES(direction == HIDING_CONTROLS, TopControlsShownRatio() > 0.f);
+ DCHECK_IMPLIES(direction == SHOWING_CONTROLS, TopControlsShownRatio() < 1.f);
if (top_controls_animation_ && animation_direction_ == direction)
return;
@@ -209,42 +182,32 @@
top_controls_animation_ = KeyframedFloatAnimationCurve::Create();
base::TimeDelta start_time = gfx::FrameTime::Now() - base::TimeTicks();
top_controls_animation_->AddKeyframe(
- FloatKeyframe::Create(start_time, client_->ControlsTopOffset(), nullptr));
- float max_ending_offset =
- (direction == SHOWING_CONTROLS ? 1 : -1) * top_controls_height_;
+ FloatKeyframe::Create(start_time, TopControlsShownRatio(), nullptr));
+ float max_ending_ratio = (direction == SHOWING_CONTROLS ? 1 : -1);
top_controls_animation_->AddKeyframe(FloatKeyframe::Create(
start_time + base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs),
- client_->ControlsTopOffset() + max_ending_offset,
+ TopControlsShownRatio() + max_ending_ratio,
EaseTimingFunction::Create()));
animation_direction_ = direction;
client_->DidChangeTopControlsPosition();
}
void TopControlsManager::StartAnimationIfNecessary() {
- if (client_->ControlsTopOffset() != 0
- && client_->ControlsTopOffset() != -top_controls_height_) {
- AnimationDirection show_controls = NO_ANIMATION;
+ if (TopControlsShownRatio() == 0.f || TopControlsShownRatio() == 1.f)
+ return;
- float top_controls_show_height =
- top_controls_height_ * top_controls_hide_threshold_;
- float top_controls_hide_height =
- top_controls_height_ * (1.f - top_controls_show_threshold_);
- if (client_->ControlsTopOffset() >= -top_controls_show_height) {
- // If we're showing so much that the hide threshold won't trigger, show.
- show_controls = SHOWING_CONTROLS;
- } else if (client_->ControlsTopOffset() <= -top_controls_hide_height) {
- // If we're showing so little that the show threshold won't trigger, hide.
- show_controls = HIDING_CONTROLS;
- } else {
- // If we could be either showing or hiding, we determine which one to
- // do based on whether or not the total scroll delta was moving up or
- // down.
- show_controls = current_scroll_delta_ <= 0.f ?
- SHOWING_CONTROLS : HIDING_CONTROLS;
- }
-
- if (show_controls != NO_ANIMATION)
- SetupAnimation(show_controls);
+ if (TopControlsShownRatio() >= 1.f - top_controls_hide_threshold_) {
+ // If we're showing so much that the hide threshold won't trigger, show.
+ SetupAnimation(SHOWING_CONTROLS);
+ } else if (TopControlsShownRatio() <= top_controls_show_threshold_) {
+ // If we're showing so little that the show threshold won't trigger, hide.
+ SetupAnimation(HIDING_CONTROLS);
+ } else {
+ // If we could be either showing or hiding, we determine which one to
+ // do based on whether or not the total scroll delta was moving up or
+ // down.
+ SetupAnimation(current_scroll_delta_ <= 0.f ? SHOWING_CONTROLS
+ : HIDING_CONTROLS);
}
}
@@ -253,11 +216,10 @@
return true;
base::TimeDelta animation_time = time - base::TimeTicks();
- float new_offset = top_controls_animation_->GetValue(animation_time);
+ float new_ratio = top_controls_animation_->GetValue(animation_time);
- if ((animation_direction_ == SHOWING_CONTROLS && new_offset >= 0) ||
- (animation_direction_ == HIDING_CONTROLS
- && new_offset <= -top_controls_height_)) {
+ if ((animation_direction_ == SHOWING_CONTROLS && new_ratio >= 1.f) ||
+ (animation_direction_ == HIDING_CONTROLS && new_ratio <= 0.f)) {
return true;
}
return false;
diff --git a/cc/input/top_controls_manager.h b/cc/input/top_controls_manager.h
index 69408ae..06f623d 100644
--- a/cc/input/top_controls_manager.h
+++ b/cc/input/top_controls_manager.h
@@ -38,8 +38,10 @@
float top_controls_hide_threshold);
virtual ~TopControlsManager();
- float ControlsTopOffset();
- float ContentTopOffset();
+ float ControlsTopOffset() const;
+ float ContentTopOffset() const;
+ float TopControlsShownRatio() const;
+ float TopControlsHeight() const;
KeyframedFloatAnimationCurve* animation() {
return top_controls_animation_.get();
@@ -60,9 +62,6 @@
void PinchEnd();
gfx::Vector2dF Animate(base::TimeTicks monotonic_time);
- void SetControlsTopOffset(float offset);
- void SetTopControlsHeight(float top_controls_height);
- float top_controls_height() { return top_controls_height_; }
protected:
TopControlsManager(TopControlsManagerClient* client,
@@ -81,7 +80,6 @@
scoped_ptr<KeyframedFloatAnimationCurve> top_controls_animation_;
AnimationDirection animation_direction_;
TopControlsState permitted_state_;
- float top_controls_height_;
float current_scroll_delta_;
float controls_scroll_begin_offset_;
diff --git a/cc/input/top_controls_manager_client.h b/cc/input/top_controls_manager_client.h
index 53b5978..a0f2f5b 100644
--- a/cc/input/top_controls_manager_client.h
+++ b/cc/input/top_controls_manager_client.h
@@ -11,8 +11,9 @@
class CC_EXPORT TopControlsManagerClient {
public:
- virtual void SetControlsTopOffset(float offset) = 0;
- virtual float ControlsTopOffset() const = 0;
+ virtual float TopControlsHeight() const = 0;
+ virtual void SetCurrentTopControlsShownRatio(float ratio) = 0;
+ virtual float CurrentTopControlsShownRatio() const = 0;
virtual void DidChangeTopControlsPosition() = 0;
virtual bool HaveRootScrollLayer() const = 0;
diff --git a/cc/input/top_controls_manager_unittest.cc b/cc/input/top_controls_manager_unittest.cc
index 0be40ca..16d0e5d 100644
--- a/cc/input/top_controls_manager_unittest.cc
+++ b/cc/input/top_controls_manager_unittest.cc
@@ -4,6 +4,8 @@
#include "cc/input/top_controls_manager.h"
+#include <algorithm>
+
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "cc/input/top_controls_manager_client.h"
@@ -27,13 +29,13 @@
: host_impl_(&proxy_, &shared_bitmap_manager_),
redraw_needed_(false),
update_draw_properties_needed_(false),
- top_controls_top_offset_(0.f),
+ top_controls_shown_ratio_(1.f),
top_controls_height_(top_controls_height),
top_controls_show_threshold_(top_controls_show_threshold),
top_controls_hide_threshold_(top_controls_hide_threshold) {
- active_tree_ =
- LayerTreeImpl::create(&host_impl_, new SyncedProperty<ScaleGroup>,
- new SyncedElasticOverscroll);
+ active_tree_ = LayerTreeImpl::create(
+ &host_impl_, new SyncedProperty<ScaleGroup>, new SyncedTopControls,
+ new SyncedElasticOverscroll);
root_scroll_layer_ = LayerImpl::Create(active_tree_.get(), 1);
}
@@ -46,11 +48,17 @@
bool HaveRootScrollLayer() const override { return true; }
- void SetControlsTopOffset(float offset) override {
- top_controls_top_offset_ = offset;
+ float TopControlsHeight() const override { return top_controls_height_; }
+
+ void SetCurrentTopControlsShownRatio(float ratio) override {
+ ratio = std::max(ratio, 0.f);
+ ratio = std::min(ratio, 1.f);
+ top_controls_shown_ratio_ = ratio;
}
- float ControlsTopOffset() const override { return top_controls_top_offset_; }
+ float CurrentTopControlsShownRatio() const override {
+ return top_controls_shown_ratio_;
+ }
LayerImpl* rootScrollLayer() {
return root_scroll_layer_.get();
@@ -61,11 +69,12 @@
manager_ = TopControlsManager::Create(this,
top_controls_show_threshold_,
top_controls_hide_threshold_);
- manager_->SetTopControlsHeight(top_controls_height_);
}
return manager_.get();
}
+ void SetTopControlsHeight(float height) { top_controls_height_ = height; }
+
private:
FakeImplProxy proxy_;
TestSharedBitmapManager shared_bitmap_manager_;
@@ -76,7 +85,7 @@
bool redraw_needed_;
bool update_draw_properties_needed_;
- float top_controls_top_offset_;
+ float top_controls_shown_ratio_;
float top_controls_height_;
float top_controls_show_threshold_;
float top_controls_hide_threshold_;
@@ -90,38 +99,38 @@
// Scroll down to hide the controls entirely.
manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
- EXPECT_EQ(-30.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
- EXPECT_EQ(-60.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-60.f, manager->ControlsTopOffset());
manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
// Scroll back up a bit and ensure the controls don't move until we cross
// the threshold.
manager->ScrollBy(gfx::Vector2dF(0.f, -10.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
manager->ScrollBy(gfx::Vector2dF(0.f, -50.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
// After hitting the threshold, further scrolling up should result in the top
// controls showing.
manager->ScrollBy(gfx::Vector2dF(0.f, -10.f));
- EXPECT_EQ(-90.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-90.f, manager->ControlsTopOffset());
manager->ScrollBy(gfx::Vector2dF(0.f, -50.f));
- EXPECT_EQ(-40.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-40.f, manager->ControlsTopOffset());
// Reset the scroll threshold by going further up the page than the initial
// threshold.
manager->ScrollBy(gfx::Vector2dF(0.f, -100.f));
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
// See that scrolling down the page now will result in the controls hiding.
manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
- EXPECT_EQ(-20.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
manager->ScrollEnd();
}
@@ -131,29 +140,29 @@
TopControlsManager* manager = client.manager();
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
manager->ScrollEnd();
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
- EXPECT_EQ(-85.f, manager->ControlsTopOffset());
- EXPECT_EQ(15.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
base::TimeTicks time = gfx::FrameTime::Now();
- float previous_offset = manager->ControlsTopOffset();
+ float previous;
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_LT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_LT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
}
TEST(TopControlsManagerTest, PartialShownShowAnimation) {
@@ -161,29 +170,29 @@
TopControlsManager* manager = client.manager();
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
manager->ScrollEnd();
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, -70.f));
- EXPECT_EQ(-30.f, manager->ControlsTopOffset());
- EXPECT_EQ(70.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(70.f, manager->ContentTopOffset());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
base::TimeTicks time = gfx::FrameTime::Now();
- float previous_offset = manager->ControlsTopOffset();
+ float previous;
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_GT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_GT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
- EXPECT_EQ(100.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
}
TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdShows) {
@@ -193,23 +202,23 @@
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
- EXPECT_EQ(-20.f, manager->ControlsTopOffset());
- EXPECT_EQ(80.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(80.f, manager->ContentTopOffset());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
base::TimeTicks time = gfx::FrameTime::Now();
- float previous_offset = manager->ControlsTopOffset();
+ float previous;
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_GT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_GT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
- EXPECT_EQ(100.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
}
TEST(TopControlsManagerTest, PartialHiddenWithAmbiguousThresholdHides) {
@@ -219,23 +228,23 @@
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
- EXPECT_EQ(-30.f, manager->ControlsTopOffset());
- EXPECT_EQ(70.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(70.f, manager->ContentTopOffset());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
base::TimeTicks time = gfx::FrameTime::Now();
- float previous_offset = manager->ControlsTopOffset();
+ float previous;
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_LT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_LT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
}
TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdHides) {
@@ -243,29 +252,29 @@
TopControlsManager* manager = client.manager();
manager->ScrollBy(gfx::Vector2dF(0.f, 200.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, -20.f));
- EXPECT_EQ(-80.f, manager->ControlsTopOffset());
- EXPECT_EQ(20.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
base::TimeTicks time = gfx::FrameTime::Now();
- float previous_offset = manager->ControlsTopOffset();
+ float previous;
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_LT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_LT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
}
TEST(TopControlsManagerTest, PartialShownWithAmbiguousThresholdShows) {
@@ -273,29 +282,29 @@
TopControlsManager* manager = client.manager();
manager->ScrollBy(gfx::Vector2dF(0.f, 200.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, -30.f));
- EXPECT_EQ(-70.f, manager->ControlsTopOffset());
- EXPECT_EQ(30.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-70.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(30.f, manager->ContentTopOffset());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
base::TimeTicks time = gfx::FrameTime::Now();
- float previous_offset = manager->ControlsTopOffset();
+ float previous;
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_GT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_GT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
- EXPECT_EQ(100.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
}
TEST(TopControlsManagerTest, PinchIgnoresScroll) {
@@ -304,24 +313,24 @@
// Hide the controls.
manager->ScrollBegin();
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
manager->PinchBegin();
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
// Scrolls are ignored during pinch.
manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
manager->PinchEnd();
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
// Scrolls should no long be ignored.
manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
- EXPECT_EQ(-85.f, manager->ControlsTopOffset());
- EXPECT_EQ(15.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
@@ -333,7 +342,7 @@
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
manager->PinchBegin();
EXPECT_FALSE(manager->animation());
@@ -342,19 +351,19 @@
EXPECT_FALSE(manager->animation());
manager->ScrollBy(gfx::Vector2dF(0.f, -15.f));
- EXPECT_EQ(-85.f, manager->ControlsTopOffset());
- EXPECT_EQ(15.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-85.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(15.f, manager->ContentTopOffset());
manager->PinchBegin();
EXPECT_TRUE(manager->animation());
base::TimeTicks time = base::TimeTicks::Now();
- float previous_offset = manager->ControlsTopOffset();
+ float previous;
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_LT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_LT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
@@ -362,41 +371,57 @@
EXPECT_FALSE(manager->animation());
manager->ScrollBy(gfx::Vector2dF(0.f, -55.f));
- EXPECT_EQ(-45.f, manager->ControlsTopOffset());
- EXPECT_EQ(55.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-45.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(55.f, manager->ContentTopOffset());
EXPECT_FALSE(manager->animation());
manager->ScrollEnd();
EXPECT_TRUE(manager->animation());
time = base::TimeTicks::Now();
- previous_offset = manager->ControlsTopOffset();
while (manager->animation()) {
+ previous = manager->TopControlsShownRatio();
time = base::TimeDelta::FromMicroseconds(100) + time;
manager->Animate(time);
- EXPECT_GT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
+ EXPECT_GT(manager->TopControlsShownRatio(), previous);
}
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
}
TEST(TopControlsManagerTest, HeightChangeMaintainsFullyVisibleControls) {
MockTopControlsManagerClient client(0.f, 0.5f, 0.5f);
TopControlsManager* manager = client.manager();
- EXPECT_EQ(0.f, manager->top_controls_height());
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
- manager->SetTopControlsHeight(100.f);
+ client.SetTopControlsHeight(100.f);
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(100.f, manager->top_controls_height());
- EXPECT_EQ(0, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(100.f, manager->TopControlsHeight());
+ EXPECT_FLOAT_EQ(0, manager->ControlsTopOffset());
- manager->SetTopControlsHeight(50.f);
+ client.SetTopControlsHeight(50.f);
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(50.f, manager->top_controls_height());
+ EXPECT_FLOAT_EQ(50.f, manager->TopControlsHeight());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+}
+
+TEST(TopControlsManagerTest, GrowingHeightKeepsTopControlsHidden) {
+ MockTopControlsManagerClient client(0.f, 0.5f, 0.5f);
+ TopControlsManager* manager = client.manager();
+ manager->UpdateTopControlsState(HIDDEN, HIDDEN, false);
EXPECT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_EQ(0.f, manager->ContentTopOffset());
+
+ client.SetTopControlsHeight(50.f);
+ EXPECT_FALSE(manager->animation());
+ EXPECT_EQ(-50.f, manager->ControlsTopOffset());
+ EXPECT_EQ(0.f, manager->ContentTopOffset());
+
+ client.SetTopControlsHeight(100.f);
+ EXPECT_FALSE(manager->animation());
+ EXPECT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_EQ(0.f, manager->ContentTopOffset());
}
TEST(TopControlsManagerTest, ShrinkingHeightKeepsTopControlsHidden) {
@@ -405,56 +430,20 @@
manager->ScrollBegin();
manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
- EXPECT_EQ(-100.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
manager->ScrollEnd();
- manager->SetTopControlsHeight(50.f);
+ client.SetTopControlsHeight(50.f);
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(-50.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-50.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
- manager->SetTopControlsHeight(0.f);
+ client.SetTopControlsHeight(0.f);
EXPECT_FALSE(manager->animation());
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+ EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
}
-TEST(TopControlsManagerTest, HiddenTopControlsReadjustOnIncreasedHeight) {
- MockTopControlsManagerClient client(10.f, 0.5f, 0.5f);
- TopControlsManager* manager = client.manager();
-
- manager->ScrollBegin();
- manager->ScrollBy(gfx::Vector2dF(0.f, 300.f));
- EXPECT_EQ(-10.f, manager->ControlsTopOffset());
- EXPECT_EQ(0.f, manager->ContentTopOffset());
- manager->ScrollEnd();
-
- manager->SetTopControlsHeight(15.f);
- EXPECT_TRUE(manager->animation());
- base::TimeTicks time = base::TimeTicks::Now();
- float previous_offset = manager->ControlsTopOffset();
- while (manager->animation()) {
- time = base::TimeDelta::FromMicroseconds(100) + time;
- manager->Animate(time);
- EXPECT_LT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
- }
- EXPECT_FALSE(manager->animation());
- EXPECT_EQ(-15.f, manager->ControlsTopOffset());
-
- manager->SetTopControlsHeight(35.f);
- EXPECT_TRUE(manager->animation());
- time = base::TimeTicks::Now();
- previous_offset = manager->ControlsTopOffset();
- while (manager->animation()) {
- time = base::TimeDelta::FromMicroseconds(100) + time;
- manager->Animate(time);
- EXPECT_GT(manager->ControlsTopOffset(), previous_offset);
- previous_offset = manager->ControlsTopOffset();
- }
- EXPECT_FALSE(manager->animation());
- EXPECT_EQ(0.f, manager->ControlsTopOffset());
-}
} // namespace
} // namespace cc
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc
index 8a95b9e..e1056be 100644
--- a/cc/layers/delegated_renderer_layer_impl.cc
+++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -255,7 +255,6 @@
void DelegatedRendererLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
AppendRainbowDebugBorder(render_pass);
@@ -282,7 +281,6 @@
DCHECK(target_render_pass_id.layer_id == render_target()->id());
AppendRenderPassQuads(render_pass,
- occlusion_in_content_space,
root_delegated_render_pass,
frame_size);
} else {
@@ -293,7 +291,6 @@
const RenderPass* delegated_render_pass =
render_passes_in_draw_order_[render_pass_index];
AppendRenderPassQuads(render_pass,
- occlusion_in_content_space,
delegated_render_pass,
frame_size);
}
@@ -349,39 +346,52 @@
break;
if (!top.IsEmpty()) {
+ bool force_anti_aliasing_off = false;
SolidColorDrawQuad* top_quad =
render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
- top_quad->SetNew(
- shared_quad_state, top, top, colors[i % kNumColors], false);
+ top_quad->SetNew(shared_quad_state, top, top, colors[i % kNumColors],
+ force_anti_aliasing_off);
SolidColorDrawQuad* bottom_quad =
render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
- bottom_quad->SetNew(shared_quad_state,
- bottom,
- bottom,
+ bottom_quad->SetNew(shared_quad_state, bottom, bottom,
colors[kNumColors - 1 - (i % kNumColors)],
- false);
+ force_anti_aliasing_off);
+
+ if (contents_opaque()) {
+ // Draws a stripe filling the layer vertically with the same color and
+ // width as the horizontal stipes along the layer's top border.
+ SolidColorDrawQuad* solid_quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ // The inner fill is more transparent then the border.
+ static const float kFillOpacity = 0.1f;
+ SkColor fill_color = SkColorSetA(
+ colors[i % kNumColors],
+ static_cast<uint8_t>(SkColorGetA(colors[i % kNumColors]) *
+ kFillOpacity));
+ gfx::Rect fill_rect(x, 0, width, content_bounds().height());
+ solid_quad->SetNew(shared_quad_state, fill_rect, fill_rect, fill_color,
+ force_anti_aliasing_off);
+ }
}
if (!left.IsEmpty()) {
+ bool force_anti_aliasing_off = false;
SolidColorDrawQuad* left_quad =
render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
- left_quad->SetNew(shared_quad_state,
- left,
- left,
+ left_quad->SetNew(shared_quad_state, left, left,
colors[kNumColors - 1 - (i % kNumColors)],
- false);
+ force_anti_aliasing_off);
SolidColorDrawQuad* right_quad =
render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
- right_quad->SetNew(
- shared_quad_state, right, right, colors[i % kNumColors], false);
+ right_quad->SetNew(shared_quad_state, right, right,
+ colors[i % kNumColors], force_anti_aliasing_off);
}
}
}
void DelegatedRendererLayerImpl::AppendRenderPassQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
const RenderPass* delegated_render_pass,
const gfx::Size& frame_size) const {
const SharedQuadState* delegated_shared_quad_state = nullptr;
@@ -437,8 +447,9 @@
}
Occlusion occlusion_in_quad_space =
- occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
- quad_content_to_delegated_target_space);
+ draw_properties()
+ .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
+ quad_content_to_delegated_target_space);
gfx::Rect quad_visible_rect =
occlusion_in_quad_space.GetUnoccludedContentRect(
diff --git a/cc/layers/delegated_renderer_layer_impl.h b/cc/layers/delegated_renderer_layer_impl.h
index 1ae3228..4a61ba1 100644
--- a/cc/layers/delegated_renderer_layer_impl.h
+++ b/cc/layers/delegated_renderer_layer_impl.h
@@ -34,7 +34,6 @@
bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
void PushPropertiesTo(LayerImpl* layer) override;
@@ -77,7 +76,6 @@
RenderPassId* output_render_pass_id) const;
void AppendRenderPassQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
const RenderPass* delegated_render_pass,
const gfx::Size& frame_size) const;
diff --git a/cc/layers/draw_properties.h b/cc/layers/draw_properties.h
index 5c78000..7cf89e7 100644
--- a/cc/layers/draw_properties.h
+++ b/cc/layers/draw_properties.h
@@ -6,6 +6,7 @@
#define CC_LAYERS_DRAW_PROPERTIES_H_
#include "base/memory/scoped_ptr.h"
+#include "cc/trees/occlusion.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/transform.h"
@@ -50,6 +51,9 @@
// Transforms objects from content space to screen space (viewport space).
gfx::Transform screen_space_transform;
+ // Known occlusion above the layer mapped to the content space of the layer.
+ Occlusion occlusion_in_content_space;
+
// DrawProperties::opacity may be different than LayerType::opacity,
// particularly in the case when a RenderSurface re-parents the layer's
// opacity, or when opacity is compounded by the hierarchy.
diff --git a/cc/layers/heads_up_display_layer.h b/cc/layers/heads_up_display_layer.h
index 7ca0992..ddc34f2 100644
--- a/cc/layers/heads_up_display_layer.h
+++ b/cc/layers/heads_up_display_layer.h
@@ -9,11 +9,11 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
-#include "cc/layers/contents_scaling_layer.h"
+#include "cc/layers/layer.h"
namespace cc {
-class CC_EXPORT HeadsUpDisplayLayer : public ContentsScalingLayer {
+class CC_EXPORT HeadsUpDisplayLayer : public Layer {
public:
static scoped_refptr<HeadsUpDisplayLayer> Create();
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index 60d984b..97fddae 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -28,6 +28,7 @@
#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"
namespace cc {
@@ -69,6 +70,7 @@
HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
int id)
: LayerImpl(tree_impl, id),
+ internal_contents_scale_(1.f),
fps_graph_(60.0, 80.0),
paint_time_graph_(16.0, 48.0),
fade_step_(0) {
@@ -94,8 +96,8 @@
scoped_ptr<ScopedResource> resource =
ScopedResource::Create(resource_provider);
- resource->Allocate(
- content_bounds(), ResourceProvider::TextureHintImmutable, RGBA_8888);
+ resource->Allocate(internal_content_bounds_,
+ ResourceProvider::TextureHintImmutable, RGBA_8888);
resources_.push_back(resource.Pass());
}
@@ -115,7 +117,7 @@
void HeadsUpDisplayLayerImpl::ReleaseUnmatchedSizeResources(
ResourceProvider* resource_provider) {
ScopedPtrVector<ScopedResource>::iterator it_erase =
- resources_.partition(ResourceSizeIsEqualTo(content_bounds()));
+ resources_.partition(ResourceSizeIsEqualTo(internal_content_bounds_));
resources_.erase(it_erase, resources_.end());
}
@@ -124,6 +126,10 @@
if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
return false;
+ internal_contents_scale_ = draw_properties().ideal_contents_scale;
+ internal_content_bounds_ =
+ gfx::ToCeiledSize(gfx::ScaleSize(bounds(), internal_contents_scale_));
+
ReleaseUnmatchedSizeResources(resource_provider);
AcquireResource(resource_provider);
return LayerImpl::WillDraw(draw_mode, resource_provider);
@@ -131,16 +137,15 @@
void HeadsUpDisplayLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
if (!resources_.back()->id())
return;
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
- PopulateSharedQuadState(shared_quad_state);
+ PopulateScaledSharedQuadState(shared_quad_state, internal_contents_scale_);
- gfx::Rect quad_rect(content_bounds());
+ gfx::Rect quad_rect(internal_content_bounds_);
gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
gfx::Rect visible_quad_rect(quad_rect);
bool premultiplied_alpha = true;
@@ -177,12 +182,13 @@
else
canvas_size.set(0, 0);
- if (canvas_size.width() != content_bounds().width() ||
- canvas_size.height() != content_bounds().height() || !hud_surface_) {
+ if (canvas_size.width() != internal_content_bounds_.width() ||
+ canvas_size.height() != internal_content_bounds_.height() ||
+ !hud_surface_) {
TRACE_EVENT0("cc", "ResizeHudCanvas");
hud_surface_ = skia::AdoptRef(SkSurface::NewRasterN32Premul(
- content_bounds().width(), content_bounds().height()));
+ internal_content_bounds_.width(), internal_content_bounds_.height()));
}
UpdateHudContents();
@@ -191,7 +197,8 @@
TRACE_EVENT0("cc", "DrawHudContents");
hud_surface_->getCanvas()->clear(SkColorSetARGB(0, 0, 0, 0));
hud_surface_->getCanvas()->save();
- hud_surface_->getCanvas()->scale(contents_scale_x(), contents_scale_y());
+ hud_surface_->getCanvas()->scale(internal_contents_scale_,
+ internal_contents_scale_);
DrawHudContents(hud_surface_->getCanvas());
@@ -203,7 +210,7 @@
size_t row_bytes = 0;
const void* pixels = hud_surface_->getCanvas()->peekPixels(&info, &row_bytes);
DCHECK(pixels);
- gfx::Rect content_rect(content_bounds());
+ gfx::Rect content_rect(internal_content_bounds_);
DCHECK(info.colorType() == kN32_SkColorType);
resource_provider->SetPixels(resources_.back()->id(),
static_cast<const uint8_t*>(pixels),
@@ -677,8 +684,9 @@
SkColor fill_color,
float stroke_width,
const std::string& label_text) const {
- gfx::Rect debug_layer_rect = gfx::ScaleToEnclosingRect(
- rect.rect, 1.0 / contents_scale_x(), 1.0 / contents_scale_y());
+ gfx::Rect debug_layer_rect =
+ gfx::ScaleToEnclosingRect(rect.rect, 1.0 / internal_contents_scale_,
+ 1.0 / internal_contents_scale_);
SkIRect sk_rect = RectToSkIRect(debug_layer_rect);
paint->setColor(fill_color);
paint->setStyle(SkPaint::kFill_Style);
@@ -696,7 +704,7 @@
// The debug_layer_rect may be huge, and converting to a floating point may
// be lossy, so intersect with the HUD layer bounds first to prevent that.
gfx::Rect clip_rect = debug_layer_rect;
- clip_rect.Intersect(gfx::Rect(content_bounds()));
+ clip_rect.Intersect(gfx::Rect(internal_content_bounds_));
SkRect sk_clip_rect = RectToSkRect(clip_rect);
canvas->save();
@@ -764,16 +772,6 @@
fill_color = DebugColors::ScreenSpaceLayerRectFillColor();
stroke_width = DebugColors::ScreenSpaceLayerRectBorderWidth();
break;
- case OCCLUDING_RECT_TYPE:
- stroke_color = DebugColors::OccludingRectBorderColor();
- fill_color = DebugColors::OccludingRectFillColor();
- stroke_width = DebugColors::OccludingRectBorderWidth();
- break;
- case NONOCCLUDING_RECT_TYPE:
- stroke_color = DebugColors::NonOccludingRectBorderColor();
- fill_color = DebugColors::NonOccludingRectFillColor();
- stroke_width = DebugColors::NonOccludingRectBorderWidth();
- break;
case TOUCH_EVENT_HANDLER_RECT_TYPE:
stroke_color = DebugColors::TouchEventHandlerRectBorderColor();
fill_color = DebugColors::TouchEventHandlerRectFillColor();
@@ -838,7 +836,7 @@
}
void HeadsUpDisplayLayerImpl::AsValueInto(
- base::debug::TracedValue* dict) const {
+ base::trace_event::TracedValue* dict) const {
LayerImpl::AsValueInto(dict);
dict->SetString("layer_name", "Heads Up Display Layer");
}
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h
index abba5dc..5c3720e 100644
--- a/cc/layers/heads_up_display_layer_impl.h
+++ b/cc/layers/heads_up_display_layer_impl.h
@@ -39,7 +39,6 @@
bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
void UpdateHudTexture(DrawMode draw_mode,
ResourceProvider* resource_provider);
@@ -71,7 +70,7 @@
const char* LayerTypeAsString() const override;
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
void UpdateHudContents();
void DrawHudContents(SkCanvas* canvas);
@@ -128,6 +127,9 @@
ScopedPtrVector<ScopedResource> resources_;
skia::RefPtr<SkSurface> hud_surface_;
+ float internal_contents_scale_;
+ gfx::Size internal_content_bounds_;
+
Graph fps_graph_;
Graph paint_time_graph_;
MemoryHistory::Entry memory_entry_;
diff --git a/cc/layers/heads_up_display_layer_impl_unittest.cc b/cc/layers/heads_up_display_layer_impl_unittest.cc
index d342d4f..4b07323 100644
--- a/cc/layers/heads_up_display_layer_impl_unittest.cc
+++ b/cc/layers/heads_up_display_layer_impl_unittest.cc
@@ -20,7 +20,7 @@
AppendQuadsData data;
bool will_draw = layer->WillDraw(draw_mode, resource_provider);
if (will_draw)
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
layer->UpdateHudTexture(draw_mode, resource_provider);
if (will_draw)
layer->DidDraw(resource_provider);
@@ -37,7 +37,8 @@
host_impl.InitializeRenderer(FakeOutputSurface::Create3d());
scoped_ptr<HeadsUpDisplayLayerImpl> layer =
HeadsUpDisplayLayerImpl::Create(host_impl.pending_tree(), 1);
- layer->SetContentBounds(gfx::Size(100, 100));
+ layer->SetBounds(gfx::Size(100, 100));
+ layer->draw_properties().ideal_contents_scale = 1.f;
// Check regular hardware draw is ok.
CheckDrawLayer(
diff --git a/cc/layers/io_surface_layer_impl.cc b/cc/layers/io_surface_layer_impl.cc
index 8d22195..6bd03fd 100644
--- a/cc/layers/io_surface_layer_impl.cc
+++ b/cc/layers/io_surface_layer_impl.cc
@@ -66,7 +66,6 @@
void IOSurfaceLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
@@ -78,7 +77,8 @@
gfx::Rect quad_rect(content_bounds());
gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
gfx::Rect visible_quad_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(quad_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ quad_rect);
if (visible_quad_rect.IsEmpty())
return;
diff --git a/cc/layers/io_surface_layer_impl.h b/cc/layers/io_surface_layer_impl.h
index 663bcef..8317760 100644
--- a/cc/layers/io_surface_layer_impl.h
+++ b/cc/layers/io_surface_layer_impl.h
@@ -27,7 +27,6 @@
void PushPropertiesTo(LayerImpl* layer_tree_impl) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
bool WillDraw(DrawMode draw_mode,
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 01e67c5..19b505b 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -1108,7 +1108,8 @@
return true;
}
-scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+Layer::TakeDebugInfo() {
if (client_)
return client_->TakeDebugInfo();
else
@@ -1298,13 +1299,24 @@
gfx::Transform Layer::draw_transform_from_property_trees(
const TransformTree& tree) const {
- gfx::Transform xform(1, 0, 0, 1, offset_to_transform_parent().x(),
- offset_to_transform_parent().y());
- if (transform_tree_index() >= 0) {
- const TransformNode* node = tree.Node(transform_tree_index());
- gfx::Transform ssxform;
- tree.ComputeTransform(node->id, node->data.target_id, &ssxform);
- xform.ConcatTransform(ssxform);
+ const TransformNode* node = tree.Node(transform_tree_index());
+ // TODO(vollick): ultimately we'll need to find this information (whether or
+ // not we establish a render surface) somewhere other than the layer.
+ const TransformNode* target_node =
+ has_render_surface_ ? node : tree.Node(node->data.content_target_id);
+
+ gfx::Transform xform;
+ const bool owns_non_root_surface = parent() && render_surface();
+ if (!owns_non_root_surface) {
+ // If you're not the root, or you don't own a surface, you need to apply
+ // your local offset.
+ xform = node->data.to_target;
+ xform.Translate(offset_to_transform_parent().x(),
+ offset_to_transform_parent().y());
+ } else {
+ // Surfaces need to apply their sublayer scale.
+ xform.Scale(target_node->data.sublayer_scale.x(),
+ target_node->data.sublayer_scale.y());
}
xform.Scale(1.0 / contents_scale_x(), 1.0 / contents_scale_y());
return xform;
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index cf1356c..873f360 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -47,13 +47,7 @@
namespace trace_event {
class ConvertableToTraceFormat;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
}
-} // namespace base
namespace cc {
@@ -383,7 +377,8 @@
virtual void OnOutputSurfaceCreated() {}
virtual bool IsSuitableForGpuRasterization() const;
- virtual scoped_refptr<base::debug::ConvertableToTraceFormat> TakeDebugInfo();
+ virtual scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+ TakeDebugInfo();
void SetLayerClient(LayerClient* client) { client_ = client; }
diff --git a/cc/layers/layer_client.h b/cc/layers/layer_client.h
index efdbe51..bcdf1c3 100644
--- a/cc/layers/layer_client.h
+++ b/cc/layers/layer_client.h
@@ -14,13 +14,7 @@
namespace trace_event {
class ConvertableToTraceFormat;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
}
-} // namespace base
namespace cc {
@@ -30,7 +24,7 @@
// If not, returns nullptr.
// If the returned pointer is non-nullptr, the caller takes
// ownership of the pointer.
- virtual scoped_refptr<base::debug::ConvertableToTraceFormat>
+ virtual scoped_refptr<base::trace_event::ConvertableToTraceFormat>
TakeDebugInfo() = 0;
protected:
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index eae3685..6e11644 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -175,7 +175,7 @@
}
void LayerImpl::SetDebugInfo(
- scoped_refptr<base::debug::ConvertableToTraceFormat> other) {
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> other) {
debug_info_ = other;
SetNeedsPushProperties();
}
@@ -261,6 +261,23 @@
draw_properties_.blend_mode, sorting_context_id_);
}
+void LayerImpl::PopulateScaledSharedQuadState(SharedQuadState* state,
+ float scale) const {
+ gfx::Transform scaled_draw_transform =
+ draw_properties_.target_space_transform;
+ scaled_draw_transform.Scale(SK_MScalar1 / scale, SK_MScalar1 / scale);
+ gfx::Size scaled_content_bounds =
+ gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale));
+ gfx::Rect scaled_visible_content_rect =
+ gfx::ScaleToEnclosingRect(visible_content_rect(), scale);
+ scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds));
+
+ state->SetAll(scaled_draw_transform, scaled_content_bounds,
+ scaled_visible_content_rect, draw_properties().clip_rect,
+ draw_properties().is_clipped, draw_properties().opacity,
+ draw_properties().blend_mode, sorting_context_id_);
+}
+
bool LayerImpl::WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) {
// WillDraw/DidDraw must be matched.
@@ -327,6 +344,22 @@
render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
debug_border_quad->SetNew(
shared_quad_state, quad_rect, visible_quad_rect, color, width);
+ if (contents_opaque()) {
+ // When opaque, draw a second inner border that is thicker than the outer
+ // border, but more transparent.
+ static const float kFillOpacity = 0.3f;
+ SkColor fill_color = SkColorSetA(
+ color, static_cast<uint8_t>(SkColorGetA(color) * kFillOpacity));
+ float fill_width = width * 3;
+ gfx::Rect fill_rect = quad_rect;
+ fill_rect.Inset(fill_width / 2.f, fill_width / 2.f);
+ gfx::Rect visible_fill_rect =
+ gfx::IntersectRects(visible_quad_rect, fill_rect);
+ DebugBorderDrawQuad* fill_quad =
+ render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
+ fill_quad->SetNew(shared_quad_state, fill_rect, visible_fill_rect,
+ fill_color, fill_width);
+ }
}
bool LayerImpl::HasDelegatedContent() const {
@@ -345,11 +378,6 @@
return RenderPassId(0, 0);
}
-bool LayerImpl::UpdateTiles(const Occlusion& occlusion_in_layer_space,
- bool resourceless_software_draw) {
- return false;
-}
-
void LayerImpl::GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
gfx::Size* resource_size) const {
NOTREACHED();
@@ -1401,7 +1429,7 @@
void LayerImpl::GetAllTilesForTracing(std::set<const Tile*>* tiles) const {
}
-void LayerImpl::AsValueInto(base::debug::TracedValue* state) const {
+void LayerImpl::AsValueInto(base::trace_event::TracedValue* state) const {
TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
TRACE_DISABLED_BY_DEFAULT("cc.debug"),
state,
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 96f915f..97fd205 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -46,15 +46,8 @@
class ConvertableToTraceFormat;
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
-using ::base::trace_event::TracedValue;
-}
class DictionaryValue;
-} // namespace base
+}
namespace cc {
@@ -205,6 +198,7 @@
LayerTreeImpl* layer_tree_impl() const { return layer_tree_impl_; }
void PopulateSharedQuadState(SharedQuadState* state) const;
+ void PopulateScaledSharedQuadState(SharedQuadState* state, float scale) const;
// WillDraw must be called before AppendQuads. If WillDraw returns false,
// AppendQuads and DidDraw will not be called. If WillDraw returns true,
// DidDraw is guaranteed to be called before another WillDraw or before
@@ -214,7 +208,6 @@
virtual bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider);
virtual void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {}
virtual void DidDraw(ResourceProvider* resource_provider);
@@ -226,11 +219,6 @@
virtual RenderPassId FirstContributingRenderPassId() const;
virtual RenderPassId NextContributingRenderPassId(RenderPassId id) const;
- // Updates the layer's tiles. This should return true if meaningful work was
- // done. That is, if an early-out was hit and as a result the internal state
- // of tiles didn't change, this function should return false.
- virtual bool UpdateTiles(const Occlusion& occlusion_in_layer_space,
- bool resourceless_software_draw);
virtual void NotifyTileStateChanged(const Tile* tile) {}
virtual ScrollbarLayerImplBase* ToScrollbarLayer();
@@ -574,7 +562,7 @@
virtual void PushPropertiesTo(LayerImpl* layer);
virtual void GetAllTilesForTracing(std::set<const Tile*>* tiles) const;
- virtual void AsValueInto(base::debug::TracedValue* dict) const;
+ virtual void AsValueInto(base::trace_event::TracedValue* dict) const;
virtual size_t GPUMemoryUsageInBytes() const;
@@ -593,7 +581,7 @@
virtual void RunMicroBenchmark(MicroBenchmarkImpl* benchmark);
virtual void SetDebugInfo(
- scoped_refptr<base::debug::ConvertableToTraceFormat> other);
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> other);
bool IsDrawnRenderSurfaceLayerListMember() const;
@@ -769,7 +757,7 @@
// hierarchy before layers can be drawn.
DrawProperties<LayerImpl> draw_properties_;
- scoped_refptr<base::debug::ConvertableToTraceFormat> debug_info_;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> debug_info_;
scoped_ptr<RenderSurfaceImpl> render_surface_;
std::vector<FrameTimingRequest> frame_timing_requests_;
diff --git a/cc/layers/nine_patch_layer_impl.cc b/cc/layers/nine_patch_layer_impl.cc
index 82ba480..832efb3 100644
--- a/cc/layers/nine_patch_layer_impl.cc
+++ b/cc/layers/nine_patch_layer_impl.cc
@@ -82,7 +82,6 @@
void NinePatchLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
CheckGeometryLimitations();
SharedQuadState* shared_quad_state =
@@ -214,7 +213,8 @@
const bool opaque = layer_tree_impl()->IsUIResourceOpaque(ui_resource_id_);
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_top_left);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_top_left);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -234,7 +234,8 @@
}
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_top_right);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_top_right);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -254,7 +255,8 @@
}
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_bottom_left);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_bottom_left);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -274,7 +276,8 @@
}
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_bottom_right);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_bottom_right);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -293,7 +296,9 @@
nearest_neighbor);
}
- visible_rect = occlusion_in_content_space.GetUnoccludedContentRect(layer_top);
+ visible_rect =
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_top);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -313,7 +318,8 @@
}
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_left);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_left);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -333,7 +339,8 @@
}
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_right);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_right);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -353,7 +360,8 @@
}
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_bottom);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_bottom);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
@@ -374,7 +382,8 @@
if (fill_center_) {
visible_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(layer_center);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ layer_center);
opaque_rect = opaque ? visible_rect : gfx::Rect();
if (!visible_rect.IsEmpty()) {
TextureDrawQuad* quad =
diff --git a/cc/layers/nine_patch_layer_impl.h b/cc/layers/nine_patch_layer_impl.h
index 5320d39..948758a 100644
--- a/cc/layers/nine_patch_layer_impl.h
+++ b/cc/layers/nine_patch_layer_impl.h
@@ -61,7 +61,6 @@
void PushPropertiesTo(LayerImpl* layer) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
base::DictionaryValue* LayerTreeAsJson() const override;
diff --git a/cc/layers/nine_patch_layer_impl_unittest.cc b/cc/layers/nine_patch_layer_impl_unittest.cc
index de1bf40..beee519 100644
--- a/cc/layers/nine_patch_layer_impl_unittest.cc
+++ b/cc/layers/nine_patch_layer_impl_unittest.cc
@@ -62,7 +62,7 @@
layer->SetImageBounds(bitmap_size);
layer->SetLayout(aperture_rect, border, fill_center);
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
// Verify quad rects
const QuadList& quads = render_pass->quad_list;
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc
index 8f4d675..36c9f82 100644
--- a/cc/layers/painted_scrollbar_layer.cc
+++ b/cc/layers/painted_scrollbar_layer.cc
@@ -4,9 +4,12 @@
#include "cc/layers/painted_scrollbar_layer.h"
+#include <algorithm>
+
#include "base/auto_reset.h"
#include "base/basictypes.h"
#include "base/trace_event/trace_event.h"
+#include "cc/base/math_util.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
#include "cc/resources/ui_resource_bitmap.h"
#include "cc/trees/layer_tree_host.h"
@@ -16,6 +19,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSize.h"
+#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/skia_util.h"
namespace cc {
@@ -38,6 +42,7 @@
: scrollbar_(scrollbar.Pass()),
scroll_layer_id_(scroll_layer_id),
clip_layer_id_(Layer::INVALID_ID),
+ internal_contents_scale_(0.f),
thumb_thickness_(scrollbar_->ThumbThickness()),
thumb_length_(scrollbar_->ThumbLength()),
is_overlay_(scrollbar_->IsOverlay()),
@@ -82,10 +87,10 @@
}
float PaintedScrollbarLayer::ClampScaleToMaxTextureSize(float scale) {
- // If the scaled content_bounds() is bigger than the max texture size of the
- // device, we need to clamp it by rescaling, since content_bounds() is used
+ // If the scaled bounds() is bigger than the max texture size of the
+ // device, we need to clamp it by rescaling, since this is used
// below to set the texture size.
- gfx::Size scaled_bounds = ComputeContentBoundsForScale(scale, scale);
+ gfx::Size scaled_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale));
if (scaled_bounds.width() > MaxTextureSize() ||
scaled_bounds.height() > MaxTextureSize()) {
if (scaled_bounds.width() > scaled_bounds.height())
@@ -96,26 +101,17 @@
return scale;
}
-void PaintedScrollbarLayer::CalculateContentsScale(
- float ideal_contents_scale,
- float* contents_scale_x,
- float* contents_scale_y,
- gfx::Size* content_bounds) {
- ContentsScalingLayer::CalculateContentsScale(
- ClampScaleToMaxTextureSize(ideal_contents_scale),
- contents_scale_x,
- contents_scale_y,
- content_bounds);
-}
-
void PaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
- ContentsScalingLayer::PushPropertiesTo(layer);
+ Layer::PushPropertiesTo(layer);
PushScrollClipPropertiesTo(layer);
PaintedScrollbarLayerImpl* scrollbar_layer =
static_cast<PaintedScrollbarLayerImpl*>(layer);
+ scrollbar_layer->set_internal_contents_scale_and_bounds(
+ internal_contents_scale_, internal_content_bounds_);
+
scrollbar_layer->SetThumbThickness(thumb_thickness_);
scrollbar_layer->SetThumbLength(thumb_length_);
if (orientation() == HORIZONTAL) {
@@ -160,7 +156,7 @@
thumb_resource_ = nullptr;
}
- ContentsScalingLayer::SetLayerTreeHost(host);
+ Layer::SetLayerTreeHost(host);
}
gfx::Rect PaintedScrollbarLayer::ScrollbarLayerRectToContentRect(
@@ -168,10 +164,10 @@
// Don't intersect with the bounds as in LayerRectToContentRect() because
// layer_rect here might be in coordinates of the containing layer.
gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect(
- layer_rect, contents_scale_x(), contents_scale_y());
- // We should never return a rect bigger than the content_bounds().
+ layer_rect, internal_contents_scale_, internal_contents_scale_);
+ // We should never return a rect bigger than the content bounds.
gfx::Size clamped_size = expanded_rect.size();
- clamped_size.SetToMin(content_bounds());
+ clamped_size.SetToMin(internal_content_bounds_);
expanded_rect.set_size(clamped_size);
return expanded_rect;
}
@@ -202,8 +198,36 @@
}
}
+void PaintedScrollbarLayer::UpdateInternalContentScale() {
+ float scale = layer_tree_host()->device_scale_factor();
+ if (layer_tree_host()
+ ->settings()
+ .layer_transforms_should_scale_layer_contents) {
+ gfx::Vector2dF transform_scales =
+ MathUtil::ComputeTransform2dScaleComponents(draw_transform(), scale);
+ scale = std::max(transform_scales.x(), transform_scales.y());
+ }
+ bool changed = false;
+ changed |= UpdateProperty(ClampScaleToMaxTextureSize(scale),
+ &internal_contents_scale_);
+ changed |= UpdateProperty(
+ gfx::ToCeiledSize(gfx::ScaleSize(bounds(), internal_contents_scale_)),
+ &internal_content_bounds_);
+ if (changed) {
+ // If the content scale or bounds change, repaint.
+ SetNeedsDisplay();
+ }
+}
+
bool PaintedScrollbarLayer::Update(ResourceUpdateQueue* queue,
const OcclusionTracker<Layer>* occlusion) {
+ {
+ base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
+ true);
+ Layer::Update(queue, occlusion);
+ UpdateInternalContentScale();
+ }
+
UpdateThumbAndTrackGeometry();
gfx::Rect track_layer_rect = gfx::Rect(location_, bounds());
@@ -225,12 +249,7 @@
if (!has_thumb_ && thumb_resource_) {
thumb_resource_ = nullptr;
SetNeedsPushProperties();
- }
-
- {
- base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
- true);
- ContentsScalingLayer::Update(queue, occlusion);
+ updated = true;
}
if (update_rect_.IsEmpty() && track_resource_)
diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h
index 950c165..ae2b125 100644
--- a/cc/layers/painted_scrollbar_layer.h
+++ b/cc/layers/painted_scrollbar_layer.h
@@ -7,7 +7,7 @@
#include "cc/base/cc_export.h"
#include "cc/input/scrollbar.h"
-#include "cc/layers/contents_scaling_layer.h"
+#include "cc/layers/layer.h"
#include "cc/layers/scrollbar_layer_interface.h"
#include "cc/layers/scrollbar_theme_painter.h"
#include "cc/resources/layer_updater.h"
@@ -17,7 +17,7 @@
class ScrollbarThemeComposite;
class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface,
- public ContentsScalingLayer {
+ public Layer {
public:
scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
@@ -41,10 +41,10 @@
void SetLayerTreeHost(LayerTreeHost* host) override;
void PushPropertiesTo(LayerImpl* layer) override;
void PushScrollClipPropertiesTo(LayerImpl* layer) override;
- void CalculateContentsScale(float ideal_contents_scale,
- float* contents_scale_x,
- float* contents_scale_y,
- gfx::Size* content_bounds) override;
+
+ const gfx::Size& internal_content_bounds() const {
+ return internal_content_bounds_;
+ }
protected:
PaintedScrollbarLayer(scoped_ptr<Scrollbar> scrollbar, int scroll_layer_id);
@@ -57,17 +57,20 @@
UIResourceId thumb_resource_id() {
return thumb_resource_.get() ? thumb_resource_->id() : 0;
}
+ void UpdateInternalContentScale();
void UpdateThumbAndTrackGeometry();
private:
gfx::Rect ScrollbarLayerRectToContentRect(const gfx::Rect& layer_rect) const;
gfx::Rect OriginThumbRect() const;
- template<typename T> void UpdateProperty(T value, T* prop) {
+ template <typename T>
+ bool UpdateProperty(T value, T* prop) {
if (*prop == value)
- return;
+ return false;
*prop = value;
SetNeedsPushProperties();
+ return true;
}
int MaxTextureSize();
@@ -81,6 +84,9 @@
int scroll_layer_id_;
int clip_layer_id_;
+ float internal_contents_scale_;
+ gfx::Size internal_content_bounds_;
+
// Snapshot of properties taken in UpdateThumbAndTrackGeometry and used in
// PushPropertiesTo.
int thumb_thickness_;
diff --git a/cc/layers/painted_scrollbar_layer_impl.cc b/cc/layers/painted_scrollbar_layer_impl.cc
index 068d42f..b05d51e 100644
--- a/cc/layers/painted_scrollbar_layer_impl.cc
+++ b/cc/layers/painted_scrollbar_layer_impl.cc
@@ -32,6 +32,7 @@
: ScrollbarLayerImplBase(tree_impl, id, orientation, false, false),
track_ui_resource_id_(0),
thumb_ui_resource_id_(0),
+ internal_contents_scale_(1.f),
thumb_thickness_(0),
thumb_length_(0),
track_start_(0),
@@ -51,6 +52,9 @@
PaintedScrollbarLayerImpl* scrollbar_layer =
static_cast<PaintedScrollbarLayerImpl*>(layer);
+ scrollbar_layer->set_internal_contents_scale_and_bounds(
+ internal_contents_scale_, internal_content_bounds_);
+
scrollbar_layer->SetThumbThickness(thumb_thickness_);
scrollbar_layer->SetThumbLength(thumb_length_);
scrollbar_layer->SetTrackStart(track_start_);
@@ -68,26 +72,28 @@
void PaintedScrollbarLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
bool premultipled_alpha = true;
bool flipped = false;
bool nearest_neighbor = false;
gfx::PointF uv_top_left(0.f, 0.f);
gfx::PointF uv_bottom_right(1.f, 1.f);
- gfx::Rect bounds_rect(bounds());
- gfx::Rect content_bounds_rect(content_bounds());
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
- PopulateSharedQuadState(shared_quad_state);
+ PopulateScaledSharedQuadState(shared_quad_state, internal_contents_scale_);
- AppendDebugBorderQuad(
- render_pass, content_bounds(), shared_quad_state, append_quads_data);
+ AppendDebugBorderQuad(render_pass, internal_content_bounds_,
+ shared_quad_state, append_quads_data);
gfx::Rect thumb_quad_rect = ComputeThumbQuadRect();
+ gfx::Rect scaled_thumb_quad_rect =
+ gfx::ScaleToEnclosingRect(thumb_quad_rect, internal_contents_scale_);
gfx::Rect visible_thumb_quad_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(thumb_quad_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ thumb_quad_rect);
+ gfx::Rect scaled_visible_thumb_quad_rect = gfx::ScaleToEnclosingRect(
+ visible_thumb_quad_rect, internal_contents_scale_);
ResourceProvider::ResourceId thumb_resource_id =
layer_tree_impl()->ResourceIdForUIResource(thumb_ui_resource_id_);
@@ -99,40 +105,29 @@
const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
TextureDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
- quad->SetNew(shared_quad_state,
- thumb_quad_rect,
- opaque_rect,
- visible_thumb_quad_rect,
- thumb_resource_id,
- premultipled_alpha,
- uv_top_left,
- uv_bottom_right,
- SK_ColorTRANSPARENT,
- opacity,
- flipped,
- nearest_neighbor);
+ quad->SetNew(shared_quad_state, scaled_thumb_quad_rect, opaque_rect,
+ scaled_visible_thumb_quad_rect, thumb_resource_id,
+ premultipled_alpha, uv_top_left, uv_bottom_right,
+ SK_ColorTRANSPARENT, opacity, flipped, nearest_neighbor);
}
- gfx::Rect track_quad_rect = content_bounds_rect;
+ gfx::Rect track_quad_rect(bounds());
+ gfx::Rect scaled_track_quad_rect(internal_content_bounds_);
gfx::Rect visible_track_quad_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(track_quad_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ track_quad_rect);
+ gfx::Rect scaled_visible_track_quad_rect = gfx::ScaleToEnclosingRect(
+ visible_track_quad_rect, internal_contents_scale_);
if (track_resource_id && !visible_track_quad_rect.IsEmpty()) {
- gfx::Rect opaque_rect(contents_opaque() ? track_quad_rect : gfx::Rect());
+ gfx::Rect opaque_rect(contents_opaque() ? scaled_track_quad_rect
+ : gfx::Rect());
const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
TextureDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
- quad->SetNew(shared_quad_state,
- track_quad_rect,
- opaque_rect,
- visible_track_quad_rect,
- track_resource_id,
- premultipled_alpha,
- uv_top_left,
- uv_bottom_right,
- SK_ColorTRANSPARENT,
- opacity,
- flipped,
- nearest_neighbor);
+ quad->SetNew(shared_quad_state, scaled_track_quad_rect, opaque_rect,
+ scaled_visible_track_quad_rect, track_resource_id,
+ premultipled_alpha, uv_top_left, uv_bottom_right,
+ SK_ColorTRANSPARENT, opacity, flipped, nearest_neighbor);
}
}
diff --git a/cc/layers/painted_scrollbar_layer_impl.h b/cc/layers/painted_scrollbar_layer_impl.h
index 8708b74..36a9be9 100644
--- a/cc/layers/painted_scrollbar_layer_impl.h
+++ b/cc/layers/painted_scrollbar_layer_impl.h
@@ -30,7 +30,6 @@
bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
void SetThumbThickness(int thumb_thickness);
@@ -45,6 +44,12 @@
thumb_ui_resource_id_ = uid;
}
+ void set_internal_contents_scale_and_bounds(float content_scale,
+ const gfx::Size& content_bounds) {
+ internal_contents_scale_ = content_scale;
+ internal_content_bounds_ = content_bounds;
+ }
+
protected:
PaintedScrollbarLayerImpl(LayerTreeImpl* tree_impl,
int id,
@@ -63,6 +68,9 @@
UIResourceId track_ui_resource_id_;
UIResourceId thumb_ui_resource_id_;
+ float internal_contents_scale_;
+ gfx::Size internal_content_bounds_;
+
int thumb_thickness_;
int thumb_length_;
int track_start_;
diff --git a/cc/layers/painted_scrollbar_layer_impl_unittest.cc b/cc/layers/painted_scrollbar_layer_impl_unittest.cc
index 3994cc3..3fb3fb2 100644
--- a/cc/layers/painted_scrollbar_layer_impl_unittest.cc
+++ b/cc/layers/painted_scrollbar_layer_impl_unittest.cc
@@ -4,6 +4,7 @@
#include "cc/layers/painted_scrollbar_layer_impl.h"
+#include "cc/quads/draw_quad.h"
#include "cc/test/layer_test_common.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -12,6 +13,8 @@
TEST(PaintedScrollbarLayerImplTest, Occlusion) {
gfx::Size layer_size(10, 1000);
+ float scale = 2.f;
+ gfx::Size scaled_layer_size(20, 2000);
gfx::Size viewport_size(1000, 1000);
LayerTestCommon::LayerImplTest impl;
@@ -36,6 +39,9 @@
impl.AddChildToRoot<PaintedScrollbarLayerImpl>(orientation);
scrollbar_layer_impl->SetBounds(layer_size);
scrollbar_layer_impl->SetContentBounds(layer_size);
+ scrollbar_layer_impl->SetContentsOpaque(true);
+ scrollbar_layer_impl->set_internal_contents_scale_and_bounds(
+ scale, scaled_layer_size);
scrollbar_layer_impl->SetDrawsContent(true);
scrollbar_layer_impl->SetThumbThickness(layer_size.width());
scrollbar_layer_impl->SetThumbLength(500);
@@ -62,6 +68,23 @@
impl.quad_list(), occluded, &partially_occluded_count);
EXPECT_EQ(2u, impl.quad_list().size());
EXPECT_EQ(0u, partially_occluded_count);
+
+ // Note: this is also testing that the thumb and track are both
+ // scaled by the internal contents scale. It's not occlusion-related
+ // but is easy to verify here.
+ const DrawQuad* thumb_quad = impl.quad_list().ElementAt(0);
+ const DrawQuad* track_quad = impl.quad_list().ElementAt(1);
+
+ gfx::Rect scaled_thumb_rect = gfx::ScaleToEnclosingRect(thumb_rect, scale);
+ EXPECT_EQ(track_quad->rect.ToString(),
+ gfx::Rect(scaled_layer_size).ToString());
+ EXPECT_EQ(track_quad->opaque_rect.ToString(),
+ gfx::Rect(scaled_layer_size).ToString());
+ EXPECT_EQ(track_quad->visible_rect.ToString(),
+ gfx::Rect(scaled_layer_size).ToString());
+ EXPECT_EQ(thumb_quad->rect.ToString(), scaled_thumb_rect.ToString());
+ EXPECT_EQ(thumb_quad->visible_rect.ToString(),
+ scaled_thumb_rect.ToString());
}
{
diff --git a/cc/layers/picture_image_layer_impl_unittest.cc b/cc/layers/picture_image_layer_impl_unittest.cc
index cf22855..d40f555 100644
--- a/cc/layers/picture_image_layer_impl_unittest.cc
+++ b/cc/layers/picture_image_layer_impl_unittest.cc
@@ -80,7 +80,7 @@
animating_transform_to_screen;
layer->draw_properties().visible_content_rect = viewport_rect;
bool resourceless_software_draw = false;
- layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ layer->UpdateTiles(resourceless_software_draw);
}
protected:
@@ -149,7 +149,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer->AppendQuads(render_pass.get(), &data);
active_layer->DidDraw(nullptr);
EXPECT_EQ(DrawQuad::TILED_CONTENT, render_pass->quad_list.front()->material);
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 52288e9..0ca2ae7 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -71,9 +71,6 @@
scoped_refptr<RasterSource> raster_source =
recording_source_->CreateRasterSource();
- raster_source->SetBackgoundColor(SafeOpaqueBackgroundColor());
- raster_source->SetRequiresClear(!contents_opaque() &&
- !client_->FillsBoundsCompletely());
layer_impl->UpdateRasterSource(raster_source, &recording_invalidation_,
nullptr);
DCHECK(recording_invalidation_.IsEmpty());
@@ -123,6 +120,10 @@
return updated;
}
+ recording_source_->SetBackgroundColor(SafeOpaqueBackgroundColor());
+ recording_source_->SetRequiresClear(!contents_opaque() &&
+ !client_->FillsBoundsCompletely());
+
TRACE_EVENT1("cc", "PictureLayer::Update",
"source_frame_number",
layer_tree_host()->source_frame_number());
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 3a0753f..f62a866 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -153,7 +153,6 @@
}
void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
// The bounds and the pile size may differ if the pile wasn't updated (ie.
// PictureLayer::Update didn't happen). In that case the pile will be empty.
@@ -172,50 +171,35 @@
render_pass, bounds(), shared_quad_state, append_quads_data);
SolidColorLayerImpl::AppendSolidQuads(
- render_pass, occlusion_in_content_space, shared_quad_state,
- visible_content_rect(), raster_source_->GetSolidColor(),
- append_quads_data);
+ render_pass, draw_properties().occlusion_in_content_space,
+ shared_quad_state, visible_content_rect(),
+ raster_source_->GetSolidColor(), append_quads_data);
return;
}
float max_contents_scale = MaximumTilingContentsScale();
- gfx::Transform scaled_draw_transform = draw_transform();
- scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale,
- SK_MScalar1 / max_contents_scale);
- gfx::Size scaled_content_bounds =
- gfx::ToCeiledSize(gfx::ScaleSize(bounds(), max_contents_scale));
- gfx::Rect scaled_visible_content_rect =
- gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale);
- scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds));
+ PopulateScaledSharedQuadState(shared_quad_state, max_contents_scale);
Occlusion scaled_occlusion =
- occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
- scaled_draw_transform);
-
- shared_quad_state->SetAll(
- scaled_draw_transform, scaled_content_bounds, scaled_visible_content_rect,
- draw_properties().clip_rect, draw_properties().is_clipped,
- draw_properties().opacity, draw_properties().blend_mode,
- sorting_context_id_);
+ draw_properties()
+ .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
+ shared_quad_state->content_to_target_transform);
if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) {
AppendDebugBorderQuad(
- render_pass,
- scaled_content_bounds,
- shared_quad_state,
- append_quads_data,
- DebugColors::DirectPictureBorderColor(),
+ render_pass, shared_quad_state->content_bounds, shared_quad_state,
+ append_quads_data, DebugColors::DirectPictureBorderColor(),
DebugColors::DirectPictureBorderWidth(layer_tree_impl()));
- gfx::Rect geometry_rect = scaled_visible_content_rect;
+ gfx::Rect geometry_rect = shared_quad_state->visible_content_rect;
gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
gfx::Rect visible_geometry_rect =
scaled_occlusion.GetUnoccludedContentRect(geometry_rect);
if (visible_geometry_rect.IsEmpty())
return;
- gfx::Size texture_size = scaled_visible_content_rect.size();
+ gfx::Rect quad_content_rect = shared_quad_state->visible_content_rect;
+ gfx::Size texture_size = quad_content_rect.size();
gfx::RectF texture_rect = gfx::RectF(texture_size);
- gfx::Rect quad_content_rect = scaled_visible_content_rect;
PictureDrawQuad* quad =
render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
@@ -226,17 +210,14 @@
return;
}
- AppendDebugBorderQuad(
- render_pass, scaled_content_bounds, shared_quad_state, append_quads_data);
+ AppendDebugBorderQuad(render_pass, shared_quad_state->content_bounds,
+ shared_quad_state, append_quads_data);
if (ShowDebugBorders()) {
for (PictureLayerTilingSet::CoverageIterator iter(
- tilings_.get(),
- max_contents_scale,
- scaled_visible_content_rect,
- ideal_contents_scale_);
- iter;
- ++iter) {
+ tilings_.get(), max_contents_scale,
+ shared_quad_state->visible_content_rect, ideal_contents_scale_);
+ iter; ++iter) {
SkColor color;
float width;
if (*iter && iter->IsReadyToDraw()) {
@@ -290,12 +271,10 @@
size_t missing_tile_count = 0u;
size_t on_demand_missing_tile_count = 0u;
only_used_low_res_last_append_quads_ = true;
- for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
- max_contents_scale,
- scaled_visible_content_rect,
- ideal_contents_scale_);
- iter;
- ++iter) {
+ for (PictureLayerTilingSet::CoverageIterator iter(
+ tilings_.get(), max_contents_scale,
+ shared_quad_state->visible_content_rect, ideal_contents_scale_);
+ iter; ++iter) {
gfx::Rect geometry_rect = iter.geometry_rect();
gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect();
gfx::Rect visible_geometry_rect =
@@ -429,8 +408,7 @@
CleanUpTilingsOnActiveLayer(last_append_quads_tilings_);
}
-bool PictureLayerImpl::UpdateTiles(const Occlusion& occlusion_in_content_space,
- bool resourceless_software_draw) {
+bool PictureLayerImpl::UpdateTiles(bool resourceless_software_draw) {
DCHECK_EQ(1.f, contents_scale_x());
DCHECK_EQ(1.f, contents_scale_y());
@@ -452,7 +430,7 @@
// only have one or two tilings (high and low res), so only clean up the
// active layer. This cleans it up here in case AppendQuads didn't run.
// If it did run, this would not remove any additional tilings.
- if (GetTree() == ACTIVE_TREE)
+ if (layer_tree_impl()->IsActiveTree())
CleanUpTilingsOnActiveLayer(last_append_quads_tilings_);
UpdateIdealScales();
@@ -473,12 +451,6 @@
if (draw_transform_is_animating())
raster_source_->SetShouldAttemptToUseDistanceFieldText();
- return UpdateTilePriorities(occlusion_in_content_space);
-}
-
-bool PictureLayerImpl::UpdateTilePriorities(
- const Occlusion& occlusion_in_content_space) {
- DCHECK_IMPLIES(raster_source_->IsSolidColor(), tilings_->num_tilings() == 0);
double current_frame_time_in_seconds =
(layer_tree_impl()->CurrentBeginFrameArgs().frame_time -
@@ -501,6 +473,12 @@
!only_used_low_res_last_append_quads_ || RequiresHighResToDraw() ||
!layer_tree_impl()->SmoothnessTakesPriority();
+ static const Occlusion kEmptyOcclusion;
+ const Occlusion& occlusion_in_content_space =
+ layer_tree_impl()->settings().use_occlusion_for_tile_prioritization
+ ? draw_properties().occlusion_in_content_space
+ : kEmptyOcclusion;
+
// Pass |occlusion_in_content_space| for |occlusion_in_layer_space| since
// they are the same space in picture layer, as contents scale is always 1.
bool updated = tilings_->UpdateTilePriorities(
@@ -1139,7 +1117,7 @@
return PictureLayerTilingSet::Create(
this, settings.max_tiles_for_interest_area,
layer_tree_impl()->use_gpu_rasterization()
- ? 0.f
+ ? settings.gpu_rasterization_skewport_target_time_in_seconds
: settings.skewport_target_time_in_seconds,
settings.skewport_extrapolation_limit_in_content_pixels);
}
@@ -1180,7 +1158,8 @@
tilings_->GetAllTilesForTracing(tiles);
}
-void PictureLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
+void PictureLayerImpl::AsValueInto(
+ base::trace_event::TracedValue* state) const {
LayerImpl::AsValueInto(state);
state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index e7f4fba..f32e56f 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -55,10 +55,7 @@
scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
void PushPropertiesTo(LayerImpl* layer) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
- bool UpdateTiles(const Occlusion& occlusion_in_content_space,
- bool resourceless_software_draw) override;
void NotifyTileStateChanged(const Tile* tile) override;
void DidBeginTracing() override;
void ReleaseResources() override;
@@ -81,6 +78,7 @@
void UpdateRasterSource(scoped_refptr<RasterSource> raster_source,
Region* new_invalidation,
const PictureLayerTilingSet* pending_set);
+ bool UpdateTiles(bool resourceless_software_draw);
// Mask-related functions.
void GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
@@ -116,7 +114,6 @@
PictureLayerTiling* AddTiling(float contents_scale);
void RemoveAllTilings();
void AddTilingsForRasterScale();
- bool UpdateTilePriorities(const Occlusion& occlusion_in_content_space);
virtual bool ShouldAdjustRasterScale() const;
virtual void RecalculateRasterScales();
void CleanUpTilingsOnActiveLayer(
@@ -132,7 +129,7 @@
void GetDebugBorderProperties(SkColor* color, float* width) const override;
void GetAllTilesForTracing(std::set<const Tile*>* tiles) const override;
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
virtual void UpdateIdealScales();
float MaximumTilingContentsScale() const;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 600f3e2..f00b2e4 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -240,7 +240,7 @@
layer->draw_properties().screen_space_transform_is_animating =
animating_transform_to_screen;
bool resourceless_software_draw = false;
- layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ layer->UpdateTiles(resourceless_software_draw);
}
static void VerifyAllTilesExistAndHavePile(
const PictureLayerTiling* tiling,
@@ -332,8 +332,11 @@
scoped_refptr<FakePicturePileImpl> pending_pile =
FakePicturePileImpl::CreateFilledPile(layer_size, layer_size);
+
+ scoped_ptr<FakePicturePile> active_recording =
+ FakePicturePile::CreateFilledPile(layer_size, layer_size);
scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateFilledPile(layer_size, layer_size);
+ FakePicturePileImpl::CreateFromPile(active_recording.get(), nullptr);
SetupTrees(pending_pile, active_pile);
@@ -347,18 +350,22 @@
for (tile_iter = tiles.begin(); tile_iter < tiles.end(); tile_iter++) {
gfx::Point tile_center = (*tile_iter)->content_rect().CenterPoint();
gfx::Rect rect(tile_center.x(), tile_center.y(), 1, 1);
- active_pile->add_draw_rect(rect);
+ active_recording->add_draw_rect(rect);
rects.push_back(SkRect::MakeXYWH(rect.x(), rect.y(), 1, 1));
}
+
// Force re-raster with newly injected content
- active_pile->RemoveRecordingAt(0, 0);
- active_pile->AddRecordingAt(0, 0);
+ active_recording->RemoveRecordingAt(0, 0);
+ active_recording->AddRecordingAt(0, 0);
+
+ scoped_refptr<FakePicturePileImpl> updated_active_pile =
+ FakePicturePileImpl::CreateFromPile(active_recording.get(), nullptr);
std::vector<SkRect>::const_iterator rect_iter = rects.begin();
for (tile_iter = tiles.begin(); tile_iter < tiles.end(); tile_iter++) {
MockCanvas mock_canvas(1000, 1000);
- active_pile->PlaybackToSharedCanvas(&mock_canvas,
- (*tile_iter)->content_rect(), 1.0f);
+ updated_active_pile->PlaybackToSharedCanvas(
+ &mock_canvas, (*tile_iter)->content_rect(), 1.0f);
// This test verifies that when drawing the contents of a specific tile
// at content scale 1.0, the playback canvas never receives content from
@@ -516,7 +523,7 @@
resourceless_software_draw);
active_layer_->draw_properties().visible_content_rect = viewport;
active_layer_->draw_properties().screen_space_transform = transform;
- active_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ active_layer_->UpdateTiles(resourceless_software_draw);
gfx::Rect visible_rect_for_tile_priority =
active_layer_->visible_rect_for_tile_priority();
@@ -540,7 +547,7 @@
viewport,
transform,
resourceless_software_draw);
- active_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ active_layer_->UpdateTiles(resourceless_software_draw);
// Transform for tile priority is updated.
EXPECT_TRANSFORMATION_MATRIX_EQ(transform,
@@ -560,7 +567,7 @@
viewport,
transform,
resourceless_software_draw);
- active_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ active_layer_->UpdateTiles(resourceless_software_draw);
EXPECT_TRANSFORMATION_MATRIX_EQ(transform,
active_layer_->screen_space_transform());
@@ -1616,7 +1623,7 @@
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
ASSERT_EQ(1U, render_pass->quad_list.size());
@@ -1631,13 +1638,14 @@
gfx::Size layer_bounds(1500, 1500);
gfx::Rect visible_rect(250, 250, 1000, 1000);
- scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> active_pile =
- FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
+ scoped_ptr<FakePicturePile> empty_recording =
+ FakePicturePile::CreateEmptyPile(tile_size, layer_bounds);
+ empty_recording->SetIsSolidColor(true);
- pending_pile->set_is_solid_color(true);
- active_pile->set_is_solid_color(true);
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFromPile(empty_recording.get(), nullptr);
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateFromPile(empty_recording.get(), nullptr);
SetupTrees(pending_pile, active_pile);
@@ -1645,7 +1653,7 @@
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
Region remaining = visible_rect;
@@ -1663,13 +1671,11 @@
gfx::Size tile_size(host_impl_.settings().default_tile_size);
scoped_refptr<FakePicturePileImpl> pending_pile =
FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds);
+ tile_size, layer_bounds, false);
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds);
+ tile_size, layer_bounds, true);
- pending_pile->set_is_solid_color(false);
- active_pile->set_is_solid_color(true);
SetupTrees(pending_pile, active_pile);
// Solid color pile should not allow tilings at any scale.
EXPECT_FALSE(active_layer_->CanHaveTilings());
@@ -1707,7 +1713,7 @@
time_ticks += base::TimeDelta::FromMilliseconds(1);
host_impl_.SetCurrentBeginFrameArgs(
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks));
- pending_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ pending_layer_->UpdateTiles(resourceless_software_draw);
int num_visible = 0;
int num_offscreen = 0;
@@ -1773,7 +1779,7 @@
time_ticks += base::TimeDelta::FromMilliseconds(200);
host_impl_.SetCurrentBeginFrameArgs(
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks));
- pending_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ pending_layer_->UpdateTiles(resourceless_software_draw);
// Intersect the two rects. Any tile outside should not be required for
// activation.
@@ -1811,7 +1817,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
// All tiles in activation rect is ready to draw.
@@ -1843,7 +1849,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
// All high res tiles drew, nothing was incomplete.
@@ -1870,7 +1876,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
EXPECT_EQ(1u, render_pass->quad_list.size());
@@ -1900,7 +1906,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
EXPECT_EQ(1u, render_pass->quad_list.size());
@@ -1937,7 +1943,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
// The missing high res tile was replaced by a low res tile.
@@ -1995,7 +2001,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
// All high res tiles drew, and the one ideal res tile drew.
@@ -2105,9 +2111,10 @@
// tiles. This is attempting to simulate scrolling past the end of recorded
// content on the active layer, where the recordings are so far away that
// no tiles are created.
+ bool is_solid_color = false;
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds);
+ tile_size, layer_bounds, is_solid_color);
SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
@@ -2597,7 +2604,7 @@
FakeOutputSurface* fake_output_surface =
static_cast<FakeOutputSurface*>(host_impl_.output_surface());
ASSERT_TRUE(fake_output_surface->InitializeAndSetContext3d(
- TestContextProvider::Create()));
+ TestContextProvider::Create(), TestContextProvider::Create()));
// These will crash PictureLayerImpl if this is not true.
ASSERT_TRUE(host_impl_.pending_tree()->needs_update_draw_properties());
@@ -2928,7 +2935,7 @@
pending_layer_->draw_properties().visible_content_rect =
gfx::Rect(1100, 1100, 500, 500);
bool resourceless_software_draw = false;
- pending_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ pending_layer_->UpdateTiles(resourceless_software_draw);
unique_tiles.clear();
high_res_tile_count = 0u;
@@ -2959,7 +2966,7 @@
pending_layer_->draw_properties().visible_content_rect =
gfx::Rect(0, 0, 500, 500);
- pending_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ pending_layer_->UpdateTiles(resourceless_software_draw);
std::vector<Tile*> high_res_tiles =
pending_layer_->HighResTiling()->AllTilesForTesting();
@@ -3030,10 +3037,13 @@
}
TEST_F(PictureLayerImplTest, TilingSetRasterQueueRequiredNoHighRes) {
+ scoped_ptr<FakePicturePile> empty_recording =
+ FakePicturePile::CreateEmptyPile(gfx::Size(256, 256),
+ gfx::Size(1024, 1024));
+ empty_recording->SetIsSolidColor(true);
+
scoped_refptr<FakePicturePileImpl> pending_pile =
- FakePicturePileImpl::CreateEmptyPile(gfx::Size(256, 256),
- gfx::Size(1024, 1024));
- pending_pile->set_is_solid_color(true);
+ FakePicturePileImpl::CreateFromPile(empty_recording.get(), nullptr);
SetupPendingTree(pending_pile);
EXPECT_FALSE(
@@ -3144,8 +3154,6 @@
if (tile->required_for_activation() ==
last_tile->required_for_activation() &&
- priority.priority_bin ==
- last_tile->priority(PENDING_TREE).priority_bin &&
std::abs(tile->contents_scale() - last_tile->contents_scale()) <
std::numeric_limits<float>::epsilon()) {
if (priority.distance_to_visible <=
@@ -3523,9 +3531,10 @@
// tiles. This is attempting to simulate scrolling past the end of recorded
// content on the active layer, where the recordings are so far away that
// no tiles are created.
+ bool is_solid_color = false;
scoped_refptr<FakePicturePileImpl> active_pile =
FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
- tile_size, layer_bounds);
+ tile_size, layer_bounds, is_solid_color);
SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region());
@@ -3578,7 +3587,7 @@
resourceless_software_draw);
active_layer_->draw_properties().visible_content_rect = viewport;
active_layer_->draw_properties().screen_space_transform = transform;
- active_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ active_layer_->UpdateTiles(resourceless_software_draw);
gfx::Rect visible_rect_for_tile_priority =
active_layer_->visible_rect_for_tile_priority();
@@ -3602,7 +3611,7 @@
viewport,
transform,
resourceless_software_draw);
- active_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ active_layer_->UpdateTiles(resourceless_software_draw);
// Transform for tile priority is updated.
EXPECT_TRANSFORMATION_MATRIX_EQ(transform,
@@ -3622,7 +3631,7 @@
viewport,
transform,
resourceless_software_draw);
- active_layer_->UpdateTiles(Occlusion(), resourceless_software_draw);
+ active_layer_->UpdateTiles(resourceless_software_draw);
EXPECT_TRANSFORMATION_MATRIX_EQ(transform,
active_layer_->screen_space_transform());
@@ -3803,7 +3812,7 @@
SK_MScalar1 / max_contents_scale);
AppendQuadsData data;
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
// SharedQuadState should have be of size 1, as we are doing AppenQuad once.
EXPECT_EQ(1u, render_pass->shared_quad_state_list.size());
@@ -3869,7 +3878,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_HARDWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
// Even when OOM, quads should be produced, and should be different material
@@ -3971,8 +3980,7 @@
tile->is_occluded(twin_tree)) {
EXPECT_TRUE(tile->is_occluded(tree));
EXPECT_FALSE(tile->is_occluded(twin_tree));
- EXPECT_FALSE(
- tile->is_occluded_for_tree_priority(tree_priority));
+ EXPECT_FALSE(tile->is_occluded_combined());
} else if (priority.distance_to_visible !=
twin_priority.distance_to_visible) {
EXPECT_LT(priority_for_tree_priority.distance_to_visible,
@@ -4685,7 +4693,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr);
- active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data);
+ active_layer_->AppendQuads(render_pass.get(), &data);
active_layer_->DidDraw(nullptr);
DrawQuad::Material expected = test_for_solid
@@ -4822,12 +4830,15 @@
scoped_refptr<FakePicturePileImpl> filled_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- scoped_refptr<FakePicturePileImpl> partial_pile =
- FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds);
- for (int i = 1; i < partial_pile->tiling().num_tiles_x(); ++i) {
- for (int j = 1; j < partial_pile->tiling().num_tiles_y(); ++j)
- partial_pile->AddRecordingAt(i, j);
+
+ scoped_ptr<FakePicturePile> partial_recording =
+ FakePicturePile::CreateEmptyPile(tile_size, layer_bounds);
+ for (int i = 1; i < partial_recording->tiling().num_tiles_x(); ++i) {
+ for (int j = 1; j < partial_recording->tiling().num_tiles_y(); ++j)
+ partial_recording->AddRecordingAt(i, j);
}
+ scoped_refptr<FakePicturePileImpl> partial_pile =
+ FakePicturePileImpl::CreateFromPile(partial_recording.get(), nullptr);
SetupPendingTreeWithFixedTileSize(filled_pile, tile_size, Region());
ActivateTree();
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 9d36235..2ca1241 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -18,7 +18,7 @@
#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/shared_quad_state.h"
#include "cc/trees/damage_tracker.h"
-#include "cc/trees/occlusion_tracker.h"
+#include "cc/trees/occlusion.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/transform.h"
@@ -53,6 +53,23 @@
return drawable_content_rect;
}
+SkColor RenderSurfaceImpl::GetDebugBorderColor() const {
+ return DebugColors::SurfaceBorderColor();
+}
+
+SkColor RenderSurfaceImpl::GetReplicaDebugBorderColor() const {
+ return DebugColors::SurfaceReplicaBorderColor();
+}
+
+float RenderSurfaceImpl::GetDebugBorderWidth() const {
+ return DebugColors::SurfaceBorderWidth(owning_layer_->layer_tree_impl());
+}
+
+float RenderSurfaceImpl::GetReplicaDebugBorderWidth() const {
+ return DebugColors::SurfaceReplicaBorderWidth(
+ owning_layer_->layer_tree_impl());
+}
+
int RenderSurfaceImpl::OwningLayerId() const {
return owning_layer_ ? owning_layer_->id() : 0;
}
@@ -132,71 +149,39 @@
pass_sink->AppendRenderPass(pass.Pass());
}
-void RenderSurfaceImpl::AppendQuads(
- RenderPass* render_pass,
- const OcclusionTracker<LayerImpl>& occlusion_tracker,
- AppendQuadsData* append_quads_data,
- bool for_replica,
- RenderPassId render_pass_id) {
- DCHECK(!for_replica || owning_layer_->has_replica());
-
- const gfx::Transform& draw_transform =
- for_replica ? replica_draw_transform_ : draw_transform_;
+void RenderSurfaceImpl::AppendQuads(RenderPass* render_pass,
+ const gfx::Transform& draw_transform,
+ const Occlusion& occlusion_in_content_space,
+ SkColor debug_border_color,
+ float debug_border_width,
+ LayerImpl* mask_layer,
+ AppendQuadsData* append_quads_data,
+ RenderPassId render_pass_id) {
gfx::Rect visible_content_rect =
- occlusion_tracker.UnoccludedContributingSurfaceContentRect(
- content_rect_, draw_transform);
+ occlusion_in_content_space.GetUnoccludedContentRect(content_rect_);
if (visible_content_rect.IsEmpty())
return;
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
- shared_quad_state->SetAll(draw_transform,
- content_rect_.size(),
- content_rect_,
- clip_rect_,
- is_clipped_,
- draw_opacity_,
+ shared_quad_state->SetAll(draw_transform, content_rect_.size(), content_rect_,
+ clip_rect_, is_clipped_, draw_opacity_,
owning_layer_->blend_mode(),
owning_layer_->sorting_context_id());
if (owning_layer_->ShowDebugBorders()) {
- SkColor color = for_replica ?
- DebugColors::SurfaceReplicaBorderColor() :
- DebugColors::SurfaceBorderColor();
- float width = for_replica ?
- DebugColors::SurfaceReplicaBorderWidth(
- owning_layer_->layer_tree_impl()) :
- DebugColors::SurfaceBorderWidth(
- owning_layer_->layer_tree_impl());
DebugBorderDrawQuad* debug_border_quad =
render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
- debug_border_quad->SetNew(
- shared_quad_state, content_rect_, visible_content_rect, color, width);
- }
-
- // TODO(shawnsingh): By using the same RenderSurfaceImpl for both the content
- // and its reflection, it's currently not possible to apply a separate mask to
- // the reflection layer or correctly handle opacity in reflections (opacity
- // must be applied after drawing both the layer and its reflection). The
- // solution is to introduce yet another RenderSurfaceImpl to draw the layer
- // and its reflection in. For now we only apply a separate reflection mask if
- // the contents don't have a mask of their own.
- LayerImpl* mask_layer = owning_layer_->mask_layer();
- if (mask_layer &&
- (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty()))
- mask_layer = nullptr;
-
- if (!mask_layer && for_replica) {
- mask_layer = owning_layer_->replica_layer()->mask_layer();
- if (mask_layer &&
- (!mask_layer->DrawsContent() || mask_layer->bounds().IsEmpty()))
- mask_layer = nullptr;
+ debug_border_quad->SetNew(shared_quad_state, content_rect_,
+ visible_content_rect, debug_border_color,
+ debug_border_width);
}
ResourceProvider::ResourceId mask_resource_id = 0;
gfx::Size mask_texture_size;
gfx::Vector2dF mask_uv_scale;
- if (mask_layer) {
+ if (mask_layer && mask_layer->DrawsContent() &&
+ !mask_layer->bounds().IsEmpty()) {
mask_layer->GetContentsResourceId(&mask_resource_id, &mask_texture_size);
gfx::Vector2dF owning_layer_draw_scale =
MathUtil::ComputeTransform2dScaleComponents(
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h
index 3303e94..2035e28 100644
--- a/cc/layers/render_surface_impl.h
+++ b/cc/layers/render_surface_impl.h
@@ -14,6 +14,7 @@
#include "cc/layers/layer_lists.h"
#include "cc/quads/render_pass.h"
#include "cc/quads/shared_quad_state.h"
+#include "cc/trees/occlusion.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/transform.h"
@@ -22,8 +23,7 @@
class DamageTracker;
class DelegatedRendererLayerImpl;
-template <typename LayerType>
-class OcclusionTracker;
+class Occlusion;
class RenderPassId;
class RenderPassSink;
class LayerImpl;
@@ -60,6 +60,12 @@
}
bool draw_opacity_is_animating() const { return draw_opacity_is_animating_; }
+ SkColor GetDebugBorderColor() const;
+ SkColor GetReplicaDebugBorderColor() const;
+
+ float GetDebugBorderWidth() const;
+ float GetReplicaDebugBorderWidth() const;
+
void SetDrawTransform(const gfx::Transform& draw_transform) {
draw_transform_ = draw_transform;
}
@@ -120,6 +126,13 @@
void SetContentRect(const gfx::Rect& content_rect);
gfx::Rect content_rect() const { return content_rect_; }
+ const Occlusion& occlusion_in_content_space() const {
+ return occlusion_in_content_space_;
+ }
+ void set_occlusion_in_content_space(const Occlusion& occlusion) {
+ occlusion_in_content_space_ = occlusion;
+ }
+
LayerImplList& layer_list() { return layer_list_; }
void AddContributingDelegatedRenderPassLayer(LayerImpl* layer);
void ClearLayerLists();
@@ -136,9 +149,12 @@
void AppendRenderPasses(RenderPassSink* pass_sink);
void AppendQuads(RenderPass* render_pass,
- const OcclusionTracker<LayerImpl>& occlusion_tracker,
+ const gfx::Transform& draw_transform,
+ const Occlusion& occlusion_in_content_space,
+ SkColor debug_border_color,
+ float debug_border_width,
+ LayerImpl* mask_layer,
AppendQuadsData* append_quads_data,
- bool for_replica,
RenderPassId render_pass_id);
private:
@@ -166,6 +182,7 @@
LayerImplList layer_list_;
std::vector<DelegatedRendererLayerImpl*>
contributing_delegated_render_pass_layer_list_;
+ Occlusion occlusion_in_content_space_;
// The nearest ancestor target surface that will contain the contents of this
// surface, and that ignores outside occlusion. This can point to itself.
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index 6afbdcb..81b15ad 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -102,23 +102,17 @@
gfx::Rect content_rect(0, 0, 50, 50);
gfx::Rect clip_rect(5, 5, 40, 40);
gfx::Transform origin;
-
origin.Translate(30, 40);
- render_surface->SetDrawTransform(origin);
render_surface->SetContentRect(content_rect);
render_surface->SetClipRect(clip_rect);
render_surface->SetDrawOpacity(1.f);
- MockOcclusionTracker<LayerImpl> occlusion_tracker;
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData append_quads_data;
- bool for_replica = false;
- render_surface->AppendQuads(render_pass.get(),
- occlusion_tracker,
- &append_quads_data,
- for_replica,
+ render_surface->AppendQuads(render_pass.get(), origin, Occlusion(),
+ SK_ColorBLACK, 1.f, nullptr, &append_quads_data,
RenderPassId(2, 0));
ASSERT_EQ(1u, render_pass->shared_quad_state_list.size());
diff --git a/cc/layers/scrollbar_layer_impl_base.h b/cc/layers/scrollbar_layer_impl_base.h
index 4a96b49..d905c88 100644
--- a/cc/layers/scrollbar_layer_impl_base.h
+++ b/cc/layers/scrollbar_layer_impl_base.h
@@ -51,6 +51,7 @@
void PushScrollClipPropertiesTo(LayerImpl* layer);
bool SetVisibleToTotalLengthRatio(float ratio);
+ // Thumb quad rect in layer space.
virtual gfx::Rect ComputeThumbQuadRect() const;
float thumb_thickness_scale_factor() {
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index b24dcb1..c70b93a 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -59,12 +59,84 @@
return host->CommitAndCreateLayerImplTree();
}
-TEST(ScrollbarLayerTest, ResolveScrollLayerPointer) {
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
+class FakeResourceTrackingLayerTreeHost : public FakeLayerTreeHost {
+ public:
+ FakeResourceTrackingLayerTreeHost(FakeLayerTreeHostClient* client,
+ const LayerTreeSettings& settings)
+ : FakeLayerTreeHost(client, settings),
+ next_id_(1),
+ total_ui_resource_created_(0),
+ total_ui_resource_deleted_(0) {
+ InitializeSingleThreaded(client, base::MessageLoopProxy::current(),
+ nullptr);
+ }
+
+ UIResourceId CreateUIResource(UIResourceClient* content) override {
+ total_ui_resource_created_++;
+ UIResourceId nid = next_id_++;
+ ui_resource_bitmap_map_.insert(
+ std::make_pair(nid, content->GetBitmap(nid, false)));
+ return nid;
+ }
+
+ // Deletes a UI resource. May safely be called more than once.
+ void DeleteUIResource(UIResourceId id) override {
+ UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id);
+ if (iter != ui_resource_bitmap_map_.end()) {
+ ui_resource_bitmap_map_.erase(iter);
+ total_ui_resource_deleted_++;
+ }
+ }
+
+ size_t UIResourceCount() { return ui_resource_bitmap_map_.size(); }
+ int TotalUIResourceDeleted() { return total_ui_resource_deleted_; }
+ int TotalUIResourceCreated() { return total_ui_resource_created_; }
+
+ gfx::Size ui_resource_size(UIResourceId id) {
+ UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id);
+ if (iter != ui_resource_bitmap_map_.end())
+ return iter->second.GetSize();
+ return gfx::Size();
+ }
+
+ UIResourceBitmap* ui_resource_bitmap(UIResourceId id) {
+ UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id);
+ if (iter != ui_resource_bitmap_map_.end())
+ return &iter->second;
+ return nullptr;
+ }
+
+ private:
+ using UIResourceBitmapMap = base::hash_map<UIResourceId, UIResourceBitmap>;
+ UIResourceBitmapMap ui_resource_bitmap_map_;
+
+ int next_id_;
+ int total_ui_resource_created_;
+ int total_ui_resource_deleted_;
+};
+
+class ScrollbarLayerTest : public testing::Test {
+ public:
+ ScrollbarLayerTest() : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {
+ layer_tree_settings_.single_thread_proxy_scheduler = false;
+ layer_tree_host_.reset(new FakeResourceTrackingLayerTreeHost(
+ &fake_client_, layer_tree_settings_));
+ fake_client_.SetLayerTreeHost(layer_tree_host_.get());
+ // Force output surface creation for renderer capabilities.
+ layer_tree_host_->Composite(base::TimeTicks());
+ EXPECT_FALSE(layer_tree_host_->output_surface_lost());
+ }
+
+ protected:
+ FakeLayerTreeHostClient fake_client_;
+ LayerTreeSettings layer_tree_settings_;
+ scoped_ptr<FakeResourceTrackingLayerTreeHost> layer_tree_host_;
+};
+
+TEST_F(ScrollbarLayerTest, ResolveScrollLayerPointer) {
scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar);
LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar(
- host.get(), scrollbar.Pass(), false, false, 0, 0);
+ layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0);
LayerImpl* cc_child1 = layer_impl_tree_root->children()[0];
PaintedScrollbarLayerImpl* cc_child2 =
@@ -75,12 +147,10 @@
EXPECT_EQ(*(cc_child1->scrollbars()->begin()), cc_child2);
}
-TEST(ScrollbarLayerTest, ResolveScrollLayerPointer_ReverseOrder) {
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
+TEST_F(ScrollbarLayerTest, ResolveScrollLayerPointer_ReverseOrder) {
scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar);
LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar(
- host.get(), scrollbar.Pass(), true, false, 0, 0);
+ layer_tree_host_.get(), scrollbar.Pass(), true, false, 0, 0);
PaintedScrollbarLayerImpl* cc_child1 =
static_cast<PaintedScrollbarLayerImpl*>(
@@ -91,14 +161,11 @@
EXPECT_EQ(*(cc_child2->scrollbars()->begin()), cc_child1);
}
-TEST(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) {
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
-
+TEST_F(ScrollbarLayerTest, ShouldScrollNonOverlayOnMainThread) {
// Create and attach a non-overlay scrollbar.
scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar);
LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar(
- host.get(), scrollbar.Pass(), false, false, 0, 0);
+ layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0);
PaintedScrollbarLayerImpl* scrollbar_layer_impl =
static_cast<PaintedScrollbarLayerImpl*>(
layer_impl_tree_root->children()[1]);
@@ -114,7 +181,7 @@
scrollbar.reset(new FakeScrollbar(false, false, true));
layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar(
- host.get(), scrollbar.Pass(), false, false, 0, 0);
+ layer_tree_host_.get(), scrollbar.Pass(), false, false, 0, 0);
scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>(
layer_impl_tree_root->children()[1]);
@@ -125,10 +192,7 @@
gfx::Point(0, 0), InputHandler::Gesture, ScrollBlocksOnNone));
}
-TEST(PaintedScrollbarLayerTest, ScrollOffsetSynchronization) {
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
-
+TEST_F(ScrollbarLayerTest, ScrollOffsetSynchronization) {
scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar);
scoped_refptr<Layer> layer_tree_root = Layer::Create();
scoped_refptr<Layer> scroll_layer = Layer::Create();
@@ -143,7 +207,7 @@
scroll_layer->SetBounds(gfx::Size(100, 200));
content_layer->SetBounds(gfx::Size(100, 200));
- host->SetRootLayer(layer_tree_root);
+ layer_tree_host_->SetRootLayer(layer_tree_root);
layer_tree_root->AddChild(scroll_layer);
scroll_layer->AddChild(content_layer);
layer_tree_root->AddChild(scrollbar_layer);
@@ -153,7 +217,8 @@
layer_tree_root->SavePaintProperties();
content_layer->SavePaintProperties();
- LayerImpl* layer_impl_tree_root = host->CommitAndCreateLayerImplTree();
+ LayerImpl* layer_impl_tree_root =
+ layer_tree_host_->CommitAndCreateLayerImplTree();
ScrollbarLayerImplBase* cc_scrollbar_layer =
static_cast<PaintedScrollbarLayerImpl*>(
@@ -172,7 +237,7 @@
ScrollbarAnimationController* scrollbar_controller =
layer_impl_tree_root->scrollbar_animation_controller();
- layer_impl_tree_root = host->CommitAndCreateLayerImplTree();
+ layer_impl_tree_root = layer_tree_host_->CommitAndCreateLayerImplTree();
EXPECT_EQ(scrollbar_controller,
layer_impl_tree_root->scrollbar_animation_controller());
@@ -186,19 +251,18 @@
EXPECT_EQ(300, cc_scrollbar_layer->maximum());
}
-#define UPDATE_AND_EXTRACT_LAYER_POINTERS() \
- do { \
- scrollbar_layer->UpdateThumbAndTrackGeometry(); \
- root_clip_layer_impl = host->CommitAndCreateLayerImplTree(); \
- root_layer_impl = root_clip_layer_impl->children()[0]; \
- scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>( \
- root_layer_impl->children()[1]); \
- scrollbar_layer_impl->ScrollbarParametersDidChange(false); \
+#define UPDATE_AND_EXTRACT_LAYER_POINTERS() \
+ do { \
+ scrollbar_layer->UpdateInternalContentScale(); \
+ scrollbar_layer->UpdateThumbAndTrackGeometry(); \
+ root_clip_layer_impl = layer_tree_host_->CommitAndCreateLayerImplTree(); \
+ root_layer_impl = root_clip_layer_impl->children()[0]; \
+ scrollbar_layer_impl = static_cast<PaintedScrollbarLayerImpl*>( \
+ root_layer_impl->children()[1]); \
+ scrollbar_layer_impl->ScrollbarParametersDidChange(false); \
} while (false)
-TEST(ScrollbarLayerTest, UpdatePropertiesOfScrollBarWhenThumbRemoved) {
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
+TEST_F(ScrollbarLayerTest, UpdatePropertiesOfScrollBarWhenThumbRemoved) {
scoped_refptr<Layer> root_clip_layer = Layer::Create();
scoped_refptr<Layer> root_layer = Layer::Create();
scoped_refptr<Layer> content_layer = Layer::Create();
@@ -211,7 +275,7 @@
root_layer->SetBounds(gfx::Size(100, 50));
content_layer->SetBounds(gfx::Size(100, 50));
- host->SetRootLayer(root_clip_layer);
+ layer_tree_host_->SetRootLayer(root_clip_layer);
root_clip_layer->AddChild(root_layer);
root_layer->AddChild(content_layer);
root_layer->AddChild(scrollbar_layer);
@@ -224,8 +288,6 @@
scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10);
scrollbar_layer->fake_scrollbar()->set_thumb_length(4);
-
- scrollbar_layer->UpdateThumbAndTrackGeometry();
LayerImpl* root_clip_layer_impl = nullptr;
LayerImpl* root_layer_impl = nullptr;
PaintedScrollbarLayerImpl* scrollbar_layer_impl = nullptr;
@@ -241,9 +303,7 @@
scrollbar_layer_impl->ComputeThumbQuadRect().ToString());
}
-TEST(ScrollbarLayerTest, ThumbRect) {
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- scoped_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(&client);
+TEST_F(ScrollbarLayerTest, ThumbRect) {
scoped_refptr<Layer> root_clip_layer = Layer::Create();
scoped_refptr<Layer> root_layer = Layer::Create();
scoped_refptr<Layer> content_layer = Layer::Create();
@@ -256,7 +316,7 @@
root_layer->SetBounds(gfx::Size(100, 50));
content_layer->SetBounds(gfx::Size(100, 50));
- host->SetRootLayer(root_clip_layer);
+ layer_tree_host_->SetRootLayer(root_clip_layer);
root_clip_layer->AddChild(root_layer);
root_layer->AddChild(content_layer);
root_layer->AddChild(scrollbar_layer);
@@ -269,7 +329,6 @@
scrollbar_layer->fake_scrollbar()->set_track_rect(gfx::Rect(30, 10, 50, 10));
scrollbar_layer->fake_scrollbar()->set_thumb_thickness(10);
scrollbar_layer->fake_scrollbar()->set_thumb_length(4);
- scrollbar_layer->UpdateThumbAndTrackGeometry();
LayerImpl* root_clip_layer_impl = nullptr;
LayerImpl* root_layer_impl = nullptr;
PaintedScrollbarLayerImpl* scrollbar_layer_impl = nullptr;
@@ -322,19 +381,15 @@
scrollbar_layer_impl->ComputeThumbQuadRect().ToString());
}
-TEST(ScrollbarLayerTest, SolidColorDrawQuads) {
+TEST_F(ScrollbarLayerTest, SolidColorDrawQuads) {
const int kThumbThickness = 3;
const int kTrackStart = 1;
const int kTrackLength = 100;
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- LayerTreeSettings layer_tree_settings;
- scoped_ptr<FakeLayerTreeHost> host =
- FakeLayerTreeHost::Create(&client, layer_tree_settings);
-
scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true));
LayerImpl* layer_impl_tree_root = LayerImplForScrollAreaAndScrollbar(
- host.get(), scrollbar.Pass(), false, true, kThumbThickness, kTrackStart);
+ layer_tree_host_.get(), scrollbar.Pass(), false, true, kThumbThickness,
+ kTrackStart);
ScrollbarLayerImplBase* scrollbar_layer_impl =
static_cast<SolidColorScrollbarLayerImpl*>(
layer_impl_tree_root->children()[1]);
@@ -347,7 +402,7 @@
{
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- scrollbar_layer_impl->AppendQuads(render_pass.get(), Occlusion(), &data);
+ scrollbar_layer_impl->AppendQuads(render_pass.get(), &data);
const QuadList& quads = render_pass->quad_list;
ASSERT_EQ(1u, quads.size());
@@ -361,7 +416,7 @@
{
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- scrollbar_layer_impl->AppendQuads(render_pass.get(), Occlusion(), &data);
+ scrollbar_layer_impl->AppendQuads(render_pass.get(), &data);
const QuadList& quads = render_pass->quad_list;
ASSERT_EQ(1u, quads.size());
@@ -377,7 +432,7 @@
{
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- scrollbar_layer_impl->AppendQuads(render_pass.get(), Occlusion(), &data);
+ scrollbar_layer_impl->AppendQuads(render_pass.get(), &data);
const QuadList& quads = render_pass->quad_list;
ASSERT_EQ(1u, quads.size());
@@ -391,7 +446,7 @@
{
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- scrollbar_layer_impl->AppendQuads(render_pass.get(), Occlusion(), &data);
+ scrollbar_layer_impl->AppendQuads(render_pass.get(), &data);
const QuadList& quads = render_pass->quad_list;
ASSERT_EQ(1u, quads.size());
@@ -400,16 +455,11 @@
}
}
-TEST(ScrollbarLayerTest, LayerDrivenSolidColorDrawQuads) {
+TEST_F(ScrollbarLayerTest, LayerDrivenSolidColorDrawQuads) {
const int kThumbThickness = 3;
const int kTrackStart = 0;
const int kTrackLength = 10;
- FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
- LayerTreeSettings layer_tree_settings;
- scoped_ptr<FakeLayerTreeHost> host =
- FakeLayerTreeHost::Create(&client, layer_tree_settings);
-
scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, true));
{
@@ -429,9 +479,10 @@
scroll_layer->AddChild(child1);
scroll_layer->InsertChild(child2, 1);
layer_tree_root->AddChild(scroll_layer);
- host->SetRootLayer(layer_tree_root);
+ layer_tree_host_->SetRootLayer(layer_tree_root);
}
- LayerImpl* layer_impl_tree_root = host->CommitAndCreateLayerImplTree();
+ LayerImpl* layer_impl_tree_root =
+ layer_tree_host_->CommitAndCreateLayerImplTree();
LayerImpl* scroll_layer_impl = layer_impl_tree_root->children()[0];
ScrollbarLayerImplBase* scrollbar_layer_impl =
@@ -450,7 +501,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- scrollbar_layer_impl->AppendQuads(render_pass.get(), Occlusion(), &data);
+ scrollbar_layer_impl->AppendQuads(render_pass.get(), &data);
const QuadList& quads = render_pass->quad_list;
ASSERT_EQ(1u, quads.size());
@@ -578,6 +629,7 @@
scrollbar_layer_->SetScrollLayer(scroll_layer_->id());
scrollbar_layer_->SetLayerTreeHost(layer_tree_host());
scrollbar_layer_->SetBounds(bounds_);
+ scrollbar_layer_->SetIsDrawable(true);
layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
PostSetNeedsCommitToMainThread();
@@ -590,9 +642,9 @@
// Check first that we're actually testing something.
EXPECT_GT(scrollbar_layer_->bounds().width(), kMaxTextureSize);
- EXPECT_EQ(scrollbar_layer_->content_bounds().width(),
+ EXPECT_EQ(scrollbar_layer_->internal_content_bounds().width(),
kMaxTextureSize - 1);
- EXPECT_EQ(scrollbar_layer_->content_bounds().height(),
+ EXPECT_EQ(scrollbar_layer_->internal_content_bounds().height(),
kMaxTextureSize - 1);
EndTest();
@@ -624,77 +676,13 @@
RunTest(true, true, true);
}
-class FakeLayerTreeHost : public LayerTreeHost {
+class ScrollbarLayerTestResourceCreationAndRelease : public ScrollbarLayerTest {
public:
- FakeLayerTreeHost(FakeLayerTreeHostClient* client,
- const LayerTreeSettings& settings)
- : LayerTreeHost(client, nullptr, nullptr, settings),
- next_id_(1),
- total_ui_resource_created_(0),
- total_ui_resource_deleted_(0) {
- InitializeSingleThreaded(client,
- base::MessageLoopProxy::current(),
- nullptr);
- }
-
- UIResourceId CreateUIResource(UIResourceClient* content) override {
- total_ui_resource_created_++;
- UIResourceId nid = next_id_++;
- ui_resource_bitmap_map_.insert(
- std::make_pair(nid, content->GetBitmap(nid, false)));
- return nid;
- }
-
- // Deletes a UI resource. May safely be called more than once.
- void DeleteUIResource(UIResourceId id) override {
- UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id);
- if (iter != ui_resource_bitmap_map_.end()) {
- ui_resource_bitmap_map_.erase(iter);
- total_ui_resource_deleted_++;
- }
- }
-
- size_t UIResourceCount() { return ui_resource_bitmap_map_.size(); }
- int TotalUIResourceDeleted() { return total_ui_resource_deleted_; }
- int TotalUIResourceCreated() { return total_ui_resource_created_; }
-
- gfx::Size ui_resource_size(UIResourceId id) {
- UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id);
- if (iter != ui_resource_bitmap_map_.end())
- return iter->second.GetSize();
- return gfx::Size();
- }
-
- UIResourceBitmap* ui_resource_bitmap(UIResourceId id) {
- UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id);
- if (iter != ui_resource_bitmap_map_.end())
- return &iter->second;
- return nullptr;
- }
-
- private:
- typedef base::hash_map<UIResourceId, UIResourceBitmap>
- UIResourceBitmapMap;
- UIResourceBitmapMap ui_resource_bitmap_map_;
-
- int next_id_;
- int total_ui_resource_created_;
- int total_ui_resource_deleted_;
-};
-
-class ScrollbarLayerTestResourceCreationAndRelease : public testing::Test {
- public:
- ScrollbarLayerTestResourceCreationAndRelease()
- : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
void TestResourceUpload(int num_updates,
size_t expected_resources,
int expected_created,
int expected_deleted,
bool use_solid_color_scrollbar) {
- layer_tree_host_.reset(
- new FakeLayerTreeHost(&fake_client_, layer_tree_settings_));
-
scoped_ptr<Scrollbar> scrollbar(new FakeScrollbar(false, true, false));
scoped_refptr<Layer> layer_tree_root = Layer::Create();
scoped_refptr<Layer> content_layer = Layer::Create();
@@ -749,22 +737,18 @@
scrollbar_layer->ClearRenderSurface();
}
-
- protected:
- FakeLayerTreeHostClient fake_client_;
- LayerTreeSettings layer_tree_settings_;
- scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
};
TEST_F(ScrollbarLayerTestResourceCreationAndRelease, ResourceUpload) {
bool use_solid_color_scrollbars = false;
TestResourceUpload(0, 0, 0, 0, use_solid_color_scrollbars);
int num_updates[3] = {1, 5, 10};
+ int created = 0;
+ int deleted = 0;
for (int j = 0; j < 3; j++) {
- TestResourceUpload(num_updates[j],
- 2,
- num_updates[j] * 2,
- (num_updates[j] - 1) * 2,
+ created += num_updates[j] * 2;
+ deleted = created - 2;
+ TestResourceUpload(num_updates[j], 2, created, deleted,
use_solid_color_scrollbars);
}
}
@@ -777,13 +761,6 @@
}
TEST_F(ScrollbarLayerTestResourceCreationAndRelease, TestResourceUpdate) {
- FakeLayerTreeHostClient fake_client_(FakeLayerTreeHostClient::DIRECT_3D);
- LayerTreeSettings layer_tree_settings_;
- scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
-
- layer_tree_host_.reset(
- new FakeLayerTreeHost(&fake_client_, layer_tree_settings_));
-
gfx::Point scrollbar_location(0, 185);
scoped_refptr<Layer> layer_tree_root = Layer::Create();
scoped_refptr<Layer> content_layer = Layer::Create();
@@ -918,15 +895,9 @@
scrollbar_layer->ClearRenderSurface();
}
-class ScaledScrollbarLayerTestResourceCreation : public testing::Test {
+class ScaledScrollbarLayerTestResourceCreation : public ScrollbarLayerTest {
public:
- ScaledScrollbarLayerTestResourceCreation()
- : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
void TestResourceUpload(const float test_scale) {
- layer_tree_host_.reset(
- new FakeLayerTreeHost(&fake_client_, layer_tree_settings_));
-
gfx::Point scrollbar_location(0, 185);
scoped_refptr<Layer> layer_tree_root = Layer::Create();
scoped_refptr<Layer> content_layer = Layer::Create();
@@ -976,20 +947,19 @@
gfx::Size thumb_size = layer_tree_host_->ui_resource_size(
scrollbar_layer->thumb_resource_id());
- EXPECT_LE(track_size.width(), scrollbar_layer->content_bounds().width());
- EXPECT_LE(track_size.height(), scrollbar_layer->content_bounds().height());
- EXPECT_LE(thumb_size.width(), scrollbar_layer->content_bounds().width());
- EXPECT_LE(thumb_size.height(), scrollbar_layer->content_bounds().height());
+ EXPECT_LE(track_size.width(),
+ scrollbar_layer->internal_content_bounds().width());
+ EXPECT_LE(track_size.height(),
+ scrollbar_layer->internal_content_bounds().height());
+ EXPECT_LE(thumb_size.width(),
+ scrollbar_layer->internal_content_bounds().width());
+ EXPECT_LE(thumb_size.height(),
+ scrollbar_layer->internal_content_bounds().height());
testing::Mock::VerifyAndClearExpectations(layer_tree_host_.get());
scrollbar_layer->ClearRenderSurface();
}
-
- protected:
- FakeLayerTreeHostClient fake_client_;
- LayerTreeSettings layer_tree_settings_;
- scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
};
TEST_F(ScaledScrollbarLayerTestResourceCreation, ScaledResourceUpload) {
@@ -1000,15 +970,9 @@
TestResourceUpload(4.1f);
}
-class ScaledScrollbarLayerTestScaledRasterization : public testing::Test {
+class ScaledScrollbarLayerTestScaledRasterization : public ScrollbarLayerTest {
public:
- ScaledScrollbarLayerTestScaledRasterization()
- : fake_client_(FakeLayerTreeHostClient::DIRECT_3D) {}
-
void TestScale(const gfx::Rect scrollbar_rect, const float test_scale) {
- layer_tree_host_.reset(
- new FakeLayerTreeHost(&fake_client_, layer_tree_settings_));
-
bool paint_during_update = true;
bool has_thumb = false;
scoped_refptr<Layer> layer_tree_root = Layer::Create();
@@ -1082,10 +1046,6 @@
(SkColorGetG(c) << SK_G32_SHIFT) |
(SkColorGetB(c) << SK_B32_SHIFT);
}
-
- FakeLayerTreeHostClient fake_client_;
- LayerTreeSettings layer_tree_settings_;
- scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
};
TEST_F(ScaledScrollbarLayerTestScaledRasterization, TestLostPrecisionInClip) {
diff --git a/cc/layers/solid_color_layer_impl.cc b/cc/layers/solid_color_layer_impl.cc
index 3376693..2762497 100644
--- a/cc/layers/solid_color_layer_impl.cc
+++ b/cc/layers/solid_color_layer_impl.cc
@@ -64,7 +64,6 @@
void SolidColorLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
@@ -75,12 +74,9 @@
// TODO(hendrikw): We need to pass the visible content rect rather than
// |content_bounds()| here.
- AppendSolidQuads(render_pass,
- occlusion_in_content_space,
- shared_quad_state,
- gfx::Rect(content_bounds()),
- background_color(),
- append_quads_data);
+ AppendSolidQuads(render_pass, draw_properties().occlusion_in_content_space,
+ shared_quad_state, gfx::Rect(content_bounds()),
+ background_color(), append_quads_data);
}
const char* SolidColorLayerImpl::LayerTypeAsString() const {
diff --git a/cc/layers/solid_color_layer_impl.h b/cc/layers/solid_color_layer_impl.h
index 3793481..213e3f1 100644
--- a/cc/layers/solid_color_layer_impl.h
+++ b/cc/layers/solid_color_layer_impl.h
@@ -30,7 +30,6 @@
// LayerImpl overrides.
scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
protected:
diff --git a/cc/layers/solid_color_layer_impl_unittest.cc b/cc/layers/solid_color_layer_impl_unittest.cc
index 7150f80..d10f35d 100644
--- a/cc/layers/solid_color_layer_impl_unittest.cc
+++ b/cc/layers/solid_color_layer_impl_unittest.cc
@@ -38,7 +38,7 @@
layer->draw_properties().render_target = layer.get();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
LayerTestCommon::VerifyQuadsExactlyCoverRect(render_pass->quad_list,
visible_content_rect);
@@ -65,7 +65,7 @@
layer->draw_properties().render_target = layer.get();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
ASSERT_EQ(render_pass->quad_list.size(), 1U);
EXPECT_EQ(
@@ -94,7 +94,7 @@
layer->draw_properties().render_target = layer.get();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
ASSERT_EQ(render_pass->quad_list.size(), 1U);
EXPECT_EQ(opacity,
@@ -120,7 +120,7 @@
layer->draw_properties().blend_mode = blend_mode;
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
ASSERT_EQ(render_pass->quad_list.size(), 1U);
EXPECT_EQ(blend_mode,
@@ -166,7 +166,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- layer_impl->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer_impl->AppendQuads(render_pass.get(), &data);
ASSERT_EQ(render_pass->quad_list.size(), 1U);
EXPECT_EQ(visible_content_rect.ToString(),
@@ -192,7 +192,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- layer_impl->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer_impl->AppendQuads(render_pass.get(), &data);
ASSERT_EQ(render_pass->quad_list.size(), 1U);
EXPECT_EQ(gfx::Rect().ToString(),
diff --git a/cc/layers/solid_color_scrollbar_layer_impl.cc b/cc/layers/solid_color_scrollbar_layer_impl.cc
index db6a502..fa1849e 100644
--- a/cc/layers/solid_color_scrollbar_layer_impl.cc
+++ b/cc/layers/solid_color_scrollbar_layer_impl.cc
@@ -95,7 +95,6 @@
void SolidColorScrollbarLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
@@ -106,7 +105,8 @@
gfx::Rect thumb_quad_rect(ComputeThumbQuadRect());
gfx::Rect visible_quad_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(thumb_quad_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ thumb_quad_rect);
if (visible_quad_rect.IsEmpty())
return;
diff --git a/cc/layers/solid_color_scrollbar_layer_impl.h b/cc/layers/solid_color_scrollbar_layer_impl.h
index 1abf552..df6179d 100644
--- a/cc/layers/solid_color_scrollbar_layer_impl.h
+++ b/cc/layers/solid_color_scrollbar_layer_impl.h
@@ -27,7 +27,6 @@
void PushPropertiesTo(LayerImpl* layer) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
protected:
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index c3df89b..966112d 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -38,7 +38,6 @@
}
void SurfaceLayerImpl::AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
@@ -52,7 +51,8 @@
gfx::Rect quad_rect(content_bounds());
gfx::Rect visible_quad_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(quad_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ quad_rect);
if (visible_quad_rect.IsEmpty())
return;
SurfaceDrawQuad* quad =
@@ -66,7 +66,7 @@
*width = DebugColors::SurfaceLayerBorderWidth(layer_tree_impl());
}
-void SurfaceLayerImpl::AsValueInto(base::debug::TracedValue* dict) const {
+void SurfaceLayerImpl::AsValueInto(base::trace_event::TracedValue* dict) const {
LayerImpl::AsValueInto(dict);
dict->SetInteger("surface_id", surface_id_.id);
}
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h
index 9ef3c6d..90c0f45 100644
--- a/cc/layers/surface_layer_impl.h
+++ b/cc/layers/surface_layer_impl.h
@@ -25,7 +25,6 @@
scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
void PushPropertiesTo(LayerImpl* layer) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
protected:
@@ -33,7 +32,7 @@
private:
void GetDebugBorderProperties(SkColor* color, float* width) const override;
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
const char* LayerTypeAsString() const override;
SurfaceId surface_id_;
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc
index 6e9cea1..d9ddee7 100644
--- a/cc/layers/texture_layer_impl.cc
+++ b/cc/layers/texture_layer_impl.cc
@@ -141,7 +141,6 @@
}
void TextureLayerImpl::AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
DCHECK(external_texture_resource_ || valid_texture_copy_);
@@ -159,7 +158,8 @@
gfx::Rect quad_rect(content_bounds());
gfx::Rect opaque_rect = opaque ? quad_rect : gfx::Rect();
gfx::Rect visible_quad_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(quad_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ quad_rect);
if (visible_quad_rect.IsEmpty())
return;
diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h
index 64de268..3d2c165 100644
--- a/cc/layers/texture_layer_impl.h
+++ b/cc/layers/texture_layer_impl.h
@@ -29,7 +29,6 @@
bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
SimpleEnclosedRegion VisibleContentOpaqueRegion() const override;
void ReleaseResources() override;
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index 33291be..6405db3 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -1402,10 +1402,7 @@
public:
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
LayerTreeImpl* tree = nullptr;
- if (host_impl->settings().impl_side_painting)
- tree = host_impl->pending_tree();
- else
- tree = host_impl->active_tree();
+ tree = host_impl->sync_tree();
tree->root_layer()->children()[0]->ReleaseResources();
}
};
diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc
index 535744d..234bd44 100644
--- a/cc/layers/tiled_layer_impl.cc
+++ b/cc/layers/tiled_layer_impl.cc
@@ -113,7 +113,7 @@
return TiledLayerImpl::Create(tree_impl, id(), synced_scroll_offset());
}
-void TiledLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
+void TiledLayerImpl::AsValueInto(base::trace_event::TracedValue* state) const {
LayerImpl::AsValueInto(state);
MathUtil::AddToTracedValue("invalidation", update_rect(), state);
}
@@ -166,7 +166,6 @@
}
void TiledLayerImpl::AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
DCHECK(tiler_);
DCHECK(!tiler_->has_empty_bounds());
@@ -225,7 +224,8 @@
continue;
gfx::Rect visible_tile_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(tile_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ tile_rect);
if (visible_tile_rect.IsEmpty())
continue;
diff --git a/cc/layers/tiled_layer_impl.h b/cc/layers/tiled_layer_impl.h
index 039bf19..c292790 100644
--- a/cc/layers/tiled_layer_impl.h
+++ b/cc/layers/tiled_layer_impl.h
@@ -36,7 +36,6 @@
bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
void GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
@@ -68,7 +67,7 @@
bool HasResourceIdForTileAt(int i, int j) const;
void GetDebugBorderProperties(SkColor* color, float* width) const override;
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
private:
const char* LayerTypeAsString() const override;
diff --git a/cc/layers/tiled_layer_impl_unittest.cc b/cc/layers/tiled_layer_impl_unittest.cc
index 148f36a..e98fd09 100644
--- a/cc/layers/tiled_layer_impl_unittest.cc
+++ b/cc/layers/tiled_layer_impl_unittest.cc
@@ -71,7 +71,7 @@
layer->SetBounds(layer_size);
AppendQuadsData data;
- layer->AppendQuads(render_pass, Occlusion(), &data);
+ layer->AppendQuads(render_pass, &data);
}
protected:
@@ -95,7 +95,7 @@
AppendQuadsData data;
EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, nullptr));
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
layer->DidDraw(nullptr);
unsigned num_tiles = num_tiles_x * num_tiles_y;
EXPECT_EQ(render_pass->quad_list.size(), num_tiles);
@@ -124,7 +124,7 @@
AppendQuadsData data;
EXPECT_TRUE(layer->WillDraw(DRAW_MODE_HARDWARE, nullptr));
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
layer->DidDraw(nullptr);
EXPECT_EQ(render_pass->quad_list.size(), 0u);
}
@@ -138,7 +138,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
EXPECT_EQ(render_pass->quad_list.size(), 0u);
}
}
@@ -158,7 +158,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
EXPECT_EQ(render_pass->quad_list.size(), 4u);
EXPECT_EQ(0u, data.num_missing_tiles);
@@ -175,7 +175,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
EXPECT_LT(0u, data.num_missing_tiles);
EXPECT_EQ(render_pass->quad_list.size(), 4u);
for (const auto& quad : render_pass->quad_list)
diff --git a/cc/layers/ui_resource_layer_impl.cc b/cc/layers/ui_resource_layer_impl.cc
index c7653e7..76900e4 100644
--- a/cc/layers/ui_resource_layer_impl.cc
+++ b/cc/layers/ui_resource_layer_impl.cc
@@ -93,7 +93,6 @@
void UIResourceLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
@@ -123,7 +122,8 @@
gfx::Rect quad_rect(bounds());
gfx::Rect opaque_rect(opaque ? quad_rect : gfx::Rect());
gfx::Rect visible_quad_rect =
- occlusion_in_content_space.GetUnoccludedContentRect(quad_rect);
+ draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
+ quad_rect);
if (visible_quad_rect.IsEmpty())
return;
diff --git a/cc/layers/ui_resource_layer_impl.h b/cc/layers/ui_resource_layer_impl.h
index d98f1fb..87d77e8 100644
--- a/cc/layers/ui_resource_layer_impl.h
+++ b/cc/layers/ui_resource_layer_impl.h
@@ -45,7 +45,6 @@
bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
base::DictionaryValue* LayerTreeAsJson() const override;
diff --git a/cc/layers/ui_resource_layer_impl_unittest.cc b/cc/layers/ui_resource_layer_impl_unittest.cc
index 7149b07..4509ae3 100644
--- a/cc/layers/ui_resource_layer_impl_unittest.cc
+++ b/cc/layers/ui_resource_layer_impl_unittest.cc
@@ -48,7 +48,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
// Verify quad rects
const QuadList& quads = render_pass->quad_list;
@@ -88,7 +88,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ layer->AppendQuads(render_pass.get(), &data);
// Verify quad rects
const QuadList& quads = render_pass->quad_list;
diff --git a/cc/layers/video_frame_provider_client_impl.h b/cc/layers/video_frame_provider_client_impl.h
index b6eb86f..39f66fb 100644
--- a/cc/layers/video_frame_provider_client_impl.h
+++ b/cc/layers/video_frame_provider_client_impl.h
@@ -7,6 +7,7 @@
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
#include "cc/layers/video_frame_provider.h"
#include "ui/gfx/transform.h"
@@ -23,12 +24,10 @@
VideoFrameProvider* provider);
VideoLayerImpl* active_video_layer() { return active_video_layer_; }
- void set_active_video_layer(VideoLayerImpl* video_layer) {
- active_video_layer_ = video_layer;
- }
+ void SetActiveVideoLayer(VideoLayerImpl* video_layer);
void Stop();
- bool Stopped() const { return !provider_; }
+ bool Stopped();
scoped_refptr<media::VideoFrame> AcquireLockAndCurrentFrame();
void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame);
@@ -53,6 +52,7 @@
// Guards the destruction of provider_ and the frame that it provides
base::Lock provider_lock_;
VideoFrameProvider* provider_;
+ base::ThreadChecker thread_checker_;
gfx::Transform stream_texture_matrix_;
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index 091f2a9..559e0ac 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -72,7 +72,7 @@
}
void VideoLayerImpl::DidBecomeActive() {
- provider_client_impl_->set_active_video_layer(this);
+ provider_client_impl_->SetActiveVideoLayer(this);
}
bool VideoLayerImpl::WillDraw(DrawMode draw_mode,
@@ -132,7 +132,6 @@
}
void VideoLayerImpl::AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
DCHECK(frame_.get());
@@ -172,7 +171,9 @@
gfx::Size coded_size = frame_->coded_size();
Occlusion occlusion_in_video_space =
- occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(transform);
+ draw_properties()
+ .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
+ transform);
gfx::Rect visible_quad_rect =
occlusion_in_video_space.GetUnoccludedContentRect(quad_rect);
if (visible_quad_rect.IsEmpty())
diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h
index 1843ec7..d05bd57 100644
--- a/cc/layers/video_layer_impl.h
+++ b/cc/layers/video_layer_impl.h
@@ -35,7 +35,6 @@
bool WillDraw(DrawMode draw_mode,
ResourceProvider* resource_provider) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
void DidDraw(ResourceProvider* resource_provider) override;
void DidBecomeActive() override;
diff --git a/cc/output/begin_frame_args.cc b/cc/output/begin_frame_args.cc
index acf24aa..3663125 100644
--- a/cc/output/begin_frame_args.cc
+++ b/cc/output/begin_frame_args.cc
@@ -59,15 +59,15 @@
#endif
}
-scoped_refptr<base::debug::ConvertableToTraceFormat> BeginFrameArgs::AsValue()
- const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+BeginFrameArgs::AsValue() const {
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get());
return state;
}
-void BeginFrameArgs::AsValueInto(base::debug::TracedValue* state) const {
+void BeginFrameArgs::AsValueInto(base::trace_event::TracedValue* state) const {
state->SetString("type", "BeginFrameArgs");
state->SetString("subtype", TypeToString(type));
state->SetDouble("frame_time_us", frame_time.ToInternalValue());
diff --git a/cc/output/begin_frame_args.h b/cc/output/begin_frame_args.h
index 47430ca..10f7f28 100644
--- a/cc/output/begin_frame_args.h
+++ b/cc/output/begin_frame_args.h
@@ -16,14 +16,7 @@
class ConvertableToTraceFormat;
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
-using ::base::trace_event::TracedValue;
}
-} // namespace base
/**
* In debug builds we trace the creation origin of BeginFrameArgs objects. We
@@ -84,8 +77,8 @@
bool IsValid() const { return interval >= base::TimeDelta(); }
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
- void AsValueInto(base::debug::TracedValue* dict) const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::trace_event::TracedValue* dict) const;
base::TimeTicks frame_time;
base::TimeTicks deadline;
diff --git a/cc/output/compositor_frame_metadata.cc b/cc/output/compositor_frame_metadata.cc
index 039f69d..dad78a0 100644
--- a/cc/output/compositor_frame_metadata.cc
+++ b/cc/output/compositor_frame_metadata.cc
@@ -10,7 +10,9 @@
: device_scale_factor(0.f),
page_scale_factor(0.f),
min_page_scale_factor(0.f),
- max_page_scale_factor(0.f) {
+ max_page_scale_factor(0.f),
+ root_overflow_x_hidden(false),
+ root_overflow_y_hidden(false) {
}
CompositorFrameMetadata::~CompositorFrameMetadata() {
diff --git a/cc/output/compositor_frame_metadata.h b/cc/output/compositor_frame_metadata.h
index a6fe2d4..e92a84d 100644
--- a/cc/output/compositor_frame_metadata.h
+++ b/cc/output/compositor_frame_metadata.h
@@ -34,6 +34,8 @@
gfx::SizeF root_layer_size;
float min_page_scale_factor;
float max_page_scale_factor;
+ bool root_overflow_x_hidden;
+ bool root_overflow_y_hidden;
// Used to position the Android location top bar and page content, whose
// precise position is computed by the renderer compositor.
diff --git a/cc/output/context_provider.h b/cc/output/context_provider.h
index 7362e8b..71d06bd 100644
--- a/cc/output/context_provider.h
+++ b/cc/output/context_provider.h
@@ -12,6 +12,10 @@
class GrContext;
+namespace base {
+class Lock;
+}
+
namespace gpu {
class ContextSupport;
namespace gles2 { class GLES2Interface; }
@@ -27,6 +31,7 @@
// Once this function has been called, the class should only be accessed
// from the same thread.
virtual bool BindToCurrentThread() = 0;
+ virtual void DetachFromThread() {}
virtual gpu::gles2::GLES2Interface* ContextGL() = 0;
virtual gpu::ContextSupport* ContextSupport() = 0;
@@ -39,6 +44,13 @@
CC_EXPORT Capabilities();
};
+ // Sets up a lock so this context can be used from multiple threads.
+ virtual void SetupLock() = 0;
+
+ // Returns the lock that should be held if using this context from multiple
+ // threads.
+ virtual base::Lock* GetLock() = 0;
+
// Returns the capabilities of the currently bound 3d context.
virtual Capabilities ContextCapabilities() = 0;
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 65a94d8..9fbd4a5 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -235,7 +235,7 @@
pass->copy_requests.begin();
it != pass->copy_requests.end();
++it) {
- if (i > 0) {
+ if (it != pass->copy_requests.begin()) {
// Doing a readback is destructive of our state on Mac, so make sure
// we restore the state between readbacks. http://crbug.com/99393.
UseRenderPass(&frame, pass);
diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc
index e01b901..1579e55 100644
--- a/cc/output/filter_operation.cc
+++ b/cc/output/filter_operation.cc
@@ -255,7 +255,7 @@
return blended_filter;
}
-void FilterOperation::AsValueInto(base::debug::TracedValue* value) const {
+void FilterOperation::AsValueInto(base::trace_event::TracedValue* value) const {
value->SetInteger("type", type_);
switch (type_) {
case FilterOperation::GRAYSCALE:
diff --git a/cc/output/filter_operation.h b/cc/output/filter_operation.h
index 157db99..44590c2 100644
--- a/cc/output/filter_operation.h
+++ b/cc/output/filter_operation.h
@@ -19,14 +19,8 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
-}
class Value;
-} // namespace base
+}
namespace cc {
@@ -229,7 +223,7 @@
const FilterOperation* to,
double progress);
- void AsValueInto(base::debug::TracedValue* value) const;
+ void AsValueInto(base::trace_event::TracedValue* value) const;
private:
FilterOperation(FilterType type, float amount);
diff --git a/cc/output/filter_operations.cc b/cc/output/filter_operations.cc
index 96c316c..92423de 100644
--- a/cc/output/filter_operations.cc
+++ b/cc/output/filter_operations.cc
@@ -197,7 +197,8 @@
return blended_filters;
}
-void FilterOperations::AsValueInto(base::debug::TracedValue* value) const {
+void FilterOperations::AsValueInto(
+ base::trace_event::TracedValue* value) const {
for (size_t i = 0; i < operations_.size(); ++i) {
value->BeginDictionary();
operations_[i].AsValueInto(value);
diff --git a/cc/output/filter_operations.h b/cc/output/filter_operations.h
index 8e37933..7018b82 100644
--- a/cc/output/filter_operations.h
+++ b/cc/output/filter_operations.h
@@ -15,14 +15,8 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
-}
class Value;
-} // namespace base
+}
namespace cc {
@@ -76,7 +70,7 @@
// a copy of this.
FilterOperations Blend(const FilterOperations& from, double progress) const;
- void AsValueInto(base::debug::TracedValue* value) const;
+ void AsValueInto(base::trace_event::TracedValue* value) const;
private:
std::vector<FilterOperation> operations_;
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 5a15efa..2612f10 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -624,7 +624,7 @@
static skia::RefPtr<SkImage> ApplyImageFilter(
scoped_ptr<GLRenderer::ScopedUseGrContext> use_gr_context,
ResourceProvider* resource_provider,
- const gfx::Point& origin,
+ const gfx::Rect& rect,
const gfx::Vector2dF& scale,
SkImageFilter* filter,
ScopedResource* source_texture_resource) {
@@ -693,7 +693,12 @@
paint.setImageFilter(filter);
canvas->clear(SK_ColorTRANSPARENT);
- canvas->translate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
+ // The origin of the filter is top-left and the origin of the source is
+ // bottom-left, but the orientation is the same, so we must translate the
+ // filter so that it renders at the bottom of the texture to avoid
+ // misregistration.
+ int y_translate = source.height() - rect.height() - rect.origin().y();
+ canvas->translate(-rect.origin().x(), y_translate);
canvas->scale(scale.x(), scale.y());
canvas->drawSprite(source, 0, 0, &paint);
@@ -858,13 +863,9 @@
skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter(
quad->background_filters, background_texture->size());
- skia::RefPtr<SkImage> background_with_filters =
- ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
- resource_provider_,
- quad->rect.origin(),
- quad->filters_scale,
- filter.get(),
- background_texture);
+ skia::RefPtr<SkImage> background_with_filters = ApplyImageFilter(
+ ScopedUseGrContext::Create(this, frame), resource_provider_, quad->rect,
+ quad->filters_scale, filter.get(), background_texture);
return background_with_filters;
}
@@ -970,12 +971,9 @@
// in the compositor.
use_color_matrix = true;
} else {
- filter_image = ApplyImageFilter(ScopedUseGrContext::Create(this, frame),
- resource_provider_,
- quad->rect.origin(),
- quad->filters_scale,
- filter.get(),
- contents_texture);
+ filter_image = ApplyImageFilter(
+ ScopedUseGrContext::Create(this, frame), resource_provider_,
+ quad->rect, quad->filters_scale, filter.get(), contents_texture);
}
}
}
@@ -2711,6 +2709,8 @@
const gfx::Rect& target_rect) {
DCHECK(texture->id());
+ // Explicitly release lock, otherwise we can crash when try to lock
+ // same texture again.
current_framebuffer_lock_ = nullptr;
SetStencilEnabled(false);
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index b65887e..b1a2b9a 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -18,16 +18,12 @@
namespace cc {
OutputSurface::OutputSurface(
- const scoped_refptr<ContextProvider>& context_provider)
+ const scoped_refptr<ContextProvider>& context_provider,
+ const scoped_refptr<ContextProvider>& worker_context_provider,
+ scoped_ptr<SoftwareOutputDevice> software_device)
: client_(NULL),
context_provider_(context_provider),
- device_scale_factor_(-1),
- external_stencil_test_enabled_(false),
- weak_ptr_factory_(this) {
-}
-
-OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
- : client_(NULL),
+ worker_context_provider_(worker_context_provider),
software_device_(software_device.Pass()),
device_scale_factor_(-1),
external_stencil_test_enabled_(false),
@@ -35,14 +31,24 @@
}
OutputSurface::OutputSurface(
+ const scoped_refptr<ContextProvider>& context_provider)
+ : OutputSurface(context_provider, nullptr, nullptr) {
+}
+
+OutputSurface::OutputSurface(
+ const scoped_refptr<ContextProvider>& context_provider,
+ const scoped_refptr<ContextProvider>& worker_context_provider)
+ : OutputSurface(context_provider, worker_context_provider, nullptr) {
+}
+
+OutputSurface::OutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
+ : OutputSurface(nullptr, nullptr, software_device.Pass()) {
+}
+
+OutputSurface::OutputSurface(
const scoped_refptr<ContextProvider>& context_provider,
scoped_ptr<SoftwareOutputDevice> software_device)
- : client_(NULL),
- context_provider_(context_provider),
- software_device_(software_device.Pass()),
- device_scale_factor_(-1),
- external_stencil_test_enabled_(false),
- weak_ptr_factory_(this) {
+ : OutputSurface(context_provider, nullptr, software_device.Pass()) {
}
void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase,
@@ -109,6 +115,18 @@
SetUpContext3d();
}
+ if (success && worker_context_provider_.get()) {
+ success = worker_context_provider_->BindToCurrentThread();
+ if (success) {
+ worker_context_provider_->SetupLock();
+ // The destructor resets the context lost callback, so base::Unretained
+ // is safe, as long as the worker threads stop using the context before
+ // the output surface is destroyed.
+ worker_context_provider_->SetLostContextCallback(base::Bind(
+ &OutputSurface::DidLoseOutputSurface, base::Unretained(this)));
+ }
+ }
+
if (!success)
client_ = NULL;
@@ -116,21 +134,33 @@
}
bool OutputSurface::InitializeAndSetContext3d(
- scoped_refptr<ContextProvider> context_provider) {
+ scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider) {
DCHECK(!context_provider_.get());
DCHECK(context_provider.get());
DCHECK(client_);
- bool success = false;
- if (context_provider->BindToCurrentThread()) {
+ bool success = context_provider->BindToCurrentThread();
+ if (success) {
context_provider_ = context_provider;
SetUpContext3d();
- client_->DeferredInitialize();
- success = true;
+ }
+ if (success && worker_context_provider.get()) {
+ success = worker_context_provider->BindToCurrentThread();
+ if (success) {
+ worker_context_provider_ = worker_context_provider;
+ // The destructor resets the context lost callback, so base::Unretained
+ // is safe, as long as the worker threads stop using the context before
+ // the output surface is destroyed.
+ worker_context_provider_->SetLostContextCallback(base::Bind(
+ &OutputSurface::DidLoseOutputSurface, base::Unretained(this)));
+ }
}
if (!success)
ResetContext3d();
+ else
+ client_->DeferredInitialize();
return success;
}
@@ -167,7 +197,12 @@
context_provider_->SetMemoryPolicyChangedCallback(
ContextProvider::MemoryPolicyChangedCallback());
}
+ if (worker_context_provider_.get()) {
+ worker_context_provider_->SetLostContextCallback(
+ ContextProvider::LostContextCallback());
+ }
context_provider_ = NULL;
+ worker_context_provider_ = NULL;
}
void OutputSurface::EnsureBackbuffer() {
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index 29e32a5..3e3b085 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -46,6 +46,11 @@
DEFAULT_MAX_FRAMES_PENDING = 2
};
+ OutputSurface(const scoped_refptr<ContextProvider>& context_provider,
+ const scoped_refptr<ContextProvider>& worker_context_provider,
+ scoped_ptr<SoftwareOutputDevice> software_device);
+ OutputSurface(const scoped_refptr<ContextProvider>& context_provider,
+ const scoped_refptr<ContextProvider>& worker_context_provider);
explicit OutputSurface(
const scoped_refptr<ContextProvider>& context_provider);
@@ -94,6 +99,9 @@
// In the event of a lost context, the entire output surface should be
// recreated.
ContextProvider* context_provider() const { return context_provider_.get(); }
+ ContextProvider* worker_context_provider() const {
+ return worker_context_provider_.get();
+ }
SoftwareOutputDevice* software_device() const {
return software_device_.get();
}
@@ -149,13 +157,15 @@
// Synchronously initialize context3d and enter hardware mode.
// This can only supported in threaded compositing mode.
bool InitializeAndSetContext3d(
- scoped_refptr<ContextProvider> context_provider);
+ scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider);
void ReleaseGL();
void PostSwapBuffersComplete();
struct OutputSurface::Capabilities capabilities_;
scoped_refptr<ContextProvider> context_provider_;
+ scoped_refptr<ContextProvider> worker_context_provider_;
scoped_ptr<SoftwareOutputDevice> software_device_;
scoped_ptr<OverlayCandidateValidator> overlay_candidate_validator_;
gfx::Size surface_size_;
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
index 4336f07..f32a96f 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -25,6 +25,10 @@
explicit TestOutputSurface(scoped_refptr<ContextProvider> context_provider)
: OutputSurface(context_provider) {}
+ TestOutputSurface(scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider)
+ : OutputSurface(worker_context_provider) {}
+
explicit TestOutputSurface(scoped_ptr<SoftwareOutputDevice> software_device)
: OutputSurface(software_device.Pass()) {}
@@ -37,9 +41,8 @@
client_->DidSwapBuffersComplete();
}
- bool InitializeNewContext3d(
- scoped_refptr<ContextProvider> new_context_provider) {
- return InitializeAndSetContext3d(new_context_provider);
+ bool InitializeNewContext3d(scoped_refptr<ContextProvider> context_provider) {
+ return InitializeAndSetContext3d(context_provider, nullptr);
}
using OutputSurface::ReleaseGL;
@@ -106,6 +109,26 @@
EXPECT_TRUE(client.did_lose_output_surface_called());
}
+TEST(OutputSurfaceTest, ClientPointerIndicatesWorkerBindToClientSuccess) {
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> worker_provider =
+ TestContextProvider::Create();
+ TestOutputSurface output_surface(provider, worker_provider);
+ EXPECT_FALSE(output_surface.HasClient());
+
+ FakeOutputSurfaceClient client;
+ EXPECT_TRUE(output_surface.BindToClient(&client));
+ EXPECT_TRUE(output_surface.HasClient());
+ EXPECT_FALSE(client.deferred_initialize_called());
+
+ // Verify DidLoseOutputSurface callback is hooked up correctly.
+ EXPECT_FALSE(client.did_lose_output_surface_called());
+ output_surface.context_provider()->ContextGL()->LoseContextCHROMIUM(
+ GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
+ output_surface.context_provider()->ContextGL()->Flush();
+ EXPECT_TRUE(client.did_lose_output_surface_called());
+}
+
TEST(OutputSurfaceTest, ClientPointerIndicatesBindToClientFailure) {
scoped_refptr<TestContextProvider> context_provider =
TestContextProvider::Create();
@@ -121,6 +144,23 @@
EXPECT_FALSE(output_surface.HasClient());
}
+TEST(OutputSurfaceTest, ClientPointerIndicatesWorkerBindToClientFailure) {
+ scoped_refptr<TestContextProvider> context_provider =
+ TestContextProvider::Create();
+ scoped_refptr<TestContextProvider> worker_context_provider =
+ TestContextProvider::Create();
+
+ // Lose the context so BindToClient fails.
+ worker_context_provider->UnboundTestContext3d()->set_context_lost(true);
+
+ TestOutputSurface output_surface(context_provider, worker_context_provider);
+ EXPECT_FALSE(output_surface.HasClient());
+
+ FakeOutputSurfaceClient client;
+ EXPECT_FALSE(output_surface.BindToClient(&client));
+ EXPECT_FALSE(output_surface.HasClient());
+}
+
class OutputSurfaceTestInitializeNewContext3d : public ::testing::Test {
public:
OutputSurfaceTestInitializeNewContext3d()
diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc
index 9a95206..71897ed 100644
--- a/cc/output/overlay_strategy_single_on_top.cc
+++ b/cc/output/overlay_strategy_single_on_top.cc
@@ -119,6 +119,20 @@
return true;
}
+bool OverlayStrategySingleOnTop::IsInvisibleQuad(const DrawQuad* draw_quad) {
+ if (draw_quad->material == DrawQuad::SOLID_COLOR) {
+ const SolidColorDrawQuad* solid_quad =
+ SolidColorDrawQuad::MaterialCast(draw_quad);
+ SkColor color = solid_quad->color;
+ float opacity = solid_quad->opacity();
+ float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity;
+ // Ignore transparent solid color quads.
+ return solid_quad->ShouldDrawWithBlending() &&
+ alpha < std::numeric_limits<float>::epsilon();
+ }
+ return false;
+}
+
bool OverlayStrategySingleOnTop::Attempt(
RenderPassList* render_passes_in_draw_order,
OverlayCandidateList* candidate_list) {
@@ -143,7 +157,7 @@
++overlap_iter) {
gfx::RectF overlap_rect = overlap_iter->rect;
overlap_iter->quadTransform().TransformRect(&overlap_rect);
- if (rect.Intersects(overlap_rect)) {
+ if (rect.Intersects(overlap_rect) && !IsInvisibleQuad(*overlap_iter)) {
intersects = true;
break;
}
diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h
index f92e104..a3fec0a 100644
--- a/cc/output/overlay_strategy_single_on_top.h
+++ b/cc/output/overlay_strategy_single_on_top.h
@@ -29,6 +29,10 @@
bool GetCandidateQuadInfo(const DrawQuad& draw_quad,
OverlayCandidate* quad_info);
+ // Returns true if |draw_quad| will not block quads underneath from becoming
+ // an overlay.
+ bool IsInvisibleQuad(const DrawQuad* draw_quad);
+
bool GetTextureQuadInfo(const TextureDrawQuad& quad,
OverlayCandidate* quad_info);
bool GetVideoQuadInfo(const StreamVideoDrawQuad& quad,
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index 4682679..6ee388a 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -156,6 +156,17 @@
mailbox, release_callback.Pass());
}
+SolidColorDrawQuad* CreateSolidColorQuadAt(
+ const SharedQuadState* shared_quad_state,
+ SkColor color,
+ RenderPass* render_pass,
+ const gfx::Rect& rect) {
+ SolidColorDrawQuad* quad =
+ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ quad->SetNew(shared_quad_state, rect, rect, color, false);
+ return quad;
+}
+
TextureDrawQuad* CreateCandidateQuadAt(ResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
@@ -592,6 +603,94 @@
EXPECT_EQ(2U, candidate_list.size());
}
+TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
+ shared_state->opacity = 0.f;
+ CreateSolidColorQuadAt(shared_state, SK_ColorBLACK, pass.get(),
+ kOverlayBottomRightRect);
+ shared_state = pass->CreateAndAppendSharedQuadState();
+ shared_state->opacity = 1.f;
+ CreateCandidateQuadAt(resource_provider_.get(), shared_state, pass.get(),
+ kOverlayBottomRightRect);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ RenderPassList original_pass_list;
+ RenderPass::CopyAll(pass_list, &original_pass_list);
+
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(1U, pass_list.size());
+ EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ CreateSolidColorQuadAt(pass->shared_quad_state_list.back(),
+ SK_ColorTRANSPARENT, pass.get(),
+ kOverlayBottomRightRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayBottomRightRect);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ RenderPassList original_pass_list;
+ RenderPass::CopyAll(pass_list, &original_pass_list);
+
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(1U, pass_list.size());
+ EXPECT_EQ(2U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, RejectOpaqueColorOnTop) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
+ shared_state->opacity = 0.5f;
+ CreateSolidColorQuadAt(shared_state, SK_ColorBLACK, pass.get(),
+ kOverlayBottomRightRect);
+ shared_state = pass->CreateAndAppendSharedQuadState();
+ shared_state->opacity = 1.f;
+ CreateCandidateQuadAt(resource_provider_.get(), shared_state, pass.get(),
+ kOverlayBottomRightRect);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ RenderPassList original_pass_list;
+ RenderPass::CopyAll(pass_list, &original_pass_list);
+
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(1U, pass_list.size());
+ EXPECT_EQ(0U, candidate_list.size());
+}
+
+TEST_F(SingleOverlayOnTopTest, RejectTransparentColorOnTopWithoutBlending) {
+ scoped_ptr<RenderPass> pass = CreateRenderPass();
+ SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
+ CreateSolidColorQuadAt(shared_state, SK_ColorTRANSPARENT, pass.get(),
+ kOverlayBottomRightRect)->opaque_rect =
+ kOverlayBottomRightRect;
+ CreateCandidateQuadAt(resource_provider_.get(), shared_state, pass.get(),
+ kOverlayBottomRightRect);
+
+ RenderPassList pass_list;
+ pass_list.push_back(pass.Pass());
+
+ RenderPassList original_pass_list;
+ RenderPass::CopyAll(pass_list, &original_pass_list);
+
+ OverlayCandidateList candidate_list;
+ overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+ EXPECT_EQ(1U, pass_list.size());
+ EXPECT_EQ(0U, candidate_list.size());
+}
+
TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) {
scoped_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateVideoQuad(resource_provider_.get(),
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index c7582fe..d7d1211 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -1395,15 +1395,19 @@
// is red, which should not appear.
gfx::Rect blue_rect(gfx::Size(100, 100));
gfx::Rect blue_clip_rect(gfx::Point(50, 50), gfx::Size(50, 50));
- scoped_refptr<FakePicturePileImpl> blue_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, blue_rect.size());
+
+ scoped_ptr<FakePicturePile> blue_recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, blue_rect.size());
SkPaint red_paint;
red_paint.setColor(SK_ColorRED);
- blue_pile->add_draw_rect_with_paint(blue_rect, red_paint);
+ blue_recording->add_draw_rect_with_paint(blue_rect, red_paint);
SkPaint blue_paint;
blue_paint.setColor(SK_ColorBLUE);
- blue_pile->add_draw_rect_with_paint(blue_clip_rect, blue_paint);
- blue_pile->RerecordPile();
+ blue_recording->add_draw_rect_with_paint(blue_clip_rect, blue_paint);
+ blue_recording->RerecordPile();
+
+ scoped_refptr<FakePicturePileImpl> blue_pile =
+ FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr);
gfx::Transform blue_content_to_target_transform;
gfx::Vector2d offset(viewport.bottom_right() - blue_rect.bottom_right());
@@ -1425,12 +1429,14 @@
1.f, blue_pile.get());
// One viewport-filling green quad.
- scoped_refptr<FakePicturePileImpl> green_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakePicturePile> green_recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
SkPaint green_paint;
green_paint.setColor(SK_ColorGREEN);
- green_pile->add_draw_rect_with_paint(viewport, green_paint);
- green_pile->RerecordPile();
+ green_recording->add_draw_rect_with_paint(viewport, green_paint);
+ green_recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> green_pile =
+ FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
gfx::Transform green_content_to_target_transform;
SharedQuadState* green_shared_state = CreateTestSharedQuadState(
@@ -1465,12 +1471,14 @@
CreateTestRenderPass(id, viewport, transform_to_root);
// One viewport-filling 0.5-opacity green quad.
- scoped_refptr<FakePicturePileImpl> green_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakePicturePile> green_recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
SkPaint green_paint;
green_paint.setColor(SK_ColorGREEN);
- green_pile->add_draw_rect_with_paint(viewport, green_paint);
- green_pile->RerecordPile();
+ green_recording->add_draw_rect_with_paint(viewport, green_paint);
+ green_recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> green_pile =
+ FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
gfx::Transform green_content_to_target_transform;
SharedQuadState* green_shared_state = CreateTestSharedQuadState(
@@ -1484,12 +1492,14 @@
texture_format, viewport, 1.f, green_pile.get());
// One viewport-filling white quad.
- scoped_refptr<FakePicturePileImpl> white_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakePicturePile> white_recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
SkPaint white_paint;
white_paint.setColor(SK_ColorWHITE);
- white_pile->add_draw_rect_with_paint(viewport, white_paint);
- white_pile->RerecordPile();
+ white_recording->add_draw_rect_with_paint(viewport, white_paint);
+ white_recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> white_pile =
+ FakePicturePileImpl::CreateFromPile(white_recording.get(), nullptr);
gfx::Transform white_content_to_target_transform;
SharedQuadState* white_shared_state = CreateTestSharedQuadState(
@@ -1553,12 +1563,14 @@
canvas.drawPoint(1, 1, SK_ColorGREEN);
}
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakePicturePile> recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
SkPaint paint;
paint.setFilterLevel(SkPaint::kLow_FilterLevel);
- pile->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
- pile->RerecordPile();
+ recording->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
+ recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
gfx::Transform content_to_target_transform;
SharedQuadState* shared_state = CreateTestSharedQuadState(
@@ -1603,12 +1615,14 @@
canvas.drawPoint(1, 1, SK_ColorGREEN);
}
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakePicturePile> recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
SkPaint paint;
paint.setFilterLevel(SkPaint::kLow_FilterLevel);
- pile->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
- pile->RerecordPile();
+ recording->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint);
+ recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
gfx::Transform content_to_target_transform;
SharedQuadState* shared_state = CreateTestSharedQuadState(
@@ -1705,16 +1719,20 @@
gfx::Transform green_content_to_target_transform;
gfx::Rect green_rect1(gfx::Point(80, 0), gfx::Size(20, 100));
gfx::Rect green_rect2(gfx::Point(0, 80), gfx::Size(100, 20));
- scoped_refptr<FakePicturePileImpl> green_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+
+ scoped_ptr<FakePicturePile> green_recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
+
SkPaint red_paint;
red_paint.setColor(SK_ColorRED);
- green_pile->add_draw_rect_with_paint(viewport, red_paint);
+ green_recording->add_draw_rect_with_paint(viewport, red_paint);
SkPaint green_paint;
green_paint.setColor(SK_ColorGREEN);
- green_pile->add_draw_rect_with_paint(green_rect1, green_paint);
- green_pile->add_draw_rect_with_paint(green_rect2, green_paint);
- green_pile->RerecordPile();
+ green_recording->add_draw_rect_with_paint(green_rect1, green_paint);
+ green_recording->add_draw_rect_with_paint(green_rect2, green_paint);
+ green_recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> green_pile =
+ FakePicturePileImpl::CreateFromPile(green_recording.get(), nullptr);
SharedQuadState* top_right_green_shared_quad_state =
CreateTestSharedQuadState(
@@ -1769,20 +1787,22 @@
blue_layer_rect1.Inset(inset, inset, inset, inset);
blue_layer_rect2.Inset(inset, inset, inset, inset);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, layer_rect.size());
+ scoped_ptr<FakePicturePile> recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, layer_rect.size());
Region outside(layer_rect);
outside.Subtract(gfx::ToEnclosingRect(union_layer_rect));
for (Region::Iterator iter(outside); iter.has_rect(); iter.next()) {
- pile->add_draw_rect_with_paint(iter.rect(), red_paint);
+ recording->add_draw_rect_with_paint(iter.rect(), red_paint);
}
SkPaint blue_paint;
blue_paint.setColor(SK_ColorBLUE);
- pile->add_draw_rect_with_paint(blue_layer_rect1, blue_paint);
- pile->add_draw_rect_with_paint(blue_layer_rect2, blue_paint);
- pile->RerecordPile();
+ recording->add_draw_rect_with_paint(blue_layer_rect1, blue_paint);
+ recording->add_draw_rect_with_paint(blue_layer_rect2, blue_paint);
+ recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording.get(), nullptr);
gfx::Rect content_rect(
gfx::ScaleToEnclosingRect(layer_rect, contents_scale));
@@ -1993,12 +2013,14 @@
CreateTestRenderPass(id, viewport, transform_to_root);
// One viewport-filling blue quad
- scoped_refptr<FakePicturePileImpl> blue_pile =
- FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size());
+ scoped_ptr<FakePicturePile> blue_recording =
+ FakePicturePile::CreateFilledPile(pile_tile_size, viewport.size());
SkPaint blue_paint;
blue_paint.setColor(SK_ColorBLUE);
- blue_pile->add_draw_rect_with_paint(viewport, blue_paint);
- blue_pile->RerecordPile();
+ blue_recording->add_draw_rect_with_paint(viewport, blue_paint);
+ blue_recording->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> blue_pile =
+ FakePicturePileImpl::CreateFromPile(blue_recording.get(), nullptr);
gfx::Transform blue_content_to_target_transform;
SharedQuadState* blue_shared_state = CreateTestSharedQuadState(
diff --git a/cc/output/shader.cc b/cc/output/shader.cc
index eb0dede..0a33e53 100644
--- a/cc/output/shader.cc
+++ b/cc/output/shader.cc
@@ -11,12 +11,24 @@
#include "cc/output/gl_renderer.h" // For the GLC() macro.
#include "gpu/command_buffer/client/gles2_interface.h"
-#define SHADER0(Src) #Src
-#define VERTEX_SHADER(Src) SetVertexTexCoordPrecision(SHADER0(Src))
-#define FRAGMENT_SHADER(Src) \
- SetFragmentTexCoordPrecision( \
- precision, \
- SetFragmentSamplerType(sampler, SetBlendModeFunctions(SHADER0(Src))))
+template <size_t size>
+std::string StripLambda(const char(&shader)[size]) {
+ // Must contain at least "[]() {}" and trailing null (included in size).
+ static_assert(size >= 8,
+ "String passed to StripLambda must be at least 8 characters");
+ DCHECK_EQ(strncmp("[]() {", shader, 6), 0);
+ DCHECK_EQ(shader[size - 2], '}');
+ return std::string(shader + 6, shader + size - 2);
+}
+
+// Shaders are passed in with lambda syntax, which tricks clang-format into
+// handling them correctly. StipLambda removes this.
+#define SHADER0(Src) StripLambda(#Src)
+#define VERTEX_SHADER(Head, Body) SetVertexTexCoordPrecision(Head + Body)
+#define FRAGMENT_SHADER(Head, Body) \
+ SetFragmentTexCoordPrecision( \
+ precision, \
+ SetFragmentSamplerType(sampler, SetBlendModeFunctions(Head + Body)))
using gpu::gles2::GLES2Interface;
@@ -63,12 +75,13 @@
return shader_string;
}
-static std::string SetVertexTexCoordPrecision(const char* shader_string) {
+static std::string SetVertexTexCoordPrecision(
+ const std::string& shader_string) {
// We unconditionally use highp in the vertex shader since
// we are unlikely to be vertex shader bound when drawing large quads.
// Also, some vertex shaders mutate the texture coordinate in such a
// way that the effective precision might be lower than expected.
- return "#define TexCoordPrecision highp\n" + std::string(shader_string);
+ return "#define TexCoordPrecision highp\n" + shader_string;
}
TexCoordPrecision TexCoordPrecisionRequired(GLES2Interface* context,
@@ -174,20 +187,25 @@
}
std::string VertexShaderPosTex::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute vec4 a_position;
- attribute TexCoordPrecision vec2 a_texCoord;
- uniform mat4 matrix;
- varying TexCoordPrecision vec2 v_texCoord;
- void main() {
- gl_Position = matrix * a_position;
- v_texCoord = a_texCoord;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderPosTex::GetShaderHead() {
+ return SHADER0([]() {
+ attribute vec4 a_position;
+ attribute TexCoordPrecision vec2 a_texCoord;
+ uniform mat4 matrix;
+ varying TexCoordPrecision vec2 v_texCoord;
+ });
+}
+
+std::string VertexShaderPosTex::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ gl_Position = matrix * a_position;
+ v_texCoord = a_texCoord;
+ }
+ });
}
VertexShaderPosTexYUVStretchOffset::VertexShaderPosTexYUVStretchOffset()
@@ -214,23 +232,28 @@
}
std::string VertexShaderPosTexYUVStretchOffset::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- precision mediump float;
- attribute vec4 a_position;
- attribute TexCoordPrecision vec2 a_texCoord;
- uniform mat4 matrix;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform TexCoordPrecision vec2 texScale;
- uniform TexCoordPrecision vec2 texOffset;
- void main() {
- gl_Position = matrix * a_position;
- v_texCoord = a_texCoord * texScale + texOffset;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderPosTexYUVStretchOffset::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ attribute vec4 a_position;
+ attribute TexCoordPrecision vec2 a_texCoord;
+ uniform mat4 matrix;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform TexCoordPrecision vec2 texScale;
+ uniform TexCoordPrecision vec2 texOffset;
+ });
+}
+
+std::string VertexShaderPosTexYUVStretchOffset::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ gl_Position = matrix * a_position;
+ v_texCoord = a_texCoord * texScale + texOffset;
+ }
+ });
}
VertexShaderPos::VertexShaderPos() : matrix_location_(-1) {
@@ -254,15 +277,20 @@
}
std::string VertexShaderPos::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute vec4 a_position;
- uniform mat4 matrix;
- void main() { gl_Position = matrix * a_position; }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderPos::GetShaderHead() {
+ return SHADER0([]() {
+ attribute vec4 a_position;
+ uniform mat4 matrix;
+ });
+}
+
+std::string VertexShaderPos::GetShaderBody() {
+ return SHADER0([]() {
+ void main() { gl_Position = matrix * a_position; }
+ });
}
VertexShaderPosTexTransform::VertexShaderPosTexTransform()
@@ -291,42 +319,52 @@
}
std::string VertexShaderPosTexTransform::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute vec4 a_position;
- attribute TexCoordPrecision vec2 a_texCoord;
- attribute float a_index;
- uniform mat4 matrix[8];
- uniform TexCoordPrecision vec4 texTransform[8];
- uniform float opacity[32];
- varying TexCoordPrecision vec2 v_texCoord;
- varying float v_alpha;
- void main() {
- int quad_index = int(a_index * 0.25); // NOLINT
- gl_Position = matrix[quad_index] * a_position;
- TexCoordPrecision vec4 texTrans = texTransform[quad_index];
- v_texCoord = a_texCoord * texTrans.zw + texTrans.xy;
- v_alpha = opacity[int(a_index)]; // NOLINT
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderPosTexTransform::GetShaderHead() {
+ return SHADER0([]() {
+ attribute vec4 a_position;
+ attribute TexCoordPrecision vec2 a_texCoord;
+ attribute float a_index;
+ uniform mat4 matrix[8];
+ uniform TexCoordPrecision vec4 texTransform[8];
+ uniform float opacity[32];
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying float v_alpha;
+ });
+}
+
+std::string VertexShaderPosTexTransform::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ int quad_index = int(a_index * 0.25); // NOLINT
+ gl_Position = matrix[quad_index] * a_position;
+ TexCoordPrecision vec4 texTrans = texTransform[quad_index];
+ v_texCoord = a_texCoord * texTrans.zw + texTrans.xy;
+ v_alpha = opacity[int(a_index)]; // NOLINT
+ }
+ });
}
std::string VertexShaderPosTexIdentity::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute vec4 a_position;
- varying TexCoordPrecision vec2 v_texCoord;
- void main() {
- gl_Position = a_position;
- v_texCoord = (a_position.xy + vec2(1.0)) * 0.5;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderPosTexIdentity::GetShaderHead() {
+ return SHADER0([]() {
+ attribute vec4 a_position;
+ varying TexCoordPrecision vec2 v_texCoord;
+ });
+}
+
+std::string VertexShaderPosTexIdentity::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ gl_Position = a_position;
+ v_texCoord = (a_position.xy + vec2(1.0)) * 0.5;
+ }
+ });
}
VertexShaderQuad::VertexShaderQuad()
@@ -352,42 +390,48 @@
}
std::string VertexShaderQuad::GetShaderString() const {
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderQuad::GetShaderHead() {
#if defined(OS_ANDROID)
// TODO(epenner): Find the cause of this 'quad' uniform
// being missing if we don't add dummy variables.
// http://crbug.com/240602
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute TexCoordPrecision vec4 a_position;
- attribute float a_index;
- uniform mat4 matrix;
- uniform TexCoordPrecision vec2 quad[4];
- uniform TexCoordPrecision vec2 dummy_uniform;
- varying TexCoordPrecision vec2 dummy_varying;
- void main() {
- vec2 pos = quad[int(a_index)]; // NOLINT
- gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
- dummy_varying = dummy_uniform;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
-// clang-format on
+ return SHADER0([]() {
+ attribute TexCoordPrecision vec4 a_position;
+ attribute float a_index;
+ uniform mat4 matrix;
+ uniform TexCoordPrecision vec2 quad[4];
+ uniform TexCoordPrecision vec2 dummy_uniform;
+ varying TexCoordPrecision vec2 dummy_varying;
+ });
#else
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute TexCoordPrecision vec4 a_position;
- attribute float a_index;
- uniform mat4 matrix;
- uniform TexCoordPrecision vec2 quad[4];
- void main() {
- vec2 pos = quad[int(a_index)]; // NOLINT
- gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
-// clang-format on
+ return SHADER0([]() {
+ attribute TexCoordPrecision vec4 a_position;
+ attribute float a_index;
+ uniform mat4 matrix;
+ uniform TexCoordPrecision vec2 quad[4];
+ });
+#endif
+}
+
+std::string VertexShaderQuad::GetShaderBody() {
+#if defined(OS_ANDROID)
+ return SHADER0([]() {
+ void main() {
+ vec2 pos = quad[int(a_index)]; // NOLINT
+ gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
+ dummy_varying = dummy_uniform;
+ }
+ });
+#else
+ return SHADER0([]() {
+ void main() {
+ vec2 pos = quad[int(a_index)]; // NOLINT
+ gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
+ }
+ });
#endif
}
@@ -419,36 +463,36 @@
}
std::string VertexShaderQuadAA::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute TexCoordPrecision vec4 a_position;
- attribute float a_index;
- uniform mat4 matrix;
- uniform vec4 viewport;
- uniform TexCoordPrecision vec2 quad[4];
- uniform TexCoordPrecision vec3 edge[8];
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec2 pos = quad[int(a_index)]; // NOLINT
- gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
- vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
- vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
- edge_dist[0] = vec4(dot(edge[0], screen_pos),
- dot(edge[1], screen_pos),
- dot(edge[2], screen_pos),
- dot(edge[3], screen_pos)) *
- gl_Position.w;
- edge_dist[1] = vec4(dot(edge[4], screen_pos),
- dot(edge[5], screen_pos),
- dot(edge[6], screen_pos),
- dot(edge[7], screen_pos)) *
- gl_Position.w;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string VertexShaderQuadAA::GetShaderHead() {
+ return SHADER0([]() {
+ attribute TexCoordPrecision vec4 a_position;
+ attribute float a_index;
+ uniform mat4 matrix;
+ uniform vec4 viewport;
+ uniform TexCoordPrecision vec2 quad[4];
+ uniform TexCoordPrecision vec3 edge[8];
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string VertexShaderQuadAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec2 pos = quad[int(a_index)]; // NOLINT
+ gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
+ vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
+ vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
+ edge_dist[0] = vec4(dot(edge[0], screen_pos), dot(edge[1], screen_pos),
+ dot(edge[2], screen_pos), dot(edge[3], screen_pos)) *
+ gl_Position.w;
+ edge_dist[1] = vec4(dot(edge[4], screen_pos), dot(edge[5], screen_pos),
+ dot(edge[6], screen_pos), dot(edge[7], screen_pos)) *
+ gl_Position.w;
+ }
+ });
}
VertexShaderQuadTexTransformAA::VertexShaderQuadTexTransformAA()
@@ -481,39 +525,39 @@
}
std::string VertexShaderQuadTexTransformAA::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute TexCoordPrecision vec4 a_position;
- attribute float a_index;
- uniform mat4 matrix;
- uniform vec4 viewport;
- uniform TexCoordPrecision vec2 quad[4];
- uniform TexCoordPrecision vec3 edge[8];
- uniform TexCoordPrecision vec4 texTrans;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec2 pos = quad[int(a_index)]; // NOLINT
- gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
- vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
- vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
- edge_dist[0] = vec4(dot(edge[0], screen_pos),
- dot(edge[1], screen_pos),
- dot(edge[2], screen_pos),
- dot(edge[3], screen_pos)) *
- gl_Position.w;
- edge_dist[1] = vec4(dot(edge[4], screen_pos),
- dot(edge[5], screen_pos),
- dot(edge[6], screen_pos),
- dot(edge[7], screen_pos)) *
- gl_Position.w;
- v_texCoord = (pos.xy + vec2(0.5)) * texTrans.zw + texTrans.xy;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string VertexShaderQuadTexTransformAA::GetShaderHead() {
+ return SHADER0([]() {
+ attribute TexCoordPrecision vec4 a_position;
+ attribute float a_index;
+ uniform mat4 matrix;
+ uniform vec4 viewport;
+ uniform TexCoordPrecision vec2 quad[4];
+ uniform TexCoordPrecision vec3 edge[8];
+ uniform TexCoordPrecision vec4 texTrans;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string VertexShaderQuadTexTransformAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec2 pos = quad[int(a_index)]; // NOLINT
+ gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
+ vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
+ vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
+ edge_dist[0] = vec4(dot(edge[0], screen_pos), dot(edge[1], screen_pos),
+ dot(edge[2], screen_pos), dot(edge[3], screen_pos)) *
+ gl_Position.w;
+ edge_dist[1] = vec4(dot(edge[4], screen_pos), dot(edge[5], screen_pos),
+ dot(edge[6], screen_pos), dot(edge[7], screen_pos)) *
+ gl_Position.w;
+ v_texCoord = (pos.xy + vec2(0.5)) * texTrans.zw + texTrans.xy;
+ }
+ });
}
VertexShaderTile::VertexShaderTile()
@@ -542,24 +586,29 @@
}
std::string VertexShaderTile::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute TexCoordPrecision vec4 a_position;
- attribute TexCoordPrecision vec2 a_texCoord;
- attribute float a_index;
- uniform mat4 matrix;
- uniform TexCoordPrecision vec2 quad[4];
- uniform TexCoordPrecision vec4 vertexTexTransform;
- varying TexCoordPrecision vec2 v_texCoord;
- void main() {
- vec2 pos = quad[int(a_index)]; // NOLINT
- gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
- v_texCoord = a_texCoord * vertexTexTransform.zw + vertexTexTransform.xy;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderTile::GetShaderHead() {
+ return SHADER0([]() {
+ attribute TexCoordPrecision vec4 a_position;
+ attribute TexCoordPrecision vec2 a_texCoord;
+ attribute float a_index;
+ uniform mat4 matrix;
+ uniform TexCoordPrecision vec2 quad[4];
+ uniform TexCoordPrecision vec4 vertexTexTransform;
+ varying TexCoordPrecision vec2 v_texCoord;
+ });
+}
+
+std::string VertexShaderTile::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec2 pos = quad[int(a_index)]; // NOLINT
+ gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
+ v_texCoord = a_texCoord * vertexTexTransform.zw + vertexTexTransform.xy;
+ }
+ });
}
VertexShaderTileAA::VertexShaderTileAA()
@@ -592,39 +641,39 @@
}
std::string VertexShaderTileAA::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute TexCoordPrecision vec4 a_position;
- attribute float a_index;
- uniform mat4 matrix;
- uniform vec4 viewport;
- uniform TexCoordPrecision vec2 quad[4];
- uniform TexCoordPrecision vec3 edge[8];
- uniform TexCoordPrecision vec4 vertexTexTransform;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec2 pos = quad[int(a_index)]; // NOLINT
- gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
- vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
- vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
- edge_dist[0] = vec4(dot(edge[0], screen_pos),
- dot(edge[1], screen_pos),
- dot(edge[2], screen_pos),
- dot(edge[3], screen_pos)) *
- gl_Position.w;
- edge_dist[1] = vec4(dot(edge[4], screen_pos),
- dot(edge[5], screen_pos),
- dot(edge[6], screen_pos),
- dot(edge[7], screen_pos)) *
- gl_Position.w;
- v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string VertexShaderTileAA::GetShaderHead() {
+ return SHADER0([]() {
+ attribute TexCoordPrecision vec4 a_position;
+ attribute float a_index;
+ uniform mat4 matrix;
+ uniform vec4 viewport;
+ uniform TexCoordPrecision vec2 quad[4];
+ uniform TexCoordPrecision vec3 edge[8];
+ uniform TexCoordPrecision vec4 vertexTexTransform;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string VertexShaderTileAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec2 pos = quad[int(a_index)]; // NOLINT
+ gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
+ vec2 ndc_pos = 0.5 * (1.0 + gl_Position.xy / gl_Position.w);
+ vec3 screen_pos = vec3(viewport.xy + viewport.zw * ndc_pos, 1.0);
+ edge_dist[0] = vec4(dot(edge[0], screen_pos), dot(edge[1], screen_pos),
+ dot(edge[2], screen_pos), dot(edge[3], screen_pos)) *
+ gl_Position.w;
+ edge_dist[1] = vec4(dot(edge[4], screen_pos), dot(edge[5], screen_pos),
+ dot(edge[6], screen_pos), dot(edge[7], screen_pos)) *
+ gl_Position.w;
+ v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
+ }
+ });
}
VertexShaderVideoTransform::VertexShaderVideoTransform()
@@ -650,22 +699,27 @@
}
std::string VertexShaderVideoTransform::GetShaderString() const {
- // clang-format off
- return VERTEX_SHADER(
- // clang-format on
- attribute vec4 a_position;
- attribute TexCoordPrecision vec2 a_texCoord;
- uniform mat4 matrix;
- uniform TexCoordPrecision mat4 texMatrix;
- varying TexCoordPrecision vec2 v_texCoord;
- void main() {
- gl_Position = matrix * a_position;
- v_texCoord =
- vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0));
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return VERTEX_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string VertexShaderVideoTransform::GetShaderHead() {
+ return SHADER0([]() {
+ attribute vec4 a_position;
+ attribute TexCoordPrecision vec2 a_texCoord;
+ uniform mat4 matrix;
+ uniform TexCoordPrecision mat4 texMatrix;
+ varying TexCoordPrecision vec2 v_texCoord;
+ });
+}
+
+std::string VertexShaderVideoTransform::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ gl_Position = matrix * a_position;
+ v_texCoord =
+ vec2(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0));
+ }
+ });
}
#define BLEND_MODE_UNIFORMS "s_backdropTexture", "backdropRect"
@@ -692,183 +746,166 @@
return "#define ApplyBlendMode(X) (X)\n" + shader_string;
}
- // clang-format off
- static const std::string kFunctionApplyBlendMode = SHADER0(
- // clang-format on
- uniform sampler2D s_backdropTexture;
- uniform TexCoordPrecision vec4 backdropRect;
+ static const std::string kFunctionApplyBlendMode = SHADER0([]() {
+ uniform sampler2D s_backdropTexture;
+ uniform TexCoordPrecision vec4 backdropRect;
- vec4 GetBackdropColor() {
- TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
- bgTexCoord.x /= backdropRect.z;
- bgTexCoord.y /= backdropRect.w;
- return texture2D(s_backdropTexture, bgTexCoord);
- }
+ vec4 GetBackdropColor() {
+ TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
+ bgTexCoord.x /= backdropRect.z;
+ bgTexCoord.y /= backdropRect.w;
+ return texture2D(s_backdropTexture, bgTexCoord);
+ }
- vec4 ApplyBlendMode(vec4 src) {
- vec4 dst = GetBackdropColor();
- return Blend(src, dst);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ vec4 ApplyBlendMode(vec4 src) {
+ vec4 dst = GetBackdropColor();
+ return Blend(src, dst);
+ }
+ });
return "precision mediump float;" + GetHelperFunctions() +
GetBlendFunction() + kFunctionApplyBlendMode + shader_string;
}
std::string FragmentTexBlendMode::GetHelperFunctions() const {
- // clang-format off
- static const std::string kFunctionHardLight = SHADER0(
- // clang-format on
- vec3 hardLight(vec4 src, vec4 dst) {
- vec3 result;
- result.r =
- (2.0 * src.r <= src.a)
- ? (2.0 * src.r * dst.r)
- : (src.a * dst.a - 2.0 * (dst.a - dst.r) * (src.a - src.r));
- result.g =
- (2.0 * src.g <= src.a)
- ? (2.0 * src.g * dst.g)
- : (src.a * dst.a - 2.0 * (dst.a - dst.g) * (src.a - src.g));
- result.b =
- (2.0 * src.b <= src.a)
- ? (2.0 * src.b * dst.b)
- : (src.a * dst.a - 2.0 * (dst.a - dst.b) * (src.a - src.b));
- result.rgb += src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
- return result;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
+ static const std::string kFunctionHardLight = SHADER0([]() {
+ vec3 hardLight(vec4 src, vec4 dst) {
+ vec3 result;
+ result.r =
+ (2.0 * src.r <= src.a)
+ ? (2.0 * src.r * dst.r)
+ : (src.a * dst.a - 2.0 * (dst.a - dst.r) * (src.a - src.r));
+ result.g =
+ (2.0 * src.g <= src.a)
+ ? (2.0 * src.g * dst.g)
+ : (src.a * dst.a - 2.0 * (dst.a - dst.g) * (src.a - src.g));
+ result.b =
+ (2.0 * src.b <= src.a)
+ ? (2.0 * src.b * dst.b)
+ : (src.a * dst.a - 2.0 * (dst.a - dst.b) * (src.a - src.b));
+ result.rgb += src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
+ return result;
+ }
+ });
- static const std::string kFunctionColorDodgeComponent = SHADER0(
- // clang-format on
- float getColorDodgeComponent(
- float srcc, float srca, float dstc, float dsta) {
- if (0.0 == dstc)
- return srcc * (1.0 - dsta);
- float d = srca - srcc;
- if (0.0 == d)
- return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
- d = min(dsta, dstc * srca / d);
- return d * srca + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
+ static const std::string kFunctionColorDodgeComponent = SHADER0([]() {
+ float getColorDodgeComponent(float srcc, float srca, float dstc,
+ float dsta) {
+ if (0.0 == dstc)
+ return srcc * (1.0 - dsta);
+ float d = srca - srcc;
+ if (0.0 == d)
+ return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+ d = min(dsta, dstc * srca / d);
+ return d * srca + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+ }
+ });
- static const std::string kFunctionColorBurnComponent = SHADER0(
- // clang-format on
- float getColorBurnComponent(
- float srcc, float srca, float dstc, float dsta) {
- if (dsta == dstc)
- return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
- if (0.0 == srcc)
- return dstc * (1.0 - srca);
- float d = max(0.0, dsta - (dsta - dstc) * srca / srcc);
- return srca * d + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
+ static const std::string kFunctionColorBurnComponent = SHADER0([]() {
+ float getColorBurnComponent(float srcc, float srca, float dstc,
+ float dsta) {
+ if (dsta == dstc)
+ return srca * dsta + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+ if (0.0 == srcc)
+ return dstc * (1.0 - srca);
+ float d = max(0.0, dsta - (dsta - dstc) * srca / srcc);
+ return srca * d + srcc * (1.0 - dsta) + dstc * (1.0 - srca);
+ }
+ });
- static const std::string kFunctionSoftLightComponentPosDstAlpha = SHADER0(
- // clang-format on
- float getSoftLightComponent(
- float srcc, float srca, float dstc, float dsta) {
- if (2.0 * srcc <= srca) {
- return (dstc * dstc * (srca - 2.0 * srcc)) / dsta +
- (1.0 - dsta) * srcc + dstc * (-srca + 2.0 * srcc + 1.0);
- } else if (4.0 * dstc <= dsta) {
- float DSqd = dstc * dstc;
- float DCub = DSqd * dstc;
- float DaSqd = dsta * dsta;
- float DaCub = DaSqd * dsta;
- return (-DaCub * srcc +
- DaSqd * (srcc - dstc * (3.0 * srca - 6.0 * srcc - 1.0)) +
- 12.0 * dsta * DSqd * (srca - 2.0 * srcc) -
- 16.0 * DCub * (srca - 2.0 * srcc)) /
- DaSqd;
- } else {
- return -sqrt(dsta * dstc) * (srca - 2.0 * srcc) - dsta * srcc +
- dstc * (srca - 2.0 * srcc + 1.0) + srcc;
- }
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
-
- static const std::string kFunctionLum = SHADER0(
- // clang-format on
- float luminance(vec3 color) { return dot(vec3(0.3, 0.59, 0.11), color); }
-
- vec3 set_luminance(vec3 hueSat, float alpha, vec3 lumColor) {
- float diff = luminance(lumColor - hueSat);
- vec3 outColor = hueSat + diff;
- float outLum = luminance(outColor);
- float minComp = min(min(outColor.r, outColor.g), outColor.b);
- float maxComp = max(max(outColor.r, outColor.g), outColor.b);
- if (minComp < 0.0 && outLum != minComp) {
- outColor = outLum +
- ((outColor - vec3(outLum, outLum, outLum)) * outLum) /
- (outLum - minComp);
- }
- if (maxComp > alpha && maxComp != outLum) {
- outColor =
- outLum +
- ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) /
- (maxComp - outLum);
- }
- return outColor;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
-
- static const std::string kFunctionSat = SHADER0(
- // clang-format on
- float saturation(vec3 color) {
- return max(max(color.r, color.g), color.b) -
- min(min(color.r, color.g), color.b);
- }
-
- vec3 set_saturation_helper(
- float minComp, float midComp, float maxComp, float sat) {
- if (minComp < maxComp) {
- vec3 result;
- result.r = 0.0;
- result.g = sat * (midComp - minComp) / (maxComp - minComp);
- result.b = sat;
- return result;
- } else {
- return vec3(0, 0, 0);
- }
- }
-
- vec3 set_saturation(vec3 hueLumColor, vec3 satColor) {
- float sat = saturation(satColor);
- if (hueLumColor.r <= hueLumColor.g) {
- if (hueLumColor.g <= hueLumColor.b) {
- hueLumColor.rgb = set_saturation_helper(
- hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);
- } else if (hueLumColor.r <= hueLumColor.b) {
- hueLumColor.rbg = set_saturation_helper(
- hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);
+ static const std::string kFunctionSoftLightComponentPosDstAlpha =
+ SHADER0([]() {
+ float getSoftLightComponent(float srcc, float srca, float dstc,
+ float dsta) {
+ if (2.0 * srcc <= srca) {
+ return (dstc * dstc * (srca - 2.0 * srcc)) / dsta +
+ (1.0 - dsta) * srcc + dstc * (-srca + 2.0 * srcc + 1.0);
+ } else if (4.0 * dstc <= dsta) {
+ float DSqd = dstc * dstc;
+ float DCub = DSqd * dstc;
+ float DaSqd = dsta * dsta;
+ float DaCub = DaSqd * dsta;
+ return (-DaCub * srcc +
+ DaSqd * (srcc - dstc * (3.0 * srca - 6.0 * srcc - 1.0)) +
+ 12.0 * dsta * DSqd * (srca - 2.0 * srcc) -
+ 16.0 * DCub * (srca - 2.0 * srcc)) /
+ DaSqd;
} else {
- hueLumColor.brg = set_saturation_helper(
- hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);
+ return -sqrt(dsta * dstc) * (srca - 2.0 * srcc) - dsta * srcc +
+ dstc * (srca - 2.0 * srcc + 1.0) + srcc;
}
- } else if (hueLumColor.r <= hueLumColor.b) {
- hueLumColor.grb = set_saturation_helper(
- hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);
- } else if (hueLumColor.g <= hueLumColor.b) {
- hueLumColor.gbr = set_saturation_helper(
- hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);
- } else {
- hueLumColor.bgr = set_saturation_helper(
- hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);
}
- return hueLumColor;
+ });
+
+ static const std::string kFunctionLum = SHADER0([]() {
+ float luminance(vec3 color) { return dot(vec3(0.3, 0.59, 0.11), color); }
+
+ vec3 set_luminance(vec3 hueSat, float alpha, vec3 lumColor) {
+ float diff = luminance(lumColor - hueSat);
+ vec3 outColor = hueSat + diff;
+ float outLum = luminance(outColor);
+ float minComp = min(min(outColor.r, outColor.g), outColor.b);
+ float maxComp = max(max(outColor.r, outColor.g), outColor.b);
+ if (minComp < 0.0 && outLum != minComp) {
+ outColor = outLum +
+ ((outColor - vec3(outLum, outLum, outLum)) * outLum) /
+ (outLum - minComp);
}
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ if (maxComp > alpha && maxComp != outLum) {
+ outColor =
+ outLum +
+ ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) /
+ (maxComp - outLum);
+ }
+ return outColor;
+ }
+ });
+
+ static const std::string kFunctionSat = SHADER0([]() {
+ float saturation(vec3 color) {
+ return max(max(color.r, color.g), color.b) -
+ min(min(color.r, color.g), color.b);
+ }
+
+ vec3 set_saturation_helper(float minComp, float midComp, float maxComp,
+ float sat) {
+ if (minComp < maxComp) {
+ vec3 result;
+ result.r = 0.0;
+ result.g = sat * (midComp - minComp) / (maxComp - minComp);
+ result.b = sat;
+ return result;
+ } else {
+ return vec3(0, 0, 0);
+ }
+ }
+
+ vec3 set_saturation(vec3 hueLumColor, vec3 satColor) {
+ float sat = saturation(satColor);
+ if (hueLumColor.r <= hueLumColor.g) {
+ if (hueLumColor.g <= hueLumColor.b) {
+ hueLumColor.rgb = set_saturation_helper(hueLumColor.r, hueLumColor.g,
+ hueLumColor.b, sat);
+ } else if (hueLumColor.r <= hueLumColor.b) {
+ hueLumColor.rbg = set_saturation_helper(hueLumColor.r, hueLumColor.b,
+ hueLumColor.g, sat);
+ } else {
+ hueLumColor.brg = set_saturation_helper(hueLumColor.b, hueLumColor.r,
+ hueLumColor.g, sat);
+ }
+ } else if (hueLumColor.r <= hueLumColor.b) {
+ hueLumColor.grb = set_saturation_helper(hueLumColor.g, hueLumColor.r,
+ hueLumColor.b, sat);
+ } else if (hueLumColor.g <= hueLumColor.b) {
+ hueLumColor.gbr = set_saturation_helper(hueLumColor.g, hueLumColor.b,
+ hueLumColor.r, sat);
+ } else {
+ hueLumColor.bgr = set_saturation_helper(hueLumColor.b, hueLumColor.g,
+ hueLumColor.r, sat);
+ }
+ return hueLumColor;
+ }
+ });
switch (blend_mode_) {
case BlendModeOverlay:
@@ -1048,85 +1085,105 @@
std::string FragmentShaderRGBATexAlpha::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType s_texture;
- uniform float alpha;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- gl_FragColor = ApplyBlendMode(texColor * alpha);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexAlpha::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType s_texture;
+ uniform float alpha;
+ });
+}
+
+std::string FragmentShaderRGBATexAlpha::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ gl_FragColor = ApplyBlendMode(texColor * alpha);
+ }
+ });
}
std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType s_texture;
- uniform float alpha;
- uniform mat4 colorMatrix;
- uniform vec4 colorOffset;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- float nonZeroAlpha = max(texColor.a, 0.00001);
- texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
- texColor = colorMatrix * texColor + colorOffset;
- texColor.rgb *= texColor.a;
- texColor = clamp(texColor, 0.0, 1.0);
- gl_FragColor = ApplyBlendMode(texColor * alpha);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType s_texture;
+ uniform float alpha;
+ uniform mat4 colorMatrix;
+ uniform vec4 colorOffset;
+ });
+}
+
+std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ float nonZeroAlpha = max(texColor.a, 0.00001);
+ texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
+ texColor = colorMatrix * texColor + colorOffset;
+ texColor.rgb *= texColor.a;
+ texColor = clamp(texColor, 0.0, 1.0);
+ gl_FragColor = ApplyBlendMode(texColor * alpha);
+ }
+ });
}
std::string FragmentShaderRGBATexVaryingAlpha::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- varying float v_alpha;
- uniform SamplerType s_texture;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- gl_FragColor = texColor * v_alpha;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexVaryingAlpha::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying float v_alpha;
+ uniform SamplerType s_texture;
+ });
+}
+
+std::string FragmentShaderRGBATexVaryingAlpha::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ gl_FragColor = texColor * v_alpha;
+ }
+ });
}
std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- varying float v_alpha;
- uniform SamplerType s_texture;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- texColor.rgb *= texColor.a;
- gl_FragColor = texColor * v_alpha;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying float v_alpha;
+ uniform SamplerType s_texture;
+ });
+}
+
+std::string FragmentShaderRGBATexPremultiplyAlpha::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ texColor.rgb *= texColor.a;
+ gl_FragColor = texColor * v_alpha;
+ }
+ });
}
FragmentTexBackgroundBinding::FragmentTexBackgroundBinding()
@@ -1158,114 +1215,144 @@
std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- varying float v_alpha;
- uniform vec4 background_color;
- uniform SamplerType s_texture;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- texColor += background_color * (1.0 - texColor.a);
- gl_FragColor = texColor * v_alpha;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying float v_alpha;
+ uniform vec4 background_color;
+ uniform SamplerType s_texture;
+ });
+}
+
+std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ texColor += background_color * (1.0 - texColor.a);
+ gl_FragColor = texColor * v_alpha;
+ }
+ });
}
std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- varying float v_alpha;
- uniform vec4 background_color;
- uniform SamplerType s_texture;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- texColor.rgb *= texColor.a;
- texColor += background_color * (1.0 - texColor.a);
- gl_FragColor = texColor * v_alpha;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying float v_alpha;
+ uniform vec4 background_color;
+ uniform SamplerType s_texture;
+ });
+}
+
+std::string FragmentShaderTexBackgroundPremultiplyAlpha::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ texColor.rgb *= texColor.a;
+ texColor += background_color * (1.0 - texColor.a);
+ gl_FragColor = texColor * v_alpha;
+ }
+ });
}
std::string FragmentShaderRGBATexOpaque::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType s_texture;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- gl_FragColor = vec4(texColor.rgb, 1.0);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexOpaque::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType s_texture;
+ });
+}
+
+std::string FragmentShaderRGBATexOpaque::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ gl_FragColor = vec4(texColor.rgb, 1.0);
+ }
+ });
}
std::string FragmentShaderRGBATex::GetShaderString(TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType s_texture;
- void main() { gl_FragColor = TextureLookup(s_texture, v_texCoord); }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATex::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType s_texture;
+ });
+}
+
+std::string FragmentShaderRGBATex::GetShaderBody() {
+ return SHADER0([]() {
+ void main() { gl_FragColor = TextureLookup(s_texture, v_texCoord); }
+ });
}
std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType s_texture;
- uniform float alpha;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- gl_FragColor =
- vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType s_texture;
+ uniform float alpha;
+ });
+}
+
+std::string FragmentShaderRGBATexSwizzleAlpha::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ gl_FragColor =
+ vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
+ }
+ });
}
std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType s_texture;
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType s_texture;
+ });
+}
+
+std::string FragmentShaderRGBATexSwizzleOpaque::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
+ }
+ });
}
FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA()
@@ -1294,25 +1381,29 @@
std::string FragmentShaderRGBATexAlphaAA::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform SamplerType s_texture;
- uniform float alpha;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- vec4 d4 = min(edge_dist[0], edge_dist[1]);
- vec2 d2 = min(d4.xz, d4.yw);
- float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
- gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string FragmentShaderRGBATexAlphaAA::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform SamplerType s_texture;
+ uniform float alpha;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string FragmentShaderRGBATexAlphaAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ vec4 d4 = min(edge_dist[0], edge_dist[1]);
+ vec2 d2 = min(d4.xz, d4.yw);
+ float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
+ gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
+ }
+ });
}
FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding()
@@ -1343,58 +1434,66 @@
std::string FragmentShaderRGBATexClampAlphaAA::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform SamplerType s_texture;
- uniform float alpha;
- uniform TexCoordPrecision vec4 fragmentTexTransform;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- TexCoordPrecision vec2 texCoord =
- clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
- fragmentTexTransform.xy;
- vec4 texColor = TextureLookup(s_texture, texCoord);
- vec4 d4 = min(edge_dist[0], edge_dist[1]);
- vec2 d2 = min(d4.xz, d4.yw);
- float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
- gl_FragColor = texColor * alpha * aa;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string FragmentShaderRGBATexClampAlphaAA::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform SamplerType s_texture;
+ uniform float alpha;
+ uniform TexCoordPrecision vec4 fragmentTexTransform;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string FragmentShaderRGBATexClampAlphaAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ TexCoordPrecision vec2 texCoord =
+ clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
+ fragmentTexTransform.xy;
+ vec4 texColor = TextureLookup(s_texture, texCoord);
+ vec4 d4 = min(edge_dist[0], edge_dist[1]);
+ vec2 d2 = min(d4.xz, d4.yw);
+ float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
+ gl_FragColor = texColor * alpha * aa;
+ }
+ });
}
std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform SamplerType s_texture;
- uniform float alpha;
- uniform TexCoordPrecision vec4 fragmentTexTransform;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- TexCoordPrecision vec2 texCoord =
- clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
- fragmentTexTransform.xy;
- vec4 texColor = TextureLookup(s_texture, texCoord);
- vec4 d4 = min(edge_dist[0], edge_dist[1]);
- vec2 d2 = min(d4.xz, d4.yw);
- float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
- gl_FragColor =
- vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha * aa;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform SamplerType s_texture;
+ uniform float alpha;
+ uniform TexCoordPrecision vec4 fragmentTexTransform;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string FragmentShaderRGBATexClampSwizzleAlphaAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ TexCoordPrecision vec2 texCoord =
+ clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw +
+ fragmentTexTransform.xy;
+ vec4 texColor = TextureLookup(s_texture, texCoord);
+ vec4 d4 = min(edge_dist[0], edge_dist[1]);
+ vec2 d2 = min(d4.xz, d4.yw);
+ float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
+ gl_FragColor =
+ vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha * aa;
+ }
+ });
}
FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask()
@@ -1434,27 +1533,32 @@
std::string FragmentShaderRGBATexAlphaMask::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
- uniform SamplerType s_mask;
- uniform TexCoordPrecision vec2 maskTexCoordScale;
- uniform TexCoordPrecision vec2 maskTexCoordOffset;
- uniform float alpha;
- void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
- TexCoordPrecision vec2 maskTexCoord =
- vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
- maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
- gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexAlphaMask::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform sampler2D s_texture;
+ uniform SamplerType s_mask;
+ uniform TexCoordPrecision vec2 maskTexCoordScale;
+ uniform TexCoordPrecision vec2 maskTexCoordOffset;
+ uniform float alpha;
+ });
+}
+
+std::string FragmentShaderRGBATexAlphaMask::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = texture2D(s_texture, v_texCoord);
+ TexCoordPrecision vec2 maskTexCoord =
+ vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
+ maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
+ gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
+ }
+ });
}
FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA()
@@ -1495,32 +1599,36 @@
std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform sampler2D s_texture;
- uniform SamplerType s_mask;
- uniform TexCoordPrecision vec2 maskTexCoordScale;
- uniform TexCoordPrecision vec2 maskTexCoordOffset;
- uniform float alpha;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
- TexCoordPrecision vec2 maskTexCoord =
- vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
- maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
- vec4 d4 = min(edge_dist[0], edge_dist[1]);
- vec2 d2 = min(d4.xz, d4.yw);
- float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
- gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform sampler2D s_texture;
+ uniform SamplerType s_mask;
+ uniform TexCoordPrecision vec2 maskTexCoordScale;
+ uniform TexCoordPrecision vec2 maskTexCoordOffset;
+ uniform float alpha;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = texture2D(s_texture, v_texCoord);
+ TexCoordPrecision vec2 maskTexCoord =
+ vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
+ maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
+ vec4 d4 = min(edge_dist[0], edge_dist[1]);
+ vec2 d2 = min(d4.xz, d4.yw);
+ float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
+ gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
+ }
+ });
}
FragmentShaderRGBATexAlphaMaskColorMatrixAA::
@@ -1568,39 +1676,43 @@
std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform sampler2D s_texture;
- uniform SamplerType s_mask;
- uniform vec2 maskTexCoordScale;
- uniform vec2 maskTexCoordOffset;
- uniform mat4 colorMatrix;
- uniform vec4 colorOffset;
- uniform float alpha;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
- float nonZeroAlpha = max(texColor.a, 0.00001);
- texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
- texColor = colorMatrix * texColor + colorOffset;
- texColor.rgb *= texColor.a;
- texColor = clamp(texColor, 0.0, 1.0);
- TexCoordPrecision vec2 maskTexCoord =
- vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
- maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
- vec4 d4 = min(edge_dist[0], edge_dist[1]);
- vec2 d2 = min(d4.xz, d4.yw);
- float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
- gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform sampler2D s_texture;
+ uniform SamplerType s_mask;
+ uniform vec2 maskTexCoordScale;
+ uniform vec2 maskTexCoordOffset;
+ uniform mat4 colorMatrix;
+ uniform vec4 colorOffset;
+ uniform float alpha;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = texture2D(s_texture, v_texCoord);
+ float nonZeroAlpha = max(texColor.a, 0.00001);
+ texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
+ texColor = colorMatrix * texColor + colorOffset;
+ texColor.rgb *= texColor.a;
+ texColor = clamp(texColor, 0.0, 1.0);
+ TexCoordPrecision vec2 maskTexCoord =
+ vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
+ maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
+ vec4 d4 = min(edge_dist[0], edge_dist[1]);
+ vec2 d2 = min(d4.xz, d4.yw);
+ float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
+ gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w * aa);
+ }
+ });
}
FragmentShaderRGBATexAlphaColorMatrixAA::
@@ -1635,32 +1747,36 @@
std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform SamplerType s_texture;
- uniform float alpha;
- uniform mat4 colorMatrix;
- uniform vec4 colorOffset;
- varying TexCoordPrecision vec2 v_texCoord;
- varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec4 texColor = TextureLookup(s_texture, v_texCoord);
- float nonZeroAlpha = max(texColor.a, 0.00001);
- texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
- texColor = colorMatrix * texColor + colorOffset;
- texColor.rgb *= texColor.a;
- texColor = clamp(texColor, 0.0, 1.0);
- vec4 d4 = min(edge_dist[0], edge_dist[1]);
- vec2 d2 = min(d4.xz, d4.yw);
- float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
- gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform SamplerType s_texture;
+ uniform float alpha;
+ uniform mat4 colorMatrix;
+ uniform vec4 colorOffset;
+ varying TexCoordPrecision vec2 v_texCoord;
+ varying TexCoordPrecision vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = TextureLookup(s_texture, v_texCoord);
+ float nonZeroAlpha = max(texColor.a, 0.00001);
+ texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
+ texColor = colorMatrix * texColor + colorOffset;
+ texColor.rgb *= texColor.a;
+ texColor = clamp(texColor, 0.0, 1.0);
+ vec4 d4 = min(edge_dist[0], edge_dist[1]);
+ vec2 d2 = min(d4.xz, d4.yw);
+ float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
+ gl_FragColor = ApplyBlendMode(texColor * alpha * aa);
+ }
+ });
}
FragmentShaderRGBATexAlphaMaskColorMatrix::
@@ -1705,34 +1821,39 @@
std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform sampler2D s_texture;
- uniform SamplerType s_mask;
- uniform vec2 maskTexCoordScale;
- uniform vec2 maskTexCoordOffset;
- uniform mat4 colorMatrix;
- uniform vec4 colorOffset;
- uniform float alpha;
- void main() {
- vec4 texColor = texture2D(s_texture, v_texCoord);
- float nonZeroAlpha = max(texColor.a, 0.00001);
- texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
- texColor = colorMatrix * texColor + colorOffset;
- texColor.rgb *= texColor.a;
- texColor = clamp(texColor, 0.0, 1.0);
- TexCoordPrecision vec2 maskTexCoord =
- vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
- maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
- vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
- gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform sampler2D s_texture;
+ uniform SamplerType s_mask;
+ uniform vec2 maskTexCoordScale;
+ uniform vec2 maskTexCoordOffset;
+ uniform mat4 colorMatrix;
+ uniform vec4 colorOffset;
+ uniform float alpha;
+ });
+}
+
+std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 texColor = texture2D(s_texture, v_texCoord);
+ float nonZeroAlpha = max(texColor.a, 0.00001);
+ texColor = vec4(texColor.rgb / nonZeroAlpha, nonZeroAlpha);
+ texColor = colorMatrix * texColor + colorOffset;
+ texColor.rgb *= texColor.a;
+ texColor = clamp(texColor, 0.0, 1.0);
+ TexCoordPrecision vec2 maskTexCoord =
+ vec2(maskTexCoordOffset.x + v_texCoord.x * maskTexCoordScale.x,
+ maskTexCoordOffset.y + v_texCoord.y * maskTexCoordScale.y);
+ vec4 maskColor = TextureLookup(s_mask, maskTexCoord);
+ gl_FragColor = ApplyBlendMode(texColor * alpha * maskColor.w);
+ }
+ });
}
FragmentShaderYUVVideo::FragmentShaderYUVVideo()
@@ -1774,31 +1895,36 @@
std::string FragmentShaderYUVVideo::GetShaderString(TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- precision mediump int;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType y_texture;
- uniform SamplerType u_texture;
- uniform SamplerType v_texture;
- uniform float alpha;
- uniform vec3 yuv_adj;
- uniform mat3 yuv_matrix;
- uniform vec4 clamp_rect;
- void main() {
- vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
- float y_raw = TextureLookup(y_texture, clamped).x;
- float u_unsigned = TextureLookup(u_texture, clamped).x;
- float v_unsigned = TextureLookup(v_texture, clamped).x;
- vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
- vec3 rgb = yuv_matrix * yuv;
- gl_FragColor = vec4(rgb, 1.0) * alpha;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderYUVVideo::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ precision mediump int;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType y_texture;
+ uniform SamplerType u_texture;
+ uniform SamplerType v_texture;
+ uniform float alpha;
+ uniform vec3 yuv_adj;
+ uniform mat3 yuv_matrix;
+ uniform vec4 clamp_rect;
+ });
+}
+
+std::string FragmentShaderYUVVideo::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
+ float y_raw = TextureLookup(y_texture, clamped).x;
+ float u_unsigned = TextureLookup(u_texture, clamped).x;
+ float v_unsigned = TextureLookup(v_texture, clamped).x;
+ vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
+ vec3 rgb = yuv_matrix * yuv;
+ gl_FragColor = vec4(rgb, 1.0) * alpha;
+ }
+ });
}
FragmentShaderYUVAVideo::FragmentShaderYUVAVideo()
@@ -1845,33 +1971,38 @@
std::string FragmentShaderYUVAVideo::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- precision mediump int;
- varying TexCoordPrecision vec2 v_texCoord;
- uniform SamplerType y_texture;
- uniform SamplerType u_texture;
- uniform SamplerType v_texture;
- uniform SamplerType a_texture;
- uniform float alpha;
- uniform vec3 yuv_adj;
- uniform mat3 yuv_matrix;
- uniform vec4 clamp_rect;
- void main() {
- vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
- float y_raw = TextureLookup(y_texture, clamped).x;
- float u_unsigned = TextureLookup(u_texture, clamped).x;
- float v_unsigned = TextureLookup(v_texture, clamped).x;
- float a_raw = TextureLookup(a_texture, clamped).x;
- vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
- vec3 rgb = yuv_matrix * yuv;
- gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderYUVAVideo::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ precision mediump int;
+ varying TexCoordPrecision vec2 v_texCoord;
+ uniform SamplerType y_texture;
+ uniform SamplerType u_texture;
+ uniform SamplerType v_texture;
+ uniform SamplerType a_texture;
+ uniform float alpha;
+ uniform vec3 yuv_adj;
+ uniform mat3 yuv_matrix;
+ uniform vec4 clamp_rect;
+ });
+}
+
+std::string FragmentShaderYUVAVideo::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec2 clamped = max(clamp_rect.xy, min(clamp_rect.zw, v_texCoord));
+ float y_raw = TextureLookup(y_texture, clamped).x;
+ float u_unsigned = TextureLookup(u_texture, clamped).x;
+ float v_unsigned = TextureLookup(v_texture, clamped).x;
+ float a_raw = TextureLookup(a_texture, clamped).x;
+ vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned) + yuv_adj;
+ vec3 rgb = yuv_matrix * yuv;
+ gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);
+ }
+ });
}
FragmentShaderColor::FragmentShaderColor() : color_location_(-1) {
@@ -1896,15 +2027,20 @@
std::string FragmentShaderColor::GetShaderString(TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform vec4 color;
- void main() { gl_FragColor = color; }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderColor::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform vec4 color;
+ });
+}
+
+std::string FragmentShaderColor::GetShaderBody() {
+ return SHADER0([]() {
+ void main() { gl_FragColor = color; }
+ });
}
FragmentShaderColorAA::FragmentShaderColorAA() : color_location_(-1) {
@@ -1929,22 +2065,26 @@
std::string FragmentShaderColorAA::GetShaderString(TexCoordPrecision precision,
SamplerType sampler) const {
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- uniform vec4 color;
- varying vec4 edge_dist[2]; // 8 edge distances.
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
- void main() {
- vec4 d4 = min(edge_dist[0], edge_dist[1]);
- vec2 d2 = min(d4.xz, d4.yw);
- float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
- gl_FragColor = color * aa;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+std::string FragmentShaderColorAA::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ uniform vec4 color;
+ varying vec4 edge_dist[2]; // 8 edge distances.
+ });
+}
+
+std::string FragmentShaderColorAA::GetShaderBody() {
+ return SHADER0([]() {
+ void main() {
+ vec4 d4 = min(edge_dist[0], edge_dist[1]);
+ vec2 d2 = min(d4.xz, d4.yw);
+ float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);
+ gl_FragColor = color * aa;
+ }
+ });
}
FragmentShaderCheckerboard::FragmentShaderCheckerboard()
@@ -1976,30 +2116,35 @@
std::string FragmentShaderCheckerboard::GetShaderString(
TexCoordPrecision precision,
SamplerType sampler) const {
+ return FRAGMENT_SHADER(GetShaderHead(), GetShaderBody());
+}
+
+std::string FragmentShaderCheckerboard::GetShaderHead() {
+ return SHADER0([]() {
+ precision mediump float;
+ precision mediump int;
+ varying vec2 v_texCoord;
+ uniform float alpha;
+ uniform float frequency;
+ uniform vec4 texTransform;
+ uniform vec4 color;
+ });
+}
+
+std::string FragmentShaderCheckerboard::GetShaderBody() {
// Shader based on Example 13-17 of "OpenGL ES 2.0 Programming Guide"
// by Munshi, Ginsburg, Shreiner.
- // clang-format off
- return FRAGMENT_SHADER(
- // clang-format on
- precision mediump float;
- precision mediump int;
- varying vec2 v_texCoord;
- uniform float alpha;
- uniform float frequency;
- uniform vec4 texTransform;
- uniform vec4 color;
- void main() {
- vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
- vec4 color2 = color;
- vec2 texCoord =
- clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
- vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
- float picker = abs(coord.x - coord.y); // NOLINT
- gl_FragColor = mix(color1, color2, picker) * alpha;
- }
- // clang-format off
- ); // NOLINT(whitespace/parens)
- // clang-format on
+ return SHADER0([]() {
+ void main() {
+ vec4 color1 = vec4(1.0, 1.0, 1.0, 1.0);
+ vec4 color2 = color;
+ vec2 texCoord =
+ clamp(v_texCoord, 0.0, 1.0) * texTransform.zw + texTransform.xy;
+ vec2 coord = mod(floor(texCoord * frequency * 2.0), 2.0);
+ float picker = abs(coord.x - coord.y); // NOLINT
+ gl_FragColor = mix(color1, color2, picker) * alpha;
+ }
+ });
}
} // namespace cc
diff --git a/cc/output/shader.h b/cc/output/shader.h
index 5adca47..3c8102e 100644
--- a/cc/output/shader.h
+++ b/cc/output/shader.h
@@ -83,6 +83,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
@@ -100,6 +102,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int tex_scale_location() const { return tex_scale_location_; }
@@ -121,6 +125,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
@@ -136,6 +142,8 @@
unsigned program,
int* base_uniform_index) {}
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class VertexShaderPosTexTransform {
@@ -146,6 +154,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int tex_transform_location() const { return tex_transform_location_; }
@@ -167,6 +177,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int viewport_location() const { return -1; }
@@ -188,6 +200,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int viewport_location() const { return viewport_location_; }
@@ -212,6 +226,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int viewport_location() const { return viewport_location_; }
@@ -237,6 +253,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int viewport_location() const { return -1; }
@@ -262,6 +280,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int viewport_location() const { return viewport_location_; }
@@ -289,6 +309,8 @@
unsigned program,
int* base_uniform_index);
std::string GetShaderString() const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int matrix_location() const { return matrix_location_; }
int tex_matrix_location() const { return tex_matrix_location_; }
@@ -402,12 +424,16 @@
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderRGBATexPremultiplyAlpha : public FragmentTexOpaqueBinding {
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderTexBackgroundVaryingAlpha
@@ -415,6 +441,8 @@
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderTexBackgroundPremultiplyAlpha
@@ -422,31 +450,41 @@
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding {
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderRGBATexColorMatrixAlpha
: public FragmentTexColorMatrixAlphaBinding {
public:
- std::string GetShaderString(
- TexCoordPrecision precision, SamplerType sampler) const;
+ std::string GetShaderString(TexCoordPrecision precision,
+ SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderRGBATexOpaque : public FragmentTexOpaqueBinding {
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderRGBATex : public FragmentTexOpaqueBinding {
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
// Swizzles the red and blue component of sampled texel with alpha.
@@ -454,6 +492,8 @@
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
// Swizzles the red and blue component of sampled texel without alpha.
@@ -461,6 +501,8 @@
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderRGBATexAlphaAA : public FragmentTexBlendMode {
@@ -472,6 +514,8 @@
int* base_uniform_index);
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
int alpha_location() const { return alpha_location_; }
int sampler_location() const { return sampler_location_; }
@@ -509,6 +553,8 @@
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
// Swizzles the red and blue component of sampled texel.
@@ -517,6 +563,8 @@
public:
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
};
class FragmentShaderRGBATexAlphaMask : public FragmentTexBlendMode {
@@ -524,6 +572,8 @@
FragmentShaderRGBATexAlphaMask();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -553,6 +603,8 @@
FragmentShaderRGBATexAlphaMaskAA();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -583,6 +635,8 @@
FragmentShaderRGBATexAlphaMaskColorMatrixAA();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -614,6 +668,8 @@
FragmentShaderRGBATexAlphaColorMatrixAA();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -635,6 +691,8 @@
FragmentShaderRGBATexAlphaMaskColorMatrix();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -666,6 +724,8 @@
FragmentShaderYUVVideo();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -695,6 +755,8 @@
FragmentShaderYUVAVideo();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -727,6 +789,8 @@
FragmentShaderColor();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -744,6 +808,8 @@
FragmentShaderColorAA();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
@@ -761,6 +827,8 @@
FragmentShaderCheckerboard();
std::string GetShaderString(
TexCoordPrecision precision, SamplerType sampler) const;
+ static std::string GetShaderHead();
+ static std::string GetShaderBody();
void Init(gpu::gles2::GLES2Interface* context,
unsigned program,
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index ceedac6..488ca09 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -160,6 +160,11 @@
DrawingFrame* frame,
const ScopedResource* texture,
const gfx::Rect& target_rect) {
+ DCHECK(texture->id());
+
+ // Explicitly release lock, otherwise we can crash when try to lock
+ // same texture again.
+ current_framebuffer_lock_ = nullptr;
current_framebuffer_lock_ = make_scoped_ptr(
new ResourceProvider::ScopedWriteLockSoftware(
resource_provider_, texture->id()));
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc
index 7f689a8..fa25200 100644
--- a/cc/output/software_renderer_unittest.cc
+++ b/cc/output/software_renderer_unittest.cc
@@ -135,7 +135,7 @@
scoped_ptr<SkBitmap> output =
DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
EXPECT_EQ(outer_rect.width(), output->info().fWidth);
- EXPECT_EQ(outer_rect.width(), output->info().fHeight);
+ EXPECT_EQ(outer_rect.height(), output->info().fHeight);
EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
EXPECT_EQ(SK_ColorYELLOW,
@@ -233,7 +233,7 @@
scoped_ptr<SkBitmap> output =
DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
EXPECT_EQ(outer_rect.width(), output->info().fWidth);
- EXPECT_EQ(outer_rect.width(), output->info().fHeight);
+ EXPECT_EQ(outer_rect.height(), output->info().fHeight);
EXPECT_EQ(SK_ColorYELLOW, output->getColor(0, 0));
EXPECT_EQ(SK_ColorYELLOW,
@@ -308,7 +308,7 @@
scoped_ptr<SkBitmap> output =
DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
EXPECT_EQ(tile_rect.width(), output->info().fWidth);
- EXPECT_EQ(tile_rect.width(), output->info().fHeight);
+ EXPECT_EQ(tile_rect.height(), output->info().fHeight);
// Check portion of tile not in visible rect isn't drawn.
const unsigned int kTransparent = SK_ColorTRANSPARENT;
@@ -350,7 +350,7 @@
scoped_ptr<SkBitmap> output =
DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
- EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
+ EXPECT_EQ(device_viewport_rect.height(), output->info().fHeight);
EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
EXPECT_EQ(SK_ColorGREEN,
@@ -372,7 +372,7 @@
output = DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
- EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
+ EXPECT_EQ(device_viewport_rect.height(), output->info().fHeight);
// If we didn't clear, the borders should still be green.
EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
@@ -417,7 +417,7 @@
scoped_ptr<SkBitmap> output =
DrawAndCopyOutput(&list, device_scale_factor, device_viewport_rect);
EXPECT_EQ(device_viewport_rect.width(), output->info().fWidth);
- EXPECT_EQ(device_viewport_rect.width(), output->info().fHeight);
+ EXPECT_EQ(device_viewport_rect.height(), output->info().fHeight);
EXPECT_EQ(SK_ColorGREEN, output->getColor(0, 0));
EXPECT_EQ(SK_ColorGREEN,
diff --git a/cc/quads/checkerboard_draw_quad.cc b/cc/quads/checkerboard_draw_quad.cc
index 68d81c7..2d8957d 100644
--- a/cc/quads/checkerboard_draw_quad.cc
+++ b/cc/quads/checkerboard_draw_quad.cc
@@ -43,7 +43,8 @@
return static_cast<const CheckerboardDrawQuad*>(quad);
}
-void CheckerboardDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void CheckerboardDrawQuad::ExtendValue(
+ base::trace_event::TracedValue* value) const {
value->SetInteger("color", color);
}
diff --git a/cc/quads/checkerboard_draw_quad.h b/cc/quads/checkerboard_draw_quad.h
index 64c583f..1ab6338 100644
--- a/cc/quads/checkerboard_draw_quad.h
+++ b/cc/quads/checkerboard_draw_quad.h
@@ -35,7 +35,7 @@
static const CheckerboardDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/content_draw_quad_base.cc b/cc/quads/content_draw_quad_base.cc
index 171e90d..66fa147 100644
--- a/cc/quads/content_draw_quad_base.cc
+++ b/cc/quads/content_draw_quad_base.cc
@@ -54,7 +54,8 @@
this->nearest_neighbor = nearest_neighbor;
}
-void ContentDrawQuadBase::ExtendValue(base::debug::TracedValue* value) const {
+void ContentDrawQuadBase::ExtendValue(
+ base::trace_event::TracedValue* value) const {
MathUtil::AddToTracedValue("tex_coord_rect", tex_coord_rect, value);
MathUtil::AddToTracedValue("texture_size", texture_size, value);
diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h
index 58aa727..8dcd2b9 100644
--- a/cc/quads/content_draw_quad_base.h
+++ b/cc/quads/content_draw_quad_base.h
@@ -45,7 +45,7 @@
protected:
ContentDrawQuadBase();
~ContentDrawQuadBase() override;
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/debug_border_draw_quad.cc b/cc/quads/debug_border_draw_quad.cc
index 43c7e6a..f91bf3b 100644
--- a/cc/quads/debug_border_draw_quad.cc
+++ b/cc/quads/debug_border_draw_quad.cc
@@ -50,7 +50,8 @@
return static_cast<const DebugBorderDrawQuad*>(quad);
}
-void DebugBorderDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void DebugBorderDrawQuad::ExtendValue(
+ base::trace_event::TracedValue* value) const {
value->SetInteger("color", color);
value->SetInteger("width", width);
}
diff --git a/cc/quads/debug_border_draw_quad.h b/cc/quads/debug_border_draw_quad.h
index a511ce1..7ee0d82 100644
--- a/cc/quads/debug_border_draw_quad.h
+++ b/cc/quads/debug_border_draw_quad.h
@@ -38,7 +38,7 @@
static const DebugBorderDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/draw_quad.cc b/cc/quads/draw_quad.cc
index 402dffe..8b8fd78 100644
--- a/cc/quads/draw_quad.cc
+++ b/cc/quads/draw_quad.cc
@@ -57,7 +57,7 @@
DrawQuad::~DrawQuad() {
}
-void DrawQuad::AsValueInto(base::debug::TracedValue* value) const {
+void DrawQuad::AsValueInto(base::trace_event::TracedValue* value) const {
value->SetInteger("material", material);
TracedValue::SetIDRef(shared_quad_state, value, "shared_state");
diff --git a/cc/quads/draw_quad.h b/cc/quads/draw_quad.h
index d9395cd..3897d1d 100644
--- a/cc/quads/draw_quad.h
+++ b/cc/quads/draw_quad.h
@@ -14,15 +14,9 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
-}
class Value;
class DictionaryValue;
-} // namespace base
+}
namespace cc {
@@ -132,7 +126,7 @@
return IsLeftEdge() || IsTopEdge() || IsRightEdge() || IsBottomEdge();
}
- void AsValueInto(base::debug::TracedValue* value) const;
+ void AsValueInto(base::trace_event::TracedValue* value) const;
protected:
DrawQuad();
@@ -143,7 +137,7 @@
const gfx::Rect& opaque_rect,
const gfx::Rect& visible_rect,
bool needs_blending);
- virtual void ExtendValue(base::debug::TracedValue* value) const = 0;
+ virtual void ExtendValue(base::trace_event::TracedValue* value) const = 0;
};
} // namespace cc
diff --git a/cc/quads/io_surface_draw_quad.cc b/cc/quads/io_surface_draw_quad.cc
index 0cc8773..8a37b0a 100644
--- a/cc/quads/io_surface_draw_quad.cc
+++ b/cc/quads/io_surface_draw_quad.cc
@@ -57,7 +57,8 @@
return static_cast<const IOSurfaceDrawQuad*>(quad);
}
-void IOSurfaceDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void IOSurfaceDrawQuad::ExtendValue(
+ base::trace_event::TracedValue* value) const {
MathUtil::AddToTracedValue("io_surface_size", io_surface_size, value);
value->SetInteger("io_surface_resource_id", io_surface_resource_id);
diff --git a/cc/quads/io_surface_draw_quad.h b/cc/quads/io_surface_draw_quad.h
index ba64384..2c77905 100644
--- a/cc/quads/io_surface_draw_quad.h
+++ b/cc/quads/io_surface_draw_quad.h
@@ -48,7 +48,7 @@
static const IOSurfaceDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/list_container_unittest.cc b/cc/quads/list_container_unittest.cc
index d41d8bd..de88750 100644
--- a/cc/quads/list_container_unittest.cc
+++ b/cc/quads/list_container_unittest.cc
@@ -34,7 +34,7 @@
void set_value(int val) { value = val; }
int get_value() { return value; }
- void ExtendValue(base::debug::TracedValue* value) const override {}
+ void ExtendValue(base::trace_event::TracedValue* value) const override {}
private:
int value;
@@ -58,7 +58,7 @@
public:
~MockDrawQuad() override { Destruct(); }
void IterateResources(const ResourceIteratorCallback& callback) override {}
- void ExtendValue(base::debug::TracedValue* value) const override {}
+ void ExtendValue(base::trace_event::TracedValue* value) const override {}
MOCK_METHOD0(Destruct, void());
};
diff --git a/cc/quads/picture_draw_quad.cc b/cc/quads/picture_draw_quad.cc
index f36a782..af6fba1 100644
--- a/cc/quads/picture_draw_quad.cc
+++ b/cc/quads/picture_draw_quad.cc
@@ -84,7 +84,7 @@
return static_cast<const PictureDrawQuad*>(quad);
}
-void PictureDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void PictureDrawQuad::ExtendValue(base::trace_event::TracedValue* value) const {
ContentDrawQuadBase::ExtendValue(value);
MathUtil::AddToTracedValue("content_rect", content_rect, value);
value->SetDouble("contents_scale", contents_scale);
diff --git a/cc/quads/picture_draw_quad.h b/cc/quads/picture_draw_quad.h
index 624b69c..31e5601 100644
--- a/cc/quads/picture_draw_quad.h
+++ b/cc/quads/picture_draw_quad.h
@@ -57,7 +57,7 @@
static const PictureDrawQuad* MaterialCast(const DrawQuad* quad);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc
index 2a6e69f..567145a 100644
--- a/cc/quads/render_pass.cc
+++ b/cc/quads/render_pass.cc
@@ -180,7 +180,7 @@
DCHECK(shared_quad_state_list.empty());
}
-void RenderPass::AsValueInto(base::debug::TracedValue* value) const {
+void RenderPass::AsValueInto(base::trace_event::TracedValue* value) const {
MathUtil::AddToTracedValue("output_rect", output_rect, value);
MathUtil::AddToTracedValue("damage_rect", damage_rect, value);
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 8a40f17..46a8084 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -24,13 +24,7 @@
class TracedValue;
}
class Value;
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
@@ -83,7 +77,7 @@
const gfx::Transform& transform_to_root_target,
bool has_transparent_background);
- void AsValueInto(base::debug::TracedValue* dict) const;
+ void AsValueInto(base::trace_event::TracedValue* dict) const;
SharedQuadState* CreateAndAppendSharedQuadState();
diff --git a/cc/quads/render_pass_draw_quad.cc b/cc/quads/render_pass_draw_quad.cc
index 41824c3..963a190 100644
--- a/cc/quads/render_pass_draw_quad.cc
+++ b/cc/quads/render_pass_draw_quad.cc
@@ -95,7 +95,8 @@
return static_cast<const RenderPassDrawQuad*>(quad);
}
-void RenderPassDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void RenderPassDrawQuad::ExtendValue(
+ base::trace_event::TracedValue* value) const {
TracedValue::SetIDRef(render_pass_id.AsTracingId(), value, "render_pass_id");
value->SetInteger("mask_resource_id", mask_resource_id);
MathUtil::AddToTracedValue("mask_texture_size", mask_texture_size, value);
diff --git a/cc/quads/render_pass_draw_quad.h b/cc/quads/render_pass_draw_quad.h
index 95ca2f2..758b8e8 100644
--- a/cc/quads/render_pass_draw_quad.h
+++ b/cc/quads/render_pass_draw_quad.h
@@ -70,7 +70,7 @@
static const RenderPassDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/shared_quad_state.cc b/cc/quads/shared_quad_state.cc
index 57670c6..5e46fcc 100644
--- a/cc/quads/shared_quad_state.cc
+++ b/cc/quads/shared_quad_state.cc
@@ -46,7 +46,7 @@
this->sorting_context_id = sorting_context_id;
}
-void SharedQuadState::AsValueInto(base::debug::TracedValue* value) const {
+void SharedQuadState::AsValueInto(base::trace_event::TracedValue* value) const {
MathUtil::AddToTracedValue("transform", content_to_target_transform, value);
MathUtil::AddToTracedValue("layer_content_bounds", content_bounds, value);
MathUtil::AddToTracedValue("layer_visible_content_rect", visible_content_rect,
diff --git a/cc/quads/shared_quad_state.h b/cc/quads/shared_quad_state.h
index 0db23e1..6f0ef92 100644
--- a/cc/quads/shared_quad_state.h
+++ b/cc/quads/shared_quad_state.h
@@ -16,13 +16,7 @@
class TracedValue;
}
class Value;
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
@@ -46,7 +40,7 @@
float opacity,
SkXfermode::Mode blend_mode,
int sorting_context_id);
- void AsValueInto(base::debug::TracedValue* dict) const;
+ void AsValueInto(base::trace_event::TracedValue* dict) const;
// Transforms from quad's original content space to its target content space.
gfx::Transform content_to_target_transform;
diff --git a/cc/quads/solid_color_draw_quad.cc b/cc/quads/solid_color_draw_quad.cc
index 8b856e0..229e98b 100644
--- a/cc/quads/solid_color_draw_quad.cc
+++ b/cc/quads/solid_color_draw_quad.cc
@@ -48,7 +48,8 @@
return static_cast<const SolidColorDrawQuad*>(quad);
}
-void SolidColorDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void SolidColorDrawQuad::ExtendValue(
+ base::trace_event::TracedValue* value) const {
value->SetInteger("color", color);
value->SetBoolean("force_anti_aliasing_off", force_anti_aliasing_off);
}
diff --git a/cc/quads/solid_color_draw_quad.h b/cc/quads/solid_color_draw_quad.h
index f70e5e3..f0f5f5a 100644
--- a/cc/quads/solid_color_draw_quad.h
+++ b/cc/quads/solid_color_draw_quad.h
@@ -38,7 +38,7 @@
static const SolidColorDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.cc b/cc/quads/stream_video_draw_quad.cc
index 3f12d39..fb6f728 100644
--- a/cc/quads/stream_video_draw_quad.cc
+++ b/cc/quads/stream_video_draw_quad.cc
@@ -50,7 +50,8 @@
return static_cast<const StreamVideoDrawQuad*>(quad);
}
-void StreamVideoDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void StreamVideoDrawQuad::ExtendValue(
+ base::trace_event::TracedValue* value) const {
value->SetInteger("resource_id", resource_id);
MathUtil::AddToTracedValue("matrix", matrix, value);
}
diff --git a/cc/quads/stream_video_draw_quad.h b/cc/quads/stream_video_draw_quad.h
index cdba60c..45c28f2 100644
--- a/cc/quads/stream_video_draw_quad.h
+++ b/cc/quads/stream_video_draw_quad.h
@@ -39,7 +39,7 @@
static const StreamVideoDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/surface_draw_quad.cc b/cc/quads/surface_draw_quad.cc
index 7ed193c..5823558 100644
--- a/cc/quads/surface_draw_quad.cc
+++ b/cc/quads/surface_draw_quad.cc
@@ -43,7 +43,7 @@
return static_cast<const SurfaceDrawQuad*>(quad);
}
-void SurfaceDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void SurfaceDrawQuad::ExtendValue(base::trace_event::TracedValue* value) const {
value->SetInteger("surface_id", surface_id.id);
}
diff --git a/cc/quads/surface_draw_quad.h b/cc/quads/surface_draw_quad.h
index bdf7838..36dc809 100644
--- a/cc/quads/surface_draw_quad.h
+++ b/cc/quads/surface_draw_quad.h
@@ -35,7 +35,7 @@
static const SurfaceDrawQuad* MaterialCast(const DrawQuad* quad);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/texture_draw_quad.cc b/cc/quads/texture_draw_quad.cc
index 4169090..318d4f8 100644
--- a/cc/quads/texture_draw_quad.cc
+++ b/cc/quads/texture_draw_quad.cc
@@ -91,7 +91,7 @@
return static_cast<const TextureDrawQuad*>(quad);
}
-void TextureDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void TextureDrawQuad::ExtendValue(base::trace_event::TracedValue* value) const {
value->SetInteger("resource_id", resource_id);
value->SetBoolean("premultiplied_alpha", premultiplied_alpha);
diff --git a/cc/quads/texture_draw_quad.h b/cc/quads/texture_draw_quad.h
index 990b276..afac6bf 100644
--- a/cc/quads/texture_draw_quad.h
+++ b/cc/quads/texture_draw_quad.h
@@ -57,7 +57,7 @@
static const TextureDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/tile_draw_quad.cc b/cc/quads/tile_draw_quad.cc
index 5d60bae..fbdae88 100644
--- a/cc/quads/tile_draw_quad.cc
+++ b/cc/quads/tile_draw_quad.cc
@@ -66,7 +66,7 @@
return static_cast<const TileDrawQuad*>(quad);
}
-void TileDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void TileDrawQuad::ExtendValue(base::trace_event::TracedValue* value) const {
ContentDrawQuadBase::ExtendValue(value);
value->SetInteger("resource_id", resource_id);
}
diff --git a/cc/quads/tile_draw_quad.h b/cc/quads/tile_draw_quad.h
index e668ddb..d7ef20a 100644
--- a/cc/quads/tile_draw_quad.h
+++ b/cc/quads/tile_draw_quad.h
@@ -42,7 +42,7 @@
static const TileDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/quads/yuv_video_draw_quad.cc b/cc/quads/yuv_video_draw_quad.cc
index 38b726d..1d0e2f3 100644
--- a/cc/quads/yuv_video_draw_quad.cc
+++ b/cc/quads/yuv_video_draw_quad.cc
@@ -79,7 +79,8 @@
return static_cast<const YUVVideoDrawQuad*>(quad);
}
-void YUVVideoDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+void YUVVideoDrawQuad::ExtendValue(
+ base::trace_event::TracedValue* value) const {
MathUtil::AddToTracedValue("tex_coord_rect", tex_coord_rect, value);
MathUtil::AddToTracedValue("tex_size", tex_size, value);
value->SetInteger("y_plane_resource_id", y_plane_resource_id);
diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
index 7ad0ba4..d57d56f 100644
--- a/cc/quads/yuv_video_draw_quad.h
+++ b/cc/quads/yuv_video_draw_quad.h
@@ -63,7 +63,7 @@
static const YUVVideoDrawQuad* MaterialCast(const DrawQuad*);
private:
- void ExtendValue(base::debug::TracedValue* value) const override;
+ void ExtendValue(base::trace_event::TracedValue* value) const override;
};
} // namespace cc
diff --git a/cc/resources/bitmap_tile_task_worker_pool.cc b/cc/resources/bitmap_tile_task_worker_pool.cc
index 77abd8d..1abbb46 100644
--- a/cc/resources/bitmap_tile_task_worker_pool.cc
+++ b/cc/resources/bitmap_tile_task_worker_pool.cc
@@ -191,10 +191,10 @@
client_->DidFinishRunningTileTasks(task_set);
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
BitmapTileTaskWorkerPool::StateAsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
state->BeginArray("tasks_pending");
for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
diff --git a/cc/resources/bitmap_tile_task_worker_pool.h b/cc/resources/bitmap_tile_task_worker_pool.h
index 20d57d2..3f03c2d 100644
--- a/cc/resources/bitmap_tile_task_worker_pool.h
+++ b/cc/resources/bitmap_tile_task_worker_pool.h
@@ -14,13 +14,7 @@
namespace trace_event {
class ConvertableToTraceFormat;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
}
-} // namespace base
namespace cc {
class ResourceProvider;
@@ -58,7 +52,8 @@
private:
void OnTaskSetFinished(TaskSet task_set);
- scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> StateAsValue()
+ const;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
TaskGraphRunner* task_graph_runner_;
diff --git a/cc/resources/clip_display_item.cc b/cc/resources/clip_display_item.cc
index 5a34dac..b124ba1 100644
--- a/cc/resources/clip_display_item.cc
+++ b/cc/resources/clip_display_item.cc
@@ -53,7 +53,7 @@
return total_size;
}
-void ClipDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void ClipDisplayItem::AsValueInto(base::trace_event::TracedValue* array) const {
std::string value = base::StringPrintf("ClipDisplayItem rect: [%s]",
clip_rect_.ToString().c_str());
for (const SkRRect& rounded_rect : rounded_clip_rects_) {
@@ -102,7 +102,8 @@
return 0;
}
-void EndClipDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void EndClipDisplayItem::AsValueInto(
+ base::trace_event::TracedValue* array) const {
array->AppendString("EndClipDisplayItem");
}
diff --git a/cc/resources/clip_display_item.h b/cc/resources/clip_display_item.h
index 70725f3..e5e72bf 100644
--- a/cc/resources/clip_display_item.h
+++ b/cc/resources/clip_display_item.h
@@ -33,7 +33,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
ClipDisplayItem(gfx::Rect clip_rect,
@@ -57,7 +57,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
EndClipDisplayItem();
diff --git a/cc/resources/clip_path_display_item.cc b/cc/resources/clip_path_display_item.cc
index 1600e55..275a7ef 100644
--- a/cc/resources/clip_path_display_item.cc
+++ b/cc/resources/clip_path_display_item.cc
@@ -38,7 +38,8 @@
return total_size;
}
-void ClipPathDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void ClipPathDisplayItem::AsValueInto(
+ base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("ClipPathDisplayItem length: %d",
clip_path_.countPoints()));
}
@@ -67,7 +68,7 @@
}
void EndClipPathDisplayItem::AsValueInto(
- base::debug::TracedValue* array) const {
+ base::trace_event::TracedValue* array) const {
array->AppendString("EndClipPathDisplayItem");
}
diff --git a/cc/resources/clip_path_display_item.h b/cc/resources/clip_path_display_item.h
index b9fa01b..a3f8e0d 100644
--- a/cc/resources/clip_path_display_item.h
+++ b/cc/resources/clip_path_display_item.h
@@ -31,7 +31,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
ClipPathDisplayItem(const SkPath& path, SkRegion::Op clip_op, bool antialias);
@@ -55,7 +55,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
EndClipPathDisplayItem();
diff --git a/cc/resources/display_item.h b/cc/resources/display_item.h
index b2c4054..ba4e733 100644
--- a/cc/resources/display_item.h
+++ b/cc/resources/display_item.h
@@ -26,7 +26,7 @@
virtual bool IsSuitableForGpuRasterization() const = 0;
virtual int ApproximateOpCount() const = 0;
virtual size_t PictureMemoryUsage() const = 0;
- virtual void AsValueInto(base::debug::TracedValue* array) const = 0;
+ virtual void AsValueInto(base::trace_event::TracedValue* array) const = 0;
protected:
DisplayItem();
diff --git a/cc/resources/display_item_list.cc b/cc/resources/display_item_list.cc
index 7a6929a..ac6ab57 100644
--- a/cc/resources/display_item_list.cc
+++ b/cc/resources/display_item_list.cc
@@ -65,10 +65,10 @@
return total_size;
}
-scoped_refptr<base::debug::ConvertableToTraceFormat> DisplayItemList::AsValue()
- const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+DisplayItemList::AsValue() const {
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
state->SetInteger("length", items_.size());
state->BeginArray("params.items");
diff --git a/cc/resources/display_item_list.h b/cc/resources/display_item_list.h
index 2147848..e16b8b8 100644
--- a/cc/resources/display_item_list.h
+++ b/cc/resources/display_item_list.h
@@ -36,7 +36,7 @@
int ApproximateOpCount() const;
size_t PictureMemoryUsage() const;
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
void EmitTraceSnapshot() const;
diff --git a/cc/resources/display_item_list_unittest.cc b/cc/resources/display_item_list_unittest.cc
index d6455a2..ddf2cb7 100644
--- a/cc/resources/display_item_list_unittest.cc
+++ b/cc/resources/display_item_list_unittest.cc
@@ -6,8 +6,11 @@
#include <vector>
+#include "cc/output/filter_operation.h"
+#include "cc/output/filter_operations.h"
#include "cc/resources/clip_display_item.h"
#include "cc/resources/drawing_display_item.h"
+#include "cc/resources/filter_display_item.h"
#include "cc/resources/transform_display_item.h"
#include "cc/test/skia_common.h"
#include "skia/ext/refptr.h"
@@ -16,6 +19,7 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/effects/SkBitmapSource.h"
#include "ui/gfx/skia_util.h"
namespace cc {
@@ -162,5 +166,50 @@
EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100));
}
+TEST(DisplayItemList, FilterItem) {
+ gfx::Rect layer_rect(100, 100);
+ FilterOperations filters;
+ unsigned char pixels[4 * 100 * 100] = {0};
+ scoped_refptr<DisplayItemList> list = DisplayItemList::Create();
+
+ SkBitmap source_bitmap;
+ source_bitmap.allocN32Pixels(50, 50);
+ SkCanvas source_canvas(source_bitmap);
+ source_canvas.clear(SkColorSetRGB(128, 128, 128));
+
+ // For most SkImageFilters, the |dst| bounds computed by computeFastBounds are
+ // dependent on the provided |src| bounds. This means, for example, that
+ // translating |src| results in a corresponding translation of |dst|. But this
+ // is not the case for all SkImageFilters; for some of them (e.g.
+ // SkBitmapSource), the computation of |dst| in computeFastBounds doesn't
+ // involve |src| at all. Incorrectly assuming such a relationship (e.g. by
+ // translating |dst| after it is computed by computeFastBounds, rather than
+ // translating |src| before it provided to computedFastBounds) can cause
+ // incorrect clipping of filter output. To test for this, we include an
+ // SkBitmapSource filter in |filters|. Here, |src| is |filter_bounds|, defined
+ // below.
+ skia::RefPtr<SkImageFilter> image_filter =
+ skia::AdoptRef(SkBitmapSource::Create(source_bitmap));
+ filters.Append(FilterOperation::CreateReferenceFilter(image_filter));
+ filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
+ gfx::RectF filter_bounds(10.f, 10.f, 50.f, 50.f);
+ list->AppendItem(FilterDisplayItem::Create(filters, filter_bounds));
+ list->AppendItem(EndFilterDisplayItem::Create());
+
+ DrawDisplayList(pixels, layer_rect, list);
+
+ SkBitmap expected_bitmap;
+ unsigned char expected_pixels[4 * 100 * 100] = {0};
+ SkPaint paint;
+ paint.setColor(SkColorSetRGB(64, 64, 64));
+ SkImageInfo info =
+ SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
+ expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
+ SkCanvas expected_canvas(expected_bitmap);
+ expected_canvas.drawRect(RectFToSkRect(filter_bounds), paint);
+
+ EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100));
+}
+
} // namespace
} // namespace cc
diff --git a/cc/resources/display_list_raster_source.cc b/cc/resources/display_list_raster_source.cc
index 8ae2918..4479a16 100644
--- a/cc/resources/display_list_raster_source.cc
+++ b/cc/resources/display_list_raster_source.cc
@@ -50,8 +50,8 @@
DisplayListRasterSource::DisplayListRasterSource(
const DisplayListRecordingSource* other)
: display_list_(other->display_list_),
- background_color_(SK_ColorTRANSPARENT),
- requires_clear_(true),
+ background_color_(other->background_color_),
+ requires_clear_(other->requires_clear_),
can_use_lcd_text_(other->can_use_lcd_text_),
is_solid_color_(other->is_solid_color_),
solid_color_(other->solid_color_),
@@ -178,20 +178,12 @@
should_attempt_to_use_distance_field_text_ = true;
}
-void DisplayListRasterSource::SetBackgoundColor(SkColor background_color) {
- background_color_ = background_color;
-}
-
-void DisplayListRasterSource::SetRequiresClear(bool requires_clear) {
- requires_clear_ = requires_clear;
-}
-
bool DisplayListRasterSource::ShouldAttemptToUseDistanceFieldText() const {
return should_attempt_to_use_distance_field_text_;
}
void DisplayListRasterSource::AsValueInto(
- base::debug::TracedValue* array) const {
+ base::trace_event::TracedValue* array) const {
if (display_list_.get())
TracedValue::AppendIDRef(display_list_.get(), array);
}
diff --git a/cc/resources/display_list_raster_source.h b/cc/resources/display_list_raster_source.h
index 8f1fd12..f095231 100644
--- a/cc/resources/display_list_raster_source.h
+++ b/cc/resources/display_list_raster_source.h
@@ -46,11 +46,9 @@
float contents_scale) const override;
bool HasRecordings() const override;
void SetShouldAttemptToUseDistanceFieldText() override;
- void SetBackgoundColor(SkColor background_color) override;
- void SetRequiresClear(bool requires_clear) override;
bool ShouldAttemptToUseDistanceFieldText() const override;
void DidBeginTracing() override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
skia::RefPtr<SkPicture> GetFlattenedPicture() override;
size_t GetPictureMemoryUsage() const override;
bool CanUseLCDText() const override;
@@ -60,16 +58,21 @@
explicit DisplayListRasterSource(const DisplayListRecordingSource* other);
~DisplayListRasterSource() override;
- scoped_refptr<DisplayItemList> display_list_;
- SkColor background_color_;
- bool requires_clear_;
- bool can_use_lcd_text_;
- bool is_solid_color_;
- SkColor solid_color_;
- gfx::Rect recorded_viewport_;
- gfx::Size size_;
- bool clear_canvas_with_debug_color_;
- int slow_down_raster_scale_factor_for_debug_;
+ // These members are const as this raster source may be in use on another
+ // thread and so should not be touched after construction.
+ const scoped_refptr<DisplayItemList> display_list_;
+ const SkColor background_color_;
+ const bool requires_clear_;
+ const bool can_use_lcd_text_;
+ const bool is_solid_color_;
+ const SkColor solid_color_;
+ const gfx::Rect recorded_viewport_;
+ const gfx::Size size_;
+ const bool clear_canvas_with_debug_color_;
+ const int slow_down_raster_scale_factor_for_debug_;
+ // TODO(enne/vmiura): this has a read/write race between raster and compositor
+ // threads with multi-threaded Ganesh. Make this const or remove it.
+ bool should_attempt_to_use_distance_field_text_;
private:
// Called when analyzing a tile. We can use AnalysisCanvas as
@@ -84,8 +87,6 @@
float contents_scale,
bool is_analysis) const;
- bool should_attempt_to_use_distance_field_text_;
-
DISALLOW_COPY_AND_ASSIGN(DisplayListRasterSource);
};
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc
index e60e4c1..01a3bce 100644
--- a/cc/resources/display_list_recording_source.cc
+++ b/cc/resources/display_list_recording_source.cc
@@ -29,8 +29,10 @@
DisplayListRecordingSource::DisplayListRecordingSource()
: slow_down_raster_scale_factor_for_debug_(0),
can_use_lcd_text_(true),
+ requires_clear_(false),
is_solid_color_(false),
solid_color_(SK_ColorTRANSPARENT),
+ background_color_(SK_ColorTRANSPARENT),
pixel_record_distance_(kPixelDistanceToRecord),
is_suitable_for_gpu_rasterization_(true) {
}
@@ -60,10 +62,9 @@
}
gfx::Rect old_recorded_viewport = recorded_viewport_;
- // TODO(wangxianzhu): Blink slimming paint doesn't support incremental
- // painting for now so we must record for the whole layer. Should measure
- // performance and determine the best choice. Consider display item caching.
- recorded_viewport_ = gfx::Rect(GetSize());
+ recorded_viewport_ = visible_layer_rect;
+ recorded_viewport_.Inset(-pixel_record_distance_, -pixel_record_distance_);
+ recorded_viewport_.Intersect(gfx::Rect(GetSize()));
if (recorded_viewport_ != old_recorded_viewport) {
// Invalidate newly-exposed and no-longer-exposed areas.
@@ -135,6 +136,14 @@
slow_down_raster_scale_factor_for_debug_ = factor;
}
+void DisplayListRecordingSource::SetBackgroundColor(SkColor background_color) {
+ background_color_ = background_color;
+}
+
+void DisplayListRecordingSource::SetRequiresClear(bool requires_clear) {
+ requires_clear_ = requires_clear;
+}
+
void DisplayListRecordingSource::SetUnsuitableForGpuRasterizationForTesting() {
is_suitable_for_gpu_rasterization_ = false;
}
diff --git a/cc/resources/display_list_recording_source.h b/cc/resources/display_list_recording_source.h
index 05e2ed7..21a24fb 100644
--- a/cc/resources/display_list_recording_source.h
+++ b/cc/resources/display_list_recording_source.h
@@ -29,6 +29,8 @@
gfx::Size GetSize() const final;
void SetEmptyBounds() override;
void SetSlowdownRasterScaleFactor(int factor) override;
+ void SetBackgroundColor(SkColor background_color) override;
+ void SetRequiresClear(bool requires_clear) override;
bool IsSuitableForGpuRasterization() const override;
void SetUnsuitableForGpuRasterizationForTesting() override;
gfx::Size GetTileGridSizeForTesting() const override;
@@ -40,8 +42,10 @@
gfx::Size size_;
int slow_down_raster_scale_factor_for_debug_;
bool can_use_lcd_text_;
+ bool requires_clear_;
bool is_solid_color_;
SkColor solid_color_;
+ SkColor background_color_;
int pixel_record_distance_;
scoped_refptr<DisplayItemList> display_list_;
diff --git a/cc/resources/drawing_display_item.cc b/cc/resources/drawing_display_item.cc
index 351fade..1ef149f 100644
--- a/cc/resources/drawing_display_item.cc
+++ b/cc/resources/drawing_display_item.cc
@@ -62,7 +62,8 @@
return SkPictureUtils::ApproximateBytesUsed(picture_.get());
}
-void DrawingDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void DrawingDisplayItem::AsValueInto(
+ base::trace_event::TracedValue* array) const {
array->BeginDictionary();
array->SetString("name", "DrawingDisplayItem");
array->SetString("location",
diff --git a/cc/resources/drawing_display_item.h b/cc/resources/drawing_display_item.h
index 49aa762..1f63ed3 100644
--- a/cc/resources/drawing_display_item.h
+++ b/cc/resources/drawing_display_item.h
@@ -32,7 +32,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
DrawingDisplayItem(skia::RefPtr<SkPicture> picture, gfx::PointF location);
diff --git a/cc/resources/eviction_tile_priority_queue.cc b/cc/resources/eviction_tile_priority_queue.cc
index b1ca48d..503b26d 100644
--- a/cc/resources/eviction_tile_priority_queue.cc
+++ b/cc/resources/eviction_tile_priority_queue.cc
@@ -22,21 +22,19 @@
if (a->IsEmpty() || b->IsEmpty())
return b->IsEmpty() < a->IsEmpty();
- WhichTree a_tree = a->NextTileIteratorTree(tree_priority_);
+ WhichTree a_tree = a->NextTileIteratorTree();
const TilingSetEvictionQueue* a_queue =
a_tree == ACTIVE_TREE ? a->active_queue.get() : a->pending_queue.get();
- WhichTree b_tree = b->NextTileIteratorTree(tree_priority_);
+ WhichTree b_tree = b->NextTileIteratorTree();
const TilingSetEvictionQueue* b_queue =
b_tree == ACTIVE_TREE ? b->active_queue.get() : b->pending_queue.get();
const Tile* a_tile = a_queue->Top();
const Tile* b_tile = b_queue->Top();
- const TilePriority& a_priority =
- a_tile->priority_for_tree_priority(tree_priority_);
- const TilePriority& b_priority =
- b_tile->priority_for_tree_priority(tree_priority_);
+ const TilePriority& a_priority = a_tile->combined_priority();
+ const TilePriority& b_priority = b_tile->combined_priority();
bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY;
// If the priority bin differs, b is lower priority if it has the higher
@@ -63,8 +61,8 @@
// Otherwise if the occlusion differs, b is lower priority if it is
// occluded.
- bool a_is_occluded = a_tile->is_occluded_for_tree_priority(tree_priority_);
- bool b_is_occluded = b_tile->is_occluded_for_tree_priority(tree_priority_);
+ bool a_is_occluded = a_tile->is_occluded_combined();
+ bool b_is_occluded = b_tile->is_occluded_combined();
if (a_is_occluded != b_is_occluded)
return b_is_occluded;
@@ -106,7 +104,7 @@
Tile* EvictionTilePriorityQueue::Top() {
DCHECK(!IsEmpty());
- return paired_queues_.front()->Top(tree_priority_);
+ return paired_queues_.front()->Top();
}
void EvictionTilePriorityQueue::Pop() {
@@ -114,7 +112,7 @@
paired_queues_.pop_heap(EvictionOrderComparator(tree_priority_));
PairedTilingSetQueue* paired_queue = paired_queues_.back();
- paired_queue->Pop(tree_priority_);
+ paired_queue->Pop();
paired_queues_.push_heap(EvictionOrderComparator(tree_priority_));
}
@@ -145,11 +143,10 @@
(!pending_queue || pending_queue->IsEmpty());
}
-Tile* EvictionTilePriorityQueue::PairedTilingSetQueue::Top(
- TreePriority tree_priority) {
+Tile* EvictionTilePriorityQueue::PairedTilingSetQueue::Top() {
DCHECK(!IsEmpty());
- WhichTree next_tree = NextTileIteratorTree(tree_priority);
+ WhichTree next_tree = NextTileIteratorTree();
TilingSetEvictionQueue* next_queue =
next_tree == ACTIVE_TREE ? active_queue.get() : pending_queue.get();
DCHECK(next_queue && !next_queue->IsEmpty());
@@ -159,11 +156,10 @@
return tile;
}
-void EvictionTilePriorityQueue::PairedTilingSetQueue::Pop(
- TreePriority tree_priority) {
+void EvictionTilePriorityQueue::PairedTilingSetQueue::Pop() {
DCHECK(!IsEmpty());
- WhichTree next_tree = NextTileIteratorTree(tree_priority);
+ WhichTree next_tree = NextTileIteratorTree();
TilingSetEvictionQueue* next_queue =
next_tree == ACTIVE_TREE ? active_queue.get() : pending_queue.get();
DCHECK(next_queue && !next_queue->IsEmpty());
@@ -171,12 +167,11 @@
next_queue->Pop();
// If not empty, use Top to DCHECK the next iterator.
- DCHECK_IMPLIES(!IsEmpty(), Top(tree_priority));
+ DCHECK_IMPLIES(!IsEmpty(), Top());
}
WhichTree
-EvictionTilePriorityQueue::PairedTilingSetQueue::NextTileIteratorTree(
- TreePriority tree_priority) const {
+EvictionTilePriorityQueue::PairedTilingSetQueue::NextTileIteratorTree() const {
DCHECK(!IsEmpty());
// If we only have one iterator with tiles, return it.
@@ -192,10 +187,8 @@
if (active_tile == pending_tile)
return ACTIVE_TREE;
- const TilePriority& active_priority =
- active_tile->priority_for_tree_priority(tree_priority);
- const TilePriority& pending_priority =
- pending_tile->priority_for_tree_priority(tree_priority);
+ const TilePriority& active_priority = active_tile->combined_priority();
+ const TilePriority& pending_priority = pending_tile->combined_priority();
// If the bins are the same and activation differs, then return the tree of
// the tile not required for activation.
diff --git a/cc/resources/eviction_tile_priority_queue.h b/cc/resources/eviction_tile_priority_queue.h
index ab705f7..32ea9af 100644
--- a/cc/resources/eviction_tile_priority_queue.h
+++ b/cc/resources/eviction_tile_priority_queue.h
@@ -25,10 +25,10 @@
~PairedTilingSetQueue();
bool IsEmpty() const;
- Tile* Top(TreePriority tree_priority);
- void Pop(TreePriority tree_priority);
+ Tile* Top();
+ void Pop();
- WhichTree NextTileIteratorTree(TreePriority tree_priority) const;
+ WhichTree NextTileIteratorTree() const;
scoped_ptr<TilingSetEvictionQueue> active_queue;
scoped_ptr<TilingSetEvictionQueue> pending_queue;
diff --git a/cc/resources/filter_display_item.cc b/cc/resources/filter_display_item.cc
index bfdd425..31abf28 100644
--- a/cc/resources/filter_display_item.cc
+++ b/cc/resources/filter_display_item.cc
@@ -6,6 +6,8 @@
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event_argument.h"
+#include "cc/output/render_surface_filters.h"
+#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/core/SkPaint.h"
@@ -14,9 +16,9 @@
namespace cc {
-FilterDisplayItem::FilterDisplayItem(skia::RefPtr<SkImageFilter> filter,
+FilterDisplayItem::FilterDisplayItem(const FilterOperations& filters,
gfx::RectF bounds)
- : filter_(filter), bounds_(bounds) {
+ : filters_(filters), bounds_(bounds) {
}
FilterDisplayItem::~FilterDisplayItem() {
@@ -25,14 +27,18 @@
void FilterDisplayItem::Raster(SkCanvas* canvas,
SkDrawPictureCallback* callback) const {
canvas->save();
- SkRect boundaries;
- filter_->computeFastBounds(gfx::RectFToSkRect(bounds_), &boundaries);
canvas->translate(bounds_.x(), bounds_.y());
- boundaries.offset(-bounds_.x(), -bounds_.y());
+
+ skia::RefPtr<SkImageFilter> image_filter =
+ RenderSurfaceFilters::BuildImageFilter(
+ filters_, gfx::SizeF(bounds_.width(), bounds_.height()));
+ SkRect boundaries;
+ image_filter->computeFastBounds(
+ SkRect::MakeWH(bounds_.width(), bounds_.height()), &boundaries);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
- paint.setImageFilter(filter_.get());
+ paint.setImageFilter(image_filter.get());
canvas->saveLayer(&boundaries, &paint);
canvas->translate(-bounds_.x(), -bounds_.y());
@@ -50,7 +56,8 @@
return sizeof(skia::RefPtr<SkImageFilter>) + sizeof(gfx::RectF);
}
-void FilterDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void FilterDisplayItem::AsValueInto(
+ base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("FilterDisplayItem bounds: [%s]",
bounds_.ToString().c_str()));
}
@@ -79,7 +86,8 @@
return 0;
}
-void EndFilterDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void EndFilterDisplayItem::AsValueInto(
+ base::trace_event::TracedValue* array) const {
array->AppendString("EndFilterDisplayItem");
}
diff --git a/cc/resources/filter_display_item.h b/cc/resources/filter_display_item.h
index 958647b..28eeb95 100644
--- a/cc/resources/filter_display_item.h
+++ b/cc/resources/filter_display_item.h
@@ -7,13 +7,12 @@
#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
+#include "cc/output/filter_operations.h"
#include "cc/resources/display_item.h"
-#include "skia/ext/refptr.h"
#include "ui/gfx/geometry/rect_f.h"
class SkCanvas;
class SkDrawPictureCallback;
-class SkImageFilter;
namespace cc {
@@ -21,10 +20,9 @@
public:
~FilterDisplayItem() override;
- static scoped_ptr<FilterDisplayItem> Create(
- skia::RefPtr<SkImageFilter> filter,
- gfx::RectF bounds) {
- return make_scoped_ptr(new FilterDisplayItem(filter, bounds));
+ static scoped_ptr<FilterDisplayItem> Create(const FilterOperations& filters,
+ gfx::RectF bounds) {
+ return make_scoped_ptr(new FilterDisplayItem(filters, bounds));
}
void Raster(SkCanvas* canvas, SkDrawPictureCallback* callback) const override;
@@ -32,13 +30,13 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
- FilterDisplayItem(skia::RefPtr<SkImageFilter> filter, gfx::RectF bounds);
+ FilterDisplayItem(const FilterOperations& filters, gfx::RectF bounds);
private:
- skia::RefPtr<SkImageFilter> filter_;
+ FilterOperations filters_;
gfx::RectF bounds_;
};
@@ -55,7 +53,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
EndFilterDisplayItem();
diff --git a/cc/resources/float_clip_display_item.cc b/cc/resources/float_clip_display_item.cc
index 0cfe463..ba98fe5 100644
--- a/cc/resources/float_clip_display_item.cc
+++ b/cc/resources/float_clip_display_item.cc
@@ -36,7 +36,8 @@
return sizeof(gfx::RectF);
}
-void FloatClipDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void FloatClipDisplayItem::AsValueInto(
+ base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("FloatClipDisplayItem rect: [%s]",
clip_rect_.ToString().c_str()));
}
@@ -65,7 +66,7 @@
}
void EndFloatClipDisplayItem::AsValueInto(
- base::debug::TracedValue* array) const {
+ base::trace_event::TracedValue* array) const {
array->AppendString("EndFloatClipDisplayItem");
}
diff --git a/cc/resources/float_clip_display_item.h b/cc/resources/float_clip_display_item.h
index c9920f2..af88c50 100644
--- a/cc/resources/float_clip_display_item.h
+++ b/cc/resources/float_clip_display_item.h
@@ -30,7 +30,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
explicit FloatClipDisplayItem(gfx::RectF clip_rect);
@@ -52,7 +52,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
EndFloatClipDisplayItem();
diff --git a/cc/resources/gpu_rasterizer.cc b/cc/resources/gpu_rasterizer.cc
index 369f12c..e0097f8 100644
--- a/cc/resources/gpu_rasterizer.cc
+++ b/cc/resources/gpu_rasterizer.cc
@@ -43,19 +43,25 @@
bool use_distance_field_text,
bool threaded_gpu_rasterization_enabled,
int msaa_sample_count)
- : context_provider_(context_provider),
- resource_provider_(resource_provider),
+ : resource_provider_(resource_provider),
use_distance_field_text_(use_distance_field_text),
threaded_gpu_rasterization_enabled_(threaded_gpu_rasterization_enabled),
msaa_sample_count_(msaa_sample_count) {
- DCHECK(context_provider_);
}
GpuRasterizer::~GpuRasterizer() {
}
PrepareTilesMode GpuRasterizer::GetPrepareTilesMode() {
- return PrepareTilesMode::PREPARE_NONE;
+ return threaded_gpu_rasterization_enabled_
+ ? PrepareTilesMode::RASTERIZE_PRIORITIZED_TILES
+ : PrepareTilesMode::PREPARE_NONE;
+}
+
+ContextProvider* GpuRasterizer::GetContextProvider(bool worker_context) {
+ return worker_context
+ ? resource_provider_->output_surface()->worker_context_provider()
+ : resource_provider_->output_surface()->context_provider();
}
void GpuRasterizer::RasterizeTiles(
@@ -63,7 +69,7 @@
ResourcePool* resource_pool,
ResourceFormat resource_format,
const UpdateTileDrawInfoCallback& update_tile_draw_info) {
- ScopedGpuRaster gpu_raster(context_provider_);
+ ScopedGpuRaster gpu_raster(GetContextProvider(false));
ScopedResourceWriteLocks locks;
@@ -86,6 +92,42 @@
multi_picture_draw_.draw(msaa_sample_count_ > 0);
}
+void GpuRasterizer::RasterizeSource(
+ bool use_worker_context,
+ ResourceProvider::ScopedWriteLockGr* write_lock,
+ const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) {
+ // Play back raster_source into temp SkPicture.
+ SkPictureRecorder recorder;
+ gfx::Size size = write_lock->resource()->size;
+ const int flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag;
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(
+ recorder.beginRecording(size.width(), size.height(), NULL, flags));
+ canvas->save();
+ raster_source->PlaybackToCanvas(canvas.get(), rect, scale);
+ canvas->restore();
+ skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording());
+
+ // Turn on distance fields for layers that have ever animated.
+ bool use_distance_field_text =
+ use_distance_field_text_ ||
+ raster_source->ShouldAttemptToUseDistanceFieldText();
+
+ // Playback picture into resource.
+ {
+ ScopedGpuRaster gpu_raster(GetContextProvider(use_worker_context));
+ write_lock->InitSkSurface(use_worker_context, use_distance_field_text,
+ raster_source->CanUseLCDText(),
+ msaa_sample_count_);
+ SkMultiPictureDraw multi_picture_draw;
+ multi_picture_draw.add(write_lock->sk_surface()->getCanvas(),
+ picture.get());
+ multi_picture_draw.draw(false);
+ write_lock->ReleaseSkSurface();
+ }
+}
+
void GpuRasterizer::PerformSolidColorAnalysis(
const Tile* tile,
RasterSource::SolidColorAnalysis* analysis) {
@@ -119,11 +161,14 @@
use_distance_field_text_ ||
tile->raster_source()->ShouldAttemptToUseDistanceFieldText();
scoped_ptr<ResourceProvider::ScopedWriteLockGr> lock(
- new ResourceProvider::ScopedWriteLockGr(
- resource_provider_, resource->id(), use_distance_field_text,
- tile->raster_source()->CanUseLCDText(), msaa_sample_count_));
+ new ResourceProvider::ScopedWriteLockGr(resource_provider_,
+ resource->id()));
- SkSurface* sk_surface = lock->get_sk_surface();
+ lock->InitSkSurface(false, use_distance_field_text,
+ tile->raster_source()->CanUseLCDText(),
+ msaa_sample_count_);
+
+ SkSurface* sk_surface = lock->sk_surface();
if (!sk_surface)
return;
diff --git a/cc/resources/gpu_rasterizer.h b/cc/resources/gpu_rasterizer.h
index 79a0596..8c75f32 100644
--- a/cc/resources/gpu_rasterizer.h
+++ b/cc/resources/gpu_rasterizer.h
@@ -28,6 +28,8 @@
bool use_distance_field_text,
bool threaded_gpu_rasterization_enabled,
int msaa_sample_count);
+
+ // Overriden from Rasterizer.
PrepareTilesMode GetPrepareTilesMode() override;
void RasterizeTiles(
const TileVector& tiles,
@@ -35,6 +37,14 @@
ResourceFormat resource_format,
const UpdateTileDrawInfoCallback& update_tile_draw_info) override;
+ void RasterizeSource(bool use_worker_context,
+ ResourceProvider::ScopedWriteLockGr* write_lock,
+ const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale);
+
+ ResourceProvider* resource_provider() { return resource_provider_; }
+
private:
GpuRasterizer(ContextProvider* context_provider,
ResourceProvider* resource_provider,
@@ -45,13 +55,13 @@
using ScopedResourceWriteLocks =
ScopedPtrVector<ResourceProvider::ScopedWriteLockGr>;
+ ContextProvider* GetContextProvider(bool worker_context);
void PerformSolidColorAnalysis(const Tile* tile,
RasterSource::SolidColorAnalysis* analysis);
void AddToMultiPictureDraw(const Tile* tile,
const ScopedResource* resource,
ScopedResourceWriteLocks* locks);
- ContextProvider* context_provider_;
ResourceProvider* resource_provider_;
SkMultiPictureDraw multi_picture_draw_;
diff --git a/cc/resources/gpu_tile_task_worker_pool.cc b/cc/resources/gpu_tile_task_worker_pool.cc
index 8249457..c57d25a 100644
--- a/cc/resources/gpu_tile_task_worker_pool.cc
+++ b/cc/resources/gpu_tile_task_worker_pool.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/trace_event/trace_event.h"
+#include "cc/resources/gpu_rasterizer.h"
#include "cc/resources/raster_buffer.h"
#include "cc/resources/raster_source.h"
#include "cc/resources/resource.h"
@@ -22,39 +23,64 @@
class RasterBufferImpl : public RasterBuffer {
public:
- RasterBufferImpl() {}
+ RasterBufferImpl(GpuRasterizer* rasterizer, const Resource* resource)
+ : rasterizer_(rasterizer),
+ lock_(rasterizer->resource_provider(), resource->id()),
+ resource_(resource) {}
// Overridden from RasterBuffer:
void Playback(const RasterSource* raster_source,
const gfx::Rect& rect,
float scale) override {
- // Don't do anything.
+ TRACE_EVENT0("cc", "RasterBufferImpl::Playback");
+ ContextProvider* context_provider = rasterizer_->resource_provider()
+ ->output_surface()
+ ->worker_context_provider();
+
+ // The context lock must be held while accessing the context on a
+ // worker thread.
+ base::AutoLock context_lock(*context_provider->GetLock());
+
+ // Allow this worker thread to bind to context_provider.
+ context_provider->DetachFromThread();
+
+ // Rasterize source into resource.
+ rasterizer_->RasterizeSource(true, &lock_, raster_source, rect, scale);
+
+ // Barrier to sync worker context output to cc context.
+ context_provider->ContextGL()->OrderingBarrierCHROMIUM();
+
+ // Allow compositor thread to bind to context_provider.
+ context_provider->DetachFromThread();
}
private:
+ GpuRasterizer* rasterizer_;
+ ResourceProvider::ScopedWriteLockGr lock_;
+ const Resource* resource_;
+
DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl);
};
} // namespace
+
// static
scoped_ptr<TileTaskWorkerPool> GpuTileTaskWorkerPool::Create(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider) {
+ GpuRasterizer* rasterizer) {
return make_scoped_ptr<TileTaskWorkerPool>(
- new GpuTileTaskWorkerPool(
- task_runner, task_graph_runner, resource_provider));
+ new GpuTileTaskWorkerPool(task_runner, task_graph_runner, rasterizer));
}
-// TODO(hendrikw): This class should be removed. See crbug.com/444938.
GpuTileTaskWorkerPool::GpuTileTaskWorkerPool(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider)
+ GpuRasterizer* rasterizer)
: task_runner_(task_runner),
task_graph_runner_(task_graph_runner),
namespace_token_(task_graph_runner_->GetNamespaceToken()),
- resource_provider_(resource_provider),
+ rasterizer_(rasterizer),
task_set_finished_weak_ptr_factory_(this),
weak_ptr_factory_(this) {
}
@@ -129,6 +155,14 @@
}
ScheduleTasksOnOriginThread(this, &graph_);
+
+ // Barrier to sync any new resources to the worker context.
+ rasterizer_->resource_provider()
+ ->output_surface()
+ ->context_provider()
+ ->ContextGL()
+ ->OrderingBarrierCHROMIUM();
+
task_graph_runner_->ScheduleTasks(namespace_token_, &graph_);
std::copy(new_task_set_finished_tasks,
@@ -146,7 +180,7 @@
}
ResourceFormat GpuTileTaskWorkerPool::GetResourceFormat() {
- return resource_provider_->best_texture_format();
+ return rasterizer_->resource_provider()->best_texture_format();
}
void GpuTileTaskWorkerPool::CompleteTasks(const Task::Vector& tasks) {
@@ -164,7 +198,8 @@
scoped_ptr<RasterBuffer> GpuTileTaskWorkerPool::AcquireBufferForRaster(
const Resource* resource) {
- return make_scoped_ptr<RasterBuffer>(new RasterBufferImpl());
+ return make_scoped_ptr<RasterBuffer>(
+ new RasterBufferImpl(rasterizer_, resource));
}
void GpuTileTaskWorkerPool::ReleaseBufferForRaster(
diff --git a/cc/resources/gpu_tile_task_worker_pool.h b/cc/resources/gpu_tile_task_worker_pool.h
index 6ac8548..5941852 100644
--- a/cc/resources/gpu_tile_task_worker_pool.h
+++ b/cc/resources/gpu_tile_task_worker_pool.h
@@ -10,7 +10,7 @@
#include "cc/resources/tile_task_worker_pool.h"
namespace cc {
-class ResourceProvider;
+class GpuRasterizer;
class CC_EXPORT GpuTileTaskWorkerPool : public TileTaskWorkerPool,
public TileTaskRunner,
@@ -21,7 +21,7 @@
static scoped_ptr<TileTaskWorkerPool> Create(
base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider);
+ GpuRasterizer* rasterizer);
// Overridden from TileTaskWorkerPool:
TileTaskRunner* AsTileTaskRunner() override;
@@ -41,7 +41,7 @@
private:
GpuTileTaskWorkerPool(base::SequencedTaskRunner* task_runner,
TaskGraphRunner* task_graph_runner,
- ResourceProvider* resource_provider);
+ GpuRasterizer* rasterizer);
void OnTaskSetFinished(TaskSet task_set);
void CompleteTasks(const Task::Vector& tasks);
@@ -50,7 +50,7 @@
TaskGraphRunner* task_graph_runner_;
const NamespaceToken namespace_token_;
TileTaskRunnerClient* client_;
- ResourceProvider* resource_provider_;
+ GpuRasterizer* rasterizer_;
TaskSetCollection tasks_pending_;
diff --git a/cc/resources/one_copy_tile_task_worker_pool.cc b/cc/resources/one_copy_tile_task_worker_pool.cc
index 23c9538..cee568a 100644
--- a/cc/resources/one_copy_tile_task_worker_pool.cc
+++ b/cc/resources/one_copy_tile_task_worker_pool.cc
@@ -467,10 +467,10 @@
}
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
OneCopyTileTaskWorkerPool::StateAsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
state->BeginArray("tasks_pending");
for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
@@ -484,7 +484,7 @@
}
void OneCopyTileTaskWorkerPool::StagingStateAsValueInto(
- base::debug::TracedValue* staging_state) const {
+ base::trace_event::TracedValue* staging_state) const {
staging_state->SetInteger("staging_resource_count",
resource_pool_->total_resource_count());
staging_state->SetInteger("bytes_used_for_staging_resources",
diff --git a/cc/resources/one_copy_tile_task_worker_pool.h b/cc/resources/one_copy_tile_task_worker_pool.h
index 85b3f32..5199667 100644
--- a/cc/resources/one_copy_tile_task_worker_pool.h
+++ b/cc/resources/one_copy_tile_task_worker_pool.h
@@ -19,14 +19,7 @@
class ConvertableToTraceFormat;
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
class ResourcePool;
@@ -104,8 +97,10 @@
void ScheduleCheckForCompletedCopyOperationsWithLockAcquired(
bool wait_if_needed);
void CheckForCompletedCopyOperations(bool wait_if_needed);
- scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
- void StagingStateAsValueInto(base::debug::TracedValue* staging_state) const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> StateAsValue()
+ const;
+ void StagingStateAsValueInto(
+ base::trace_event::TracedValue* staging_state) const;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
TaskGraphRunner* task_graph_runner_;
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index 6bbeeaa..cf5e59b 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -461,19 +461,19 @@
return *this;
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
Picture::AsTraceableRasterData(float scale) const {
- scoped_refptr<base::debug::TracedValue> raster_data =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> raster_data =
+ new base::trace_event::TracedValue();
TracedValue::SetIDRef(this, raster_data.get(), "picture_id");
raster_data->SetDouble("scale", scale);
return raster_data;
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
Picture::AsTraceableRecordData() const {
- scoped_refptr<base::debug::TracedValue> record_data =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> record_data =
+ new base::trace_event::TracedValue();
TracedValue::SetIDRef(this, record_data.get(), "picture_id");
MathUtil::AddToTracedValue("layer_rect", layer_rect_, record_data.get());
return record_data;
diff --git a/cc/resources/picture.h b/cc/resources/picture.h
index a2a4ec2..81c9c53 100644
--- a/cc/resources/picture.h
+++ b/cc/resources/picture.h
@@ -149,9 +149,9 @@
gfx::Point max_pixel_cell_;
gfx::Size cell_size_;
- scoped_refptr<base::debug::ConvertableToTraceFormat>
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>
AsTraceableRasterData(float scale) const;
- scoped_refptr<base::debug::ConvertableToTraceFormat>
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>
AsTraceableRecordData() const;
friend class base::RefCountedThreadSafe<Picture>;
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index 033f9f6..1e7281d 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -23,7 +23,8 @@
namespace cc {
namespace {
-const float kSoonBorderDistanceInScreenPixels = 312.f;
+const float kSoonBorderDistanceViewportPercentage = 0.15f;
+const float kMaxSoonBorderDistanceInScreenPixels = 312.f;
} // namespace
@@ -83,6 +84,17 @@
it->second->set_shared(false);
}
+// static
+float PictureLayerTiling::CalculateSoonBorderDistance(
+ const gfx::Rect& visible_rect_in_content_space,
+ float content_to_screen_scale) {
+ float max_dimension = std::max(visible_rect_in_content_space.width(),
+ visible_rect_in_content_space.height());
+ return std::min(
+ kMaxSoonBorderDistanceInScreenPixels / content_to_screen_scale,
+ max_dimension * kSoonBorderDistanceViewportPercentage);
+}
+
Tile* PictureLayerTiling::CreateTile(int i,
int j,
const PictureLayerTiling* twin_tiling,
@@ -605,7 +617,8 @@
// Calculate the soon border rect.
float content_to_screen_scale = ideal_contents_scale / contents_scale_;
gfx::Rect soon_border_rect = visible_rect_in_content_space;
- float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale;
+ float border = CalculateSoonBorderDistance(visible_rect_in_content_space,
+ content_to_screen_scale);
soon_border_rect.Inset(-border, -border, -border, -border);
last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds;
@@ -866,7 +879,8 @@
tiles->insert(it->second.get());
}
-void PictureLayerTiling::AsValueInto(base::debug::TracedValue* state) const {
+void PictureLayerTiling::AsValueInto(
+ base::trace_event::TracedValue* state) const {
state->SetInteger("num_tiles", tiles_.size());
state->SetDouble("content_scale", contents_scale_);
MathUtil::AddToTracedValue("tiling_size", tiling_size(), state);
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index c9672c9..65e7ee0 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -24,13 +24,7 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
@@ -66,6 +60,10 @@
~PictureLayerTiling();
+ static float CalculateSoonBorderDistance(
+ const gfx::Rect& visible_rect_in_content_space,
+ float content_to_screen_scale);
+
// Create a tiling with no tiles. CreateTile() must be called to add some.
static scoped_ptr<PictureLayerTiling> Create(
float contents_scale,
@@ -214,7 +212,7 @@
const Occlusion& occlusion_in_layer_space);
void GetAllTilesForTracing(std::set<const Tile*>* tiles) const;
- void AsValueInto(base::debug::TracedValue* array) const;
+ void AsValueInto(base::trace_event::TracedValue* array) const;
size_t GPUMemoryUsageInBytes() const;
struct RectExpansionCache {
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index 7c36a3f..d931543 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -65,6 +65,13 @@
// Copy over tilings that are shared with the |twin_set| tiling set (if it
// exists).
if (twin_set) {
+ if (twin_set->tilings_.empty()) {
+ // If the twin (pending) tiling set is empty, it was not updated for the
+ // current frame. So we drop tilings from our set as well, instead of
+ // leaving behind unshared tilings that are all non-ideal.
+ RemoveAllTilings();
+ }
+
for (PictureLayerTiling* twin_tiling : twin_set->tilings_) {
float contents_scale = twin_tiling->contents_scale();
DCHECK_GE(contents_scale, minimum_contents_scale);
@@ -479,7 +486,8 @@
region_iter_.has_rect();
}
-void PictureLayerTilingSet::AsValueInto(base::debug::TracedValue* state) const {
+void PictureLayerTilingSet::AsValueInto(
+ base::trace_event::TracedValue* state) const {
for (size_t i = 0; i < tilings_.size(); ++i) {
state->BeginDictionary();
tilings_[i]->AsValueInto(state);
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index 3e31ed9..fc1e581 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -17,13 +17,7 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
@@ -157,7 +151,7 @@
Region::Iterator region_iter_;
};
- void AsValueInto(base::debug::TracedValue* array) const;
+ void AsValueInto(base::trace_event::TracedValue* array) const;
size_t GPUMemoryUsageInBytes() const;
TilingRange GetTilingRange(TilingRangeType type) const;
diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc
index fccd3c8..d4a8778 100644
--- a/cc/resources/picture_layer_tiling_unittest.cc
+++ b/cc/resources/picture_layer_tiling_unittest.cc
@@ -691,10 +691,11 @@
tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion());
tiling->UpdateAllTilePrioritiesForTesting();
- gfx::Rect soon_rect = viewport;
- soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
- gfx::Rect soon_rect_in_content_space =
- gfx::ToEnclosedRect(gfx::ScaleRect(soon_rect, 0.25f));
+ // Compute the soon border.
+ float inset = PictureLayerTiling::CalculateSoonBorderDistance(
+ viewport_in_content_space, 1.0f / 0.25f);
+ gfx::Rect soon_rect_in_content_space = viewport_in_content_space;
+ soon_rect_in_content_space.Inset(-inset, -inset);
// Sanity checks.
for (int i = 0; i < 47; ++i) {
@@ -763,10 +764,11 @@
gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f));
gfx::Rect skewport = tiling->ComputeSkewport(2.0, viewport_in_content_space);
- soon_rect = viewport;
- soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
- soon_rect_in_content_space =
- gfx::ToEnclosedRect(gfx::ScaleRect(soon_rect, 0.25f));
+ // Compute the soon border.
+ inset = PictureLayerTiling::CalculateSoonBorderDistance(
+ viewport_in_content_space, 1.0f / 0.25f);
+ soon_rect_in_content_space = viewport_in_content_space;
+ soon_rect_in_content_space.Inset(-inset, -inset);
EXPECT_EQ(0, skewport.x());
EXPECT_EQ(10, skewport.y());
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index dcfe49e..7e94e18 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -152,6 +152,12 @@
*record_rects = vertical_clustering;
}
+#ifdef NDEBUG
+const bool kDefaultClearCanvasSetting = false;
+#else
+const bool kDefaultClearCanvasSetting = true;
+#endif
+
} // namespace
namespace cc {
@@ -162,8 +168,11 @@
slow_down_raster_scale_factor_for_debug_(0),
can_use_lcd_text_(true),
has_any_recordings_(false),
+ clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
+ requires_clear_(true),
is_solid_color_(false),
solid_color_(SK_ColorTRANSPARENT),
+ background_color_(SK_ColorTRANSPARENT),
pixel_record_distance_(kPixelDistanceToRecord),
is_suitable_for_gpu_rasterization_(true) {
tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize));
@@ -623,6 +632,14 @@
slow_down_raster_scale_factor_for_debug_ = factor;
}
+void PicturePile::SetBackgroundColor(SkColor background_color) {
+ background_color_ = background_color;
+}
+
+void PicturePile::SetRequiresClear(bool requires_clear) {
+ requires_clear_ = requires_clear;
+}
+
bool PicturePile::IsSuitableForGpuRasterization() const {
return is_suitable_for_gpu_rasterization_;
}
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index 8000c42..2a9a3ce 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -34,6 +34,8 @@
gfx::Size GetSize() const final;
void SetEmptyBounds() override;
void SetSlowdownRasterScaleFactor(int factor) override;
+ void SetBackgroundColor(SkColor background_color) override;
+ void SetRequiresClear(bool requires_clear) override;
bool IsSuitableForGpuRasterization() const override;
void SetUnsuitableForGpuRasterizationForTesting() override;
gfx::Size GetTileGridSizeForTesting() const override;
@@ -97,8 +99,11 @@
// A hint about whether there are any recordings. This may be a false
// positive.
bool has_any_recordings_;
+ bool clear_canvas_with_debug_color_;
+ bool requires_clear_;
bool is_solid_color_;
SkColor solid_color_;
+ SkColor background_color_;
int pixel_record_distance_;
private:
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc
index c56a88f..d629888 100644
--- a/cc/resources/picture_pile_impl.cc
+++ b/cc/resources/picture_pile_impl.cc
@@ -16,16 +16,6 @@
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/gfx/geometry/rect_conversions.h"
-namespace {
-
-#ifdef NDEBUG
-const bool kDefaultClearCanvasSetting = false;
-#else
-const bool kDefaultClearCanvasSetting = true;
-#endif
-
-} // namespace
-
namespace cc {
scoped_refptr<PicturePileImpl> PicturePileImpl::CreateFromPicturePile(
@@ -40,7 +30,7 @@
is_solid_color_(false),
solid_color_(SK_ColorTRANSPARENT),
has_any_recordings_(false),
- clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
+ clear_canvas_with_debug_color_(false),
min_contents_scale_(0.f),
slow_down_raster_scale_factor_for_debug_(0),
should_attempt_to_use_distance_field_text_(false) {
@@ -49,14 +39,14 @@
PicturePileImpl::PicturePileImpl(const PicturePile* other)
: picture_map_(other->picture_map_),
tiling_(other->tiling_),
- background_color_(SK_ColorTRANSPARENT),
- requires_clear_(true),
+ background_color_(other->background_color_),
+ requires_clear_(other->requires_clear_),
can_use_lcd_text_(other->can_use_lcd_text_),
is_solid_color_(other->is_solid_color_),
solid_color_(other->solid_color_),
recorded_viewport_(other->recorded_viewport_),
has_any_recordings_(other->has_any_recordings_),
- clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
+ clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
min_contents_scale_(other->min_contents_scale_),
slow_down_raster_scale_factor_for_debug_(
other->slow_down_raster_scale_factor_for_debug_),
@@ -88,7 +78,6 @@
RasterSourceHelper::PrepareForPlaybackToCanvas(
canvas, canvas_rect, gfx::Rect(tiling_.tiling_size()), contents_scale,
background_color_, clear_canvas_with_debug_color_, requires_clear_);
-
RasterCommon(canvas,
NULL,
canvas_rect,
@@ -367,19 +356,12 @@
should_attempt_to_use_distance_field_text_ = true;
}
-void PicturePileImpl::SetBackgoundColor(SkColor background_color) {
- background_color_ = background_color;
-}
-
-void PicturePileImpl::SetRequiresClear(bool requires_clear) {
- requires_clear_ = requires_clear;
-}
-
bool PicturePileImpl::ShouldAttemptToUseDistanceFieldText() const {
return should_attempt_to_use_distance_field_text_;
}
-void PicturePileImpl::AsValueInto(base::debug::TracedValue* pictures) const {
+void PicturePileImpl::AsValueInto(
+ base::trace_event::TracedValue* pictures) const {
gfx::Rect tiling_rect(tiling_.tiling_size());
std::set<const void*> appended_pictures;
bool include_borders = true;
@@ -453,10 +435,8 @@
void PicturePileImpl::DidBeginTracing() {
std::set<const void*> processed_pictures;
- for (PictureMap::iterator it = picture_map_.begin();
- it != picture_map_.end();
- ++it) {
- const Picture* picture = it->second.GetPicture();
+ for (const auto& map_pair : picture_map_) {
+ const Picture* picture = map_pair.second.GetPicture();
if (picture && (processed_pictures.count(picture) == 0)) {
picture->EmitTraceSnapshot();
processed_pictures.insert(picture);
diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h
index b3bfa60..1f94cec 100644
--- a/cc/resources/picture_pile_impl.h
+++ b/cc/resources/picture_pile_impl.h
@@ -52,8 +52,6 @@
bool CoversRect(const gfx::Rect& content_rect,
float contents_scale) const override;
void SetShouldAttemptToUseDistanceFieldText() override;
- void SetBackgoundColor(SkColor background_color) override;
- void SetRequiresClear(bool requires_clear) override;
bool ShouldAttemptToUseDistanceFieldText() const override;
gfx::Size GetSize() const override;
bool IsSolidColor() const override;
@@ -63,7 +61,7 @@
// Tracing functionality.
void DidBeginTracing() override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
skia::RefPtr<SkPicture> GetFlattenedPicture() override;
size_t GetPictureMemoryUsage() const override;
@@ -106,18 +104,23 @@
int buffer_pixels() const { return tiling_.border_texels(); }
- PictureMap picture_map_;
- TilingData tiling_;
- SkColor background_color_;
- bool requires_clear_;
- bool can_use_lcd_text_;
- bool is_solid_color_;
- SkColor solid_color_;
- gfx::Rect recorded_viewport_;
- bool has_any_recordings_;
- bool clear_canvas_with_debug_color_;
- float min_contents_scale_;
- int slow_down_raster_scale_factor_for_debug_;
+ // These members are const as this raster source may be in use on another
+ // thread and so should not be touched after construction.
+ const PictureMap picture_map_;
+ const TilingData tiling_;
+ const SkColor background_color_;
+ const bool requires_clear_;
+ const bool can_use_lcd_text_;
+ const bool is_solid_color_;
+ const SkColor solid_color_;
+ const gfx::Rect recorded_viewport_;
+ const bool has_any_recordings_;
+ const bool clear_canvas_with_debug_color_;
+ const float min_contents_scale_;
+ const int slow_down_raster_scale_factor_for_debug_;
+ // TODO(enne/vmiura): this has a read/write race between raster and compositor
+ // threads with multi-threaded Ganesh. Make this const or remove it.
+ bool should_attempt_to_use_distance_field_text_;
private:
typedef std::map<const Picture*, Region> PictureRegionMap;
@@ -146,8 +149,6 @@
gfx::Rect PaddedRect(const PictureMapKey& key) const;
- bool should_attempt_to_use_distance_field_text_;
-
DISALLOW_COPY_AND_ASSIGN(PicturePileImpl);
};
diff --git a/cc/resources/picture_pile_impl_unittest.cc b/cc/resources/picture_pile_impl_unittest.cc
index 6e9afc7..72a8158 100644
--- a/cc/resources/picture_pile_impl_unittest.cc
+++ b/cc/resources/picture_pile_impl_unittest.cc
@@ -19,21 +19,25 @@
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
- SkColor solid_color = SkColorSetARGB(255, 12, 23, 34);
SkPaint solid_paint;
+ SkColor solid_color = SkColorSetARGB(255, 12, 23, 34);
solid_paint.setColor(solid_color);
SkColor non_solid_color = SkColorSetARGB(128, 45, 56, 67);
SkPaint non_solid_paint;
non_solid_paint.setColor(non_solid_color);
- pile->add_draw_rect_with_paint(gfx::Rect(0, 0, 400, 400), solid_paint);
- pile->RerecordPile();
+ recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 400, 400),
+ solid_paint);
+ recording_source->RerecordPile();
- // Ensure everything is solid
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
+
+ // Ensure everything is solid.
for (int y = 0; y <= 300; y += 100) {
for (int x = 0; x <= 300; x += 100) {
RasterSource::SolidColorAnalysis analysis;
@@ -44,9 +48,11 @@
}
}
- // One pixel non solid
- pile->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1), non_solid_paint);
- pile->RerecordPile();
+ // Add one non-solid pixel and recreate the raster source.
+ recording_source->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1),
+ non_solid_paint);
+ recording_source->RerecordPile();
+ pile = FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
RasterSource::SolidColorAnalysis analysis;
pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 100, 100), 1.0, &analysis);
@@ -56,7 +62,7 @@
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
- // Boundaries should be clipped
+ // Boundaries should be clipped.
analysis.is_solid_color = false;
pile->PerformSolidColorAnalysis(gfx::Rect(350, 0, 100, 100), 1.0, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
@@ -78,8 +84,8 @@
gfx::Size tile_size(100, 100);
gfx::Size layer_bounds(400, 400);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
SkColor solid_color = SkColorSetARGB(255, 12, 23, 34);
SkPaint solid_paint;
@@ -89,10 +95,14 @@
SkPaint non_solid_paint;
non_solid_paint.setColor(non_solid_color);
- pile->add_draw_rect_with_paint(gfx::Rect(0, 0, 400, 400), solid_paint);
- pile->RerecordPile();
+ recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 400, 400),
+ solid_paint);
+ recording_source->RerecordPile();
- // Ensure everything is solid
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
+
+ // Ensure everything is solid.
for (int y = 0; y <= 30; y += 10) {
for (int x = 0; x <= 30; x += 10) {
RasterSource::SolidColorAnalysis analysis;
@@ -103,9 +113,11 @@
}
}
- // One pixel non solid
- pile->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1), non_solid_paint);
- pile->RerecordPile();
+ // Add one non-solid pixel and recreate the raster source.
+ recording_source->add_draw_rect_with_paint(gfx::Rect(50, 50, 1, 1),
+ non_solid_paint);
+ recording_source->RerecordPile();
+ pile = FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
RasterSource::SolidColorAnalysis analysis;
pile->PerformSolidColorAnalysis(gfx::Rect(0, 0, 10, 10), 0.1f, &analysis);
@@ -115,7 +127,7 @@
EXPECT_TRUE(analysis.is_solid_color);
EXPECT_EQ(analysis.solid_color, solid_color);
- // Boundaries should be clipped
+ // Boundaries should be clipped.
analysis.is_solid_color = false;
pile->PerformSolidColorAnalysis(gfx::Rect(35, 0, 10, 10), 0.1f, &analysis);
EXPECT_TRUE(analysis.is_solid_color);
@@ -209,24 +221,30 @@
gfx::Size tile_size(128, 128);
gfx::Size layer_bounds(256, 256);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
-
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
SkPaint simple_paint;
simple_paint.setColor(SkColorSetARGB(255, 12, 23, 34));
SkBitmap non_discardable_bitmap;
CreateBitmap(gfx::Size(128, 128), "notdiscardable", &non_discardable_bitmap);
- pile->add_draw_rect_with_paint(gfx::Rect(0, 0, 256, 256), simple_paint);
- pile->add_draw_rect_with_paint(gfx::Rect(128, 128, 512, 512), simple_paint);
- pile->add_draw_rect_with_paint(gfx::Rect(512, 0, 256, 256), simple_paint);
- pile->add_draw_rect_with_paint(gfx::Rect(0, 512, 256, 256), simple_paint);
- pile->add_draw_bitmap(non_discardable_bitmap, gfx::Point(128, 0));
- pile->add_draw_bitmap(non_discardable_bitmap, gfx::Point(0, 128));
- pile->add_draw_bitmap(non_discardable_bitmap, gfx::Point(150, 150));
+ recording_source->add_draw_rect_with_paint(gfx::Rect(0, 0, 256, 256),
+ simple_paint);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(128, 128, 512, 512),
+ simple_paint);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(512, 0, 256, 256),
+ simple_paint);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(0, 512, 256, 256),
+ simple_paint);
+ recording_source->add_draw_bitmap(non_discardable_bitmap, gfx::Point(128, 0));
+ recording_source->add_draw_bitmap(non_discardable_bitmap, gfx::Point(0, 128));
+ recording_source->add_draw_bitmap(non_discardable_bitmap,
+ gfx::Point(150, 150));
+ recording_source->RerecordPile();
- pile->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
// Tile sized iterators.
{
@@ -282,8 +300,8 @@
gfx::Size tile_size(128, 128);
gfx::Size layer_bounds(256, 256);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
SkBitmap discardable_bitmap[2][2];
CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][0]);
@@ -296,11 +314,15 @@
// |---|---|
// | x | x |
// |---|---|
- pile->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
- pile->add_draw_bitmap(discardable_bitmap[1][0], gfx::Point(0, 130));
- pile->add_draw_bitmap(discardable_bitmap[1][1], gfx::Point(140, 140));
+ recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
+ recording_source->add_draw_bitmap(discardable_bitmap[1][0],
+ gfx::Point(0, 130));
+ recording_source->add_draw_bitmap(discardable_bitmap[1][1],
+ gfx::Point(140, 140));
+ recording_source->RerecordPile();
- pile->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
// Tile sized iterators. These should find only one pixel ref.
{
@@ -392,8 +414,8 @@
gfx::Size tile_size(256, 256);
gfx::Size layer_bounds(512, 512);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
SkBitmap discardable_bitmap[2][2];
CreateBitmap(gfx::Size(32, 32), "discardable", &discardable_bitmap[0][0]);
@@ -406,11 +428,15 @@
// |---|---|
// | | x |
// |---|---|
- pile->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
- pile->add_draw_bitmap(discardable_bitmap[0][1], gfx::Point(260, 0));
- pile->add_draw_bitmap(discardable_bitmap[1][1], gfx::Point(260, 260));
+ recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
+ recording_source->add_draw_bitmap(discardable_bitmap[0][1],
+ gfx::Point(260, 0));
+ recording_source->add_draw_bitmap(discardable_bitmap[1][1],
+ gfx::Point(260, 260));
+ recording_source->RerecordPile();
- pile->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
// Tile sized iterators. These should find only one pixel ref.
{
@@ -523,8 +549,8 @@
gfx::Size tile_size(256, 256);
gfx::Size layer_bounds(512, 512);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
SkBitmap non_discardable_bitmap;
CreateBitmap(gfx::Size(512, 512), "notdiscardable", &non_discardable_bitmap);
@@ -541,12 +567,16 @@
// |---|---|
// | | x |
// |---|---|
- pile->add_draw_bitmap(non_discardable_bitmap, gfx::Point(0, 0));
- pile->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
- pile->add_draw_bitmap(discardable_bitmap[0][1], gfx::Point(260, 0));
- pile->add_draw_bitmap(discardable_bitmap[1][1], gfx::Point(260, 260));
+ recording_source->add_draw_bitmap(non_discardable_bitmap, gfx::Point(0, 0));
+ recording_source->add_draw_bitmap(discardable_bitmap[0][0], gfx::Point(0, 0));
+ recording_source->add_draw_bitmap(discardable_bitmap[0][1],
+ gfx::Point(260, 0));
+ recording_source->add_draw_bitmap(discardable_bitmap[1][1],
+ gfx::Point(260, 260));
+ recording_source->RerecordPile();
- pile->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
// Tile sized iterators. These should find only one pixel ref.
{
@@ -640,19 +670,25 @@
float contents_scale = 1.5f;
float raster_divisions = 2.f;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
+ recording_source->SetBackgroundColor(SK_ColorBLACK);
+ recording_source->SetIsSolidColor(false);
+ recording_source->SetRequiresClear(false);
+ recording_source->SetClearCanvasWithDebugColor(false);
+
// Because the caller sets content opaque, it also promises that it
// has at least filled in layer_bounds opaquely.
SkPaint white_paint;
white_paint.setColor(SK_ColorWHITE);
- pile->add_draw_rect_with_paint(gfx::Rect(layer_bounds), white_paint);
+ recording_source->add_draw_rect_with_paint(gfx::Rect(layer_bounds),
+ white_paint);
- pile->SetMinContentsScale(contents_scale);
- pile->set_background_color(SK_ColorBLACK);
- pile->SetRequiresClear(false);
- pile->set_clear_canvas_with_debug_color(false);
- pile->RerecordPile();
+ recording_source->SetMinContentsScale(contents_scale);
+ recording_source->RerecordPile();
+
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
gfx::Size content_bounds(
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
@@ -703,14 +739,16 @@
gfx::Size layer_bounds(5, 3);
float contents_scale = 0.5f;
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- pile->set_background_color(SK_ColorTRANSPARENT);
- pile->SetRequiresClear(true);
- pile->SetMinContentsScale(contents_scale);
- pile->set_clear_canvas_with_debug_color(false);
- pile->RerecordPile();
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
+ recording_source->SetBackgroundColor(SK_ColorTRANSPARENT);
+ recording_source->SetRequiresClear(true);
+ recording_source->SetMinContentsScale(contents_scale);
+ recording_source->SetClearCanvasWithDebugColor(false);
+ recording_source->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
gfx::Size content_bounds(
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
@@ -743,21 +781,24 @@
// Pick an opaque color to not have to deal with premultiplication off-by-one.
SkColor test_color = SkColorSetARGB(255, 45, 56, 67);
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- pile->set_background_color(SK_ColorTRANSPARENT);
- pile->SetRequiresClear(true);
- pile->SetMinContentsScale(MinContentsScale());
- pile->set_clear_canvas_with_debug_color(true);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
+ recording_source->SetBackgroundColor(SK_ColorTRANSPARENT);
+ recording_source->SetRequiresClear(true);
+ recording_source->SetMinContentsScale(MinContentsScale());
+ recording_source->SetClearCanvasWithDebugColor(true);
+
SkPaint color_paint;
color_paint.setColor(test_color);
// Additive paint, so that if two paints overlap, the color will change.
color_paint.setXfermodeMode(SkXfermode::kPlus_Mode);
// Paint outside the layer to make sure that blending works.
- pile->add_draw_rect_with_paint(gfx::RectF(bigger_than_layer_bounds),
- color_paint);
- pile->RerecordPile();
+ recording_source->add_draw_rect_with_paint(
+ gfx::RectF(bigger_than_layer_bounds), color_paint);
+ recording_source->RerecordPile();
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
gfx::Size content_bounds(
gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)));
@@ -793,25 +834,33 @@
gfx::Size tile_size(128, 128);
gfx::Size layer_bounds(320, 128);
- // Fake picture pile impl uses a tile grid the size of the tile. So,
+ // Fake picture pile uses a tile grid the size of the tile. So,
// any iteration that intersects with a tile will return all pixel refs
// inside of it.
- scoped_refptr<FakePicturePileImpl> pile =
- FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
- pile->SetMinContentsScale(0.5f);
+ scoped_ptr<FakePicturePile> recording_source =
+ FakePicturePile::CreateFilledPile(tile_size, layer_bounds);
+ recording_source->SetMinContentsScale(0.5f);
// Bitmaps 0-2 are exactly on tiles 0-2, so that they overlap the borders
// of adjacent tiles.
- gfx::Rect bitmap_rects[] = {pile->tiling().TileBounds(0, 0),
- pile->tiling().TileBounds(1, 0),
- pile->tiling().TileBounds(2, 0), };
+ gfx::Rect bitmap_rects[] = {
+ recording_source->tiling().TileBounds(0, 0),
+ recording_source->tiling().TileBounds(1, 0),
+ recording_source->tiling().TileBounds(2, 0),
+ };
SkBitmap discardable_bitmap[arraysize(bitmap_rects)];
for (size_t i = 0; i < arraysize(bitmap_rects); ++i) {
CreateBitmap(bitmap_rects[i].size(), "discardable", &discardable_bitmap[i]);
- pile->add_draw_bitmap(discardable_bitmap[i], bitmap_rects[i].origin());
+ recording_source->add_draw_bitmap(discardable_bitmap[i],
+ bitmap_rects[i].origin());
}
+ recording_source->RerecordPile();
+
+ scoped_refptr<FakePicturePileImpl> pile =
+ FakePicturePileImpl::CreateFromPile(recording_source.get(), nullptr);
+
// Sanity check that bitmaps 0-2 intersect the borders of their adjacent
// tiles, but not the actual tiles.
EXPECT_TRUE(
@@ -827,8 +876,6 @@
bitmap_rects[2].Intersects(pile->tiling().TileBoundsWithBorder(1, 0)));
EXPECT_FALSE(bitmap_rects[2].Intersects(pile->tiling().TileBounds(1, 0)));
- pile->RerecordPile();
-
// Tile-sized iterators.
{
// Because tile 0's borders extend onto tile 1, it will include both
diff --git a/cc/resources/pixel_buffer_tile_task_worker_pool.cc b/cc/resources/pixel_buffer_tile_task_worker_pool.cc
index 69afb83..f74e066 100644
--- a/cc/resources/pixel_buffer_tile_task_worker_pool.cc
+++ b/cc/resources/pixel_buffer_tile_task_worker_pool.cc
@@ -701,10 +701,10 @@
completed_tasks_.clear();
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
PixelBufferTileTaskWorkerPool::StateAsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
state->SetInteger("completed_count", completed_raster_tasks_.size());
state->BeginArray("pending_count");
for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
@@ -719,7 +719,7 @@
}
void PixelBufferTileTaskWorkerPool::ThrottleStateAsValueInto(
- base::debug::TracedValue* throttle_state) const {
+ base::trace_event::TracedValue* throttle_state) const {
throttle_state->SetInteger("bytes_available_for_upload",
max_bytes_pending_upload_ - bytes_pending_upload_);
throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
diff --git a/cc/resources/pixel_buffer_tile_task_worker_pool.h b/cc/resources/pixel_buffer_tile_task_worker_pool.h
index edff89a..82e5916 100644
--- a/cc/resources/pixel_buffer_tile_task_worker_pool.h
+++ b/cc/resources/pixel_buffer_tile_task_worker_pool.h
@@ -20,14 +20,7 @@
class ConvertableToTraceFormat;
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
class ResourceProvider;
@@ -101,8 +94,10 @@
void CheckForCompletedRasterizerTasks();
const char* StateName() const;
- scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
- void ThrottleStateAsValueInto(base::debug::TracedValue* throttle_state) const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> StateAsValue()
+ const;
+ void ThrottleStateAsValueInto(
+ base::trace_event::TracedValue* throttle_state) const;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
TaskGraphRunner* task_graph_runner_;
diff --git a/cc/resources/raster_source.h b/cc/resources/raster_source.h
index e890375..929e49d 100644
--- a/cc/resources/raster_source.h
+++ b/cc/resources/raster_source.h
@@ -86,16 +86,13 @@
// during rasterization.
virtual void SetShouldAttemptToUseDistanceFieldText() = 0;
- virtual void SetBackgoundColor(SkColor background_color) = 0;
- virtual void SetRequiresClear(bool requires_clear) = 0;
-
// Return true iff this raster source would benefit from using distance
// field text.
virtual bool ShouldAttemptToUseDistanceFieldText() const = 0;
// Tracing functionality.
virtual void DidBeginTracing() = 0;
- virtual void AsValueInto(base::debug::TracedValue* array) const = 0;
+ virtual void AsValueInto(base::trace_event::TracedValue* array) const = 0;
virtual skia::RefPtr<SkPicture> GetFlattenedPicture() = 0;
virtual size_t GetPictureMemoryUsage() const = 0;
diff --git a/cc/resources/raster_tile_priority_queue_all.cc b/cc/resources/raster_tile_priority_queue_all.cc
index e9836cd..9baa9b3 100644
--- a/cc/resources/raster_tile_priority_queue_all.cc
+++ b/cc/resources/raster_tile_priority_queue_all.cc
@@ -280,10 +280,10 @@
pending_queue_.get(), nullptr);
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
RasterTilePriorityQueueAll::PairedTilingSetQueue::StateAsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
bool active_queue_has_tile = active_queue_ && !active_queue_->IsEmpty();
TilePriority::PriorityBin active_priority_bin = TilePriority::EVENTUALLY;
diff --git a/cc/resources/raster_tile_priority_queue_all.h b/cc/resources/raster_tile_priority_queue_all.h
index c2b8910..4bd1085 100644
--- a/cc/resources/raster_tile_priority_queue_all.h
+++ b/cc/resources/raster_tile_priority_queue_all.h
@@ -33,7 +33,8 @@
WhichTree NextTileIteratorTree(TreePriority tree_priority) const;
void SkipTilesReturnedByTwin(TreePriority tree_priority);
- scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> StateAsValue()
+ const;
const TilingSetRasterQueueAll* active_queue() const {
return active_queue_.get();
diff --git a/cc/resources/recording_source.h b/cc/resources/recording_source.h
index d96c0fa..8915361 100644
--- a/cc/resources/recording_source.h
+++ b/cc/resources/recording_source.h
@@ -45,6 +45,8 @@
virtual gfx::Size GetSize() const = 0;
virtual void SetEmptyBounds() = 0;
virtual void SetSlowdownRasterScaleFactor(int factor) = 0;
+ virtual void SetBackgroundColor(SkColor background_color) = 0;
+ virtual void SetRequiresClear(bool requires_clear) = 0;
virtual bool IsSuitableForGpuRasterization() const = 0;
// TODO(hendrikw): Figure out how to remove this.
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index b90b594..42ef4b3 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -1087,17 +1087,25 @@
ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
ResourceProvider* resource_provider,
- ResourceProvider::ResourceId resource_id,
- bool use_distance_field_text,
- bool can_use_lcd_text,
- int msaa_sample_count)
+ ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider),
resource_(resource_provider->LockForWrite(resource_id)) {
- // Create the sk_surface.
+ DCHECK(thread_checker_.CalledOnValidThread());
+ resource_provider_->LazyAllocate(resource_);
+}
+
+ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(resource_->locked_for_write);
+ resource_provider_->UnlockForWrite(resource_);
+}
- resource_provider_->LazyAllocate(resource_);
+void ResourceProvider::ScopedWriteLockGr::InitSkSurface(
+ bool use_worker_context,
+ bool use_distance_field_text,
+ bool can_use_lcd_text,
+ int msaa_sample_count) {
+ DCHECK(resource_->locked_for_write);
GrBackendTextureDesc desc;
desc.fFlags = kRenderTarget_GrBackendTextureFlag;
@@ -1108,7 +1116,8 @@
desc.fTextureHandle = resource_->gl_id;
desc.fSampleCnt = msaa_sample_count;
- class GrContext* gr_context = resource_provider_->GrContext();
+ class GrContext* gr_context =
+ resource_provider_->GrContext(use_worker_context);
skia::RefPtr<GrTexture> gr_texture =
skia::AdoptRef(gr_context->wrapBackendTexture(desc));
if (gr_texture) {
@@ -1124,12 +1133,13 @@
}
sk_surface_ = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
gr_texture->asRenderTarget(), &surface_props));
+ return;
}
+ sk_surface_.clear();
}
-ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
- DCHECK(thread_checker_.CalledOnValidThread());
- resource_provider_->UnlockForWrite(resource_);
+void ResourceProvider::ScopedWriteLockGr::ReleaseSkSurface() {
+ sk_surface_.clear();
}
ResourceProvider::SynchronousFence::SynchronousFence(
@@ -2135,8 +2145,10 @@
return context_provider ? context_provider->ContextGL() : NULL;
}
-class GrContext* ResourceProvider::GrContext() const {
- ContextProvider* context_provider = output_surface_->context_provider();
+class GrContext* ResourceProvider::GrContext(bool worker_context) const {
+ ContextProvider* context_provider =
+ worker_context ? output_surface_->worker_context_provider()
+ : output_surface_->context_provider();
return context_provider ? context_provider->GrContext() : NULL;
}
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index 1fb5b60..167ef20 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -332,13 +332,17 @@
class CC_EXPORT ScopedWriteLockGr {
public:
ScopedWriteLockGr(ResourceProvider* resource_provider,
- ResourceProvider::ResourceId resource_id,
- bool use_distance_field_text,
- bool can_use_lcd_text,
- int msaa_sample_count);
+ ResourceProvider::ResourceId resource_id);
~ScopedWriteLockGr();
- SkSurface* get_sk_surface() { return sk_surface_.get(); }
+ void InitSkSurface(bool use_worker_context,
+ bool use_distance_field_text,
+ bool can_use_lcd_text,
+ int msaa_sample_count);
+ void ReleaseSkSurface();
+
+ SkSurface* sk_surface() { return sk_surface_.get(); }
+ ResourceProvider::Resource* resource() { return resource_; }
private:
ResourceProvider* resource_provider_;
@@ -426,6 +430,8 @@
static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl);
+ OutputSurface* output_surface() { return output_surface_; }
+
private:
struct Resource {
enum Origin { Internal, External, Delegated };
@@ -560,7 +566,7 @@
// Returns NULL if the output_surface_ does not have a ContextProvider.
gpu::gles2::GLES2Interface* ContextGL() const;
- class GrContext* GrContext() const;
+ class GrContext* GrContext(bool worker_context) const;
OutputSurface* output_surface_;
SharedBitmapManager* shared_bitmap_manager_;
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index 53741ab..2bba801 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -3518,7 +3518,7 @@
scoped_refptr<TestContextProvider> context_provider =
TestContextProvider::Create(context_owned.Pass());
- output_surface->InitializeAndSetContext3d(context_provider);
+ output_surface->InitializeAndSetContext3d(context_provider, nullptr);
resource_provider->InitializeGL();
CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
diff --git a/cc/resources/tile.cc b/cc/resources/tile.cc
index b0b4525..39d48a8 100644
--- a/cc/resources/tile.cc
+++ b/cc/resources/tile.cc
@@ -49,7 +49,7 @@
"cc::Tile", this);
}
-void Tile::AsValueInto(base::debug::TracedValue* res) const {
+void Tile::AsValueInto(base::trace_event::TracedValue* res) const {
TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
TRACE_DISABLED_BY_DEFAULT("cc.debug"), res, "cc::Tile", this);
TracedValue::SetIDRef(raster_source_.get(), res, "picture_pile");
diff --git a/cc/resources/tile.h b/cc/resources/tile.h
index 2394dcb..698f43d 100644
--- a/cc/resources/tile.h
+++ b/cc/resources/tile.h
@@ -68,18 +68,8 @@
void set_shared(bool is_shared) { is_shared_ = is_shared; }
bool is_shared() const { return is_shared_; }
- bool is_occluded_for_tree_priority(TreePriority tree_priority) const {
- switch (tree_priority) {
- case SMOOTHNESS_TAKES_PRIORITY:
- return is_occluded_[ACTIVE_TREE];
- case NEW_CONTENT_TAKES_PRIORITY:
- return is_occluded_[PENDING_TREE];
- case SAME_PRIORITY_FOR_BOTH_TREES:
- return is_occluded_[ACTIVE_TREE] && is_occluded_[PENDING_TREE];
- default:
- NOTREACHED();
- return false;
- }
+ bool is_occluded_combined() const {
+ return is_occluded_[ACTIVE_TREE] && is_occluded_[PENDING_TREE];
}
// TODO(vmpstr): Move this to the iterators.
@@ -102,7 +92,7 @@
!draw_info_.IsReadyToDraw();
}
- void AsValueInto(base::debug::TracedValue* dict) const;
+ void AsValueInto(base::trace_event::TracedValue* dict) const;
inline bool IsReadyToDraw() const { return draw_info_.IsReadyToDraw(); }
diff --git a/cc/resources/tile_draw_info.cc b/cc/resources/tile_draw_info.cc
index 518a74b..7761d72 100644
--- a/cc/resources/tile_draw_info.cc
+++ b/cc/resources/tile_draw_info.cc
@@ -28,7 +28,7 @@
return false;
}
-void TileDrawInfo::AsValueInto(base::debug::TracedValue* state) const {
+void TileDrawInfo::AsValueInto(base::trace_event::TracedValue* state) const {
state->SetBoolean("is_solid_color", mode_ == SOLID_COLOR_MODE);
state->SetBoolean("is_transparent",
mode_ == SOLID_COLOR_MODE && !SkColorGetA(solid_color_));
diff --git a/cc/resources/tile_draw_info.h b/cc/resources/tile_draw_info.h
index 8437f5b..54ca946 100644
--- a/cc/resources/tile_draw_info.h
+++ b/cc/resources/tile_draw_info.h
@@ -59,7 +59,7 @@
resource_ = resource.Pass();
}
- void AsValueInto(base::debug::TracedValue* state) const;
+ void AsValueInto(base::trace_event::TracedValue* state) const;
private:
friend class Tile;
diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc
index 2b247aa..94b6332 100644
--- a/cc/resources/tile_manager.cc
+++ b/cc/resources/tile_manager.cc
@@ -184,10 +184,10 @@
RasterTaskCompletionStats::RasterTaskCompletionStats()
: completed_count(0u), canceled_count(0u) {}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
state->SetInteger("completed_count", stats.completed_count);
state->SetInteger("canceled_count", stats.canceled_count);
return state;
@@ -477,15 +477,16 @@
update_visible_tiles_stats_ = RasterTaskCompletionStats();
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
TileManager::BasicStateAsValue() const {
- scoped_refptr<base::debug::TracedValue> value =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> value =
+ new base::trace_event::TracedValue();
BasicStateAsValueInto(value.get());
return value;
}
-void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const {
+void TileManager::BasicStateAsValueInto(
+ base::trace_event::TracedValue* state) const {
state->SetInteger("tile_count", tiles_.size());
state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_);
state->BeginDictionary("global_state");
diff --git a/cc/resources/tile_manager.h b/cc/resources/tile_manager.h
index 0af823e..2bdc9e1 100644
--- a/cc/resources/tile_manager.h
+++ b/cc/resources/tile_manager.h
@@ -30,14 +30,7 @@
class ConvertableToTraceFormat;
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
class PictureLayerImpl;
@@ -87,8 +80,8 @@
size_t completed_count;
size_t canceled_count;
};
-scoped_refptr<base::debug::ConvertableToTraceFormat>
- RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats);
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats);
// This class manages tiles, deciding which should get rasterized and which
// should no longer have any memory assigned to them. Tile objects are "owned"
@@ -135,9 +128,9 @@
int source_frame_number,
int flags);
- scoped_refptr<base::debug::ConvertableToTraceFormat> BasicStateAsValue()
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> BasicStateAsValue()
const;
- void BasicStateAsValueInto(base::debug::TracedValue* dict) const;
+ void BasicStateAsValueInto(base::trace_event::TracedValue* dict) const;
const MemoryHistory::Entry& memory_stats_from_last_assign() const {
return memory_stats_from_last_assign_;
}
diff --git a/cc/resources/tile_manager_perftest.cc b/cc/resources/tile_manager_perftest.cc
index bb4ce7c..7c316ac 100644
--- a/cc/resources/tile_manager_perftest.cc
+++ b/cc/resources/tile_manager_perftest.cc
@@ -179,7 +179,7 @@
std::vector<FakePictureLayerImpl*> layers = CreateLayers(layer_count, 10);
bool resourceless_software_draw = false;
for (const auto& layer : layers)
- layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ layer->UpdateTiles(resourceless_software_draw);
timer_.Reset();
do {
@@ -207,7 +207,7 @@
std::vector<FakePictureLayerImpl*> layers = CreateLayers(layer_count, 100);
bool resourceless_software_draw = false;
for (const auto& layer : layers)
- layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ layer->UpdateTiles(resourceless_software_draw);
int priority_count = 0;
timer_.Reset();
@@ -243,7 +243,7 @@
std::vector<FakePictureLayerImpl*> layers = CreateLayers(layer_count, 10);
bool resourceless_software_draw = false;
for (const auto& layer : layers) {
- layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ layer->UpdateTiles(resourceless_software_draw);
for (size_t i = 0; i < layer->num_tilings(); ++i) {
tile_manager()->InitializeTilesWithResourcesForTesting(
layer->tilings()->tiling_at(i)->AllTilesForTesting());
@@ -278,7 +278,7 @@
CreateLayers(layer_count, tile_count);
bool resourceless_software_draw = false;
for (const auto& layer : layers) {
- layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ layer->UpdateTiles(resourceless_software_draw);
for (size_t i = 0; i < layer->num_tilings(); ++i) {
tile_manager()->InitializeTilesWithResourcesForTesting(
layer->tilings()->tiling_at(i)->AllTilesForTesting());
@@ -387,7 +387,7 @@
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
host_impl_.UpdateCurrentBeginFrameArgs(args);
for (const auto& layer : layers)
- layer->UpdateTiles(Occlusion(), resourceless_software_draw);
+ layer->UpdateTiles(resourceless_software_draw);
GlobalStateThatImpactsTilePriority global_state(GlobalStateForTest());
tile_manager()->PrepareTiles(global_state);
diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc
index 0e12af6..4f441b3 100644
--- a/cc/resources/tile_manager_unittest.cc
+++ b/cc/resources/tile_manager_unittest.cc
@@ -662,7 +662,7 @@
Tile* last_tile = NULL;
smoothness_tiles.clear();
tile_count = 0;
- // Here we expect to get increasing ACTIVE_TREE priority_bin.
+ // Here we expect to get increasing combined priority_bin.
queue = host_impl_.BuildEvictionQueue(SMOOTHNESS_TAKES_PRIORITY);
int distance_increasing = 0;
int distance_decreasing = 0;
@@ -674,16 +674,16 @@
if (!last_tile)
last_tile = tile;
- EXPECT_GE(last_tile->priority(ACTIVE_TREE).priority_bin,
- tile->priority(ACTIVE_TREE).priority_bin);
- if (last_tile->priority(ACTIVE_TREE).priority_bin ==
- tile->priority(ACTIVE_TREE).priority_bin) {
+ const TilePriority& last_priority = last_tile->combined_priority();
+ const TilePriority& priority = tile->combined_priority();
+
+ EXPECT_GE(last_priority.priority_bin, priority.priority_bin);
+ if (last_priority.priority_bin == priority.priority_bin) {
EXPECT_LE(last_tile->required_for_activation(),
tile->required_for_activation());
if (last_tile->required_for_activation() ==
tile->required_for_activation()) {
- if (last_tile->priority(ACTIVE_TREE).distance_to_visible >=
- tile->priority(ACTIVE_TREE).distance_to_visible)
+ if (last_priority.distance_to_visible >= priority.distance_to_visible)
++distance_decreasing;
else
++distance_increasing;
@@ -696,14 +696,15 @@
queue->Pop();
}
+ // Ensure that the distance is decreasing many more times than increasing.
EXPECT_EQ(3, distance_increasing);
- EXPECT_EQ(16, distance_decreasing);
+ EXPECT_EQ(17, distance_decreasing);
EXPECT_EQ(tile_count, smoothness_tiles.size());
EXPECT_EQ(all_tiles, smoothness_tiles);
std::set<Tile*> new_content_tiles;
last_tile = NULL;
- // Here we expect to get increasing PENDING_TREE priority_bin.
+ // Again, we expect to get increasing combined priority_bin.
queue = host_impl_.BuildEvictionQueue(NEW_CONTENT_TAKES_PRIORITY);
distance_decreasing = 0;
distance_increasing = 0;
@@ -714,16 +715,16 @@
if (!last_tile)
last_tile = tile;
- EXPECT_GE(last_tile->priority(PENDING_TREE).priority_bin,
- tile->priority(PENDING_TREE).priority_bin);
- if (last_tile->priority(PENDING_TREE).priority_bin ==
- tile->priority(PENDING_TREE).priority_bin) {
+ const TilePriority& last_priority = last_tile->combined_priority();
+ const TilePriority& priority = tile->combined_priority();
+
+ EXPECT_GE(last_priority.priority_bin, priority.priority_bin);
+ if (last_priority.priority_bin == priority.priority_bin) {
EXPECT_LE(last_tile->required_for_activation(),
tile->required_for_activation());
if (last_tile->required_for_activation() ==
tile->required_for_activation()) {
- if (last_tile->priority(PENDING_TREE).distance_to_visible >=
- tile->priority(PENDING_TREE).distance_to_visible)
+ if (last_priority.distance_to_visible >= priority.distance_to_visible)
++distance_decreasing;
else
++distance_increasing;
@@ -735,8 +736,9 @@
queue->Pop();
}
+ // Ensure that the distance is decreasing many more times than increasing.
EXPECT_EQ(3, distance_increasing);
- EXPECT_EQ(16, distance_decreasing);
+ EXPECT_EQ(17, distance_decreasing);
EXPECT_EQ(tile_count, new_content_tiles.size());
EXPECT_EQ(all_tiles, new_content_tiles);
}
@@ -771,6 +773,12 @@
CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks));
host_impl_.pending_tree()->UpdateDrawProperties();
+ ActivateTree();
+ SetupPendingTree(pending_pile);
+
+ FakePictureLayerImpl* active_child_layer =
+ static_cast<FakePictureLayerImpl*>(active_layer_->children()[0]);
+
std::set<Tile*> all_tiles;
size_t tile_count = 0;
scoped_ptr<RasterTilePriorityQueue> raster_queue(host_impl_.BuildRasterQueue(
@@ -797,6 +805,15 @@
pending_child_layer->LowResTiling()->ComputeTilePriorityRects(
viewport, 1.0f, 1.0, Occlusion());
+ active_layer_->HighResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
+ Occlusion());
+ active_layer_->LowResTiling()->ComputeTilePriorityRects(viewport, 1.0f, 1.0,
+ Occlusion());
+ active_child_layer->HighResTiling()->ComputeTilePriorityRects(
+ viewport, 1.0f, 1.0, Occlusion());
+ active_child_layer->LowResTiling()->ComputeTilePriorityRects(
+ viewport, 1.0f, 1.0, Occlusion());
+
// Populate all tiles directly from the tilings.
all_tiles.clear();
std::vector<Tile*> pending_high_res_tiles =
@@ -812,12 +829,14 @@
std::vector<Tile*> pending_child_high_res_tiles =
pending_child_layer->HighResTiling()->AllTilesForTesting();
pending_child_layer->HighResTiling()->SetAllTilesOccludedForTesting();
+ active_child_layer->HighResTiling()->SetAllTilesOccludedForTesting();
all_tiles.insert(pending_child_high_res_tiles.begin(),
pending_child_high_res_tiles.end());
std::vector<Tile*> pending_child_low_res_tiles =
pending_child_layer->LowResTiling()->AllTilesForTesting();
pending_child_layer->LowResTiling()->SetAllTilesOccludedForTesting();
+ active_child_layer->LowResTiling()->SetAllTilesOccludedForTesting();
all_tiles.insert(pending_child_low_res_tiles.begin(),
pending_child_low_res_tiles.end());
@@ -835,7 +854,7 @@
if (!last_tile)
last_tile = tile;
- bool tile_is_occluded = tile->is_occluded_for_tree_priority(tree_priority);
+ bool tile_is_occluded = tile->is_occluded_combined();
// The only way we will encounter an occluded tile after an unoccluded
// tile is if the priorty bin decreased, the tile is required for
@@ -843,8 +862,7 @@
if (tile_is_occluded) {
occluded_count++;
- bool last_tile_is_occluded =
- last_tile->is_occluded_for_tree_priority(tree_priority);
+ bool last_tile_is_occluded = last_tile->is_occluded_combined();
if (!last_tile_is_occluded) {
TilePriority::PriorityBin tile_priority_bin =
tile->priority_for_tree_priority(tree_priority).priority_bin;
@@ -1069,11 +1087,12 @@
RasterTilePriorityQueueStaticViewport) {
FakePictureLayerTilingClient client;
- gfx::Rect viewport(50, 50, 100, 100);
- gfx::Size layer_bounds(800, 800);
+ gfx::Rect viewport(50, 50, 500, 500);
+ gfx::Size layer_bounds(1600, 1600);
+ float inset = PictureLayerTiling::CalculateSoonBorderDistance(viewport, 1.0f);
gfx::Rect soon_rect = viewport;
- soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
+ soon_rect.Inset(-inset, -inset);
client.SetTileSize(gfx::Size(30, 30));
client.set_tree(ACTIVE_TREE);
@@ -1093,7 +1112,7 @@
tiling_set->UpdateTilePriorities(viewport, 1.0f, 1.0, Occlusion(), true);
std::vector<Tile*> all_tiles = tiling->AllTilesForTesting();
// Sanity check.
- EXPECT_EQ(841u, all_tiles.size());
+ EXPECT_EQ(3364u, all_tiles.size());
// The explanation of each iteration is as follows:
// 1. First iteration tests that we can get all of the tiles correctly.
@@ -1205,8 +1224,10 @@
tiling_set->UpdateTilePriorities(moved_viewport, 1.0f, 2.0, Occlusion(),
true);
+ float inset =
+ PictureLayerTiling::CalculateSoonBorderDistance(moved_viewport, 1.0f);
gfx::Rect soon_rect = moved_viewport;
- soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
+ soon_rect.Inset(-inset, -inset);
// There are 3 bins in TilePriority.
bool have_tiles[3] = {};
diff --git a/cc/resources/tile_priority.cc b/cc/resources/tile_priority.cc
index 5ef26f2..33dfcbe 100644
--- a/cc/resources/tile_priority.cc
+++ b/cc/resources/tile_priority.cc
@@ -48,7 +48,7 @@
return "<unknown TilePriority::PriorityBin value>";
}
-void TilePriority::AsValueInto(base::debug::TracedValue* state) const {
+void TilePriority::AsValueInto(base::trace_event::TracedValue* state) const {
state->SetString("resolution", TileResolutionToString(resolution));
state->SetString("priority_bin", TilePriorityBinToString(priority_bin));
state->SetDouble("distance_to_visible",
@@ -86,7 +86,7 @@
}
void GlobalStateThatImpactsTilePriority::AsValueInto(
- base::debug::TracedValue* state) const {
+ base::trace_event::TracedValue* state) const {
state->SetString("memory_limit_policy",
TileMemoryLimitPolicyToString(memory_limit_policy));
state->SetInteger("soft_memory_limit_in_bytes", soft_memory_limit_in_bytes);
diff --git a/cc/resources/tile_priority.h b/cc/resources/tile_priority.h
index 405ca92..5067aa6 100644
--- a/cc/resources/tile_priority.h
+++ b/cc/resources/tile_priority.h
@@ -74,7 +74,7 @@
}
}
- void AsValueInto(base::debug::TracedValue* dict) const;
+ void AsValueInto(base::trace_event::TracedValue* dict) const;
bool operator ==(const TilePriority& other) const {
return resolution == other.resolution &&
@@ -151,7 +151,7 @@
return !(*this == other);
}
- void AsValueInto(base::debug::TracedValue* dict) const;
+ void AsValueInto(base::trace_event::TracedValue* dict) const;
};
} // namespace cc
diff --git a/cc/resources/tile_task_worker_pool_perftest.cc b/cc/resources/tile_task_worker_pool_perftest.cc
index 483b71f..450bcbe 100644
--- a/cc/resources/tile_task_worker_pool_perftest.cc
+++ b/cc/resources/tile_task_worker_pool_perftest.cc
@@ -9,6 +9,7 @@
#include "cc/debug/lap_timer.h"
#include "cc/output/context_provider.h"
#include "cc/resources/bitmap_tile_task_worker_pool.h"
+#include "cc/resources/gpu_rasterizer.h"
#include "cc/resources/gpu_tile_task_worker_pool.h"
#include "cc/resources/one_copy_tile_task_worker_pool.h"
#include "cc/resources/pixel_buffer_tile_task_worker_pool.h"
@@ -89,6 +90,8 @@
reinterpret_cast<GrBackendContext>(null_interface.get())));
return gr_context_.get();
}
+ void SetupLock() override {}
+ base::Lock* GetLock() override { return &context_lock_; }
bool IsContextLost() override { return false; }
void VerifyContexts() override {}
void DeleteCachedResources() override {}
@@ -103,6 +106,7 @@
scoped_ptr<PerfGLES2Interface> context_gl_;
skia::RefPtr<class GrContext> gr_context_;
TestContextSupport support_;
+ base::Lock context_lock_;
};
enum TileTaskWorkerPoolType {
@@ -228,6 +232,7 @@
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<FakeOutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
+ scoped_ptr<Rasterizer> rasterizer_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_ptr<TaskGraphRunner> task_graph_runner_;
LapTimer timer_;
@@ -267,7 +272,7 @@
Create3dOutputSurfaceAndResourceProvider();
tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
task_runner_.get(), task_graph_runner_.get(),
- resource_provider_.get());
+ static_cast<GpuRasterizer*>(rasterizer_.get()));
break;
case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
CreateSoftwareOutputSurfaceAndResourceProvider();
diff --git a/cc/resources/tile_task_worker_pool_unittest.cc b/cc/resources/tile_task_worker_pool_unittest.cc
index 68758f6..1e84674 100644
--- a/cc/resources/tile_task_worker_pool_unittest.cc
+++ b/cc/resources/tile_task_worker_pool_unittest.cc
@@ -10,6 +10,7 @@
#include "base/cancelable_callback.h"
#include "cc/base/unique_notifier.h"
#include "cc/resources/bitmap_tile_task_worker_pool.h"
+#include "cc/resources/gpu_rasterizer.h"
#include "cc/resources/gpu_tile_task_worker_pool.h"
#include "cc/resources/one_copy_tile_task_worker_pool.h"
#include "cc/resources/picture_pile.h"
@@ -126,6 +127,7 @@
TileTaskWorkerPoolTest()
: context_provider_(TestContextProvider::Create()),
+ worker_context_provider_(TestContextProvider::Create()),
all_tile_tasks_finished_(
base::MessageLoopProxy::current().get(),
base::Bind(&TileTaskWorkerPoolTest::AllTileTasksFinished,
@@ -160,10 +162,12 @@
break;
case TILE_TASK_WORKER_POOL_TYPE_GPU:
Create3dOutputSurfaceAndResourceProvider();
+ rasterizer_ = GpuRasterizer::Create(
+ context_provider_.get(), resource_provider_.get(), false, false, 0);
tile_task_worker_pool_ = GpuTileTaskWorkerPool::Create(
base::MessageLoopProxy::current().get(),
TileTaskWorkerPool::GetTaskGraphRunner(),
- resource_provider_.get());
+ static_cast<GpuRasterizer*>(rasterizer_.get()));
break;
case TILE_TASK_WORKER_POOL_TYPE_BITMAP:
CreateSoftwareOutputSurfaceAndResourceProvider();
@@ -271,7 +275,8 @@
private:
void Create3dOutputSurfaceAndResourceProvider() {
- output_surface_ = FakeOutputSurface::Create3d(context_provider_).Pass();
+ output_surface_ = FakeOutputSurface::Create3d(
+ context_provider_, worker_context_provider_).Pass();
CHECK(output_surface_->BindToClient(&output_surface_client_));
TestWebGraphicsContext3D* context3d = context_provider_->TestContext3d();
context3d->set_support_sync_query(true);
@@ -306,6 +311,8 @@
protected:
scoped_refptr<TestContextProvider> context_provider_;
+ scoped_refptr<TestContextProvider> worker_context_provider_;
+ scoped_ptr<Rasterizer> rasterizer_;
FakeOutputSurfaceClient output_surface_client_;
scoped_ptr<FakeOutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
diff --git a/cc/resources/transform_display_item.cc b/cc/resources/transform_display_item.cc
index 7ab2421..a25f347 100644
--- a/cc/resources/transform_display_item.cc
+++ b/cc/resources/transform_display_item.cc
@@ -36,7 +36,8 @@
return sizeof(gfx::Transform);
}
-void TransformDisplayItem::AsValueInto(base::debug::TracedValue* array) const {
+void TransformDisplayItem::AsValueInto(
+ base::trace_event::TracedValue* array) const {
array->AppendString(base::StringPrintf("TransformDisplayItem transform: [%s]",
transform_.ToString().c_str()));
}
@@ -65,7 +66,7 @@
}
void EndTransformDisplayItem::AsValueInto(
- base::debug::TracedValue* array) const {
+ base::trace_event::TracedValue* array) const {
array->AppendString("EndTransformDisplayItem");
}
diff --git a/cc/resources/transform_display_item.h b/cc/resources/transform_display_item.h
index 0e62623..fe0dbd2 100644
--- a/cc/resources/transform_display_item.h
+++ b/cc/resources/transform_display_item.h
@@ -29,7 +29,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
explicit TransformDisplayItem(const gfx::Transform& transform);
@@ -51,7 +51,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
EndTransformDisplayItem();
diff --git a/cc/resources/transparency_display_item.cc b/cc/resources/transparency_display_item.cc
index 369e51b..1c37b73 100644
--- a/cc/resources/transparency_display_item.cc
+++ b/cc/resources/transparency_display_item.cc
@@ -42,7 +42,7 @@
}
void TransparencyDisplayItem::AsValueInto(
- base::debug::TracedValue* array) const {
+ base::trace_event::TracedValue* array) const {
array->AppendString(
base::StringPrintf("TransparencyDisplayItem opacity: %f, blend_mode: %d",
opacity_, blend_mode_));
@@ -72,7 +72,7 @@
}
void EndTransparencyDisplayItem::AsValueInto(
- base::debug::TracedValue* array) const {
+ base::trace_event::TracedValue* array) const {
array->AppendString("EndTransparencyDisplayItem");
}
diff --git a/cc/resources/transparency_display_item.h b/cc/resources/transparency_display_item.h
index 9697406..d7ae7be 100644
--- a/cc/resources/transparency_display_item.h
+++ b/cc/resources/transparency_display_item.h
@@ -32,7 +32,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
TransparencyDisplayItem(float opacity, SkXfermode::Mode blend_mode);
@@ -55,7 +55,7 @@
bool IsSuitableForGpuRasterization() const override;
int ApproximateOpCount() const override;
size_t PictureMemoryUsage() const override;
- void AsValueInto(base::debug::TracedValue* array) const override;
+ void AsValueInto(base::trace_event::TracedValue* array) const override;
protected:
EndTransparencyDisplayItem();
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index 6375057..0e772eb 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -296,7 +296,9 @@
ResourceProvider::ScopedWriteLockSoftware lock(
resource_provider_, plane_resource.resource_id);
SkCanvas canvas(lock.sk_bitmap());
- video_renderer_->Copy(video_frame, &canvas);
+ // This is software path, so canvas and video_frame are always backed
+ // by software.
+ video_renderer_->Copy(video_frame, &canvas, media::Context3D());
SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resource);
}
diff --git a/cc/resources/zero_copy_tile_task_worker_pool.cc b/cc/resources/zero_copy_tile_task_worker_pool.cc
index 9432214..8b80aa3 100644
--- a/cc/resources/zero_copy_tile_task_worker_pool.cc
+++ b/cc/resources/zero_copy_tile_task_worker_pool.cc
@@ -196,10 +196,10 @@
client_->DidFinishRunningTileTasks(task_set);
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
ZeroCopyTileTaskWorkerPool::StateAsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
state->BeginArray("tasks_pending");
for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set)
diff --git a/cc/resources/zero_copy_tile_task_worker_pool.h b/cc/resources/zero_copy_tile_task_worker_pool.h
index 4f3085c..b64e0f5 100644
--- a/cc/resources/zero_copy_tile_task_worker_pool.h
+++ b/cc/resources/zero_copy_tile_task_worker_pool.h
@@ -14,13 +14,7 @@
namespace trace_event {
class ConvertableToTraceFormat;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
}
-} // namespace base
namespace cc {
class ResourceProvider;
@@ -58,7 +52,8 @@
private:
void OnTaskSetFinished(TaskSet task_set);
- scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> StateAsValue()
+ const;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
TaskGraphRunner* task_graph_runner_;
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc
index 9b200e9..42b8f6f 100644
--- a/cc/scheduler/begin_frame_source.cc
+++ b/cc/scheduler/begin_frame_source.cc
@@ -53,7 +53,7 @@
}
void BeginFrameObserverMixIn::AsValueInto(
- base::debug::TracedValue* dict) const {
+ base::trace_event::TracedValue* dict) const {
dict->BeginDictionary("last_begin_frame_args_");
last_begin_frame_args_.AsValueInto(dict);
dict->EndDictionary();
@@ -117,7 +117,8 @@
}
// Tracing support
-void BeginFrameSourceMixIn::AsValueInto(base::debug::TracedValue* dict) const {
+void BeginFrameSourceMixIn::AsValueInto(
+ base::trace_event::TracedValue* dict) const {
// As the observer might try to trace the source, prevent an infinte loop
// from occuring.
if (inside_as_value_into_) {
@@ -198,7 +199,7 @@
// Tracing support
void BackToBackBeginFrameSource::AsValueInto(
- base::debug::TracedValue* dict) const {
+ base::trace_event::TracedValue* dict) const {
dict->SetString("type", "BackToBackBeginFrameSource");
BeginFrameSourceMixIn::AsValueInto(dict);
dict->SetBoolean("send_begin_frame_posted_", send_begin_frame_posted_);
@@ -264,13 +265,9 @@
}
}
-bool SyntheticBeginFrameSource::NeedsBeginFrames() const {
- return time_source_->Active();
-}
-
// Tracing support
void SyntheticBeginFrameSource::AsValueInto(
- base::debug::TracedValue* dict) const {
+ base::trace_event::TracedValue* dict) const {
dict->SetString("type", "SyntheticBeginFrameSource");
BeginFrameSourceMixIn::AsValueInto(dict);
@@ -406,14 +403,6 @@
}
// BeginFrameSource support
-bool BeginFrameSourceMultiplexer::NeedsBeginFrames() const {
- if (active_source_) {
- return active_source_->NeedsBeginFrames();
- } else {
- return false;
- }
-}
-
void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange(
bool needs_begin_frames) {
DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange",
@@ -439,7 +428,7 @@
// Tracing support
void BeginFrameSourceMultiplexer::AsValueInto(
- base::debug::TracedValue* dict) const {
+ base::trace_event::TracedValue* dict) const {
dict->SetString("type", "BeginFrameSourceMultiplexer");
dict->SetInteger("minimum_interval_us", minimum_interval_.InMicroseconds());
diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h
index 1612a28..d845dac 100644
--- a/cc/scheduler/begin_frame_source.h
+++ b/cc/scheduler/begin_frame_source.h
@@ -50,7 +50,7 @@
virtual const BeginFrameArgs LastUsedBeginFrameArgs() const = 0;
// Tracing support
- virtual void AsValueInto(base::debug::TracedValue* dict) const = 0;
+ virtual void AsValueInto(base::trace_event::TracedValue* dict) const = 0;
};
// Simple mix in which implements a BeginFrameObserver which checks the
@@ -75,7 +75,7 @@
const BeginFrameArgs LastUsedBeginFrameArgs() const override;
// Outputs last_begin_frame_args_
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
protected:
// Subclasses should override this method!
@@ -122,7 +122,7 @@
// Tracing support - Recommend (but not required) to call this implementation
// in any override.
- virtual void AsValueInto(base::debug::TracedValue* dict) const = 0;
+ virtual void AsValueInto(base::trace_event::TracedValue* dict) const = 0;
};
// Simple mix in which implements a BeginFrameSource.
@@ -137,7 +137,7 @@
~BeginFrameSourceMixIn() override {}
// BeginFrameSource
- bool NeedsBeginFrames() const override;
+ bool NeedsBeginFrames() const final;
void SetNeedsBeginFrames(bool needs_begin_frames) final;
void DidFinishFrame(size_t remaining_frames) override {}
void AddObserver(BeginFrameObserver* obs) final;
@@ -146,7 +146,7 @@
// Tracing support - Recommend (but not required) to call this implementation
// in any override.
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
protected:
BeginFrameSourceMixIn();
@@ -178,7 +178,7 @@
void DidFinishFrame(size_t remaining_frames) override;
// Tracing
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
protected:
explicit BackToBackBeginFrameSource(
@@ -210,11 +210,8 @@
base::TimeDelta initial_vsync_interval);
~SyntheticBeginFrameSource() override;
- // BeginFrameSource
- bool NeedsBeginFrames() const override;
-
// Tracing
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
// VSyncParameterObserver
void OnUpdateVSyncParameters(base::TimeTicks new_vsync_timebase,
@@ -260,14 +257,13 @@
const BeginFrameArgs LastUsedBeginFrameArgs() const override;
// BeginFrameSource
- bool NeedsBeginFrames() const override;
void DidFinishFrame(size_t remaining_frames) override;
// BeginFrameSourceMixIn
void OnNeedsBeginFramesChange(bool needs_begin_frames) override;
// Tracing
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
protected:
BeginFrameSourceMultiplexer();
diff --git a/cc/scheduler/begin_frame_source_unittest.cc b/cc/scheduler/begin_frame_source_unittest.cc
index 0972762..22126be 100644
--- a/cc/scheduler/begin_frame_source_unittest.cc
+++ b/cc/scheduler/begin_frame_source_unittest.cc
@@ -64,7 +64,7 @@
MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&));
MOCK_CONST_METHOD0(LastUsedBeginFrameArgs, const BeginFrameArgs());
- virtual void AsValueInto(base::debug::TracedValue* dict) const {
+ virtual void AsValueInto(base::trace_event::TracedValue* dict) const {
dict->SetString("type", "MockBeginFrameObserver");
dict->BeginDictionary("last_begin_frame_args");
LastUsedBeginFrameArgs().AsValueInto(dict);
@@ -284,7 +284,7 @@
public:
BeginFrameSource* source_;
- void AsValueInto(base::debug::TracedValue* dict) const override {
+ void AsValueInto(base::trace_event::TracedValue* dict) const override {
dict->SetString("type", "LoopingBeginFrameObserver");
dict->BeginDictionary("source");
source_->AsValueInto(dict);
@@ -305,8 +305,8 @@
obs.source_ = &source;
source.AddObserver(&obs);
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
source.AsValueInto(state.get());
}
diff --git a/cc/scheduler/delay_based_time_source.cc b/cc/scheduler/delay_based_time_source.cc
index 457f718..ef43524 100644
--- a/cc/scheduler/delay_based_time_source.cc
+++ b/cc/scheduler/delay_based_time_source.cc
@@ -234,34 +234,20 @@
// now=37 tick_target=16.667 new_target=50.000 -->
// tick(), PostDelayedTask(floor(50.000-37)) --> PostDelayedTask(13)
base::TimeTicks DelayBasedTimeSource::NextTickTarget(base::TimeTicks now) {
- base::TimeDelta new_interval = next_parameters_.interval;
-
- // |interval_offset| is the offset from |now| to the next multiple of
- // |interval| after |tick_target|, possibly negative if in the past.
- base::TimeDelta interval_offset = base::TimeDelta::FromInternalValue(
- (next_parameters_.tick_target - now).ToInternalValue() %
- new_interval.ToInternalValue());
- // If |now| is exactly on the interval (i.e. offset==0), don't adjust.
- // Otherwise, if |tick_target| was in the past, adjust forward to the next
- // tick after |now|.
- if (interval_offset.ToInternalValue() != 0 &&
- next_parameters_.tick_target < now) {
- interval_offset += new_interval;
- }
-
- base::TimeTicks new_tick_target = now + interval_offset;
+ base::TimeTicks new_tick_target = now.SnappedToNextTick(
+ next_parameters_.tick_target, next_parameters_.interval);
DCHECK(now <= new_tick_target)
<< "now = " << now.ToInternalValue()
<< "; new_tick_target = " << new_tick_target.ToInternalValue()
- << "; new_interval = " << new_interval.InMicroseconds()
- << "; tick_target = " << next_parameters_.tick_target.ToInternalValue()
- << "; interval_offset = " << interval_offset.ToInternalValue();
+ << "; new_interval = " << next_parameters_.interval.InMicroseconds()
+ << "; tick_target = " << next_parameters_.tick_target.ToInternalValue();
// Avoid double ticks when:
// 1) Turning off the timer and turning it right back on.
// 2) Jittery data is passed to SetTimebaseAndInterval().
- if (new_tick_target - last_tick_time_ <= new_interval / kDoubleTickDivisor)
- new_tick_target += new_interval;
+ if (new_tick_target - last_tick_time_ <=
+ next_parameters_.interval / kDoubleTickDivisor)
+ new_tick_target += next_parameters_.interval;
return new_tick_target;
}
@@ -290,7 +276,8 @@
return "DelayBasedTimeSourceHighRes";
}
-void DelayBasedTimeSource::AsValueInto(base::debug::TracedValue* state) const {
+void DelayBasedTimeSource::AsValueInto(
+ base::trace_event::TracedValue* state) const {
state->SetString("type", TypeString());
state->SetDouble("last_tick_time_us", LastTickTime().ToInternalValue());
state->SetDouble("next_tick_time_us", NextTickTime().ToInternalValue());
diff --git a/cc/scheduler/delay_based_time_source.h b/cc/scheduler/delay_based_time_source.h
index da968a6..4d7276c 100644
--- a/cc/scheduler/delay_based_time_source.h
+++ b/cc/scheduler/delay_based_time_source.h
@@ -15,14 +15,8 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
-}
class SingleThreadTaskRunner;
-} // namespace base
+}
namespace cc {
@@ -61,7 +55,7 @@
// Virtual for testing.
virtual base::TimeTicks Now() const;
- virtual void AsValueInto(base::debug::TracedValue* dict) const;
+ virtual void AsValueInto(base::trace_event::TracedValue* dict) const;
protected:
DelayBasedTimeSource(base::TimeDelta interval,
diff --git a/cc/scheduler/delay_based_time_source_unittest.cc b/cc/scheduler/delay_based_time_source_unittest.cc
index 0af8b02..f721b11 100644
--- a/cc/scheduler/delay_based_time_source_unittest.cc
+++ b/cc/scheduler/delay_based_time_source_unittest.cc
@@ -508,23 +508,6 @@
EXPECT_EQ(13, task_runner->NextPendingTaskDelay().InMilliseconds());
}
-TEST(DelayBasedTimeSourceTest, TestOverflow) {
- // int(big_now / interval) < 0, so this causes a crash if the number of
- // intervals elapsed is attempted to be stored in an int.
- base::TimeDelta interval = base::TimeDelta::FromInternalValue(4000);
- base::TimeTicks big_now = base::TimeTicks::FromInternalValue(8635916564000);
-
- scoped_refptr<base::TestSimpleTaskRunner> task_runner =
- new base::TestSimpleTaskRunner;
- FakeTimeSourceClient client;
- scoped_refptr<FakeDelayBasedTimeSource> timer =
- FakeDelayBasedTimeSource::Create(interval, task_runner.get());
- timer->SetClient(&client);
- timer->SetNow(big_now);
- timer->SetActive(true);
- EXPECT_EQ(0, task_runner->NextPendingTaskDelay().InMilliseconds());
-}
-
TEST(DelayBasedTimeSourceTest, TestReturnValueWhenTimerIsDeActivated) {
scoped_refptr<base::TestSimpleTaskRunner> task_runner =
new base::TestSimpleTaskRunner;
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 43812e8..ed8c0a2 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -740,15 +740,15 @@
RescheduleBeginImplFrameDeadlineIfNeeded();
}
-scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue()
+scoped_refptr<base::trace_event::ConvertableToTraceFormat> Scheduler::AsValue()
const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get());
return state;
}
-void Scheduler::AsValueInto(base::debug::TracedValue* state) const {
+void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const {
state->BeginDictionary("state_machine");
state_machine_.AsValueInto(state, Now());
state->EndDictionary();
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index ddc3f2f..82f305a 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -27,14 +27,8 @@
namespace trace_event {
class ConvertableToTraceFormat;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
-}
class SingleThreadTaskRunner;
-} // namespace base
+}
namespace cc {
@@ -170,8 +164,8 @@
void SetDeferCommits(bool defer_commits);
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
- void AsValueInto(base::debug::TracedValue* value) const override;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::trace_event::TracedValue* value) const override;
void SetContinuousPainting(bool continuous_painting) {
state_machine_.SetContinuousPainting(continuous_painting);
diff --git a/cc/scheduler/scheduler_settings.cc b/cc/scheduler/scheduler_settings.cc
index c1db76b..8713391 100644
--- a/cc/scheduler/scheduler_settings.cc
+++ b/cc/scheduler/scheduler_settings.cc
@@ -46,10 +46,10 @@
SchedulerSettings::~SchedulerSettings() {}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
SchedulerSettings::AsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
state->SetBoolean("use_external_begin_frame_source",
use_external_begin_frame_source);
state->SetBoolean("forward_begin_frames_to_children",
diff --git a/cc/scheduler/scheduler_settings.h b/cc/scheduler/scheduler_settings.h
index 90c1a9c..fe90f43 100644
--- a/cc/scheduler/scheduler_settings.h
+++ b/cc/scheduler/scheduler_settings.h
@@ -14,13 +14,7 @@
namespace trace_event {
class ConvertableToTraceFormat;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
}
-} // namespace base
namespace cc {
class LayerTreeSettings;
@@ -49,7 +43,7 @@
base::TimeDelta background_frame_interval;
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
};
} // namespace cc
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 7bce7ee..4e6509f 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -148,15 +148,15 @@
return "???";
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
SchedulerStateMachine::AsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get(), gfx::FrameTime::Now());
return state;
}
-void SchedulerStateMachine::AsValueInto(base::debug::TracedValue* state,
+void SchedulerStateMachine::AsValueInto(base::trace_event::TracedValue* state,
base::TimeTicks now) const {
state->BeginDictionary("major_state");
state->SetString("next_action", ActionToString(NextAction()));
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index fb87c84..f77df28 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -21,15 +21,8 @@
class ConvertableToTraceFormat;
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::ConvertableToTraceFormat;
-using ::base::trace_event::TracedValue;
-}
class Value;
-} // namespace base
+}
namespace cc {
@@ -121,8 +114,9 @@
};
static const char* ActionToString(Action action);
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
- void AsValueInto(base::debug::TracedValue* dict, base::TimeTicks now) const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::trace_event::TracedValue* dict,
+ base::TimeTicks now) const;
Action NextAction() const;
void UpdateState(Action action);
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index e4ce6b3..ac52271 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -189,7 +189,8 @@
bool begin_frame_is_sent_to_children_;
base::TimeTicks posted_begin_impl_frame_deadline_;
std::vector<const char*> actions_;
- std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat>> states_;
+ std::vector<scoped_refptr<base::trace_event::ConvertableToTraceFormat>>
+ states_;
TestScheduler* scheduler_;
};
diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc
index 068fe03..b99e2b4 100644
--- a/cc/surfaces/surface_display_output_surface.cc
+++ b/cc/surfaces/surface_display_output_surface.cc
@@ -17,7 +17,7 @@
SurfaceManager* surface_manager,
SurfaceIdAllocator* allocator,
const scoped_refptr<ContextProvider>& context_provider)
- : OutputSurface(context_provider, nullptr),
+ : OutputSurface(context_provider),
display_client_(NULL),
surface_manager_(surface_manager),
factory_(surface_manager, this),
diff --git a/cc/test/data/enlarged_texture_on_threshold.png b/cc/test/data/enlarged_texture_on_threshold.png
new file mode 100644
index 0000000..6b232be
--- /dev/null
+++ b/cc/test/data/enlarged_texture_on_threshold.png
Binary files differ
diff --git a/cc/test/failure_output_surface.cc b/cc/test/failure_output_surface.cc
index 2c87853..c0d5fdb 100644
--- a/cc/test/failure_output_surface.cc
+++ b/cc/test/failure_output_surface.cc
@@ -7,7 +7,7 @@
namespace cc {
FailureOutputSurface::FailureOutputSurface(bool is_delegating)
- : FakeOutputSurface(nullptr, nullptr, is_delegating) {
+ : FakeOutputSurface(static_cast<ContextProvider*>(nullptr), is_delegating) {
}
bool FailureOutputSurface::BindToClient(OutputSurfaceClient* client) {
diff --git a/cc/test/fake_layer_tree_host.h b/cc/test/fake_layer_tree_host.h
index 3daf471..858574f 100644
--- a/cc/test/fake_layer_tree_host.h
+++ b/cc/test/fake_layer_tree_host.h
@@ -51,10 +51,11 @@
bool needs_commit() { return needs_commit_; }
- private:
+ protected:
FakeLayerTreeHost(FakeLayerTreeHostClient* client,
const LayerTreeSettings& settings);
+ private:
FakeImplProxy proxy_;
FakeLayerTreeHostClient* client_;
TestSharedBitmapManager manager_;
diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc
index d54d2d1..0279421 100644
--- a/cc/test/fake_output_surface.cc
+++ b/cc/test/fake_output_surface.cc
@@ -16,6 +16,21 @@
FakeOutputSurface::FakeOutputSurface(
scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider,
+ bool delegated_rendering)
+ : OutputSurface(context_provider, worker_context_provider),
+ client_(NULL),
+ num_sent_frames_(0),
+ has_external_stencil_test_(false),
+ framebuffer_(0) {
+ if (delegated_rendering) {
+ capabilities_.delegated_rendering = true;
+ capabilities_.max_frames_pending = 1;
+ }
+}
+
+FakeOutputSurface::FakeOutputSurface(
+ scoped_refptr<ContextProvider> context_provider,
bool delegated_rendering)
: OutputSurface(context_provider),
client_(NULL),
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h
index a564eef..39a78ea 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -24,7 +24,7 @@
static scoped_ptr<FakeOutputSurface> Create3d() {
return make_scoped_ptr(new FakeOutputSurface(
- TestContextProvider::Create(), false));
+ TestContextProvider::Create(), TestContextProvider::Create(), false));
}
static scoped_ptr<FakeOutputSurface> Create3d(
@@ -33,6 +33,13 @@
}
static scoped_ptr<FakeOutputSurface> Create3d(
+ scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider) {
+ return make_scoped_ptr(new FakeOutputSurface(
+ context_provider, worker_context_provider, false));
+ }
+
+ static scoped_ptr<FakeOutputSurface> Create3d(
scoped_ptr<TestWebGraphicsContext3D> context) {
return make_scoped_ptr(new FakeOutputSurface(
TestContextProvider::Create(context.Pass()), false));
@@ -46,7 +53,7 @@
static scoped_ptr<FakeOutputSurface> CreateDelegating3d() {
return make_scoped_ptr(new FakeOutputSurface(
- TestContextProvider::Create(), true));
+ TestContextProvider::Create(), TestContextProvider::Create(), true));
}
static scoped_ptr<FakeOutputSurface> CreateDelegating3d(
@@ -128,9 +135,12 @@
scoped_refptr<ContextProvider> context_provider,
bool delegated_rendering);
- FakeOutputSurface(
- scoped_ptr<SoftwareOutputDevice> software_device,
- bool delegated_rendering);
+ FakeOutputSurface(scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider,
+ bool delegated_rendering);
+
+ FakeOutputSurface(scoped_ptr<SoftwareOutputDevice> software_device,
+ bool delegated_rendering);
FakeOutputSurface(
scoped_refptr<ContextProvider> context_provider,
diff --git a/cc/test/fake_painted_scrollbar_layer.h b/cc/test/fake_painted_scrollbar_layer.h
index e86a2e9..033d920 100644
--- a/cc/test/fake_painted_scrollbar_layer.h
+++ b/cc/test/fake_painted_scrollbar_layer.h
@@ -40,6 +40,7 @@
FakeScrollbar* fake_scrollbar() {
return fake_scrollbar_;
}
+ using PaintedScrollbarLayer::UpdateInternalContentScale;
using PaintedScrollbarLayer::UpdateThumbAndTrackGeometry;
private:
diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc
index 43db7bc..5ac6f69 100644
--- a/cc/test/fake_picture_layer_impl.cc
+++ b/cc/test/fake_picture_layer_impl.cc
@@ -86,10 +86,8 @@
void FakePictureLayerImpl::AppendQuads(
RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) {
- PictureLayerImpl::AppendQuads(
- render_pass, occlusion_in_content_space, append_quads_data);
+ PictureLayerImpl::AppendQuads(render_pass, append_quads_data);
++append_quads_count_;
}
@@ -137,6 +135,12 @@
UpdateRasterSource(raster_source, &invalidation_temp, pending_set);
}
+void FakePictureLayerImpl::SetIsDrawnRenderSurfaceLayerListMember(bool is) {
+ draw_properties().last_drawn_render_surface_layer_list_id =
+ is ? layer_tree_impl()->current_render_surface_list_id()
+ : layer_tree_impl()->current_render_surface_list_id() - 1;
+}
+
void FakePictureLayerImpl::CreateAllTiles() {
for (size_t i = 0; i < num_tilings(); ++i)
tilings_->tiling_at(i)->CreateAllTilesForTesting();
diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h
index caac373..115fe55 100644
--- a/cc/test/fake_picture_layer_impl.h
+++ b/cc/test/fake_picture_layer_impl.h
@@ -53,7 +53,6 @@
scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
void PushPropertiesTo(LayerImpl* layer_impl) override;
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override;
gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override;
@@ -113,6 +112,8 @@
void set_fixed_tile_size(const gfx::Size& size) { fixed_tile_size_ = size; }
+ void SetIsDrawnRenderSurfaceLayerListMember(bool is);
+
void CreateAllTiles();
void SetAllTilesVisible();
void SetAllTilesReady();
diff --git a/cc/test/fake_picture_pile.cc b/cc/test/fake_picture_pile.cc
index 912ec06..cc0a7ba 100644
--- a/cc/test/fake_picture_pile.cc
+++ b/cc/test/fake_picture_pile.cc
@@ -4,12 +4,101 @@
#include "cc/test/fake_picture_pile.h"
+#include <utility>
+
#include "cc/test/fake_picture_pile_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
+namespace {
+
+scoped_ptr<FakePicturePile> CreatePile(const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds,
+ bool is_filled) {
+ scoped_ptr<FakePicturePile> pile(
+ new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale,
+ ImplSidePaintingSettings().default_tile_grid_size));
+ pile->tiling().SetBorderTexels(0);
+ pile->tiling().SetTilingSize(layer_bounds);
+ pile->tiling().SetMaxTextureSize(tile_size);
+ pile->SetRecordedViewport(is_filled ? gfx::Rect(layer_bounds) : gfx::Rect());
+ pile->SetHasAnyRecordings(is_filled);
+ if (is_filled) {
+ for (int x = 0; x < pile->tiling().num_tiles_x(); ++x) {
+ for (int y = 0; y < pile->tiling().num_tiles_y(); ++y)
+ pile->AddRecordingAt(x, y);
+ }
+ }
+ return pile;
+}
+
+} // namespace
+
+scoped_ptr<FakePicturePile> FakePicturePile::CreateFilledPile(
+ const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds) {
+ bool is_filled = true;
+ return CreatePile(tile_size, layer_bounds, is_filled);
+}
+
+scoped_ptr<FakePicturePile> FakePicturePile::CreateEmptyPile(
+ const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds) {
+ bool is_filled = false;
+ return CreatePile(tile_size, layer_bounds, is_filled);
+}
+
scoped_refptr<RasterSource> FakePicturePile::CreateRasterSource() const {
return FakePicturePileImpl::CreateFromPile(this, playback_allowed_event_);
}
+void FakePicturePile::AddRecordingAt(int x, int y) {
+ EXPECT_GE(x, 0);
+ EXPECT_GE(y, 0);
+ EXPECT_LT(x, tiling_.num_tiles_x());
+ EXPECT_LT(y, tiling_.num_tiles_y());
+
+ if (HasRecordingAt(x, y))
+ return;
+ gfx::Rect bounds(tiling().TileBounds(x, y));
+ bounds.Inset(-buffer_pixels(), -buffer_pixels());
+
+ scoped_refptr<Picture> picture(
+ Picture::Create(bounds, &client_, tile_grid_size_, true,
+ RecordingSource::RECORD_NORMALLY));
+ picture_map_[std::pair<int, int>(x, y)].SetPicture(picture);
+ EXPECT_TRUE(HasRecordingAt(x, y));
+
+ has_any_recordings_ = true;
+}
+
+void FakePicturePile::RemoveRecordingAt(int x, int y) {
+ EXPECT_GE(x, 0);
+ EXPECT_GE(y, 0);
+ EXPECT_LT(x, tiling_.num_tiles_x());
+ EXPECT_LT(y, tiling_.num_tiles_y());
+
+ if (!HasRecordingAt(x, y))
+ return;
+ picture_map_.erase(std::pair<int, int>(x, y));
+ EXPECT_FALSE(HasRecordingAt(x, y));
+}
+
+bool FakePicturePile::HasRecordingAt(int x, int y) const {
+ PictureMap::const_iterator found = picture_map_.find(PictureMapKey(x, y));
+ if (found == picture_map_.end())
+ return false;
+ return !!found->second.GetPicture();
+}
+
+void FakePicturePile::RerecordPile() {
+ for (int y = 0; y < num_tiles_y(); ++y) {
+ for (int x = 0; x < num_tiles_x(); ++x) {
+ RemoveRecordingAt(x, y);
+ AddRecordingAt(x, y);
+ }
+ }
+}
+
} // namespace cc
diff --git a/cc/test/fake_picture_pile.h b/cc/test/fake_picture_pile.h
index 55b4c36..054eaa2 100644
--- a/cc/test/fake_picture_pile.h
+++ b/cc/test/fake_picture_pile.h
@@ -6,6 +6,8 @@
#define CC_TEST_FAKE_PICTURE_PILE_H_
#include "cc/resources/picture_pile.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/impl_side_painting_settings.h"
namespace base {
class WaitableEvent;
@@ -24,6 +26,13 @@
playback_allowed_event_(nullptr) {}
~FakePicturePile() override {}
+ static scoped_ptr<FakePicturePile> CreateFilledPile(
+ const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds);
+ static scoped_ptr<FakePicturePile> CreateEmptyPile(
+ const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds);
+
// PicturePile overrides.
scoped_refptr<RasterSource> CreateRasterSource() const override;
@@ -53,6 +62,10 @@
has_any_recordings_ = has_recordings;
}
+ void SetClearCanvasWithDebugColor(bool clear) {
+ clear_canvas_with_debug_color_ = clear;
+ }
+
void SetPlaybackAllowedEvent(base::WaitableEvent* event) {
playback_allowed_event_ = event;
}
@@ -61,11 +74,42 @@
bool is_solid_color() const { return is_solid_color_; }
SkColor solid_color() const { return solid_color_; }
+ void SetIsSolidColor(bool is_solid) { is_solid_color_ = is_solid; }
void SetPixelRecordDistance(int d) { pixel_record_distance_ = d; }
+ void add_draw_rect(const gfx::RectF& rect) {
+ client_.add_draw_rect(rect, default_paint_);
+ }
+
+ void add_draw_bitmap(const SkBitmap& bitmap, const gfx::Point& point) {
+ client_.add_draw_bitmap(bitmap, point, default_paint_);
+ }
+
+ void add_draw_rect_with_paint(const gfx::RectF& rect, const SkPaint& paint) {
+ client_.add_draw_rect(rect, paint);
+ }
+
+ void add_draw_bitmap_with_paint(const SkBitmap& bitmap,
+ const gfx::Point& point,
+ const SkPaint& paint) {
+ client_.add_draw_bitmap(bitmap, point, paint);
+ }
+
+ void set_default_paint(const SkPaint& paint) { default_paint_ = paint; }
+
+ void AddRecordingAt(int x, int y);
+ void RemoveRecordingAt(int x, int y);
+ bool HasRecordingAt(int x, int y) const;
+ int num_tiles_x() const { return tiling_.num_tiles_x(); }
+ int num_tiles_y() const { return tiling_.num_tiles_y(); }
+ void RerecordPile();
+
private:
base::WaitableEvent* playback_allowed_event_;
+
+ FakeContentLayerClient client_;
+ SkPaint default_paint_;
};
} // namespace cc
diff --git a/cc/test/fake_picture_pile_impl.cc b/cc/test/fake_picture_pile_impl.cc
index bdba092..8353d27 100644
--- a/cc/test/fake_picture_pile_impl.cc
+++ b/cc/test/fake_picture_pile_impl.cc
@@ -10,7 +10,6 @@
#include "base/synchronization/waitable_event.h"
#include "cc/resources/picture_pile.h"
-#include "cc/test/fake_picture_pile.h"
#include "cc/test/impl_side_painting_settings.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -29,43 +28,47 @@
FakePicturePileImpl::~FakePicturePileImpl() {}
-scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateFilledPile(
+scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreatePile(
const gfx::Size& tile_size,
- const gfx::Size& layer_bounds) {
+ const gfx::Size& layer_bounds,
+ bool is_filled) {
FakePicturePile pile(ImplSidePaintingSettings().minimum_contents_scale,
ImplSidePaintingSettings().default_tile_grid_size);
pile.tiling().SetBorderTexels(0);
pile.tiling().SetTilingSize(layer_bounds);
pile.tiling().SetMaxTextureSize(tile_size);
- pile.SetRecordedViewport(gfx::Rect(layer_bounds));
- pile.SetHasAnyRecordings(true);
-
+ pile.SetRecordedViewport(is_filled ? gfx::Rect(layer_bounds) : gfx::Rect());
+ pile.SetHasAnyRecordings(is_filled);
+ if (is_filled) {
+ for (int x = 0; x < pile.tiling().num_tiles_x(); ++x) {
+ for (int y = 0; y < pile.tiling().num_tiles_y(); ++y)
+ pile.AddRecordingAt(x, y);
+ }
+ }
scoped_refptr<FakePicturePileImpl> pile_impl(
new FakePicturePileImpl(&pile, nullptr));
- for (int x = 0; x < pile_impl->tiling().num_tiles_x(); ++x) {
- for (int y = 0; y < pile_impl->tiling().num_tiles_y(); ++y)
- pile_impl->AddRecordingAt(x, y);
- }
return pile_impl;
}
+scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateFilledPile(
+ const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds) {
+ bool is_filled = true;
+ return CreatePile(tile_size, layer_bounds, is_filled);
+}
+
scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateEmptyPile(
const gfx::Size& tile_size,
const gfx::Size& layer_bounds) {
- FakePicturePile pile(ImplSidePaintingSettings().minimum_contents_scale,
- ImplSidePaintingSettings().default_tile_grid_size);
- pile.tiling().SetBorderTexels(0);
- pile.tiling().SetTilingSize(layer_bounds);
- pile.tiling().SetMaxTextureSize(tile_size);
- pile.SetRecordedViewport(gfx::Rect());
- pile.SetHasAnyRecordings(false);
- return make_scoped_refptr(new FakePicturePileImpl(&pile, nullptr));
+ bool is_filled = false;
+ return CreatePile(tile_size, layer_bounds, is_filled);
}
scoped_refptr<FakePicturePileImpl>
FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
const gfx::Size& tile_size,
- const gfx::Size& layer_bounds) {
+ const gfx::Size& layer_bounds,
+ bool is_solid_color) {
FakePicturePile pile(ImplSidePaintingSettings().minimum_contents_scale,
ImplSidePaintingSettings().default_tile_grid_size);
pile.tiling().SetBorderTexels(0);
@@ -74,6 +77,7 @@
// This simulates a false positive for this flag.
pile.SetRecordedViewport(gfx::Rect());
pile.SetHasAnyRecordings(true);
+ pile.SetIsSolidColor(is_solid_color);
return make_scoped_refptr(new FakePicturePileImpl(&pile, nullptr));
}
@@ -87,10 +91,9 @@
pile.tiling().SetMaxTextureSize(size);
pile.SetRecordedViewport(gfx::Rect(size));
pile.SetHasAnyRecordings(true);
-
+ pile.AddRecordingAt(0, 0);
scoped_refptr<FakePicturePileImpl> pile_impl(
new FakePicturePileImpl(&pile, nullptr));
- pile_impl->AddRecordingAt(0, 0);
return pile_impl;
}
@@ -109,38 +112,6 @@
PicturePileImpl::PlaybackToCanvas(canvas, canvas_rect, contents_scale);
}
-void FakePicturePileImpl::AddRecordingAt(int x, int y) {
- EXPECT_GE(x, 0);
- EXPECT_GE(y, 0);
- EXPECT_LT(x, tiling_.num_tiles_x());
- EXPECT_LT(y, tiling_.num_tiles_y());
-
- if (HasRecordingAt(x, y))
- return;
- gfx::Rect bounds(tiling().TileBounds(x, y));
- bounds.Inset(-buffer_pixels(), -buffer_pixels());
-
- scoped_refptr<Picture> picture(
- Picture::Create(bounds, &client_, tile_grid_size_, true,
- RecordingSource::RECORD_NORMALLY));
- picture_map_[std::pair<int, int>(x, y)].SetPicture(picture);
- EXPECT_TRUE(HasRecordingAt(x, y));
-
- has_any_recordings_ = true;
-}
-
-void FakePicturePileImpl::RemoveRecordingAt(int x, int y) {
- EXPECT_GE(x, 0);
- EXPECT_GE(y, 0);
- EXPECT_LT(x, tiling_.num_tiles_x());
- EXPECT_LT(y, tiling_.num_tiles_y());
-
- if (!HasRecordingAt(x, y))
- return;
- picture_map_.erase(std::pair<int, int>(x, y));
- EXPECT_FALSE(HasRecordingAt(x, y));
-}
-
bool FakePicturePileImpl::HasRecordingAt(int x, int y) const {
PictureMap::const_iterator found = picture_map_.find(PictureMapKey(x, y));
if (found == picture_map_.end())
@@ -148,46 +119,4 @@
return !!found->second.GetPicture();
}
-void FakePicturePileImpl::RerecordPile() {
- for (int y = 0; y < num_tiles_y(); ++y) {
- for (int x = 0; x < num_tiles_x(); ++x) {
- RemoveRecordingAt(x, y);
- AddRecordingAt(x, y);
- }
- }
-}
-
-void FakePicturePileImpl::SetMinContentsScale(float min_contents_scale) {
- if (min_contents_scale_ == min_contents_scale)
- return;
-
- // Picture contents are played back scaled. When the final contents scale is
- // less than 1 (i.e. low res), then multiple recorded pixels will be used
- // to raster one final pixel. To avoid splitting a final pixel across
- // pictures (which would result in incorrect rasterization due to blending), a
- // buffer margin is added so that any picture can be snapped to integral
- // final pixels.
- //
- // For example, if a 1/4 contents scale is used, then that would be 3 buffer
- // pixels, since that's the minimum number of pixels to add so that resulting
- // content can be snapped to a four pixel aligned grid.
- int buffer_pixels = static_cast<int>(ceil(1 / min_contents_scale) - 1);
- buffer_pixels = std::max(0, buffer_pixels);
- SetBufferPixels(buffer_pixels);
- min_contents_scale_ = min_contents_scale;
-}
-
-void FakePicturePileImpl::SetBufferPixels(int new_buffer_pixels) {
- if (new_buffer_pixels == buffer_pixels())
- return;
-
- Clear();
- tiling_.SetBorderTexels(new_buffer_pixels);
-}
-
-void FakePicturePileImpl::Clear() {
- picture_map_.clear();
- recorded_viewport_ = gfx::Rect();
-}
-
} // namespace cc
diff --git a/cc/test/fake_picture_pile_impl.h b/cc/test/fake_picture_pile_impl.h
index 3a43702..a21509a 100644
--- a/cc/test/fake_picture_pile_impl.h
+++ b/cc/test/fake_picture_pile_impl.h
@@ -7,7 +7,7 @@
#include "base/memory/ref_counted.h"
#include "cc/resources/picture_pile_impl.h"
-#include "cc/test/fake_content_layer_client.h"
+#include "cc/test/fake_picture_pile.h"
namespace base {
class WaitableEvent;
@@ -17,6 +17,11 @@
class FakePicturePileImpl : public PicturePileImpl {
public:
+ static scoped_refptr<FakePicturePileImpl> CreatePile(
+ const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds,
+ bool is_filled);
+
static scoped_refptr<FakePicturePileImpl> CreateFilledPileWithDefaultTileSize(
const gfx::Size& layer_bounds) {
return CreateFilledPile(gfx::Size(512, 512), layer_bounds);
@@ -32,8 +37,9 @@
const gfx::Size& tile_size,
const gfx::Size& layer_bounds);
static scoped_refptr<FakePicturePileImpl>
- CreateEmptyPileThatThinksItHasRecordings(const gfx::Size& tile_size,
- const gfx::Size& layer_bounds);
+ CreateEmptyPileThatThinksItHasRecordings(const gfx::Size& tile_size,
+ const gfx::Size& layer_bounds,
+ bool is_solid_color);
static scoped_refptr<FakePicturePileImpl> CreateInfiniteFilledPile();
static scoped_refptr<FakePicturePileImpl> CreateFromPile(
const PicturePile* other,
@@ -44,63 +50,18 @@
const gfx::Rect& canvas_rect,
float contents_scale) const override;
- TilingData& tiling() { return tiling_; }
-
- void AddRecordingAt(int x, int y);
- void RemoveRecordingAt(int x, int y);
- void RerecordPile();
-
- void add_draw_rect(const gfx::RectF& rect) {
- client_.add_draw_rect(rect, default_paint_);
- }
-
- void add_draw_bitmap(const SkBitmap& bitmap, const gfx::Point& point) {
- client_.add_draw_bitmap(bitmap, point, default_paint_);
- }
-
- void add_draw_rect_with_paint(const gfx::RectF& rect, const SkPaint& paint) {
- client_.add_draw_rect(rect, paint);
- }
-
- void add_draw_bitmap_with_paint(const SkBitmap& bitmap,
- const gfx::Point& point,
- const SkPaint& paint) {
- client_.add_draw_bitmap(bitmap, point, paint);
- }
-
- void set_default_paint(const SkPaint& paint) {
- default_paint_ = paint;
- }
-
- void set_background_color(SkColor color) {
- background_color_ = color;
- }
-
- void set_clear_canvas_with_debug_color(bool clear) {
- clear_canvas_with_debug_color_ = clear;
- }
-
- void set_is_solid_color(bool is_solid_color) {
- is_solid_color_ = is_solid_color;
- }
+ const TilingData& tiling() { return tiling_; }
bool HasRecordingAt(int x, int y) const;
-
int num_tiles_x() const { return tiling_.num_tiles_x(); }
int num_tiles_y() const { return tiling_.num_tiles_y(); }
- void SetMinContentsScale(float scale);
- void SetBufferPixels(int new_buffer_pixels);
- void Clear();
-
protected:
FakePicturePileImpl();
FakePicturePileImpl(const PicturePile* other,
base::WaitableEvent* playback_allowed_event);
~FakePicturePileImpl() override;
- FakeContentLayerClient client_;
- SkPaint default_paint_;
base::WaitableEvent* playback_allowed_event_;
gfx::Size tile_grid_size_;
};
diff --git a/cc/test/fake_proxy.cc b/cc/test/fake_proxy.cc
index 4490c76..b288c07 100644
--- a/cc/test/fake_proxy.cc
+++ b/cc/test/fake_proxy.cc
@@ -12,6 +12,10 @@
bool FakeProxy::IsStarted() const { return true; }
+bool FakeProxy::CommitToActiveTree() const {
+ return false;
+}
+
const RendererCapabilities& FakeProxy::GetRendererCapabilities() const {
return capabilities_;
}
@@ -38,7 +42,7 @@
return false;
}
-void FakeProxy::AsValueInto(base::debug::TracedValue*) const {
+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 e77d4f9..2309fef 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -23,6 +23,7 @@
void FinishAllRendering() override {}
bool IsStarted() const override;
+ bool CommitToActiveTree() const override;
void SetOutputSurface(scoped_ptr<OutputSurface>) override {}
void SetLayerTreeHostClientReady() override {}
void SetVisible(bool visible) override {}
@@ -45,7 +46,7 @@
bool SupportsImplScrolling() const override;
void SetDebugState(const LayerTreeDebugState& debug_state) override {}
bool MainFrameWillHappenForTesting() override;
- void AsValueInto(base::debug::TracedValue* state) const 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_test_common.cc b/cc/test/layer_test_common.cc
index 7e835b8..83f756d 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -75,9 +75,17 @@
// Quads that are fully occluded on one axis only should be shrunken.
for (const auto& quad : quads) {
- DCHECK(quad->quadTransform().IsIdentityOrIntegerTranslation());
gfx::Rect target_rect =
MathUtil::MapEnclosingClippedRect(quad->quadTransform(), quad->rect);
+ if (!quad->quadTransform().IsIdentityOrIntegerTranslation()) {
+ DCHECK(quad->quadTransform().IsPositiveScaleOrTranslation())
+ << quad->quadTransform().ToString();
+ gfx::RectF target_rectf =
+ MathUtil::MapClippedRect(quad->quadTransform(), quad->rect);
+ // Scale transforms allowed, as long as the final transformed rect
+ // ends up on integer boundaries for ease of testing.
+ DCHECK_EQ(target_rectf.ToString(), gfx::RectF(target_rect).ToString());
+ }
gfx::Rect target_visible_rect = MathUtil::MapEnclosingClippedRect(
quad->quadTransform(), quad->visible_rect);
@@ -129,9 +137,10 @@
Occlusion occlusion(layer_impl->draw_transform(),
SimpleEnclosedRegion(occluded),
SimpleEnclosedRegion());
+ layer_impl->draw_properties().occlusion_in_content_space = occlusion;
layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider());
- layer_impl->AppendQuads(render_pass_.get(), occlusion, &data);
+ layer_impl->AppendQuads(render_pass_.get(), &data);
layer_impl->DidDraw(resource_provider());
}
@@ -147,9 +156,10 @@
Occlusion occlusion(layer_impl->draw_transform(),
SimpleEnclosedRegion(occluded),
SimpleEnclosedRegion());
+ layer_impl->draw_properties().occlusion_in_content_space = occlusion;
layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider());
- layer_impl->AppendQuads(given_render_pass, occlusion, &data);
+ layer_impl->AppendQuads(given_render_pass, &data);
layer_impl->DidDraw(resource_provider());
}
@@ -160,12 +170,12 @@
render_pass_->quad_list.clear();
render_pass_->shared_quad_state_list.clear();
- occlusion_tracker_.set_occluded_target_rect_for_contributing_surface(
- occluded);
- bool for_replica = false;
- RenderPassId id(1, 1);
+
surface_impl->AppendQuads(
- render_pass_.get(), occlusion_tracker_, &data, for_replica, id);
+ render_pass_.get(), gfx::Transform(),
+ Occlusion(gfx::Transform(), SimpleEnclosedRegion(occluded),
+ SimpleEnclosedRegion()),
+ SK_ColorBLACK, 1.f, nullptr, &data, RenderPassId(1, 1));
}
} // namespace cc
diff --git a/cc/test/layer_test_common.h b/cc/test/layer_test_common.h
index 9b63f3f..dfd9729 100644
--- a/cc/test/layer_test_common.h
+++ b/cc/test/layer_test_common.h
@@ -9,7 +9,6 @@
#include "base/memory/scoped_ptr.h"
#include "cc/quads/render_pass.h"
#include "cc/test/fake_layer_tree_host.h"
-#include "cc/test/mock_occlusion_tracker.h"
#include "cc/trees/layer_tree_host_impl.h"
#define EXPECT_SET_NEEDS_COMMIT(expect, code_to_test) \
@@ -128,7 +127,6 @@
scoped_ptr<FakeLayerTreeHost> host_;
scoped_ptr<LayerImpl> root_layer_impl_;
scoped_ptr<RenderPass> render_pass_;
- MockOcclusionTracker<LayerImpl> occlusion_tracker_;
};
};
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index cf62d53..6b6c00b 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -183,7 +183,7 @@
*tile_task_worker_pool = GpuTileTaskWorkerPool::Create(
task_runner, TileTaskWorkerPool::GetTaskGraphRunner(),
- resource_provider);
+ static_cast<GpuRasterizer*>(host_impl->rasterizer()));
break;
case ZERO_COPY_TILE_TASK_WORKER_POOL:
EXPECT_TRUE(context_provider);
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc
index 8a053fa..f7ab9c2 100644
--- a/cc/test/layer_tree_pixel_test.cc
+++ b/cc/test/layer_tree_pixel_test.cc
@@ -11,6 +11,7 @@
#include "cc/layers/texture_layer.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
+#include "cc/output/direct_renderer.h"
#include "cc/resources/texture_mailbox.h"
#include "cc/test/paths.h"
#include "cc/test/pixel_comparator.h"
@@ -52,7 +53,8 @@
case PIXEL_TEST_GL: {
bool flipped_output_surface = false;
output_surface = make_scoped_ptr(new PixelTestOutputSurface(
- new TestInProcessContextProvider, flipped_output_surface));
+ new TestInProcessContextProvider, new TestInProcessContextProvider,
+ flipped_output_surface));
break;
}
}
@@ -67,6 +69,9 @@
if (commit_tree->source_frame_number() != 0)
return;
+ DirectRenderer* renderer = static_cast<DirectRenderer*>(impl->renderer());
+ renderer->SetEnlargePassTextureAmountForTesting(enlarge_texture_amount_);
+
gfx::Rect viewport = impl->DeviceViewport();
// The viewport has a 0,0 origin without external influence.
EXPECT_EQ(gfx::Point().ToString(), viewport.origin().ToString());
diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h
index 91081f8..8d02280 100644
--- a/cc/test/layer_tree_pixel_test.h
+++ b/cc/test/layer_tree_pixel_test.h
@@ -91,6 +91,10 @@
uint32 sync_point,
bool lost_resource);
+ void set_enlarge_texture_amount(const gfx::Vector2d& enlarge_texture_amount) {
+ enlarge_texture_amount_ = enlarge_texture_amount;
+ }
+
// Common CSS colors defined for tests to use.
static const SkColor kCSSOrange = 0xffffa500;
static const SkColor kCSSBrown = 0xffa52a2a;
@@ -106,6 +110,7 @@
std::vector<scoped_refptr<TextureLayer>> texture_layers_;
int pending_texture_mailbox_callbacks_;
bool impl_side_painting_;
+ gfx::Vector2d enlarge_texture_amount_;
};
} // namespace cc
diff --git a/cc/test/ordered_simple_task_runner.cc b/cc/test/ordered_simple_task_runner.cc
index 852396e..e337909 100644
--- a/cc/test/ordered_simple_task_runner.cc
+++ b/cc/test/ordered_simple_task_runner.cc
@@ -60,16 +60,16 @@
return ShouldRunBefore(other);
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
TestOrderablePendingTask::AsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get());
return state;
}
void TestOrderablePendingTask::AsValueInto(
- base::debug::TracedValue* state) const {
+ base::trace_event::TracedValue* state) const {
state->SetInteger("id", task_id_);
state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
state->SetString("posted_from", location.ToString());
@@ -255,17 +255,17 @@
return RunUntilTime(now_src_->Now() + period);
}
-// base::debug tracing functionality
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+// base::trace_event tracing functionality
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
OrderedSimpleTaskRunner::AsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get());
return state;
}
void OrderedSimpleTaskRunner::AsValueInto(
- base::debug::TracedValue* state) const {
+ base::trace_event::TracedValue* state) const {
state->SetInteger("pending_tasks", pending_tasks_.size());
state->BeginArray("tasks");
diff --git a/cc/test/ordered_simple_task_runner.h b/cc/test/ordered_simple_task_runner.h
index b6e03ba..54b1db4 100644
--- a/cc/test/ordered_simple_task_runner.h
+++ b/cc/test/ordered_simple_task_runner.h
@@ -34,9 +34,9 @@
bool operator==(const TestOrderablePendingTask& other) const;
bool operator<(const TestOrderablePendingTask& other) const;
- // debug tracing functions
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
- void AsValueInto(base::debug::TracedValue* state) const;
+ // base::trace_event tracing functionality
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::trace_event::TracedValue* state) const;
private:
static size_t task_id_counter;
@@ -102,9 +102,9 @@
bool RunUntilTime(base::TimeTicks time);
bool RunForPeriod(base::TimeDelta period);
- // base::debug tracing functionality
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
- virtual void AsValueInto(base::debug::TracedValue* state) const;
+ // base::trace_event tracing functionality
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
+ virtual void AsValueInto(base::trace_event::TracedValue* state) const;
// Common conditions to run for, exposed publicly to allow external users to
// use their own combinations.
diff --git a/cc/test/pixel_test.cc b/cc/test/pixel_test.cc
index aecd657..c2dc5b5 100644
--- a/cc/test/pixel_test.cc
+++ b/cc/test/pixel_test.cc
@@ -127,7 +127,8 @@
enable_pixel_output_.reset(new gfx::DisableNullDrawGLBindings);
output_surface_.reset(new PixelTestOutputSurface(
- new TestInProcessContextProvider, flipped_output_surface));
+ new TestInProcessContextProvider, new TestInProcessContextProvider,
+ flipped_output_surface));
output_surface_->BindToClient(output_surface_client_.get());
shared_bitmap_manager_.reset(new TestSharedBitmapManager);
diff --git a/cc/test/pixel_test_output_surface.cc b/cc/test/pixel_test_output_surface.cc
index ced1898..616103c 100644
--- a/cc/test/pixel_test_output_surface.cc
+++ b/cc/test/pixel_test_output_surface.cc
@@ -11,14 +11,25 @@
PixelTestOutputSurface::PixelTestOutputSurface(
scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider,
bool flipped_output_surface)
- : OutputSurface(context_provider), external_stencil_test_(false) {
+ : OutputSurface(context_provider, worker_context_provider),
+ external_stencil_test_(false) {
capabilities_.flipped_output_surface = flipped_output_surface;
}
PixelTestOutputSurface::PixelTestOutputSurface(
+ scoped_refptr<ContextProvider> context_provider,
+ bool flipped_output_surface)
+ : PixelTestOutputSurface(context_provider,
+ nullptr,
+ flipped_output_surface) {
+}
+
+PixelTestOutputSurface::PixelTestOutputSurface(
scoped_ptr<SoftwareOutputDevice> software_device)
- : OutputSurface(software_device.Pass()), external_stencil_test_(false) {}
+ : OutputSurface(software_device.Pass()), external_stencil_test_(false) {
+}
void PixelTestOutputSurface::Reshape(const gfx::Size& size,
float scale_factor) {
diff --git a/cc/test/pixel_test_output_surface.h b/cc/test/pixel_test_output_surface.h
index a58e2c4..27819c1 100644
--- a/cc/test/pixel_test_output_surface.h
+++ b/cc/test/pixel_test_output_surface.h
@@ -13,6 +13,10 @@
public:
explicit PixelTestOutputSurface(
scoped_refptr<ContextProvider> context_provider,
+ scoped_refptr<ContextProvider> worker_context_provider,
+ bool flipped_output_surface);
+ explicit PixelTestOutputSurface(
+ scoped_refptr<ContextProvider> context_provider,
bool flipped_output_surface);
explicit PixelTestOutputSurface(
scoped_ptr<SoftwareOutputDevice> software_device);
diff --git a/cc/test/scheduler_test_common.cc b/cc/test/scheduler_test_common.cc
index 03e65ab..94bcf5f 100644
--- a/cc/test/scheduler_test_common.cc
+++ b/cc/test/scheduler_test_common.cc
@@ -37,7 +37,8 @@
void FakeBeginFrameSource::DidFinishFrame(size_t remaining_frames) {
remaining_frames_ = remaining_frames;
}
-void FakeBeginFrameSource::AsValueInto(base::debug::TracedValue* dict) const {
+void FakeBeginFrameSource::AsValueInto(
+ base::trace_event::TracedValue* dict) const {
dict->SetString("type", "FakeBeginFrameSource");
BeginFrameSourceMixIn::AsValueInto(dict);
}
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 93cff9b..00cdd75 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -90,7 +90,7 @@
// BeginFrameSource
void DidFinishFrame(size_t remaining_frames) override;
- void AsValueInto(base::debug::TracedValue* dict) const override;
+ void AsValueInto(base::trace_event::TracedValue* dict) const override;
~FakeBeginFrameSource() override {}
};
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc
index 4c24fe1..bf85ea3 100644
--- a/cc/test/test_context_provider.cc
+++ b/cc/test/test_context_provider.cc
@@ -13,7 +13,7 @@
#include "cc/test/test_gles2_interface.h"
#include "cc/test/test_web_graphics_context_3d.h"
#include "third_party/skia/include/gpu/GrContext.h"
-#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+#include "third_party/skia/include/gpu/gl/SkNullGLContext.h"
namespace cc {
@@ -69,6 +69,10 @@
return true;
}
+void TestContextProvider::DetachFromThread() {
+ context_thread_checker_.DetachFromThread();
+}
+
ContextProvider::Capabilities TestContextProvider::ContextCapabilities() {
DCHECK(bound_);
DCHECK(context_thread_checker_.CalledOnValidThread());
@@ -95,14 +99,21 @@
if (gr_context_)
return gr_context_.get();
- skia::RefPtr<const GrGLInterface> null_interface =
- skia::AdoptRef(GrGLCreateNullInterface());
+ skia::RefPtr<class SkGLContext> gl_context =
+ skia::AdoptRef(SkNullGLContext::Create(kNone_GrGLStandard));
+ gl_context->makeCurrent();
gr_context_ = skia::AdoptRef(GrContext::Create(
- kOpenGL_GrBackend,
- reinterpret_cast<GrBackendContext>(null_interface.get())));
+ kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(gl_context->gl())));
return gr_context_.get();
}
+void TestContextProvider::SetupLock() {
+}
+
+base::Lock* TestContextProvider::GetLock() {
+ return &context_lock_;
+}
+
bool TestContextProvider::IsContextLost() {
DCHECK(bound_);
DCHECK(context_thread_checker_.CalledOnValidThread());
diff --git a/cc/test/test_context_provider.h b/cc/test/test_context_provider.h
index 3be8b43..9dd7b62 100644
--- a/cc/test/test_context_provider.h
+++ b/cc/test/test_context_provider.h
@@ -29,10 +29,13 @@
scoped_ptr<TestWebGraphicsContext3D> context);
bool BindToCurrentThread() override;
+ void DetachFromThread() override;
Capabilities ContextCapabilities() override;
gpu::gles2::GLES2Interface* ContextGL() override;
gpu::ContextSupport* ContextSupport() override;
class GrContext* GrContext() override;
+ void SetupLock() override;
+ base::Lock* GetLock() override;
bool IsContextLost() override;
void VerifyContexts() override;
void DeleteCachedResources() override;
@@ -74,6 +77,8 @@
base::Lock destroyed_lock_;
bool destroyed_;
+ base::Lock context_lock_;
+
LostContextCallback lost_context_callback_;
MemoryPolicyChangedCallback memory_policy_changed_callback_;
skia::RefPtr<class GrContext> gr_context_;
diff --git a/cc/test/test_in_process_context_provider.cc b/cc/test/test_in_process_context_provider.cc
index 34b0493..3539bd2 100644
--- a/cc/test/test_in_process_context_provider.cc
+++ b/cc/test/test_in_process_context_provider.cc
@@ -124,6 +124,13 @@
return gr_context_.get();
}
+void TestInProcessContextProvider::SetupLock() {
+}
+
+base::Lock* TestInProcessContextProvider::GetLock() {
+ return &context_lock_;
+}
+
ContextProvider::Capabilities
TestInProcessContextProvider::ContextCapabilities() {
ContextProvider::Capabilities capabilities;
diff --git a/cc/test/test_in_process_context_provider.h b/cc/test/test_in_process_context_provider.h
index 0533ff4..9fa77b7 100644
--- a/cc/test/test_in_process_context_provider.h
+++ b/cc/test/test_in_process_context_provider.h
@@ -5,6 +5,7 @@
#ifndef CC_TEST_TEST_IN_PROCESS_CONTEXT_PROVIDER_H_
#define CC_TEST_TEST_IN_PROCESS_CONTEXT_PROVIDER_H_
+#include "base/synchronization/lock.h"
#include "cc/output/context_provider.h"
#include "cc/test/test_gpu_memory_buffer_manager.h"
#include "cc/test/test_image_factory.h"
@@ -31,6 +32,8 @@
gpu::gles2::GLES2Interface* ContextGL() override;
gpu::ContextSupport* ContextSupport() override;
class GrContext* GrContext() override;
+ void SetupLock() override;
+ base::Lock* GetLock() override;
Capabilities ContextCapabilities() override;
bool IsContextLost() override;
void VerifyContexts() override;
@@ -51,6 +54,7 @@
TestImageFactory image_factory_;
scoped_ptr<gpu::GLInProcessContext> context_;
skia::RefPtr<class GrContext> gr_context_;
+ base::Lock context_lock_;
};
} // namespace cc
diff --git a/cc/test/test_now_source.cc b/cc/test/test_now_source.cc
index 2ffb36e..0576d06 100644
--- a/cc/test/test_now_source.cc
+++ b/cc/test/test_now_source.cc
@@ -93,14 +93,14 @@
}
// TestNowSource::Tracing functions
-void TestNowSource::AsValueInto(base::debug::TracedValue* state) const {
+void TestNowSource::AsValueInto(base::trace_event::TracedValue* state) const {
state->SetInteger("now_in_microseconds", now_.ToInternalValue());
}
-scoped_refptr<base::debug::ConvertableToTraceFormat> TestNowSource::AsValue()
- const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+TestNowSource::AsValue() const {
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueInto(state.get());
return state;
}
diff --git a/cc/test/test_now_source.h b/cc/test/test_now_source.h
index 5538e89..54e5a28 100644
--- a/cc/test/test_now_source.h
+++ b/cc/test/test_now_source.h
@@ -33,8 +33,8 @@
static const base::TimeTicks kAbsoluteMaxNow;
// Tracing functions
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
- void AsValueInto(base::debug::TracedValue* state) const;
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::trace_event::TracedValue* state) const;
std::string ToString() const;
protected:
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 8217ce0..c9ead98 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -250,8 +250,8 @@
}
void ComputeTransforms(TransformTree* transform_tree) {
- for (int i = 0; i < static_cast<int>(transform_tree->size()); ++i)
- transform_tree->UpdateScreenSpaceTransform(i);
+ for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i)
+ transform_tree->UpdateTransforms(i);
}
void ComputeVisibleRectsUsingPropertyTrees(
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index fa4dd5d..f478078 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -119,7 +119,7 @@
debug_state_(settings.initial_debug_state),
top_controls_shrink_blink_size_(false),
top_controls_height_(0.f),
- top_controls_content_offset_(0.f),
+ top_controls_shown_ratio_(0.f),
device_scale_factor_(1.f),
visible_(true),
page_scale_factor_(1.f),
@@ -335,20 +335,10 @@
sync_tree->PassSwapPromises(&swap_promise_list_);
- // Track the change in top controls height to offset the top_controls_delta
- // properly. This is so that the top controls offset will be maintained
- // across height changes.
- float top_controls_height_delta =
- sync_tree->top_controls_height() - top_controls_height_;
-
sync_tree->set_top_controls_shrink_blink_size(
top_controls_shrink_blink_size_);
sync_tree->set_top_controls_height(top_controls_height_);
- sync_tree->set_top_controls_content_offset(top_controls_content_offset_);
- sync_tree->set_top_controls_delta(sync_tree->top_controls_delta() -
- sync_tree->sent_top_controls_delta() -
- top_controls_height_delta);
- sync_tree->set_sent_top_controls_delta(0.f);
+ sync_tree->PushTopControlsFromMainThread(top_controls_shown_ratio_);
host_impl->SetUseGpuRasterization(UseGpuRasterization());
host_impl->set_gpu_rasterization_status(GetGpuRasterizationStatus());
@@ -691,11 +681,11 @@
SetNeedsCommit();
}
-void LayerTreeHost::SetTopControlsContentOffset(float offset) {
- if (top_controls_content_offset_ == offset)
+void LayerTreeHost::SetTopControlsShownRatio(float ratio) {
+ if (top_controls_shown_ratio_ == ratio)
return;
- top_controls_content_offset_ = offset;
+ top_controls_shown_ratio_ = ratio;
SetNeedsCommit();
}
@@ -1229,7 +1219,7 @@
animate));
}
-void LayerTreeHost::AsValueInto(base::debug::TracedValue* state) const {
+void LayerTreeHost::AsValueInto(base::trace_event::TracedValue* state) const {
state->BeginDictionary("proxy");
proxy_->AsValueInto(state);
state->EndDictionary();
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index f41e023..b17b5a4 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -212,7 +212,7 @@
void SetViewportSize(const gfx::Size& device_viewport_size);
void SetTopControlsShrinkBlinkSize(bool shrink);
void SetTopControlsHeight(float height);
- void SetTopControlsContentOffset(float offset);
+ void SetTopControlsShownRatio(float ratio);
gfx::Size device_viewport_size() const { return device_viewport_size_; }
@@ -273,7 +273,7 @@
}
// Obtains a thorough dump of the LayerTreeHost as a value.
- void AsValueInto(base::debug::TracedValue* value) const;
+ void AsValueInto(base::trace_event::TracedValue* value) const;
bool in_paint_layer_contents() const { return in_paint_layer_contents_; }
@@ -416,7 +416,7 @@
gfx::Size device_viewport_size_;
bool top_controls_shrink_blink_size_;
float top_controls_height_;
- float top_controls_content_offset_;
+ float top_controls_shown_ratio_;
float device_scale_factor_;
bool visible_;
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index f21ed3f..70c5037 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -21,6 +21,7 @@
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
#include "ui/gfx/transform.h"
+#include "ui/gfx/transform_util.h"
namespace cc {
@@ -1202,30 +1203,12 @@
}
};
-static bool ValidateRenderSurface(LayerImpl* layer) {
- // There are a few cases in which it is incorrect to not have a
- // render_surface.
- if (layer->render_surface())
- return true;
-
- return layer->filters().IsEmpty() && layer->background_filters().IsEmpty() &&
- !layer->mask_layer() && !layer->replica_layer() &&
- !IsRootLayer(layer) && !layer->is_root_for_isolated_group() &&
- !layer->HasCopyRequest();
-}
-
-static bool ValidateRenderSurface(Layer* layer) {
- return true;
-}
-
// Recursively walks the layer tree to compute any information that is needed
// before doing the main recursion.
template <typename LayerType>
static void PreCalculateMetaInformation(
LayerType* layer,
PreCalculateMetaInformationRecursiveData* recursive_data) {
- DCHECK(ValidateRenderSurface(layer));
-
layer->draw_properties().sorted_for_recursion = false;
layer->draw_properties().has_child_with_a_scroll_parent = false;
@@ -1271,11 +1254,6 @@
recursive_data->layer_or_descendant_has_input_handler;
}
-static void RoundTranslationComponents(gfx::Transform* transform) {
- transform->matrix().set(0, 3, MathUtil::Round(transform->matrix().get(0, 3)));
- transform->matrix().set(1, 3, MathUtil::Round(transform->matrix().get(1, 3)));
-}
-
template <typename LayerType>
struct SubtreeGlobals {
LayerSorter* layer_sorter;
@@ -1701,7 +1679,7 @@
// blurriness. To avoid side-effects, do this only if the transform is
// simple.
gfx::Vector2dF previous_translation = combined_transform.To2dTranslation();
- RoundTranslationComponents(&combined_transform);
+ combined_transform.RoundTranslationComponents();
gfx::Vector2dF current_translation = combined_transform.To2dTranslation();
// This rounding changes the scroll delta, and so must be included
@@ -2491,6 +2469,12 @@
std::abs(r1.height() - r2.height()) <= tolerance;
}
+static bool ApproximatelyEqual(const gfx::Transform& a,
+ const gfx::Transform& b) {
+ static const float tolerance = 0.01f;
+ return gfx::MatrixDistance(a, b) < tolerance;
+}
+
void LayerTreeHostCommon::CalculateDrawProperties(
CalcDrawPropsMainInputs* inputs) {
UpdateRenderSurfaces(inputs->root_layer,
@@ -2520,8 +2504,8 @@
DCHECK(inputs->root_layer->render_surface());
if (inputs->verify_property_trees) {
- // TODO(ajuma): Can we efficiently cache some of this rather than
- // starting from scratch every frame?
+ // The translation from layer to property trees is an intermediate state. We
+ // will eventually get these data passed directly to the compositor.
TransformTree transform_tree;
ClipTree clip_tree;
ComputeVisibleRectsUsingPropertyTrees(
@@ -2530,23 +2514,24 @@
gfx::Rect(inputs->device_viewport_size), inputs->device_transform,
&transform_tree, &clip_tree);
- bool failed = false;
LayerIterator<Layer> it, end;
for (it = LayerIterator<Layer>::Begin(inputs->render_surface_layer_list),
end = LayerIterator<Layer>::End(inputs->render_surface_layer_list);
it != end; ++it) {
Layer* current_layer = *it;
- if (it.represents_itself()) {
- if (!failed && current_layer->DrawsContent() &&
- !ApproximatelyEqual(
- current_layer->visible_content_rect(),
- current_layer->visible_rect_from_property_trees())) {
- failed = true;
- }
- }
- }
+ if (!it.represents_itself() || !current_layer->DrawsContent())
+ continue;
- CHECK(!failed);
+ const bool visible_rects_match =
+ ApproximatelyEqual(current_layer->visible_content_rect(),
+ current_layer->visible_rect_from_property_trees());
+ CHECK(visible_rects_match);
+
+ const bool draw_transforms_match = ApproximatelyEqual(
+ current_layer->draw_transform(),
+ current_layer->draw_transform_from_property_trees(transform_tree));
+ CHECK(draw_transforms_match);
+ }
}
}
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 672ffe8..3cb2858 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -68,7 +68,6 @@
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_impl.h"
-#include "cc/trees/occlusion_tracker.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/tree_synchronizer.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -235,8 +234,9 @@
SetDebugState(settings.initial_debug_state);
// LTHI always has an active tree.
- active_tree_ = LayerTreeImpl::create(this, new SyncedProperty<ScaleGroup>(),
- new SyncedElasticOverscroll);
+ active_tree_ =
+ LayerTreeImpl::create(this, new SyncedProperty<ScaleGroup>(),
+ new SyncedTopControls, new SyncedElasticOverscroll);
TRACE_EVENT_OBJECT_CREATED_WITH_ID(
TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", id_);
@@ -295,7 +295,7 @@
if (!settings_.impl_side_painting && output_surface_)
output_surface_->ForceReclaimResources();
- if (UsePendingTreeForSync())
+ if (settings_.impl_side_painting && !proxy_->CommitToActiveTree())
CreatePendingTree();
}
@@ -548,7 +548,7 @@
}
void LayerTreeHostImpl::FrameData::AsValueInto(
- base::debug::TracedValue* value) const {
+ base::trace_event::TracedValue* value) const {
value->SetBoolean("has_no_damage", has_no_damage);
// Quad data can be quite large, so only dump render passes if we select
@@ -588,51 +588,54 @@
}
}
-static void AppendQuadsForLayer(
- RenderPass* target_render_pass,
- LayerImpl* layer,
- const OcclusionTracker<LayerImpl>& occlusion_tracker,
- AppendQuadsData* append_quads_data) {
- layer->AppendQuads(
- target_render_pass,
- occlusion_tracker.GetCurrentOcclusionForLayer(layer->draw_transform()),
- append_quads_data);
-}
-
static void AppendQuadsForRenderSurfaceLayer(
RenderPass* target_render_pass,
LayerImpl* layer,
const RenderPass* contributing_render_pass,
- const OcclusionTracker<LayerImpl>& occlusion_tracker,
AppendQuadsData* append_quads_data) {
- bool is_replica = false;
- layer->render_surface()->AppendQuads(target_render_pass,
- occlusion_tracker,
- append_quads_data,
- is_replica,
- contributing_render_pass->id);
+ RenderSurfaceImpl* surface = layer->render_surface();
+ const gfx::Transform& draw_transform = surface->draw_transform();
+ const Occlusion& occlusion = surface->occlusion_in_content_space();
+ SkColor debug_border_color = surface->GetDebugBorderColor();
+ float debug_border_width = surface->GetDebugBorderWidth();
+ LayerImpl* mask_layer = layer->mask_layer();
+
+ surface->AppendQuads(target_render_pass, draw_transform, occlusion,
+ debug_border_color, debug_border_width, mask_layer,
+ append_quads_data, contributing_render_pass->id);
// Add replica after the surface so that it appears below the surface.
if (layer->has_replica()) {
- is_replica = true;
- layer->render_surface()->AppendQuads(target_render_pass,
- occlusion_tracker,
- append_quads_data,
- is_replica,
- contributing_render_pass->id);
+ const gfx::Transform& replica_draw_transform =
+ surface->replica_draw_transform();
+ Occlusion replica_occlusion = occlusion.GetOcclusionWithGivenDrawTransform(
+ surface->replica_draw_transform());
+ SkColor replica_debug_border_color = surface->GetReplicaDebugBorderColor();
+ float replica_debug_border_width = surface->GetReplicaDebugBorderWidth();
+ // TODO(danakj): By using the same RenderSurfaceImpl for both the
+ // content and its reflection, it's currently not possible to apply a
+ // separate mask to the reflection layer or correctly handle opacity in
+ // reflections (opacity must be applied after drawing both the layer and its
+ // reflection). The solution is to introduce yet another RenderSurfaceImpl
+ // to draw the layer and its reflection in. For now we only apply a separate
+ // reflection mask if the contents don't have a mask of their own.
+ LayerImpl* replica_mask_layer =
+ mask_layer ? mask_layer : layer->replica_layer()->mask_layer();
+
+ surface->AppendQuads(target_render_pass, replica_draw_transform,
+ replica_occlusion, replica_debug_border_color,
+ replica_debug_border_width, replica_mask_layer,
+ append_quads_data, contributing_render_pass->id);
}
}
-static void AppendQuadsToFillScreen(
- const gfx::Rect& root_scroll_layer_rect,
- RenderPass* target_render_pass,
- LayerImpl* root_layer,
- SkColor screen_background_color,
- const OcclusionTracker<LayerImpl>& occlusion_tracker) {
+static void AppendQuadsToFillScreen(const gfx::Rect& root_scroll_layer_rect,
+ RenderPass* target_render_pass,
+ LayerImpl* root_layer,
+ SkColor screen_background_color,
+ const Region& fill_region) {
if (!root_layer || !SkColorGetA(screen_background_color))
return;
-
- Region fill_region = occlusion_tracker.ComputeVisibleRegionInScreen();
if (fill_region.IsEmpty())
return;
@@ -736,23 +739,14 @@
root_pass->damage_rect = root_pass->output_rect;
}
- OcclusionTracker<LayerImpl> occlusion_tracker(
- active_tree_->root_layer()->render_surface()->content_rect());
- occlusion_tracker.set_minimum_tracking_size(
- settings_.minimum_occlusion_tracking_size);
-
- if (debug_state_.show_occluding_rects) {
- occlusion_tracker.set_occluding_screen_space_rects_container(
- &frame->occluding_screen_space_rects);
- }
- if (debug_state_.show_non_occluding_rects) {
- occlusion_tracker.set_non_occluding_screen_space_rects_container(
- &frame->non_occluding_screen_space_rects);
- }
-
- // Add quads to the Render passes in front-to-back order to allow for testing
- // occlusion and performing culling during the tree walk.
- typedef LayerIterator<LayerImpl> LayerIteratorType;
+ // Grab this region here before iterating layers. Taking copy requests from
+ // the layers while constructing the render passes will dirty the render
+ // surface layer list and this unoccluded region, flipping the dirty bit to
+ // true, and making us able to query for it without doing
+ // UpdateDrawProperties again. The value inside the Region is not actually
+ // changed until UpdateDrawProperties happens, so a reference to it is safe.
+ const Region& unoccluded_screen_space_region =
+ active_tree_->UnoccludedScreenSpaceRegion();
// Typically when we are missing a texture and use a checkerboard quad, we
// still draw the frame. However when the layer being checkerboarded is moving
@@ -770,19 +764,15 @@
int num_missing_tiles = 0;
int num_incomplete_tiles = 0;
- LayerIteratorType end =
- LayerIteratorType::End(frame->render_surface_layer_list);
- for (LayerIteratorType it =
- LayerIteratorType::Begin(frame->render_surface_layer_list);
- it != end;
- ++it) {
+ auto end = LayerIterator<LayerImpl>::End(frame->render_surface_layer_list);
+ for (auto it =
+ LayerIterator<LayerImpl>::Begin(frame->render_surface_layer_list);
+ it != end; ++it) {
RenderPassId target_render_pass_id =
it.target_render_surface_layer()->render_surface()->GetRenderPassId();
RenderPass* target_render_pass =
frame->render_passes_by_id[target_render_pass_id];
- occlusion_tracker.EnterLayer(it);
-
AppendQuadsData append_quads_data;
if (it.represents_target_render_surface()) {
@@ -800,13 +790,12 @@
AppendQuadsForRenderSurfaceLayer(target_render_pass,
*it,
contributing_render_pass,
- occlusion_tracker,
&append_quads_data);
} else if (it.represents_itself() &&
!it->visible_content_rect().IsEmpty()) {
bool occluded =
- occlusion_tracker.GetCurrentOcclusionForLayer(it->draw_transform())
- .IsOccluded(it->visible_content_rect());
+ it->draw_properties().occlusion_in_content_space.IsOccluded(
+ it->visible_content_rect());
if (!occluded && it->WillDraw(draw_mode, resource_provider_.get())) {
DCHECK_EQ(active_tree_, it->layer_tree_impl());
@@ -820,20 +809,14 @@
RenderPass* render_pass =
frame->render_passes_by_id[contributing_render_pass_id];
- AppendQuadsForLayer(render_pass,
- *it,
- occlusion_tracker,
- &append_quads_data);
+ it->AppendQuads(render_pass, &append_quads_data);
contributing_render_pass_id =
it->NextContributingRenderPassId(contributing_render_pass_id);
}
}
- AppendQuadsForLayer(target_render_pass,
- *it,
- occlusion_tracker,
- &append_quads_data);
+ it->AppendQuads(target_render_pass, &append_quads_data);
// For layers that represent themselves, add composite frame timing
// requests if the visible rect intersects the requested rect.
@@ -872,8 +855,6 @@
if (RequiresHighResToDraw())
draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
}
-
- occlusion_tracker.LeaveLayer(it);
}
if (have_copy_request ||
@@ -894,10 +875,8 @@
frame->render_passes.back()->has_transparent_background = false;
AppendQuadsToFillScreen(
active_tree_->RootScrollLayerDeviceViewportBounds(),
- frame->render_passes.back(),
- active_tree_->root_layer(),
- active_tree_->background_color(),
- occlusion_tracker);
+ frame->render_passes.back(), active_tree_->root_layer(),
+ active_tree_->background_color(), unoccluded_screen_space_region);
}
RemoveRenderPasses(CullRenderPassesWithNoQuads(), frame);
@@ -1113,8 +1092,10 @@
void LayerTreeHostImpl::ResetTreesForTesting() {
if (active_tree_)
active_tree_->DetachLayerTree();
- active_tree_ = LayerTreeImpl::create(this, active_tree()->page_scale_factor(),
- active_tree()->elastic_overscroll());
+ active_tree_ =
+ LayerTreeImpl::create(this, active_tree()->page_scale_factor(),
+ active_tree()->top_controls_shown_ratio(),
+ active_tree()->elastic_overscroll());
if (pending_tree_)
pending_tree_->DetachLayerTree();
pending_tree_ = nullptr;
@@ -1206,32 +1187,31 @@
std::vector<PictureLayerImpl::Pair>* layer_pairs,
bool need_valid_tile_priorities) const {
DCHECK(layer_pairs->empty());
- for (std::vector<PictureLayerImpl*>::const_iterator it =
- picture_layers_.begin();
- it != picture_layers_.end();
- ++it) {
- PictureLayerImpl* layer = *it;
- if (!layer->IsOnActiveOrPendingTree() ||
- (need_valid_tile_priorities && !layer->HasValidTilePriorities()))
+ for (auto& layer : active_tree_->picture_layers()) {
+ if (need_valid_tile_priorities && !layer->HasValidTilePriorities())
continue;
-
PictureLayerImpl* twin_layer = layer->GetPendingOrActiveTwinLayer();
-
// Ignore the twin layer when tile priorities are invalid.
if (need_valid_tile_priorities && twin_layer &&
- !twin_layer->HasValidTilePriorities())
- twin_layer = NULL;
+ !twin_layer->HasValidTilePriorities()) {
+ twin_layer = nullptr;
+ }
+ layer_pairs->push_back(PictureLayerImpl::Pair(layer, twin_layer));
+ }
- // If the current tree is ACTIVE_TREE, then always generate a layer_pair.
- // If current tree is PENDING_TREE, then only generate a layer_pair if
- // there is no twin layer.
- if (layer->GetTree() == ACTIVE_TREE) {
- DCHECK_IMPLIES(twin_layer, twin_layer->GetTree() == PENDING_TREE);
- layer_pairs->push_back(PictureLayerImpl::Pair(layer, twin_layer));
- } else if (!twin_layer) {
- DCHECK(layer->GetTree() == PENDING_TREE);
- layer_pairs->push_back(PictureLayerImpl::Pair(NULL, layer));
+ if (pending_tree_) {
+ for (auto& layer : pending_tree_->picture_layers()) {
+ if (need_valid_tile_priorities && !layer->HasValidTilePriorities())
+ continue;
+ if (PictureLayerImpl* twin_layer = layer->GetPendingOrActiveTwinLayer()) {
+ if (!need_valid_tile_priorities ||
+ twin_layer->HasValidTilePriorities()) {
+ // Already captured from the active tree.
+ continue;
+ }
+ }
+ layer_pairs->push_back(PictureLayerImpl::Pair(nullptr, layer));
}
}
}
@@ -1265,11 +1245,6 @@
is_likely_to_require_a_draw_ = is_likely_to_require_a_draw;
}
-const std::vector<PictureLayerImpl*>& LayerTreeHostImpl::GetPictureLayers()
- const {
- return picture_layers_;
-}
-
void LayerTreeHostImpl::NotifyReadyToActivate() {
client_->NotifyReadyToActivate();
}
@@ -1452,6 +1427,16 @@
active_tree_->GetViewportSelection(&metadata.selection_start,
&metadata.selection_end);
+ LayerImpl* root_layer_for_overflow = OuterViewportScrollLayer()
+ ? OuterViewportScrollLayer()
+ : InnerViewportScrollLayer();
+ if (root_layer_for_overflow) {
+ metadata.root_overflow_x_hidden =
+ !root_layer_for_overflow->user_scrollable_horizontal();
+ metadata.root_overflow_y_hidden =
+ !root_layer_for_overflow->user_scrollable_vertical();
+ }
+
if (!InnerViewportScrollLayer())
return metadata;
@@ -1499,8 +1484,6 @@
active_tree_->root_layer(),
active_tree_->hud_layer(),
*frame->render_surface_layer_list,
- frame->occluding_screen_space_rects,
- frame->non_occluding_screen_space_rects,
debug_state_);
}
@@ -1678,9 +1661,9 @@
active_tree_->top_controls_shrink_blink_size()
? active_tree_->top_controls_height()
: 0.f;
- inner_container->SetBoundsDelta(
- gfx::Vector2dF(0, top_controls_layout_height -
- active_tree_->total_top_controls_content_offset()));
+ inner_container->SetBoundsDelta(gfx::Vector2dF(
+ 0,
+ top_controls_layout_height - top_controls_manager_->ContentTopOffset()));
if (!outer_container || outer_container->BoundsForScrolling().IsEmpty())
return;
@@ -1768,16 +1751,9 @@
else
pending_tree_ =
LayerTreeImpl::create(this, active_tree()->page_scale_factor(),
+ active_tree()->top_controls_shown_ratio(),
active_tree()->elastic_overscroll());
- // Update the delta from the active tree, which may have
- // adjusted its delta prior to the pending tree being created.
- DCHECK_EQ(0.f, pending_tree_->sent_top_controls_delta());
- pending_tree_->set_top_controls_delta(
- active_tree_->top_controls_delta() -
- active_tree_->sent_top_controls_delta());
- pending_tree_->set_top_controls_height(active_tree_->top_controls_height());
-
client_->OnCanDrawStateChanged(CanDraw());
TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree:waiting", pending_tree_.get());
}
@@ -1812,14 +1788,6 @@
active_tree_->SetRootLayerScrollOffsetDelegate(
root_layer_scroll_offset_delegate_);
- if (top_controls_manager_) {
- top_controls_manager_->SetTopControlsHeight(
- active_tree_->top_controls_height());
- top_controls_manager_->SetControlsTopOffset(
- active_tree_->total_top_controls_content_offset() -
- active_tree_->top_controls_height());
- }
-
UpdateViewportContainerSizes();
} else {
active_tree_->ProcessUIResourceRequestQueue();
@@ -1831,7 +1799,7 @@
client_->RenewTreePriority();
// If we have any picture layers, then by activating we also modified tile
// priorities.
- if (!picture_layers_.empty())
+ if (!active_tree_->picture_layers().empty())
DidModifyTilePriorities();
}
@@ -2039,7 +2007,7 @@
*tile_task_worker_pool = GpuTileTaskWorkerPool::Create(
task_runner, TileTaskWorkerPool::GetTaskGraphRunner(),
- resource_provider_.get());
+ static_cast<GpuRasterizer*>(rasterizer_.get()));
return;
}
@@ -2104,12 +2072,6 @@
single_thread_synchronous_task_graph_runner_ = nullptr;
}
-bool LayerTreeHostImpl::UsePendingTreeForSync() const {
- // In impl-side painting, synchronize to the pending tree so that it has
- // time to raster before being displayed.
- return settings_.impl_side_painting;
-}
-
bool LayerTreeHostImpl::IsSynchronousSingleThreaded() const {
return !proxy_->HasImplThread() && !settings_.single_thread_proxy_scheduler;
}
@@ -2298,15 +2260,17 @@
SetFullRootLayerDamage();
}
-void LayerTreeHostImpl::SetControlsTopOffset(float offset) {
- float current_top_offset = active_tree_->top_controls_content_offset() -
- active_tree_->top_controls_height();
- active_tree_->set_top_controls_delta(offset - current_top_offset);
+float LayerTreeHostImpl::TopControlsHeight() const {
+ return active_tree_->top_controls_height();
}
-float LayerTreeHostImpl::ControlsTopOffset() const {
- return active_tree_->total_top_controls_content_offset() -
- active_tree_->top_controls_height();
+void LayerTreeHostImpl::SetCurrentTopControlsShownRatio(float ratio) {
+ if (active_tree_->SetCurrentTopControlsShownRatio(ratio))
+ DidChangeTopControlsPosition();
+}
+
+float LayerTreeHostImpl::CurrentTopControlsShownRatio() const {
+ return active_tree_->CurrentTopControlsShownRatio();
}
void LayerTreeHostImpl::BindToClient(InputHandlerClient* client) {
@@ -3059,11 +3023,11 @@
CollectScrollDeltas(scroll_info.get(), active_tree_->root_layer());
scroll_info->page_scale_delta =
active_tree_->page_scale_factor()->PullDeltaForMainThread();
+ scroll_info->top_controls_delta =
+ active_tree()->top_controls_shown_ratio()->PullDeltaForMainThread();
scroll_info->elastic_overscroll_delta =
active_tree_->elastic_overscroll()->PullDeltaForMainThread();
scroll_info->swap_promises.swap(swap_promises_for_main_thread_scroll_update_);
- scroll_info->top_controls_delta = active_tree()->top_controls_delta();
- active_tree_->set_sent_top_controls_delta(scroll_info->top_controls_delta);
return scroll_info.Pass();
}
@@ -3282,26 +3246,27 @@
BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
LayerTreeHostImpl::AsValue() const {
return AsValueWithFrame(NULL);
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
LayerTreeHostImpl::AsValueWithFrame(FrameData* frame) const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
AsValueWithFrameInto(frame, state.get());
return state;
}
-void LayerTreeHostImpl::AsValueInto(base::debug::TracedValue* value) const {
+void LayerTreeHostImpl::AsValueInto(
+ base::trace_event::TracedValue* value) const {
return AsValueWithFrameInto(NULL, value);
}
void LayerTreeHostImpl::AsValueWithFrameInto(
FrameData* frame,
- base::debug::TracedValue* state) const {
+ base::trace_event::TracedValue* state) const {
if (this->pending_tree_) {
state->BeginDictionary("activation_state");
ActivationStateAsValueInto(state);
@@ -3347,16 +3312,16 @@
}
}
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
LayerTreeHostImpl::ActivationStateAsValue() const {
- scoped_refptr<base::debug::TracedValue> state =
- new base::debug::TracedValue();
+ scoped_refptr<base::trace_event::TracedValue> state =
+ new base::trace_event::TracedValue();
ActivationStateAsValueInto(state.get());
return state;
}
void LayerTreeHostImpl::ActivationStateAsValueInto(
- base::debug::TracedValue* state) const {
+ base::trace_event::TracedValue* state) const {
TracedValue::SetIDRef(this, state, "lthi");
if (tile_manager_) {
state->BeginDictionary("tile_manager");
@@ -3509,17 +3474,4 @@
(*it)->OnForwardScrollUpdateToMainThreadOnImpl();
}
-void LayerTreeHostImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) {
- DCHECK(std::find(picture_layers_.begin(), picture_layers_.end(), layer) ==
- picture_layers_.end());
- picture_layers_.push_back(layer);
-}
-
-void LayerTreeHostImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) {
- std::vector<PictureLayerImpl*>::iterator it =
- std::find(picture_layers_.begin(), picture_layers_.end(), layer);
- DCHECK(it != picture_layers_.end());
- picture_layers_.erase(it);
-}
-
} // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index f4052f1..6dd0d5a 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -174,15 +174,18 @@
ScrollElasticityHelper* CreateScrollElasticityHelper() override;
// TopControlsManagerClient implementation.
- void SetControlsTopOffset(float offset) override;
- float ControlsTopOffset() const override;
+ float TopControlsHeight() const override;
+ void SetCurrentTopControlsShownRatio(float offset) override;
+ float CurrentTopControlsShownRatio() const override;
void DidChangeTopControlsPosition() override;
bool HaveRootScrollLayer() const override;
+ void UpdateViewportContainerSizes();
+
struct CC_EXPORT FrameData : public RenderPassSink {
FrameData();
~FrameData() override;
- void AsValueInto(base::debug::TracedValue* value) const;
+ void AsValueInto(base::trace_event::TracedValue* value) const;
std::vector<gfx::Rect> occluding_screen_space_rects;
std::vector<gfx::Rect> non_occluding_screen_space_rects;
@@ -254,10 +257,6 @@
TreePriority tree_priority) override;
void SetIsLikelyToRequireADraw(bool is_likely_to_require_a_draw) override;
- // Returns existing picture layers.
- // TODO(vmpstr): Remove this, it's only used in tests.
- const std::vector<PictureLayerImpl*>& GetPictureLayers() const;
-
// ScrollbarAnimationControllerClient implementation.
void PostDelayedScrollbarFade(const base::Closure& start_fade,
base::TimeDelta delay) override;
@@ -314,6 +313,7 @@
}
ResourcePool* resource_pool() { return resource_pool_.get(); }
Renderer* renderer() { return renderer_.get(); }
+ Rasterizer* rasterizer() { return rasterizer_.get(); }
const RendererCapabilitiesImpl& GetRendererCapabilities() const;
virtual bool SwapBuffers(const FrameData& frame);
@@ -449,15 +449,15 @@
return begin_impl_frame_interval_;
}
- void AsValueInto(base::debug::TracedValue* value) const;
+ void AsValueInto(base::trace_event::TracedValue* value) const;
void AsValueWithFrameInto(FrameData* frame,
- base::debug::TracedValue* value) const;
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
- scoped_refptr<base::debug::ConvertableToTraceFormat> AsValueWithFrame(
+ 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::debug::ConvertableToTraceFormat> ActivationStateAsValue()
- const;
- void ActivationStateAsValueInto(base::debug::TracedValue* value) 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_; }
@@ -495,9 +495,6 @@
void InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor);
void RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor);
- void RegisterPictureLayerImpl(PictureLayerImpl* layer);
- void UnregisterPictureLayerImpl(PictureLayerImpl* layer);
-
void GetPictureLayerImplPairs(std::vector<PictureLayerImpl::Pair>* layers,
bool need_valid_tile_priorities) const;
@@ -530,7 +527,6 @@
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
int id);
- void UpdateViewportContainerSizes();
// Virtual for testing.
virtual void AnimateLayers(base::TimeTicks monotonic_time);
@@ -550,7 +546,6 @@
void RecreateTreeResources();
void EnforceZeroBudget(bool zero_budget);
- bool UsePendingTreeForSync() const;
bool IsSynchronousSingleThreaded() const;
// Scroll by preferring to move the outer viewport first, only moving the
@@ -732,8 +727,6 @@
int id_;
std::set<SwapPromiseMonitor*> swap_promise_monitor_;
-
- std::vector<PictureLayerImpl*> picture_layers_;
std::vector<PictureLayerImpl::Pair> picture_layer_pairs_;
bool requires_high_res_to_draw_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 1c486e3..07fb048 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1839,6 +1839,8 @@
EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
EXPECT_EQ(4.f, metadata.max_page_scale_factor);
+ EXPECT_FALSE(metadata.root_overflow_x_hidden);
+ EXPECT_FALSE(metadata.root_overflow_y_hidden);
}
// Scrolling should update metadata immediately.
@@ -1857,6 +1859,24 @@
EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
}
+ // Root "overflow: hidden" properties should be reflected.
+ {
+ host_impl_->active_tree()
+ ->InnerViewportScrollLayer()
+ ->set_user_scrollable_horizontal(false);
+ CompositorFrameMetadata metadata =
+ host_impl_->MakeCompositorFrameMetadata();
+ EXPECT_TRUE(metadata.root_overflow_x_hidden);
+ EXPECT_FALSE(metadata.root_overflow_y_hidden);
+
+ host_impl_->active_tree()
+ ->InnerViewportScrollLayer()
+ ->set_user_scrollable_vertical(false);
+ metadata = host_impl_->MakeCompositorFrameMetadata();
+ EXPECT_TRUE(metadata.root_overflow_x_hidden);
+ EXPECT_TRUE(metadata.root_overflow_y_hidden);
+ }
+
// Page scale should update metadata correctly (shrinking only the viewport).
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
@@ -1904,11 +1924,9 @@
}
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override {
append_quads_called_ = true;
- LayerImpl::AppendQuads(
- render_pass, occlusion_in_content_space, append_quads_data);
+ LayerImpl::AppendQuads(render_pass, append_quads_data);
}
void DidDraw(ResourceProvider* provider) override {
@@ -2131,10 +2149,8 @@
}
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override {
- LayerImpl::AppendQuads(
- render_pass, occlusion_in_content_space, append_quads_data);
+ LayerImpl::AppendQuads(render_pass, append_quads_data);
if (had_incomplete_tile_)
append_quads_data->num_incomplete_tiles++;
if (tile_missing_)
@@ -2456,10 +2472,7 @@
LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
if (init && settings.calculate_top_controls_position) {
host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
- host_impl_->active_tree()->set_top_controls_delta(top_controls_height_);
- host_impl_->top_controls_manager()->SetTopControlsHeight(
- top_controls_height_);
- host_impl_->DidChangeTopControlsPosition();
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
}
return init;
}
@@ -2493,6 +2506,7 @@
host_impl_->DidChangeTopControlsPosition();
host_impl_->CreatePendingTree();
+ host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
root =
LayerImpl::Create(host_impl_->sync_tree(), 1);
root_clip =
@@ -2524,6 +2538,7 @@
const gfx::Size& scroll_layer_size) {
CreateHostImpl(settings_, CreateOutputSurface());
host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
+ host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
host_impl_->DidChangeTopControlsPosition();
scoped_ptr<LayerImpl> root =
@@ -2602,8 +2617,8 @@
host_impl_->active_tree()->InnerViewportScrollLayer();
DCHECK(inner_viewport_scroll_layer);
host_impl_->ScrollEnd();
- EXPECT_EQ(top_controls_scroll_delta,
- inner_viewport_scroll_layer->FixedContainerSizeDelta());
+ EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
+ inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
}
// In this test, the outer viewport is initially unscrollable. We test that a
@@ -2634,8 +2649,7 @@
// The entire scroll delta should have been used to hide the top controls.
// The viewport layers should be resized back to their full sizes.
- EXPECT_EQ(0.f,
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
@@ -2657,8 +2671,7 @@
// The entire scroll delta should have been used to show the top controls.
// The outer viewport should be resized to accomodate and scrolled to the
// bottom of the document to keep the viewport in place.
- EXPECT_EQ(50.f,
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
@@ -2704,8 +2717,8 @@
gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
host_impl_->top_controls_manager()->ScrollBegin();
host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
- EXPECT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
- host_impl_->top_controls_manager()->ContentTopOffset());
+ EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
+ host_impl_->top_controls_manager()->ContentTopOffset());
EXPECT_VECTOR_EQ(top_controls_scroll_delta,
outer_viewport_scroll_layer->FixedContainerSizeDelta());
host_impl_->ScrollEnd();
@@ -2742,8 +2755,7 @@
DrawFrame();
// Show top controls
- EXPECT_EQ(top_controls_height_,
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
LayerImpl* outer_viewport_scroll_layer =
host_impl_->active_tree()->OuterViewportScrollLayer();
@@ -2777,7 +2789,7 @@
// Top controls should be hidden
EXPECT_EQ(scroll_delta.y(),
top_controls_height_ -
- host_impl_->active_tree()->total_top_controls_content_offset());
+ host_impl_->top_controls_manager()->ContentTopOffset());
}
// Ensure setting the top controls position explicitly using the setters on the
@@ -2787,14 +2799,18 @@
SetupTopControlsAndScrollLayer();
DrawFrame();
- host_impl_->active_tree()->set_top_controls_delta(0.f);
- host_impl_->active_tree()->set_top_controls_content_offset(30.f);
- EXPECT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
- EXPECT_EQ(-20.f, host_impl_->top_controls_manager()->ControlsTopOffset());
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
+ host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
+ 30.f / top_controls_height_);
+ host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
+ EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-20.f,
+ host_impl_->top_controls_manager()->ControlsTopOffset());
- host_impl_->active_tree()->set_top_controls_delta(-30.f);
- EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
- EXPECT_EQ(-50.f, host_impl_->top_controls_manager()->ControlsTopOffset());
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
+ EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-50.f,
+ host_impl_->top_controls_manager()->ControlsTopOffset());
host_impl_->DidChangeTopControlsPosition();
@@ -2811,18 +2827,22 @@
SetupTopControlsAndScrollLayer();
DrawFrame();
- host_impl_->sync_tree()->set_top_controls_content_offset(15.f);
-
- host_impl_->active_tree()->set_top_controls_content_offset(20.f);
- host_impl_->active_tree()->set_top_controls_delta(-20.f);
- host_impl_->active_tree()->set_sent_top_controls_delta(-5.f);
+ host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
+ 20.f / top_controls_height_);
+ host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
+ 15.f / top_controls_height_);
+ host_impl_->active_tree()
+ ->top_controls_shown_ratio()
+ ->PullDeltaForMainThread();
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
+ host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
+ top_controls_height_);
host_impl_->DidChangeTopControlsPosition();
LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
- EXPECT_EQ(0.f,
- host_impl_->active_tree()->total_top_controls_content_offset());
host_impl_->ActivateSyncTree();
@@ -2830,11 +2850,13 @@
EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
- EXPECT_EQ(0.f, host_impl_->active_tree()->sent_top_controls_delta());
- EXPECT_EQ(-15.f, host_impl_->active_tree()->top_controls_delta());
- EXPECT_EQ(15.f, host_impl_->active_tree()->top_controls_content_offset());
- EXPECT_EQ(0.f,
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_FLOAT_EQ(
+ -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
+ top_controls_height_);
+ EXPECT_FLOAT_EQ(
+ 15.f,
+ host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
+ top_controls_height_);
}
// Test that changing the top controls layout height is correctly applied to
@@ -2846,11 +2868,13 @@
SetupTopControlsAndScrollLayer();
DrawFrame();
- host_impl_->sync_tree()->set_top_controls_content_offset(50.f);
+ host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
- host_impl_->active_tree()->set_top_controls_content_offset(50.f);
- host_impl_->active_tree()->set_top_controls_delta(-50.f);
+ host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
+ 1.f);
+ host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
host_impl_->DidChangeTopControlsPosition();
LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
@@ -2872,9 +2896,11 @@
EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
- host_impl_->active_tree()->set_top_controls_delta(0.f);
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
host_impl_->DidChangeTopControlsPosition();
+ EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
+ EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
@@ -2889,8 +2915,7 @@
gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
DrawFrame();
- EXPECT_EQ(top_controls_height_,
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
@@ -2910,17 +2935,15 @@
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
// scrolling down at the max extents no longer hides the top controls
- EXPECT_EQ(0.f,
- top_controls_height_ -
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
// forcefully hide the top controls by 25px
host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
host_impl_->ScrollEnd();
- EXPECT_EQ(scroll_delta.y(),
- top_controls_height_ -
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_FLOAT_EQ(scroll_delta.y(),
+ top_controls_height_ -
+ host_impl_->top_controls_manager()->ContentTopOffset());
inner_scroll->ClampScrollToMaxScrollOffset();
outer_scroll->ClampScrollToMaxScrollOffset();
@@ -2956,8 +2979,8 @@
gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
DrawFrame();
- EXPECT_EQ(top_controls_height_,
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_FLOAT_EQ(top_controls_height_,
+ host_impl_->top_controls_manager()->ContentTopOffset());
gfx::Vector2dF scroll_delta(0.f, 25.f);
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -2965,9 +2988,9 @@
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
host_impl_->ScrollEnd();
- EXPECT_EQ(scroll_delta.y(),
- top_controls_height_ -
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_FLOAT_EQ(scroll_delta.y(),
+ top_controls_height_ -
+ host_impl_->top_controls_manager()->ContentTopOffset());
// Top controls were hidden by 25px so the inner viewport should have expanded
// by that much.
@@ -2993,7 +3016,7 @@
DrawFrame();
EXPECT_EQ(top_controls_height_,
- host_impl_->active_tree()->total_top_controls_content_offset());
+ host_impl_->top_controls_manager()->ContentTopOffset());
// Send a gesture scroll that will scroll the outer viewport, make sure the
// top controls get scrolled.
@@ -3005,16 +3028,16 @@
host_impl_->CurrentlyScrollingLayer());
host_impl_->ScrollEnd();
- EXPECT_EQ(scroll_delta.y(),
- top_controls_height_ -
- host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_FLOAT_EQ(scroll_delta.y(),
+ top_controls_height_ -
+ host_impl_->top_controls_manager()->ContentTopOffset());
scroll_delta = gfx::Vector2dF(0.f, 50.f);
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
- EXPECT_EQ(0, host_impl_->active_tree()->total_top_controls_content_offset());
+ EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
host_impl_->CurrentlyScrollingLayer());
@@ -3031,8 +3054,8 @@
host_impl_->ScrollBy(gfx::Point(), scroll_delta);
EXPECT_EQ(top_controls_height_,
- host_impl_->active_tree()->total_top_controls_content_offset());
- EXPECT_EQ(
+ host_impl_->top_controls_manager()->ContentTopOffset());
+ EXPECT_FLOAT_EQ(
inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
@@ -3065,8 +3088,8 @@
host_impl_->top_controls_manager()->ScrollBegin();
host_impl_->top_controls_manager()->ScrollBy(
gfx::Vector2dF(0.f, scroll_increment_y));
- EXPECT_EQ(-scroll_increment_y,
- host_impl_->top_controls_manager()->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-scroll_increment_y,
+ host_impl_->top_controls_manager()->ContentTopOffset());
// Now that top controls have moved, expect the clip to resize.
EXPECT_EQ(gfx::Size(viewport_size_.width(),
viewport_size_.height() + scroll_increment_y),
@@ -3075,8 +3098,8 @@
host_impl_->top_controls_manager()->ScrollBy(
gfx::Vector2dF(0.f, scroll_increment_y));
host_impl_->top_controls_manager()->ScrollEnd();
- EXPECT_EQ(-2 * scroll_increment_y,
- host_impl_->top_controls_manager()->ContentTopOffset());
+ EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
+ host_impl_->top_controls_manager()->ContentTopOffset());
// Now that top controls have moved, expect the clip to resize.
EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
@@ -4413,7 +4436,6 @@
}
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override {
quads_appended_ = true;
@@ -5138,7 +5160,6 @@
}
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override {
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
@@ -6592,8 +6613,8 @@
// DeferredInitialize and hardware draw.
did_update_renderer_capabilities_ = false;
- EXPECT_TRUE(
- output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
+ EXPECT_TRUE(output_surface_->InitializeAndSetContext3d(
+ onscreen_context_provider_, nullptr));
EXPECT_EQ(onscreen_context_provider_.get(),
host_impl_->output_surface()->context_provider());
EXPECT_TRUE(did_update_renderer_capabilities_);
@@ -6623,8 +6644,8 @@
// DeferredInitialize fails.
did_update_renderer_capabilities_ = false;
- EXPECT_FALSE(
- output_surface_->InitializeAndSetContext3d(onscreen_context_provider_));
+ EXPECT_FALSE(output_surface_->InitializeAndSetContext3d(
+ onscreen_context_provider_, nullptr));
EXPECT_FALSE(host_impl_->output_surface()->context_provider());
EXPECT_FALSE(did_update_renderer_capabilities_);
@@ -7412,9 +7433,8 @@
settings.calculate_top_controls_position = true;
CreateHostImpl(settings, CreateOutputSurface());
host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
- host_impl_->active_tree()->set_top_controls_delta(top_controls_height_);
- host_impl_->top_controls_manager()->SetTopControlsHeight(
- top_controls_height_);
+ host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
+ host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
}
protected:
@@ -7436,23 +7456,23 @@
host_impl_->CreatePendingTree();
host_impl_->sync_tree()->set_top_controls_height(100);
host_impl_->ActivateSyncTree();
- EXPECT_EQ(100, host_impl_->top_controls_manager()->top_controls_height());
+ EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
}
TEST_F(LayerTreeHostImplWithTopControlsTest,
TopControlsStayFullyVisibleOnHeightChange) {
SetupScrollAndContentsLayers(gfx::Size(100, 100));
- EXPECT_EQ(0.f, host_impl_->ControlsTopOffset());
+ EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
host_impl_->CreatePendingTree();
host_impl_->sync_tree()->set_top_controls_height(0);
host_impl_->ActivateSyncTree();
- EXPECT_EQ(0.f, host_impl_->ControlsTopOffset());
+ EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
host_impl_->CreatePendingTree();
host_impl_->sync_tree()->set_top_controls_height(50);
host_impl_->ActivateSyncTree();
- EXPECT_EQ(0.f, host_impl_->ControlsTopOffset());
+ EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
}
TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
@@ -8017,17 +8037,26 @@
scoped_ptr<PictureLayerImpl> layer =
FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
layer->SetBounds(gfx::Size(10, 10));
+ scoped_ptr<FakePictureLayerImpl> nondraw_layer =
+ FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
+ nondraw_layer->SetBounds(gfx::Size(10, 10));
scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
gfx::Size(10, 10), gfx::Size(10, 10)));
Region empty_invalidation;
const PictureLayerTilingSet* null_tiling_set = nullptr;
layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
+ nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
+ layer->AddChild(nondraw_layer.Pass());
host_impl_->pending_tree()->SetRootLayer(layer.Pass());
LayerTreeImpl* pending_tree = host_impl_->pending_tree();
LayerImpl* pending_layer = pending_tree->root_layer();
+ FakePictureLayerImpl* pending_nondraw_layer =
+ static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
+
+ pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
std::vector<PictureLayerImpl::Pair> layer_pairs;
host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
@@ -8039,10 +8068,16 @@
LayerTreeImpl* active_tree = host_impl_->active_tree();
LayerImpl* active_layer = active_tree->root_layer();
+ FakePictureLayerImpl* active_nondraw_layer =
+ static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
EXPECT_NE(active_tree, pending_tree);
EXPECT_NE(active_layer, pending_layer);
+ EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
EXPECT_NE(nullptr, active_tree);
EXPECT_NE(nullptr, active_layer);
+ EXPECT_NE(nullptr, active_nondraw_layer);
+
+ active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
host_impl_->CreatePendingTree();
@@ -8067,20 +8102,192 @@
host_impl_->pending_tree()->root_layer()->AddChild(
FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
- LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[0];
+ LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
layer_pairs.clear();
host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
EXPECT_EQ(2u, layer_pairs.size());
-
// The pair ordering is flaky, so make it consistent.
if (layer_pairs[0].active != active_layer)
std::swap(layer_pairs[0], layer_pairs[1]);
-
EXPECT_EQ(active_layer, layer_pairs[0].active);
EXPECT_EQ(pending_layer, layer_pairs[0].pending);
EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
EXPECT_EQ(nullptr, layer_pairs[1].active);
+
+ host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
+
+ // Have the pending layer be part of the RSLL now. It should appear in the
+ // list without an active twin.
+ pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
+
+ layer_pairs.clear();
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
+ EXPECT_EQ(2u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ EXPECT_EQ(active_layer, layer_pairs[0].active);
+ EXPECT_EQ(pending_layer, layer_pairs[0].pending);
+ EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
+ EXPECT_EQ(nullptr, layer_pairs[1].active);
+
+ // Have the active layer be part of the RSLL now instead. It should appear in
+ // the list without a pending twin.
+ pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
+ active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
+
+ layer_pairs.clear();
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
+ EXPECT_EQ(2u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ EXPECT_EQ(active_layer, layer_pairs[0].active);
+ EXPECT_EQ(pending_layer, layer_pairs[0].pending);
+ EXPECT_EQ(nullptr, layer_pairs[1].pending);
+ EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
+}
+
+TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairsWithNonRSLLMembers) {
+ host_impl_->CreatePendingTree();
+
+ scoped_ptr<PictureLayerImpl> layer =
+ FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
+ layer->SetBounds(gfx::Size(10, 10));
+ scoped_ptr<FakePictureLayerImpl> nondraw_layer =
+ FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
+ nondraw_layer->SetBounds(gfx::Size(10, 10));
+
+ scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
+ gfx::Size(10, 10), gfx::Size(10, 10)));
+ Region empty_invalidation;
+ const PictureLayerTilingSet* null_tiling_set = nullptr;
+ layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
+ nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
+
+ layer->AddChild(nondraw_layer.Pass());
+ host_impl_->pending_tree()->SetRootLayer(layer.Pass());
+
+ LayerTreeImpl* pending_tree = host_impl_->pending_tree();
+ LayerImpl* pending_layer = pending_tree->root_layer();
+ FakePictureLayerImpl* pending_nondraw_layer =
+ static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
+
+ pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
+
+ std::vector<PictureLayerImpl::Pair> layer_pairs;
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
+ EXPECT_EQ(2u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].pending != pending_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ EXPECT_EQ(pending_layer, layer_pairs[0].pending);
+ EXPECT_EQ(nullptr, layer_pairs[0].active);
+ EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
+ EXPECT_EQ(nullptr, layer_pairs[1].active);
+
+ host_impl_->ActivateSyncTree();
+
+ LayerTreeImpl* active_tree = host_impl_->active_tree();
+ LayerImpl* active_layer = active_tree->root_layer();
+ FakePictureLayerImpl* active_nondraw_layer =
+ static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
+ EXPECT_NE(active_tree, pending_tree);
+ EXPECT_NE(active_layer, pending_layer);
+ EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
+ EXPECT_NE(nullptr, active_tree);
+ EXPECT_NE(nullptr, active_layer);
+ EXPECT_NE(nullptr, active_nondraw_layer);
+
+ active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
+
+ host_impl_->CreatePendingTree();
+
+ layer_pairs.clear();
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
+ EXPECT_EQ(2u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ EXPECT_EQ(active_layer, layer_pairs[0].active);
+ EXPECT_EQ(pending_layer, layer_pairs[0].pending);
+ EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
+ EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
+
+ // Activate, the active layer has no twin now.
+ host_impl_->ActivateSyncTree();
+
+ layer_pairs.clear();
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
+ EXPECT_EQ(2u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ EXPECT_EQ(active_layer, layer_pairs[0].active);
+ EXPECT_EQ(nullptr, layer_pairs[0].pending);
+ EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
+ EXPECT_EQ(nullptr, layer_pairs[1].pending);
+
+ // Create another layer in the pending tree that's not in the active tree. We
+ // should get three pairs including the nondraw layers.
+ host_impl_->CreatePendingTree();
+ host_impl_->pending_tree()->root_layer()->AddChild(
+ FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
+
+ LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
+
+ layer_pairs.clear();
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
+ EXPECT_EQ(3u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[2]);
+ if (layer_pairs[1].pending != new_pending_layer)
+ std::swap(layer_pairs[1], layer_pairs[2]);
+ EXPECT_EQ(active_layer, layer_pairs[0].active);
+ EXPECT_EQ(pending_layer, layer_pairs[0].pending);
+ EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
+ EXPECT_EQ(nullptr, layer_pairs[1].active);
+ EXPECT_EQ(active_nondraw_layer, layer_pairs[2].active);
+ EXPECT_EQ(pending_nondraw_layer, layer_pairs[2].pending);
+
+ host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
+
+ // Have the pending layer be part of the RSLL now. It should appear in the
+ // list, as should its active twin since we don't request only layers with
+ // valid draw properties.
+ pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
+
+ layer_pairs.clear();
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
+ EXPECT_EQ(2u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ EXPECT_EQ(active_layer, layer_pairs[0].active);
+ EXPECT_EQ(pending_layer, layer_pairs[0].pending);
+ EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
+ EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
+
+ // Have the active layer be part of the RSLL now instead. It should appear in
+ // the list, as should its pending twin since we don't request only layers
+ // with valid draw properties.
+ pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
+ active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
+
+ layer_pairs.clear();
+ host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
+ EXPECT_EQ(2u, layer_pairs.size());
+ // The pair ordering is flaky, so make it consistent.
+ if (layer_pairs[0].active != active_layer)
+ std::swap(layer_pairs[0], layer_pairs[1]);
+ EXPECT_EQ(active_layer, layer_pairs[0].active);
+ EXPECT_EQ(pending_layer, layer_pairs[0].pending);
+ EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
+ EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
}
TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index bf8e3e2..76acaa8 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -395,6 +395,62 @@
base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_sw.png")));
}
+class EnlargedTextureWithAlphaThresholdFilter
+ : public LayerTreeHostFiltersPixelTest {
+ protected:
+ void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) {
+ // Rectangles choosen so that if flipped, the test will fail.
+ gfx::Rect rect1(10, 10, 10, 15);
+ gfx::Rect rect2(20, 25, 70, 65);
+
+ scoped_refptr<SolidColorLayer> child1 =
+ CreateSolidColorLayer(rect1, SK_ColorRED);
+ scoped_refptr<SolidColorLayer> child2 =
+ CreateSolidColorLayer(rect2, SK_ColorGREEN);
+ scoped_refptr<SolidColorLayer> background =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE);
+ scoped_refptr<SolidColorLayer> filter_layer =
+ CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
+
+ // Make sure a transformation does not cause misregistration of the filter
+ // and source texture.
+ gfx::Transform filter_transform;
+ filter_transform.Scale(2.f, 2.f);
+ filter_layer->SetTransform(filter_transform);
+ filter_layer->AddChild(child1);
+ filter_layer->AddChild(child2);
+
+ rect1.Inset(-5, -5);
+ rect2.Inset(-5, -5);
+ SkRegion alpha_region;
+ SkIRect rects[2] = {gfx::RectToSkIRect(rect1), gfx::RectToSkIRect(rect2)};
+ alpha_region.setRects(rects, 2);
+ FilterOperations filters;
+ filters.Append(
+ FilterOperation::CreateAlphaThresholdFilter(alpha_region, 0.f, 0.f));
+ filter_layer->SetFilters(filters);
+
+ background->AddChild(filter_layer);
+
+ // Force the allocation a larger textures.
+ set_enlarge_texture_amount(gfx::Vector2d(50, 50));
+
+ RunPixelTest(test_type, background, image_name);
+ }
+};
+
+TEST_F(EnlargedTextureWithAlphaThresholdFilter, GL) {
+ RunPixelTestType(
+ PIXEL_TEST_GL,
+ base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_threshold.png")));
+}
+
+TEST_F(EnlargedTextureWithAlphaThresholdFilter, Software) {
+ RunPixelTestType(
+ PIXEL_TEST_SOFTWARE,
+ base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_threshold.png")));
+}
+
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
index 5d828c5..d32817c 100644
--- a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
+++ b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
@@ -42,7 +42,7 @@
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
AppendQuadsData data;
- picture_layer->AppendQuads(render_pass.get(), Occlusion(), &data);
+ picture_layer->AppendQuads(render_pass.get(), &data);
for (const auto& quad : render_pass->quad_list)
EXPECT_EQ(quad->material, DrawQuad::PICTURE_CONTENT);
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc
index 0a06144..b372904 100644
--- a/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -19,18 +19,30 @@
namespace cc {
namespace {
-class LayerTreeHostReadbackPixelTest : public LayerTreePixelTest {
+// Can't templatize a class on its own members, so ReadbackType and
+// ReadbackTestConfig are declared here, before LayerTreeHostReadbackPixelTest.
+enum ReadbackType {
+ READBACK_INVALID,
+ READBACK_DEFAULT,
+ READBACK_BITMAP,
+};
+
+struct ReadbackTestConfig {
+ ReadbackTestConfig(LayerTreePixelTest::PixelTestType pixel_test_type_,
+ ReadbackType readback_type_)
+ : pixel_test_type(pixel_test_type_), readback_type(readback_type_) {}
+ LayerTreePixelTest::PixelTestType pixel_test_type;
+ ReadbackType readback_type;
+};
+
+class LayerTreeHostReadbackPixelTest
+ : public LayerTreePixelTest,
+ public testing::WithParamInterface<ReadbackTestConfig> {
protected:
LayerTreeHostReadbackPixelTest()
: readback_type_(READBACK_INVALID),
insert_copy_request_after_frame_count_(0) {}
- enum ReadbackType {
- READBACK_INVALID,
- READBACK_DEFAULT,
- READBACK_BITMAP,
- };
-
void RunReadbackTest(PixelTestType test_type,
ReadbackType readback_type,
scoped_refptr<Layer> content_root,
@@ -124,7 +136,7 @@
void IgnoreReadbackResult(scoped_ptr<CopyOutputResult> result) {
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayer_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackRootLayer) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
@@ -132,55 +144,11 @@
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
background->AddChild(green);
- RunReadbackTest(PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
- base::FilePath(FILE_PATH_LITERAL("green.png")));
+ RunReadbackTest(GetParam().pixel_test_type, GetParam().readback_type,
+ background, base::FilePath(FILE_PATH_LITERAL("green.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayer_Software_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- RunReadbackTest(PIXEL_TEST_SOFTWARE,
- READBACK_BITMAP,
- background,
- base::FilePath(FILE_PATH_LITERAL("green.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayer_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- RunReadbackTest(PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- base::FilePath(FILE_PATH_LITERAL("green.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayer_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- RunReadbackTest(PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- base::FilePath(FILE_PATH_LITERAL("green.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayerWithChild_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackRootLayerWithChild) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
@@ -193,51 +161,11 @@
green->AddChild(blue);
RunReadbackTest(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayerWithChild_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- RunReadbackTest(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackRootLayerWithChild_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- RunReadbackTest(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayer_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayer) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
@@ -246,46 +174,11 @@
background->AddChild(green);
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green.png")));
+ GetParam().pixel_test_type, GetParam().readback_type, background,
+ green.get(), base::FilePath(FILE_PATH_LITERAL("green.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayer_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayer_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayer_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayer) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
@@ -294,47 +187,11 @@
background->AddChild(green);
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small.png")));
+ GetParam().pixel_test_type, GetParam().readback_type, background,
+ green.get(), base::FilePath(FILE_PATH_LITERAL("green_small.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayer_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(100, 100, 100, 100), SK_ColorGREEN);
- background->AddChild(green);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayer_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(100, 100, 100, 100), SK_ColorGREEN);
- background->AddChild(green);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackSmallNonRootLayerWithChild_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayerWithChild) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
@@ -347,56 +204,12 @@
green->AddChild(blue);
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
green.get(),
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackSmallNonRootLayerWithChild_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(100, 100, 100, 100), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSmallNonRootLayerWithChild_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(100, 100, 100, 100), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackSubtreeSurroundsTargetLayer_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackSubtreeSurroundsTargetLayer) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
@@ -414,66 +227,13 @@
copy_subrect_ = gfx::Rect(0, 0, 100, 100);
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
target.get(),
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackSubtreeSurroundsLayer_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(100, 100, 100, 100), SK_ColorRED);
- background->AddChild(target);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(-100, -100, 300, 300), SK_ColorGREEN);
- target->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
-
- copy_subrect_ = gfx::Rect(0, 0, 100, 100);
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSubtreeSurroundsTargetLayer_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(100, 100, 100, 100), SK_ColorRED);
- background->AddChild(target);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(-100, -100, 300, 300), SK_ColorGREEN);
- target->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
-
- copy_subrect_ = gfx::Rect(0, 0, 100, 100);
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackSubtreeExtendsBeyondTargetLayer_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest,
+ ReadbackSubtreeExtendsBeyondTargetLayer) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
@@ -491,66 +251,12 @@
copy_subrect_ = gfx::Rect(50, 50, 100, 100);
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
target.get(),
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackSubtreeExtendsBeyondTargetLayer_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(50, 50, 150, 150), SK_ColorRED);
- background->AddChild(target);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(50, 50, 200, 200), SK_ColorGREEN);
- target->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(100, 100, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
-
- copy_subrect_ = gfx::Rect(50, 50, 100, 100);
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackSubtreeExtendsBeyondTargetLayer_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(50, 50, 150, 150), SK_ColorRED);
- background->AddChild(target);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(50, 50, 200, 200), SK_ColorGREEN);
- target->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(100, 100, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
-
- copy_subrect_ = gfx::Rect(50, 50, 100, 100);
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackHiddenSubtree_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackHiddenSubtree) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK);
@@ -564,57 +270,13 @@
hidden_target->AddChild(blue);
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
hidden_target.get(),
base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackHiddenSubtree_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK);
-
- scoped_refptr<SolidColorLayer> hidden_target =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- hidden_target->SetHideLayerAndSubtree(true);
- background->AddChild(hidden_target);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
- hidden_target->AddChild(blue);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- hidden_target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackHiddenSubtree_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK);
-
- scoped_refptr<SolidColorLayer> hidden_target =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- hidden_target->SetHideLayerAndSubtree(true);
- background->AddChild(hidden_target);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
- hidden_target->AddChild(blue);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- hidden_target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest,
- HiddenSubtreeNotVisibleWhenDrawnForReadback_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest,
+ HiddenSubtreeNotVisibleWhenDrawnForReadback) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK);
@@ -629,57 +291,11 @@
hidden_target->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
base::Bind(&IgnoreReadbackResult)));
- RunReadbackTest(PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
- base::FilePath(FILE_PATH_LITERAL("black.png")));
+ RunReadbackTest(GetParam().pixel_test_type, GetParam().readback_type,
+ background, base::FilePath(FILE_PATH_LITERAL("black.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest,
- HiddenSubtreeNotVisibleWhenDrawnForReadback_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK);
-
- scoped_refptr<SolidColorLayer> hidden_target =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- hidden_target->SetHideLayerAndSubtree(true);
- background->AddChild(hidden_target);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
- hidden_target->AddChild(blue);
-
- hidden_target->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
- base::Bind(&IgnoreReadbackResult)));
- RunReadbackTest(PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- base::FilePath(FILE_PATH_LITERAL("black.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest,
- HiddenSubtreeNotVisibleWhenDrawnForReadback_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLACK);
-
- scoped_refptr<SolidColorLayer> hidden_target =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- hidden_target->SetHideLayerAndSubtree(true);
- background->AddChild(hidden_target);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
- hidden_target->AddChild(blue);
-
- hidden_target->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
- base::Bind(&IgnoreReadbackResult)));
- RunReadbackTest(PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- base::FilePath(FILE_PATH_LITERAL("black.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSubrect_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackSubrect) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
@@ -695,57 +311,11 @@
copy_subrect_ = gfx::Rect(50, 50, 100, 100);
RunReadbackTest(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSubrect_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(100, 100, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- // Grab the middle of the root layer.
- copy_subrect_ = gfx::Rect(50, 50, 100, 100);
-
- RunReadbackTest(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackSubrect_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(100, 100, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- // Grab the middle of the root layer.
- copy_subrect_ = gfx::Rect(50, 50, 100, 100);
-
- RunReadbackTest(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerSubrect_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerSubrect) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
@@ -761,60 +331,12 @@
copy_subrect_ = gfx::Rect(25, 25, 100, 100);
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
green.get(),
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerSubrect_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(25, 25, 150, 150), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(75, 75, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- // Grab the middle of the green layer.
- copy_subrect_ = gfx::Rect(25, 25, 100, 100);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerSubrect_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(25, 25, 150, 150), SK_ColorGREEN);
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(75, 75, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- // Grab the middle of the green layer.
- copy_subrect_ = gfx::Rect(25, 25, 100, 100);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackWhenNoDamage_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackWhenNoDamage) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
@@ -832,65 +354,12 @@
insert_copy_request_after_frame_count_ = 1;
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
target.get(),
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackWhenNoDamage_GL_Bitmap) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> parent =
- CreateSolidColorLayer(gfx::Rect(0, 0, 150, 150), SK_ColorRED);
- background->AddChild(parent);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(0, 0, 100, 100), SK_ColorGREEN);
- parent->AddChild(target);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
-
- insert_copy_request_after_frame_count_ = 1;
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackWhenNoDamage_GL) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> parent =
- CreateSolidColorLayer(gfx::Rect(0, 0, 150, 150), SK_ColorRED);
- background->AddChild(parent);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(0, 0, 100, 100), SK_ColorGREEN);
- parent->AddChild(target);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
-
- insert_copy_request_after_frame_count_ = 1;
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackOutsideViewportWhenNoDamage_Software) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackOutsideViewportWhenNoDamage) {
scoped_refptr<SolidColorLayer> background =
CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
@@ -909,66 +378,81 @@
insert_copy_request_after_frame_count_ = 1;
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
target.get(),
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest,
- ReadbackOutsideViewportWhenNoDamage_GL_Bitmap) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerOutsideViewport) {
scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
- scoped_refptr<SolidColorLayer> parent =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorRED);
- EXPECT_FALSE(parent->masks_to_bounds());
- background->AddChild(parent);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(250, 250, 100, 100), SK_ColorGREEN);
- parent->AddChild(target);
+ scoped_refptr<SolidColorLayer> green =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
+ // Only the top left quarter of the layer is inside the viewport, so the
+ // blue layer is entirely outside.
+ green->SetPosition(gfx::Point(100, 100));
+ background->AddChild(green);
scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
+ CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
+ green->AddChild(blue);
- insert_copy_request_after_frame_count_ = 1;
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_BITMAP,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
+ GetParam().pixel_test_type, GetParam().readback_type, background,
+ green.get(),
+ base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackOutsideViewportWhenNoDamage_GL) {
+TEST_P(LayerTreeHostReadbackPixelTest, ReadbackNonRootOrFirstLayer) {
+ // This test has 3 render passes with the copy request on the render pass in
+ // the middle. This test caught an issue where copy requests on non-root
+ // non-first render passes were being treated differently from the first
+ // render pass.
scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> parent =
- CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorRED);
- EXPECT_FALSE(parent->masks_to_bounds());
- background->AddChild(parent);
-
- scoped_refptr<SolidColorLayer> target =
- CreateSolidColorLayer(gfx::Rect(250, 250, 100, 100), SK_ColorGREEN);
- parent->AddChild(target);
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(50, 50, 50, 50), SK_ColorBLUE);
- target->AddChild(blue);
+ CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
+ blue->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&IgnoreReadbackResult)));
+ background->AddChild(blue);
- insert_copy_request_after_frame_count_ = 1;
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- target.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
+ GetParam().pixel_test_type, GetParam().readback_type, background,
+ background.get(),
+ base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
}
+TEST_P(LayerTreeHostReadbackPixelTest, MultipleReadbacksOnLayer) {
+ // This test has 2 copy requests on the background layer. One is added in the
+ // test body, another is added in RunReadbackTestWithReadbackTarget. For every
+ // copy request after the first, state must be restored via a call to
+ // UseRenderPass (see http://crbug.com/99393). This test ensures that the
+ // renderer correctly handles cases where UseRenderPass is called multiple
+ // times for a single layer.
+ scoped_refptr<SolidColorLayer> background =
+ CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
+
+ background->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
+ base::Bind(&IgnoreReadbackResult)));
+
+ RunReadbackTestWithReadbackTarget(
+ GetParam().pixel_test_type, GetParam().readback_type, background,
+ background.get(), base::FilePath(FILE_PATH_LITERAL("green.png")));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ LayerTreeHostReadbackPixelTests,
+ LayerTreeHostReadbackPixelTest,
+ ::testing::Values(
+ ReadbackTestConfig(LayerTreeHostReadbackPixelTest::PIXEL_TEST_SOFTWARE,
+ READBACK_DEFAULT),
+ ReadbackTestConfig(LayerTreeHostReadbackPixelTest::PIXEL_TEST_GL,
+ READBACK_DEFAULT),
+ ReadbackTestConfig(LayerTreeHostReadbackPixelTest::PIXEL_TEST_GL,
+ READBACK_BITMAP)));
+
class LayerTreeHostReadbackDeviceScalePixelTest
: public LayerTreeHostReadbackPixelTest {
protected:
@@ -999,7 +483,7 @@
SolidColorContentLayerClient blue_client_;
};
-TEST_F(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackSubrect_Software) {
+TEST_P(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackSubrect) {
scoped_refptr<FakePictureLayer> background =
FakePictureLayer::Create(&white_client_);
background->SetBounds(gfx::Size(100, 100));
@@ -1022,43 +506,11 @@
copy_subrect_ = gfx::Rect(25, 25, 50, 50);
device_scale_factor_ = 2.f;
RunReadbackTest(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackSubrect_GL) {
- scoped_refptr<FakePictureLayer> background =
- FakePictureLayer::Create(&white_client_);
- background->SetBounds(gfx::Size(100, 100));
- background->SetIsDrawable(true);
-
- scoped_refptr<FakePictureLayer> green =
- FakePictureLayer::Create(&green_client_);
- green->SetBounds(gfx::Size(100, 100));
- green->SetIsDrawable(true);
- background->AddChild(green);
-
- scoped_refptr<FakePictureLayer> blue =
- FakePictureLayer::Create(&blue_client_);
- blue->SetPosition(gfx::Point(50, 50));
- blue->SetBounds(gfx::Size(25, 25));
- blue->SetIsDrawable(true);
- green->AddChild(blue);
-
- // Grab the middle of the root layer.
- copy_subrect_ = gfx::Rect(25, 25, 50, 50);
- device_scale_factor_ = 2.f;
- RunReadbackTest(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackDeviceScalePixelTest,
- ReadbackNonRootLayerSubrect_Software) {
+TEST_P(LayerTreeHostReadbackDeviceScalePixelTest, ReadbackNonRootLayerSubrect) {
scoped_refptr<FakePictureLayer> background =
FakePictureLayer::Create(&white_client_);
background->SetBounds(gfx::Size(100, 100));
@@ -1082,67 +534,21 @@
copy_subrect_ = gfx::Rect(25, 25, 50, 50);
device_scale_factor_ = 2.f;
RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_SOFTWARE,
- READBACK_DEFAULT,
- background,
+ GetParam().pixel_test_type, GetParam().readback_type, background,
green.get(),
base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
}
-TEST_F(LayerTreeHostReadbackDeviceScalePixelTest,
- ReadbackNonRootLayerSubrect_GL) {
- scoped_refptr<FakePictureLayer> background =
- FakePictureLayer::Create(&white_client_);
- background->SetBounds(gfx::Size(100, 100));
- background->SetIsDrawable(true);
-
- scoped_refptr<FakePictureLayer> green =
- FakePictureLayer::Create(&green_client_);
- green->SetPosition(gfx::Point(10, 20));
- green->SetBounds(gfx::Size(90, 80));
- green->SetIsDrawable(true);
- background->AddChild(green);
-
- scoped_refptr<FakePictureLayer> blue =
- FakePictureLayer::Create(&blue_client_);
- blue->SetPosition(gfx::Point(50, 50));
- blue->SetBounds(gfx::Size(25, 25));
- blue->SetIsDrawable(true);
- green->AddChild(blue);
-
- // Grab the green layer's content with blue in the bottom right.
- copy_subrect_ = gfx::Rect(25, 25, 50, 50);
- device_scale_factor_ = 2.f;
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_small_with_blue_corner.png")));
-}
-
-TEST_F(LayerTreeHostReadbackPixelTest, ReadbackNonRootLayerOutsideViewport) {
- scoped_refptr<SolidColorLayer> background =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
-
- scoped_refptr<SolidColorLayer> green =
- CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorGREEN);
- // Only the top left quarter of the layer is inside the viewport, so the
- // blue layer is entirely outside.
- green->SetPosition(gfx::Point(100, 100));
- background->AddChild(green);
-
- scoped_refptr<SolidColorLayer> blue =
- CreateSolidColorLayer(gfx::Rect(150, 150, 50, 50), SK_ColorBLUE);
- green->AddChild(blue);
-
- RunReadbackTestWithReadbackTarget(
- PIXEL_TEST_GL,
- READBACK_DEFAULT,
- background,
- green.get(),
- base::FilePath(FILE_PATH_LITERAL("green_with_blue_corner.png")));
-}
+INSTANTIATE_TEST_CASE_P(
+ LayerTreeHostReadbackDeviceScalePixelTests,
+ LayerTreeHostReadbackDeviceScalePixelTest,
+ ::testing::Values(
+ ReadbackTestConfig(LayerTreeHostReadbackPixelTest::PIXEL_TEST_SOFTWARE,
+ READBACK_DEFAULT),
+ ReadbackTestConfig(LayerTreeHostReadbackPixelTest::PIXEL_TEST_GL,
+ READBACK_DEFAULT),
+ ReadbackTestConfig(LayerTreeHostReadbackPixelTest::PIXEL_TEST_GL,
+ READBACK_BITMAP)));
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index cff3b1f..bb6dc17 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -82,7 +82,8 @@
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
- const std::vector<PictureLayerImpl*>& layers = impl->GetPictureLayers();
+ const std::vector<PictureLayerImpl*>& layers =
+ impl->sync_tree()->picture_layers();
required_for_activation_count_ = 0;
for (const auto& layer : layers) {
FakePictureLayerImpl* fake_layer =
@@ -139,7 +140,9 @@
FakeContentLayerClient client_;
};
-SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestReadyToActivateNonEmpty);
+// Multi-thread only because in single thread the commit goes directly to the
+// active tree, so notify ready to activate is skipped.
+MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestReadyToActivateNonEmpty);
// Test if the LTHI receives ReadyToDraw notifications from the TileManager when
// no raster tasks get scheduled.
@@ -154,7 +157,8 @@
void NotifyReadyToDrawOnThread(LayerTreeHostImpl* impl) override {
did_notify_ready_to_draw_ = true;
- const std::vector<PictureLayerImpl*>& layers = impl->GetPictureLayers();
+ const std::vector<PictureLayerImpl*>& layers =
+ impl->active_tree()->picture_layers();
all_tiles_required_for_draw_are_ready_to_draw_ =
impl->tile_manager()->IsReadyToDraw();
for (const auto& layer : layers) {
@@ -578,7 +582,7 @@
void AfterTest() override {
EXPECT_EQ(gfx::Size(40, 40).ToString(),
- scrollbar_->content_bounds().ToString());
+ scrollbar_->internal_content_bounds().ToString());
}
private:
@@ -1793,7 +1797,6 @@
~EvictionTestLayerImpl() override {}
void AppendQuads(RenderPass* render_pass,
- const Occlusion& occlusion_in_content_space,
AppendQuadsData* append_quads_data) override {
ASSERT_TRUE(has_texture_);
ASSERT_NE(0u, layer_tree_impl()->resource_provider()->num_resources());
@@ -2940,8 +2943,10 @@
static_cast<FakeOutputSurface*>(host_impl->output_surface());
scoped_refptr<TestContextProvider> context_provider =
TestContextProvider::Create(); // Not bound to thread.
- EXPECT_TRUE(
- fake_output_surface->InitializeAndSetContext3d(context_provider));
+ scoped_refptr<TestContextProvider> worker_context_provider =
+ TestContextProvider::Create(); // Not bound to thread.
+ EXPECT_TRUE(fake_output_surface->InitializeAndSetContext3d(
+ context_provider, worker_context_provider));
did_initialize_gl_ = true;
}
@@ -5172,7 +5177,7 @@
}
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
- EXPECT_TRUE(host_impl->pending_tree()->use_gpu_rasterization());
+ EXPECT_TRUE(host_impl->sync_tree()->use_gpu_rasterization());
EXPECT_TRUE(host_impl->use_gpu_rasterization());
}
@@ -5797,14 +5802,17 @@
MULTI_THREAD_IMPL_TEST_F(RasterizeWithGpuRasterizationCreatesResources);
-class GpuRasterizationRasterizesVisibleOnly : public LayerTreeHostTest {
+class SynchronousGpuRasterizationRasterizesVisibleOnly
+ : public LayerTreeHostTest {
protected:
- GpuRasterizationRasterizesVisibleOnly() : viewport_size_(1024, 2048) {}
+ SynchronousGpuRasterizationRasterizesVisibleOnly()
+ : viewport_size_(1024, 2048) {}
void InitializeSettings(LayerTreeSettings* settings) override {
settings->impl_side_painting = true;
settings->gpu_rasterization_enabled = true;
settings->gpu_rasterization_forced = true;
+ settings->threaded_gpu_rasterization_enabled = false;
}
void SetupTree() override {
@@ -5856,7 +5864,54 @@
gfx::Size viewport_size_;
};
-MULTI_THREAD_IMPL_TEST_F(GpuRasterizationRasterizesVisibleOnly);
+MULTI_THREAD_IMPL_TEST_F(SynchronousGpuRasterizationRasterizesVisibleOnly);
+
+class ThreadedGpuRasterizationRasterizesBorderTiles : public LayerTreeHostTest {
+ protected:
+ ThreadedGpuRasterizationRasterizesBorderTiles()
+ : viewport_size_(1024, 2048) {}
+
+ void InitializeSettings(LayerTreeSettings* settings) override {
+ settings->impl_side_painting = true;
+ settings->gpu_rasterization_enabled = true;
+ settings->gpu_rasterization_forced = true;
+ settings->threaded_gpu_rasterization_enabled = true;
+ }
+
+ void SetupTree() override {
+ client_.set_fill_with_nonsolid_color(true);
+
+ scoped_ptr<FakePicturePile> pile(
+ new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale,
+ ImplSidePaintingSettings().default_tile_grid_size));
+ scoped_refptr<FakePictureLayer> root =
+ FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass());
+ root->SetBounds(gfx::Size(10000, 10000));
+ root->SetContentsOpaque(true);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeHostTest::SetupTree();
+ layer_tree_host()->SetViewportSize(viewport_size_);
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
+ LayerTreeHostImpl::FrameData* frame_data,
+ DrawResult draw_result) override {
+ EXPECT_EQ(10u, host_impl->resource_provider()->num_resources());
+ EndTest();
+ return draw_result;
+ }
+
+ void AfterTest() override {}
+
+ private:
+ FakeContentLayerClient client_;
+ gfx::Size viewport_size_;
+};
+
+MULTI_THREAD_IMPL_TEST_F(ThreadedGpuRasterizationRasterizesBorderTiles);
class LayerTreeHostTestContinuousDrawWhenCreatingVisibleTiles
: public LayerTreeHostTest {
diff --git a/cc/trees/layer_tree_host_unittest_occlusion.cc b/cc/trees/layer_tree_host_unittest_occlusion.cc
index fe87e44..9974ae4 100644
--- a/cc/trees/layer_tree_host_unittest_occlusion.cc
+++ b/cc/trees/layer_tree_host_unittest_occlusion.cc
@@ -5,623 +5,266 @@
#include "cc/trees/layer_tree_host.h"
#include "cc/layers/layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
+#include "cc/layers/picture_layer.h"
+#include "cc/test/fake_content_layer_client.h"
#include "cc/test/layer_tree_test.h"
-#include "cc/test/test_occlusion_tracker.h"
+#include "cc/trees/layer_tree_impl.h"
namespace cc {
namespace {
-class TestLayer : public Layer {
- public:
- static scoped_refptr<TestLayer> Create() {
- return make_scoped_refptr(new TestLayer());
- }
-
- bool Update(ResourceUpdateQueue* update_queue,
- const OcclusionTracker<Layer>* occlusion) override {
- if (!occlusion)
- return false;
-
- const TestOcclusionTracker<Layer>* test_occlusion =
- static_cast<const TestOcclusionTracker<Layer>*>(occlusion);
- occlusion_ = UnionSimpleEnclosedRegions(
- test_occlusion->occlusion_from_inside_target(),
- test_occlusion->occlusion_from_outside_target());
- return false;
- }
-
- const SimpleEnclosedRegion& occlusion() const { return occlusion_; }
- const SimpleEnclosedRegion& expected_occlusion() const {
- return expected_occlusion_;
- }
- void set_expected_occlusion(const gfx::Rect& occlusion) {
- expected_occlusion_ = SimpleEnclosedRegion(occlusion);
- }
-
- private:
- TestLayer() : Layer() {
- SetIsDrawable(true);
- }
- ~TestLayer() override {}
-
- SimpleEnclosedRegion occlusion_;
- SimpleEnclosedRegion expected_occlusion_;
-};
+#define EXPECT_OCCLUSION_EQ(expected, actual) \
+ EXPECT_TRUE(expected.IsEqual(actual)) \
+ << " Expected: " << expected.ToString() << std::endl \
+ << " Actual: " << actual.ToString();
class LayerTreeHostOcclusionTest : public LayerTreeTest {
+ protected:
+ void InitializeSettings(LayerTreeSettings* settings) override {
+ settings->minimum_occlusion_tracking_size = gfx::Size();
+ }
+};
+
+// Verify occlusion is set on the layer draw properties.
+class LayerTreeHostOcclusionTestDrawPropertiesOnLayer
+ : public LayerTreeHostOcclusionTest {
public:
- LayerTreeHostOcclusionTest()
- : root_(TestLayer::Create()),
- child_(TestLayer::Create()),
- child2_(TestLayer::Create()),
- grand_child_(TestLayer::Create()),
- mask_(TestLayer::Create()) {
+ void SetupTree() override {
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(100, 100));
+ root->SetIsDrawable(true);
+
+ scoped_refptr<Layer> child = Layer::Create();
+ child->SetBounds(gfx::Size(50, 60));
+ child->SetPosition(gfx::PointF(10.f, 5.5f));
+ child->SetContentsOpaque(true);
+ child->SetIsDrawable(true);
+ root->AddChild(child);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeTest::SetupTree();
}
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
- void DidCommit() override {
- TestLayer* root = static_cast<TestLayer*>(layer_tree_host()->root_layer());
- VerifyOcclusion(root);
+ void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->active_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ // Verify the draw properties are valid.
+ EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember());
+ EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember());
+
+ EXPECT_OCCLUSION_EQ(
+ Occlusion(child->draw_transform(), SimpleEnclosedRegion(),
+ SimpleEnclosedRegion()),
+ child->draw_properties().occlusion_in_content_space);
+ EXPECT_OCCLUSION_EQ(
+ Occlusion(root->draw_transform(), SimpleEnclosedRegion(),
+ SimpleEnclosedRegion(gfx::Rect(10, 6, 50, 59))),
+ root->draw_properties().occlusion_in_content_space);
+ EndTest();
+ }
+
+ void AfterTest() override {}
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestDrawPropertiesOnLayer);
+
+// Verify occlusion is set on the render surfaces.
+class LayerTreeHostOcclusionTestDrawPropertiesOnSurface
+ : public LayerTreeHostOcclusionTest {
+ public:
+ void SetupTree() override {
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(100, 100));
+ root->SetIsDrawable(true);
+
+ scoped_refptr<Layer> child = Layer::Create();
+ child->SetBounds(gfx::Size(1, 1));
+ child->SetPosition(gfx::PointF(10.f, 5.5f));
+ child->SetIsDrawable(true);
+ child->SetForceRenderSurface(true);
+ root->AddChild(child);
+
+ scoped_refptr<Layer> child2 = Layer::Create();
+ child2->SetBounds(gfx::Size(10, 12));
+ child2->SetPosition(gfx::PointF(13.f, 8.5f));
+ child2->SetContentsOpaque(true);
+ child2->SetIsDrawable(true);
+ root->AddChild(child2);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeTest::SetupTree();
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->active_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ RenderSurfaceImpl* surface = child->render_surface();
+
+ // Verify the draw properties are valid.
+ EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember());
+ EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember());
+ EXPECT_EQ(child, child->render_target());
+
+ EXPECT_OCCLUSION_EQ(
+ Occlusion(surface->draw_transform(), SimpleEnclosedRegion(),
+ SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))),
+ surface->occlusion_in_content_space());
+ EndTest();
+ }
+
+ void AfterTest() override {}
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+ LayerTreeHostOcclusionTestDrawPropertiesOnSurface);
+
+// Verify occlusion is set on mask layers.
+class LayerTreeHostOcclusionTestDrawPropertiesOnMask
+ : public LayerTreeHostOcclusionTest {
+ public:
+ void SetupTree() override {
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(100, 100));
+ root->SetIsDrawable(true);
+
+ scoped_refptr<Layer> child = Layer::Create();
+ child->SetBounds(gfx::Size(30, 40));
+ child->SetPosition(gfx::PointF(10.f, 5.5f));
+ child->SetIsDrawable(true);
+ root->AddChild(child);
+
+ scoped_refptr<Layer> make_surface_bigger = Layer::Create();
+ make_surface_bigger->SetBounds(gfx::Size(100, 100));
+ make_surface_bigger->SetPosition(gfx::PointF(-10.f, -15.f));
+ make_surface_bigger->SetIsDrawable(true);
+ child->AddChild(make_surface_bigger);
+
+ scoped_refptr<Layer> mask = PictureLayer::Create(&client_);
+ mask->SetBounds(gfx::Size(30, 40));
+ mask->SetIsDrawable(true);
+ child->SetMaskLayer(mask.get());
+
+ scoped_refptr<Layer> child2 = Layer::Create();
+ child2->SetBounds(gfx::Size(10, 12));
+ child2->SetPosition(gfx::PointF(13.f, 8.5f));
+ child2->SetContentsOpaque(true);
+ child2->SetIsDrawable(true);
+ root->AddChild(child2);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeTest::SetupTree();
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->active_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ RenderSurfaceImpl* surface = child->render_surface();
+ LayerImpl* mask = child->mask_layer();
+
+ // Verify the draw properties are valid.
+ EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember());
+ EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember());
+ EXPECT_EQ(child, child->render_target());
+
+ gfx::Transform transform = surface->draw_transform();
+ transform.PreconcatTransform(child->draw_transform());
+
+ EXPECT_OCCLUSION_EQ(
+ Occlusion(transform, SimpleEnclosedRegion(),
+ SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))),
+ mask->draw_properties().occlusion_in_content_space);
EndTest();
}
void AfterTest() override {}
- void VerifyOcclusion(TestLayer* layer) const {
- EXPECT_EQ(layer->expected_occlusion().ToString(),
- layer->occlusion().ToString());
-
- for (size_t i = 0; i < layer->children().size(); ++i) {
- TestLayer* child = static_cast<TestLayer*>(layer->children()[i].get());
- VerifyOcclusion(child);
- }
- }
-
- void SetLayerPropertiesForTesting(TestLayer* layer,
- TestLayer* parent,
- const gfx::Transform& transform,
- const gfx::PointF& position,
- const gfx::Size& bounds,
- bool opaque) const {
- layer->RemoveAllChildren();
- if (parent)
- parent->AddChild(layer);
- layer->SetTransform(transform);
- layer->SetPosition(position);
- layer->SetBounds(bounds);
- layer->SetContentsOpaque(opaque);
- }
-
- protected:
- void InitializeSettings(LayerTreeSettings* settings) override {
- settings->minimum_occlusion_tracking_size = gfx::Size();
- }
-
- scoped_refptr<TestLayer> root_;
- scoped_refptr<TestLayer> child_;
- scoped_refptr<TestLayer> child2_;
- scoped_refptr<TestLayer> grand_child_;
- scoped_refptr<TestLayer> mask_;
-
- gfx::Transform identity_matrix_;
+ FakeContentLayerClient client_;
};
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestDrawPropertiesOnMask);
-class LayerTreeHostOcclusionTestOcclusionSurfaceClipping
+// Verify occlusion is set to empty inside the subtree of a replica. This is
+// done because the tile system does not know about replicas, and so would not
+// know that something is unoccluded on the replica even though it's occluded on
+// the original.
+class LayerTreeHostOcclusionTestDrawPropertiesInsideReplica
: public LayerTreeHostOcclusionTest {
public:
void SetupTree() override {
- // The child layer is a surface and the grand_child is opaque, but clipped
- // to the child and root
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), false);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(100, 100));
+ root->SetIsDrawable(true);
- child_->SetMasksToBounds(true);
- child_->SetForceRenderSurface(true);
+ scoped_refptr<Layer> child = Layer::Create();
+ child->SetBounds(gfx::Size(1, 1));
+ child->SetPosition(gfx::PointF(10.f, 5.5f));
+ child->SetIsDrawable(true);
+ child->SetForceRenderSurface(true);
+ root->AddChild(child);
- child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
- root_->set_expected_occlusion(gfx::Rect(10, 10, 10, 190));
+ scoped_refptr<Layer> replica = Layer::Create();
+ gfx::Transform translate;
+ translate.Translate(20.f, 4.f);
+ replica->SetTransform(translate);
+ child->SetReplicaLayer(replica.get());
- layer_tree_host()->SetRootLayer(root_);
+ scoped_refptr<Layer> mask = PictureLayer::Create(&client_);
+ mask->SetBounds(gfx::Size(30, 40));
+ mask->SetIsDrawable(true);
+ child->SetMaskLayer(mask.get());
+
+ scoped_refptr<Layer> child2 = Layer::Create();
+ child2->SetBounds(gfx::Size(10, 12));
+ child2->SetPosition(gfx::PointF(13.f, 8.5f));
+ child2->SetContentsOpaque(true);
+ child2->SetIsDrawable(true);
+ root->AddChild(child2);
+
+ layer_tree_host()->SetRootLayer(root);
LayerTreeTest::SetupTree();
}
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->active_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ RenderSurfaceImpl* surface = child->render_surface();
+ LayerImpl* mask = child->mask_layer();
+
+ // Verify the draw properties are valid.
+ EXPECT_TRUE(root->IsDrawnRenderSurfaceLayerListMember());
+ EXPECT_TRUE(child->IsDrawnRenderSurfaceLayerListMember());
+ EXPECT_EQ(child, child->render_target());
+
+ // No occlusion from on child, which is part of the replica.
+ EXPECT_OCCLUSION_EQ(Occlusion(),
+ child->draw_properties().occlusion_in_content_space);
+ // Occlusion on the surface is okay.
+ EXPECT_OCCLUSION_EQ(
+ Occlusion(surface->draw_transform(), SimpleEnclosedRegion(),
+ SimpleEnclosedRegion(gfx::Rect(13, 9, 10, 11))),
+ surface->occlusion_in_content_space());
+ // No occlusion on the replica'd mask.
+ EXPECT_OCCLUSION_EQ(Occlusion(),
+ mask->draw_properties().occlusion_in_content_space);
+ EndTest();
+ }
+
+ void AfterTest() override {}
+
+ FakeContentLayerClient client_;
};
SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionSurfaceClipping);
-
-class LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer is opaque, then it adds to the occlusion seen by the
- // root_.
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetForceRenderSurface(true);
-
- child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
- root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionSurfaceClippingOpaque);
-
-class LayerTreeHostOcclusionTestOcclusionTwoChildren
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // Add a second child to the root layer and the regions should merge
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), false);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetForceRenderSurface(true);
-
- grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
- child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
- root_->set_expected_occlusion(gfx::Rect(10, 10, 20, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionTwoChildren);
-
-class LayerTreeHostOcclusionTestOcclusionMask
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer has a mask on it, then it shouldn't contribute to
- // occlusion on stuff below it.
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(20.f, 20.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(500, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetForceRenderSurface(true);
- child_->SetMaskLayer(mask_.get());
-
- child_->set_expected_occlusion(gfx::Rect(0, 0, 180, 180));
- root_->set_expected_occlusion(gfx::Rect(10, 10, 190, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionMask);
-
-class LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer with a mask is below child2, then child2 should
- // contribute to occlusion on everything, and child shouldn't contribute
- // to the root_.
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetForceRenderSurface(true);
- child_->SetMaskLayer(mask_.get());
-
- grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
- child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
- root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionMaskBelowOcclusion);
-
-class LayerTreeHostOcclusionTestOcclusionOpacity
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer has a non-opaque opacity, then it shouldn't
- // contribute to occlusion on stuff below it
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetForceRenderSurface(true);
- child_->SetOpacity(0.5f);
-
- child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
- root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionOpacity);
-
-class LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer with non-opaque opacity is below child2, then
- // child2 should contribute to occlusion on everything, and child shouldn't
- // contribute to the root_.
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetForceRenderSurface(true);
- child_->SetOpacity(0.5f);
-
- grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
- child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
- root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionOpacityBelowOcclusion);
-
-class LayerTreeHostOcclusionTestOcclusionBlending
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer has a blend mode, then it shouldn't
- // contribute to occlusion on stuff below it
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetBlendMode(SkXfermode::kMultiply_Mode);
- child_->SetForceRenderSurface(true);
-
- child_->set_expected_occlusion(gfx::Rect(0, 0, 10, 190));
- root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionBlending);
-
-class LayerTreeHostOcclusionTestOcclusionBlendingBelowOcclusion
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer with a blend mode is below child2, then
- // child2 should contribute to occlusion on everything, and child shouldn't
- // contribute to the root_.
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(-10.f, -10.f), gfx::Size(20, 500), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(20.f, 10.f), gfx::Size(10, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetBlendMode(SkXfermode::kMultiply_Mode);
-
- grand_child_->set_expected_occlusion(gfx::Rect(10, 0, 10, 190));
- child_->set_expected_occlusion(gfx::Rect(0, 0, 20, 190));
- root_->set_expected_occlusion(gfx::Rect(20, 10, 10, 190));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionBlendingBelowOcclusion);
-
-class LayerTreeHostOcclusionTestOcclusionOpacityFilter
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- FilterOperations filters;
- filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
-
- // If the child layer has a filter that changes alpha values, and is below
- // child2, then child2 should contribute to occlusion on everything,
- // and child shouldn't contribute to the root
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(child_.get(),
- root_.get(),
- identity_matrix_,
- gfx::PointF(0.f, 0.f),
- gfx::Size(500, 500),
- true);
- SetLayerPropertiesForTesting(grand_child_.get(),
- child_.get(),
- identity_matrix_,
- gfx::PointF(0.f, 0.f),
- gfx::Size(500, 500),
- true);
- SetLayerPropertiesForTesting(child2_.get(),
- root_.get(),
- identity_matrix_,
- gfx::PointF(10.f, 10.f),
- gfx::Size(30, 30),
- true);
-
- child_->SetMasksToBounds(true);
- child_->SetFilters(filters);
-
- // child2_ occludes grand_child_, showing it does occlude inside child_'s
- // subtree.
- grand_child_->set_expected_occlusion(gfx::Rect(10, 10, 30, 30));
- // grand_child_ occludes child_, showing there is more occlusion in
- // child_'s subtree.
- child_->set_expected_occlusion(gfx::Rect(0, 0, 200, 200));
- // child2_'s occlusion reaches the root, but child_'s subtree does not.
- root_->set_expected_occlusion(gfx::Rect(10, 10, 30, 30));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionOpacityFilter);
-
-class LayerTreeHostOcclusionTestOcclusionBlurFilter
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- gfx::Transform child_transform;
- child_transform.Translate(250.0, 250.0);
- child_transform.Rotate(90.0);
- child_transform.Translate(-250.0, -250.0);
-
- FilterOperations filters;
- filters.Append(FilterOperation::CreateBlurFilter(10.f));
-
- // If the child layer has a filter that moves pixels/changes alpha, and is
- // below child2, then child should not inherit occlusion from outside its
- // subtree, and should not contribute to the root
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(200, 200), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), child_transform,
- gfx::PointF(30.f, 30.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(10.f, 10.f), gfx::Size(500, 500), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(10.f, 70.f), gfx::Size(500, 500), true);
-
- child_->SetMasksToBounds(true);
- child_->SetFilters(filters);
-
- child_->set_expected_occlusion(gfx::Rect(10, 330, 160, 170));
- root_->set_expected_occlusion(gfx::Rect(10, 70, 190, 130));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(
- LayerTreeHostOcclusionTestOcclusionBlurFilter);
-
-class LayerTreeHostOcclusionTestOcclusionCopyRequest
- : public LayerTreeHostOcclusionTest {
- public:
- static void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {}
-
- void SetupTree() override {
- // If the child layer has copy request, and is below child2,
- // then child should not inherit occlusion from outside its subtree.
- // The child layer will still receive occlusion from inside, and
- // the root layer will recive occlusion from child.
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(), gfx::Size(100, 100), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(), gfx::Size(75, 75), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(), gfx::Size(75, 50), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(0.f, 25.f), gfx::Size(75, 75), true);
-
- child_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
- base::Bind(&CopyOutputCallback)));
- EXPECT_TRUE(child_->HasCopyRequest());
-
- child_->set_expected_occlusion(gfx::Rect(0, 0, 75, 50));
- root_->set_expected_occlusion(gfx::Rect(0, 0, 75, 100));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionCopyRequest);
-
-class LayerTreeHostOcclusionTestOcclusionReplica
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // If the child layer has copy request, and is below child2,
- // then child should not inherit occlusion from outside its subtree.
- // The child layer will still receive occlusion from inside, and
- // the root layer will recive occlusion from child.
- SetLayerPropertiesForTesting(
- root_.get(), NULL, identity_matrix_,
- gfx::PointF(), gfx::Size(100, 100), true);
- SetLayerPropertiesForTesting(
- child_.get(), root_.get(), identity_matrix_,
- gfx::PointF(), gfx::Size(75, 75), true);
- SetLayerPropertiesForTesting(
- grand_child_.get(), child_.get(), identity_matrix_,
- gfx::PointF(), gfx::Size(75, 50), true);
- SetLayerPropertiesForTesting(
- child2_.get(), root_.get(), identity_matrix_,
- gfx::PointF(0.f, 25.f), gfx::Size(75, 75), true);
-
- scoped_refptr<Layer> replica_layer(Layer::Create());
- child_->SetReplicaLayer(replica_layer.get());
- EXPECT_TRUE(child_->has_replica());
-
- child_->set_expected_occlusion(gfx::Rect(0, 0, 75, 50));
- root_->set_expected_occlusion(gfx::Rect(0, 0, 75, 100));
-
- layer_tree_host()->SetRootLayer(root_);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestOcclusionReplica);
-
-class LayerTreeHostOcclusionTestManySurfaces
- : public LayerTreeHostOcclusionTest {
- public:
- void SetupTree() override {
- // We create enough RenderSurfaces that it will trigger Vector reallocation
- // while computing occlusion.
- std::vector<scoped_refptr<TestLayer>> layers;
- int num_surfaces = 200;
- int root_width = 400;
- int root_height = 400;
-
- for (int i = 0; i < num_surfaces; ++i) {
- layers.push_back(TestLayer::Create());
- if (i == 0) {
- SetLayerPropertiesForTesting(
- layers.back().get(), NULL, identity_matrix_,
- gfx::PointF(0.f, 0.f),
- gfx::Size(root_width, root_height), true);
- } else {
- SetLayerPropertiesForTesting(
- layers.back().get(), layers[layers.size() - 2].get(),
- identity_matrix_,
- gfx::PointF(1.f, 1.f),
- gfx::Size(root_width-i, root_height-i), true);
- layers.back()->SetForceRenderSurface(true);
- }
- }
-
- for (int i = 1; i < num_surfaces; ++i) {
- scoped_refptr<TestLayer> child = TestLayer::Create();
- SetLayerPropertiesForTesting(
- child.get(), layers[i].get(), identity_matrix_,
- gfx::PointF(0.f, 0.f), gfx::Size(root_width, root_height), false);
- }
-
- for (int i = 0; i < num_surfaces-1; ++i) {
- gfx::Rect expected_occlusion(1, 1, root_width-i-1, root_height-i-1);
- layers[i]->set_expected_occlusion(expected_occlusion);
- }
-
- layer_tree_host()->SetRootLayer(layers[0]);
- LayerTreeTest::SetupTree();
- }
-};
-
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostOcclusionTestManySurfaces);
+ LayerTreeHostOcclusionTestDrawPropertiesInsideReplica);
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest_picture.cc b/cc/trees/layer_tree_host_unittest_picture.cc
index 159200a..5ce47cd 100644
--- a/cc/trees/layer_tree_host_unittest_picture.cc
+++ b/cc/trees/layer_tree_host_unittest_picture.cc
@@ -135,7 +135,8 @@
int activates_;
};
-SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestTwinLayer);
+// There is no pending layers in single thread mode.
+MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestTwinLayer);
class LayerTreeHostPictureTestResizeViewportWithGpuRaster
: public LayerTreeHostPictureTest {
@@ -158,7 +159,7 @@
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
- void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+ void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
LayerImpl* child = impl->sync_tree()->root_layer()->children()[0];
FakePictureLayerImpl* picture_impl =
static_cast<FakePictureLayerImpl*>(child);
@@ -324,8 +325,247 @@
scoped_refptr<FakePictureLayer> picture_;
};
-SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(
+// Multi-thread only since there is no recycle tree in single thread.
+MULTI_THREAD_IMPL_TEST_F(
LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree);
+class LayerTreeHostPictureTestRSLLMembership : public LayerTreeHostPictureTest {
+ void SetupTree() override {
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(100, 100));
+
+ child_ = Layer::Create();
+ root->AddChild(child_);
+
+ // Don't be solid color so the layer has tilings/tiles.
+ client_.set_fill_with_nonsolid_color(true);
+ picture_ = FakePictureLayer::Create(&client_);
+ picture_->SetBounds(gfx::Size(100, 100));
+ child_->AddChild(picture_);
+
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeHostPictureTest::SetupTree();
+ }
+
+ void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+ void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->sync_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ LayerImpl* gchild = child->children()[0];
+ FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
+
+ switch (impl->sync_tree()->source_frame_number()) {
+ case 0:
+ // On 1st commit the layer has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ break;
+ case 1:
+ // On 2nd commit, the layer is transparent, but its tilings are left
+ // there.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ break;
+ case 2:
+ // On 3rd commit, the layer is visible again, so has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ }
+ }
+
+ void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->active_tree()->root_layer();
+ LayerImpl* child = root->children()[0];
+ LayerImpl* gchild = child->children()[0];
+ FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
+
+ switch (impl->active_tree()->source_frame_number()) {
+ case 0:
+ // On 1st commit the layer has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ break;
+ case 1:
+ // On 2nd commit, the layer is transparent, but its tilings are left
+ // there.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ break;
+ case 2:
+ // On 3rd commit, the layer is visible again, so has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ EndTest();
+ }
+ }
+
+ void DidCommit() override {
+ switch (layer_tree_host()->source_frame_number()) {
+ case 1:
+ // For the 2nd commit, change opacity to 0 so that the layer will not be
+ // part of the visible frame.
+ child_->SetOpacity(0.f);
+ break;
+ case 2:
+ // For the 3rd commit, change opacity to 1 so that the layer will again
+ // be part of the visible frame.
+ child_->SetOpacity(1.f);
+ }
+ }
+
+ void AfterTest() override {}
+
+ FakeContentLayerClient client_;
+ scoped_refptr<Layer> child_;
+ scoped_refptr<FakePictureLayer> picture_;
+};
+
+SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembership);
+
+class LayerTreeHostPictureTestRSLLMembershipWithScale
+ : public LayerTreeHostPictureTest {
+ void SetupTree() override {
+ scoped_refptr<Layer> root = Layer::Create();
+ root->SetBounds(gfx::Size(100, 100));
+
+ pinch_ = Layer::Create();
+ pinch_->SetBounds(gfx::Size(500, 500));
+ pinch_->SetScrollClipLayerId(root->id());
+ pinch_->SetIsContainerForFixedPositionLayers(true);
+ root->AddChild(pinch_);
+
+ // Don't be solid color so the layer has tilings/tiles.
+ client_.set_fill_with_nonsolid_color(true);
+ picture_ = FakePictureLayer::Create(&client_);
+ picture_->SetBounds(gfx::Size(100, 100));
+ pinch_->AddChild(picture_);
+
+ layer_tree_host()->RegisterViewportLayers(NULL, root, pinch_, pinch_);
+ layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 1.f, 4.f);
+ layer_tree_host()->SetRootLayer(root);
+ LayerTreeHostPictureTest::SetupTree();
+ }
+
+ void InitializeSettings(LayerTreeSettings* settings) override {
+ settings->layer_transforms_should_scale_layer_contents = true;
+ }
+
+ void BeginTest() override {
+ frame_ = 0;
+ draws_in_frame_ = 0;
+ last_frame_drawn_ = -1;
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->sync_tree()->root_layer();
+ LayerImpl* pinch = root->children()[0];
+ LayerImpl* gchild = pinch->children()[0];
+ FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
+
+ switch (frame_) {
+ case 0:
+ // On 1st commit the layer has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ break;
+ case 1:
+ // On 2nd commit, the layer is transparent, so does not have tilings.
+ EXPECT_EQ(0u, picture->tilings()->num_tilings());
+ break;
+ case 2:
+ // On 3rd commit, the layer is visible again, so has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ }
+ }
+
+ void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
+ LayerImpl* root = impl->active_tree()->root_layer();
+ LayerImpl* pinch = root->children()[0];
+ LayerImpl* gchild = pinch->children()[0];
+ FakePictureLayerImpl* picture = static_cast<FakePictureLayerImpl*>(gchild);
+
+ if (frame_ != last_frame_drawn_)
+ draws_in_frame_ = 0;
+ ++draws_in_frame_;
+ last_frame_drawn_ = frame_;
+
+ switch (frame_) {
+ case 0:
+ if (draws_in_frame_ == 1) {
+ // On 1st commit the layer has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ EXPECT_EQ(1.f, picture->HighResTiling()->contents_scale());
+
+ // Pinch zoom in to change the scale on the active tree.
+ impl->PinchGestureBegin();
+ impl->PinchGestureUpdate(2.f, gfx::Point(1, 1));
+ impl->PinchGestureEnd();
+ } else if (picture->tilings()->num_tilings() == 1) {
+ // If the pinch gesture caused a commit we could get here with a
+ // pending tree.
+ EXPECT_FALSE(impl->pending_tree());
+ // The active layer now has only a 2.f scale tiling, which means the
+ // recycled layer's tiling is destroyed.
+ EXPECT_EQ(2.f, picture->HighResTiling()->contents_scale());
+ EXPECT_EQ(0u, picture->GetRecycledTwinLayer()
+ ->picture_layer_tiling_set()
+ ->num_tilings());
+
+ ++frame_;
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep,
+ base::Unretained(this)));
+ }
+ break;
+ case 1:
+ EXPECT_EQ(1, draws_in_frame_);
+ // On 2nd commit, the layer is transparent, so does not create
+ // tilings. Since the 1.f tiling was destroyed in the recycle tree, it
+ // has no tilings left. This is propogated to the active tree.
+ EXPECT_EQ(0u, picture->picture_layer_tiling_set()->num_tilings());
+ EXPECT_EQ(0u, picture->GetRecycledTwinLayer()
+ ->picture_layer_tiling_set()
+ ->num_tilings());
+ ++frame_;
+ MainThreadTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &LayerTreeHostPictureTestRSLLMembershipWithScale::NextStep,
+ base::Unretained(this)));
+ break;
+ case 2:
+ EXPECT_EQ(1, draws_in_frame_);
+ // On 3rd commit, the layer is visible again, so has tilings.
+ EXPECT_GT(picture->tilings()->num_tilings(), 0u);
+ EndTest();
+ }
+ }
+
+ void NextStep() {
+ switch (frame_) {
+ case 1:
+ // For the 2nd commit, change opacity to 0 so that the layer will not be
+ // part of the visible frame.
+ pinch_->SetOpacity(0.f);
+ break;
+ case 2:
+ // For the 3rd commit, change opacity to 1 so that the layer will again
+ // be part of the visible frame.
+ pinch_->SetOpacity(1.f);
+ break;
+ }
+ }
+
+ void AfterTest() override {}
+
+ FakeContentLayerClient client_;
+ scoped_refptr<Layer> pinch_;
+ scoped_refptr<FakePictureLayer> picture_;
+ int frame_;
+ int draws_in_frame_;
+ int last_frame_drawn_;
+};
+
+// Multi-thread only because in single thread you can't pinch zoom on the
+// compositor thread.
+MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestRSLLMembershipWithScale);
+
} // namespace
} // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 80ccf14..4093c42 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -4,6 +4,7 @@
#include "cc/trees/layer_tree_impl.h"
+#include <algorithm>
#include <limits>
#include <set>
@@ -76,6 +77,7 @@
LayerTreeImpl::LayerTreeImpl(
LayerTreeHostImpl* layer_tree_host_impl,
scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
+ scoped_refptr<SyncedTopControls> top_controls_shown_ratio,
scoped_refptr<SyncedElasticOverscroll> elastic_overscroll)
: layer_tree_host_impl_(layer_tree_host_impl),
source_frame_number_(-1),
@@ -102,9 +104,7 @@
render_surface_layer_list_id_(0),
top_controls_shrink_blink_size_(false),
top_controls_height_(0),
- top_controls_content_offset_(0),
- top_controls_delta_(0),
- sent_top_controls_delta_(0) {
+ top_controls_shown_ratio_(top_controls_shown_ratio) {
}
LayerTreeImpl::~LayerTreeImpl() {
@@ -210,20 +210,10 @@
target_tree->PassSwapPromises(&swap_promise_list_);
- // Track the change in top controls height to offset the top_controls_delta
- // properly. This is so that the top controls offset will be maintained
- // across height changes.
- float top_controls_height_delta =
- target_tree->top_controls_height_ - top_controls_height_;
-
- target_tree->top_controls_shrink_blink_size_ =
- top_controls_shrink_blink_size_;
- target_tree->top_controls_height_ = top_controls_height_;
- target_tree->top_controls_content_offset_ = top_controls_content_offset_;
- target_tree->top_controls_delta_ = target_tree->top_controls_delta_ -
- target_tree->sent_top_controls_delta_ -
- top_controls_height_delta;
- target_tree->sent_top_controls_delta_ = 0.f;
+ target_tree->set_top_controls_shrink_blink_size(
+ top_controls_shrink_blink_size_);
+ target_tree->set_top_controls_height(top_controls_height_);
+ target_tree->PushTopControls(nullptr);
// Active tree already shares the page_scale_factor object with pending
// tree so only the limits need to be provided.
@@ -364,6 +354,48 @@
DidUpdatePageScale();
}
+void LayerTreeImpl::set_top_controls_shrink_blink_size(bool shrink) {
+ if (top_controls_shrink_blink_size_ == shrink)
+ return;
+
+ top_controls_shrink_blink_size_ = shrink;
+ if (IsActiveTree())
+ layer_tree_host_impl_->UpdateViewportContainerSizes();
+}
+
+void LayerTreeImpl::set_top_controls_height(float top_controls_height) {
+ if (top_controls_height_ == top_controls_height)
+ return;
+
+ top_controls_height_ = top_controls_height;
+ if (IsActiveTree())
+ layer_tree_host_impl_->UpdateViewportContainerSizes();
+}
+
+bool LayerTreeImpl::SetCurrentTopControlsShownRatio(float ratio) {
+ ratio = std::max(ratio, 0.f);
+ ratio = std::min(ratio, 1.f);
+ return top_controls_shown_ratio_->SetCurrent(ratio);
+}
+
+void LayerTreeImpl::PushTopControlsFromMainThread(
+ float top_controls_shown_ratio) {
+ PushTopControls(&top_controls_shown_ratio);
+}
+
+void LayerTreeImpl::PushTopControls(const float* top_controls_shown_ratio) {
+ DCHECK(top_controls_shown_ratio || IsActiveTree());
+
+ if (top_controls_shown_ratio) {
+ DCHECK(!IsActiveTree() || !layer_tree_host_impl_->pending_tree());
+ top_controls_shown_ratio_->PushFromMainThread(*top_controls_shown_ratio);
+ }
+ if (IsActiveTree()) {
+ if (top_controls_shown_ratio_->PushPendingToActive())
+ layer_tree_host_impl_->DidChangeTopControlsPosition();
+ }
+}
+
bool LayerTreeImpl::SetPageScaleFactorLimits(float min_page_scale_factor,
float max_page_scale_factor) {
if (min_page_scale_factor == min_page_scale_factor_ &&
@@ -451,12 +483,9 @@
DCHECK(IsActiveTree());
page_scale_factor()->AbortCommit();
+ top_controls_shown_ratio()->AbortCommit();
elastic_overscroll()->AbortCommit();
- top_controls_content_offset_ += sent_top_controls_delta_;
- top_controls_delta_ -= sent_top_controls_delta_;
- sent_top_controls_delta_ = 0.f;
-
if (!root_layer())
return;
@@ -520,12 +549,9 @@
render_surface_layer_list_.clear();
{
- TRACE_EVENT2("cc",
- "LayerTreeImpl::UpdateDrawProperties",
- "IsActive",
- IsActiveTree(),
- "SourceFrameNumber",
- source_frame_number_);
+ TRACE_EVENT2(
+ "cc", "LayerTreeImpl::UpdateDrawProperties::CalculateDrawProperties",
+ "IsActive", IsActiveTree(), "SourceFrameNumber", source_frame_number_);
LayerImpl* page_scale_layer =
page_scale_layer_ ? page_scale_layer_ : InnerViewportContainerLayer();
bool can_render_to_separate_surface =
@@ -548,66 +574,93 @@
}
{
- TRACE_EVENT_BEGIN2("cc", "LayerTreeImpl::UpdateTilePriorities", "IsActive",
- IsActiveTree(), "SourceFrameNumber",
- source_frame_number_);
- scoped_ptr<OcclusionTracker<LayerImpl>> occlusion_tracker;
- if (settings().use_occlusion_for_tile_prioritization) {
- occlusion_tracker.reset(new OcclusionTracker<LayerImpl>(
- root_layer()->render_surface()->content_rect()));
- occlusion_tracker->set_minimum_tracking_size(
- settings().minimum_occlusion_tracking_size);
- }
-
- bool resourceless_software_draw = (layer_tree_host_impl_->GetDrawMode() ==
- DRAW_MODE_RESOURCELESS_SOFTWARE);
+ TRACE_EVENT2("cc", "LayerTreeImpl::UpdateDrawProperties::Occlusion",
+ "IsActive", IsActiveTree(), "SourceFrameNumber",
+ source_frame_number_);
+ OcclusionTracker<LayerImpl> occlusion_tracker(
+ root_layer()->render_surface()->content_rect());
+ occlusion_tracker.set_minimum_tracking_size(
+ settings().minimum_occlusion_tracking_size);
// LayerIterator is used here instead of CallFunctionForSubtree to only
// UpdateTilePriorities on layers that will be visible (and thus have valid
// draw properties) and not because any ordering is required.
- typedef LayerIterator<LayerImpl> LayerIteratorType;
- LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
- size_t layers_updated_count = 0;
- bool tile_priorities_updated = false;
- for (LayerIteratorType it =
- LayerIteratorType::Begin(&render_surface_layer_list_);
- it != end;
- ++it) {
- if (occlusion_tracker)
- occlusion_tracker->EnterLayer(it);
+ auto end = LayerIterator<LayerImpl>::End(&render_surface_layer_list_);
+ for (auto it = LayerIterator<LayerImpl>::Begin(&render_surface_layer_list_);
+ it != end; ++it) {
+ occlusion_tracker.EnterLayer(it);
- LayerImpl* layer = *it;
- const Occlusion& occlusion_in_content_space =
- occlusion_tracker ? occlusion_tracker->GetCurrentOcclusionForLayer(
- layer->draw_transform())
- : Occlusion();
+ // There are very few render targets so this should be cheap to do for
+ // each layer instead of something more complicated.
+ bool inside_replica = false;
+ LayerImpl* layer = it->render_target();
+ while (layer && !inside_replica) {
+ if (layer->render_target()->has_replica())
+ inside_replica = true;
+ layer = layer->render_target()->parent();
+ }
+
+ // Don't use occlusion if a layer will appear in a replica, since the
+ // tile raster code does not know how to look for the replica and would
+ // consider it occluded even though the replica is visible.
+ // Since occlusion is only used for browser compositor (i.e.
+ // use_occlusion_for_tile_prioritization) and it won't use replicas,
+ // this should matter not.
if (it.represents_itself()) {
- tile_priorities_updated |= layer->UpdateTiles(
- occlusion_in_content_space, resourceless_software_draw);
- ++layers_updated_count;
+ Occlusion occlusion =
+ inside_replica ? Occlusion()
+ : occlusion_tracker.GetCurrentOcclusionForLayer(
+ it->draw_transform());
+ it->draw_properties().occlusion_in_content_space = occlusion;
}
- if (!it.represents_contributing_render_surface()) {
- if (occlusion_tracker)
- occlusion_tracker->LeaveLayer(it);
+ if (it.represents_contributing_render_surface()) {
+ // Surfaces aren't used by the tile raster code, so they can have
+ // occlusion regardless of replicas.
+ Occlusion occlusion =
+ occlusion_tracker.GetCurrentOcclusionForContributingSurface(
+ it->render_surface()->draw_transform());
+ it->render_surface()->set_occlusion_in_content_space(occlusion);
+ // Masks are used to draw the contributing surface, so should have
+ // the same occlusion as the surface (nothing inside the surface
+ // occludes them).
+ if (LayerImpl* mask = it->mask_layer()) {
+ Occlusion mask_occlusion =
+ inside_replica
+ ? Occlusion()
+ : occlusion_tracker.GetCurrentOcclusionForContributingSurface(
+ it->render_surface()->draw_transform() *
+ it->draw_transform());
+ mask->draw_properties().occlusion_in_content_space = mask_occlusion;
+ }
+ if (LayerImpl* replica = it->replica_layer()) {
+ if (LayerImpl* mask = replica->mask_layer())
+ mask->draw_properties().occlusion_in_content_space = Occlusion();
+ }
+ }
+
+ occlusion_tracker.LeaveLayer(it);
+ }
+
+ unoccluded_screen_space_region_ =
+ occlusion_tracker.ComputeVisibleRegionInScreen();
+ }
+
+ {
+ TRACE_EVENT_BEGIN2("cc", "LayerTreeImpl::UpdateDrawProperties::UpdateTiles",
+ "IsActive", IsActiveTree(), "SourceFrameNumber",
+ source_frame_number_);
+ const bool resourceless_software_draw =
+ (layer_tree_host_impl_->GetDrawMode() ==
+ DRAW_MODE_RESOURCELESS_SOFTWARE);
+ size_t layers_updated_count = 0;
+ bool tile_priorities_updated = false;
+ for (PictureLayerImpl* layer : picture_layers_) {
+ if (!layer->IsDrawnRenderSurfaceLayerListMember())
continue;
- }
-
- if (layer->mask_layer()) {
- tile_priorities_updated |= layer->mask_layer()->UpdateTiles(
- occlusion_in_content_space, resourceless_software_draw);
- ++layers_updated_count;
- }
- if (layer->replica_layer() && layer->replica_layer()->mask_layer()) {
- tile_priorities_updated |=
- layer->replica_layer()->mask_layer()->UpdateTiles(
- occlusion_in_content_space, resourceless_software_draw);
- ++layers_updated_count;
- }
-
- if (occlusion_tracker)
- occlusion_tracker->LeaveLayer(it);
+ ++layers_updated_count;
+ tile_priorities_updated |= layer->UpdateTiles(resourceless_software_draw);
}
if (tile_priorities_updated)
@@ -628,6 +681,13 @@
return render_surface_layer_list_;
}
+const Region& LayerTreeImpl::UnoccludedScreenSpaceRegion() const {
+ // If this assert triggers, then the render_surface_layer_list_ is dirty, so
+ // the unoccluded_screen_space_region_ is not valid anymore.
+ DCHECK(!needs_update_draw_properties_);
+ return unoccluded_screen_space_region_;
+}
+
gfx::Size LayerTreeImpl::ScrollableSize() const {
LayerImpl* root_scroll_layer = OuterViewportScrollLayer()
? OuterViewportScrollLayer()
@@ -739,6 +799,10 @@
return layer_tree_host_impl_->settings();
}
+const LayerTreeDebugState& LayerTreeImpl::debug_state() const {
+ return layer_tree_host_impl_->debug_state();
+}
+
const RendererCapabilitiesImpl& LayerTreeImpl::GetRendererCapabilities() const {
return layer_tree_host_impl_->GetRendererCapabilities();
}
@@ -775,6 +839,14 @@
return layer_tree_host_impl_->device_viewport_size();
}
+float LayerTreeImpl::device_scale_factor() const {
+ return layer_tree_host_impl_->device_scale_factor();
+}
+
+DebugRectHistory* LayerTreeImpl::debug_rect_history() const {
+ return layer_tree_host_impl_->debug_rect_history();
+}
+
bool LayerTreeImpl::IsActiveTree() const {
return layer_tree_host_impl_->active_tree() == this;
}
@@ -882,18 +954,6 @@
layer_tree_host_impl_->SetNeedsRedraw();
}
-const LayerTreeDebugState& LayerTreeImpl::debug_state() const {
- return layer_tree_host_impl_->debug_state();
-}
-
-float LayerTreeImpl::device_scale_factor() const {
- return layer_tree_host_impl_->device_scale_factor();
-}
-
-DebugRectHistory* LayerTreeImpl::debug_rect_history() const {
- return layer_tree_host_impl_->debug_rect_history();
-}
-
AnimationRegistrar* LayerTreeImpl::animationRegistrar() const {
return layer_tree_host_impl_->animation_registrar();
}
@@ -912,7 +972,7 @@
}
}
-void LayerTreeImpl::AsValueInto(base::debug::TracedValue* state) const {
+void LayerTreeImpl::AsValueInto(base::trace_event::TracedValue* state) const {
TracedValue::MakeDictIntoImplicitSnapshot(state, "cc::LayerTreeImpl", this);
state->SetInteger("source_frame_number", source_frame_number_);
@@ -1120,6 +1180,19 @@
layer_tree_host_impl_->SetNeedsCommit();
}
+void LayerTreeImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) {
+ DCHECK(std::find(picture_layers_.begin(), picture_layers_.end(), layer) ==
+ picture_layers_.end());
+ picture_layers_.push_back(layer);
+}
+
+void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) {
+ std::vector<PictureLayerImpl*>::iterator it =
+ std::find(picture_layers_.begin(), picture_layers_.end(), layer);
+ DCHECK(it != picture_layers_.end());
+ picture_layers_.erase(it);
+}
+
void LayerTreeImpl::AddLayerWithCopyOutputRequest(LayerImpl* layer) {
// Only the active tree needs to know about layers with copy requests, as
// they are aborted if not serviced during draw.
@@ -1532,14 +1605,6 @@
}
}
-void LayerTreeImpl::RegisterPictureLayerImpl(PictureLayerImpl* layer) {
- layer_tree_host_impl_->RegisterPictureLayerImpl(layer);
-}
-
-void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) {
- layer_tree_host_impl_->UnregisterPictureLayerImpl(layer);
-}
-
void LayerTreeImpl::InputScrollAnimationFinished() {
layer_tree_host_impl_->ScrollEnd();
}
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 2329139..54c8660 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -22,13 +22,7 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
}
-} // namespace base
namespace cc {
@@ -55,6 +49,7 @@
struct SelectionHandle;
typedef std::vector<UIResourceRequest> UIResourceRequestQueue;
+typedef SyncedProperty<AdditionGroup<float>> SyncedTopControls;
typedef SyncedProperty<AdditionGroup<gfx::Vector2dF>> SyncedElasticOverscroll;
class CC_EXPORT LayerTreeImpl {
@@ -62,9 +57,11 @@
static scoped_ptr<LayerTreeImpl> create(
LayerTreeHostImpl* layer_tree_host_impl,
scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
+ scoped_refptr<SyncedTopControls> top_controls_shown_ratio,
scoped_refptr<SyncedElasticOverscroll> elastic_overscroll) {
- return make_scoped_ptr(new LayerTreeImpl(
- layer_tree_host_impl, page_scale_factor, elastic_overscroll));
+ return make_scoped_ptr(
+ new LayerTreeImpl(layer_tree_host_impl, page_scale_factor,
+ top_controls_shown_ratio, elastic_overscroll));
}
virtual ~LayerTreeImpl();
@@ -75,6 +72,7 @@
// Methods called by the layer tree that pass-through or access LTHI.
// ---------------------------------------------------------------------------
const LayerTreeSettings& settings() const;
+ const LayerTreeDebugState& debug_state() const;
const RendererCapabilitiesImpl& GetRendererCapabilities() const;
ContextProvider* context_provider() const;
OutputSurface* output_surface() const;
@@ -84,6 +82,8 @@
PaintTimeCounter* paint_time_counter() const;
MemoryHistory* memory_history() const;
gfx::Size device_viewport_size() const;
+ float device_scale_factor() const;
+ DebugRectHistory* debug_rect_history() const;
bool IsActiveTree() const;
bool IsPendingTree() const;
bool IsRecycleTree() const;
@@ -111,13 +111,10 @@
// ---------------------------------------------------------------------------
void SetNeedsRedraw();
- // TODO(nduca): These are implemented in cc files temporarily, but will become
- // trivial accessors in a followup patch.
- const LayerTreeDebugState& debug_state() const;
- float device_scale_factor() const;
- DebugRectHistory* debug_rect_history() const;
+ // Tracing methods.
+ // ---------------------------------------------------------------------------
void GetAllTilesForTracing(std::set<const Tile*>* tiles) const;
- void AsValueInto(base::debug::TracedValue* dict) const;
+ void AsValueInto(base::trace_event::TracedValue* dict) const;
// Other public methods
// ---------------------------------------------------------------------------
@@ -192,6 +189,13 @@
return elastic_overscroll_.get();
}
+ SyncedTopControls* top_controls_shown_ratio() {
+ return top_controls_shown_ratio_.get();
+ }
+ const SyncedTopControls* top_controls_shown_ratio() const {
+ return top_controls_shown_ratio_.get();
+ }
+
// Updates draw properties and render surface layer list, as well as tile
// priorities. Returns false if it was unable to update.
bool UpdateDrawProperties();
@@ -216,6 +220,7 @@
void set_ui_resource_request_queue(const UIResourceRequestQueue& queue);
const LayerImplList& RenderSurfaceLayerList() const;
+ const Region& UnoccludedScreenSpaceRegion() const;
// These return the size of the root scrollable area and the size of
// the user-visible scrolling viewport, in CSS layout coordinates.
@@ -273,6 +278,12 @@
bool IsUIResourceOpaque(UIResourceId uid) const;
+ void RegisterPictureLayerImpl(PictureLayerImpl* layer);
+ void UnregisterPictureLayerImpl(PictureLayerImpl* layer);
+ const std::vector<PictureLayerImpl*>& picture_layers() const {
+ return picture_layers_;
+ }
+
void AddLayerWithCopyOutputRequest(LayerImpl* layer);
void RemoveLayerWithCopyOutputRequest(LayerImpl* layer);
const std::vector<LayerImpl*>& LayersWithCopyOutputRequest() const;
@@ -300,39 +311,17 @@
void GetViewportSelection(ViewportSelectionBound* start,
ViewportSelectionBound* end);
- void RegisterPictureLayerImpl(PictureLayerImpl* layer);
- void UnregisterPictureLayerImpl(PictureLayerImpl* layer);
-
- void set_top_controls_shrink_blink_size(bool shrink) {
- top_controls_shrink_blink_size_ = shrink;
- }
- void set_top_controls_height(float height) { top_controls_height_ = height; }
- void set_top_controls_content_offset(float offset) {
- top_controls_content_offset_ = offset;
- }
- void set_top_controls_delta(float delta) {
- top_controls_delta_ = delta;
- }
- void set_sent_top_controls_delta(float sent_delta) {
- sent_top_controls_delta_ = sent_delta;
- }
-
+ void set_top_controls_shrink_blink_size(bool shrink);
bool top_controls_shrink_blink_size() const {
return top_controls_shrink_blink_size_;
}
+ bool SetCurrentTopControlsShownRatio(float ratio);
+ float CurrentTopControlsShownRatio() const {
+ return top_controls_shown_ratio_->Current(IsActiveTree());
+ }
+ void set_top_controls_height(float top_controls_height);
float top_controls_height() const { return top_controls_height_; }
- float top_controls_content_offset() const {
- return top_controls_content_offset_;
- }
- float top_controls_delta() const {
- return top_controls_delta_;
- }
- float sent_top_controls_delta() const {
- return sent_top_controls_delta_;
- }
- float total_top_controls_content_offset() const {
- return top_controls_content_offset_ + top_controls_delta_;
- }
+ void PushTopControlsFromMainThread(float top_controls_shown_ratio);
void SetPendingPageScaleAnimation(
scoped_ptr<PendingPageScaleAnimation> pending_animation);
@@ -342,6 +331,7 @@
explicit LayerTreeImpl(
LayerTreeHostImpl* layer_tree_host_impl,
scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor,
+ scoped_refptr<SyncedTopControls> top_controls_shown_ratio,
scoped_refptr<SyncedElasticOverscroll> elastic_overscroll);
void ProcessLayersRecursive(LayerImpl* current,
void (LayerImpl::*function)());
@@ -353,7 +343,7 @@
float max_page_scale_factor);
void DidUpdatePageScale();
void HideInnerViewportScrollbarsIfNearMinimumScale();
-
+ void PushTopControls(const float* top_controls_shown_ratio);
LayerTreeHostImpl* layer_tree_host_impl_;
int source_frame_number_;
scoped_ptr<LayerImpl> root_layer_;
@@ -384,6 +374,7 @@
typedef base::hash_map<int, LayerImpl*> LayerIdMap;
LayerIdMap layer_id_map_;
+ std::vector<PictureLayerImpl*> picture_layers_;
std::vector<LayerImpl*> layers_with_copy_output_request_;
// Persisted state for non-impl-side-painting.
@@ -391,6 +382,9 @@
// List of visible layers for the most recently prepared frame.
LayerImplList render_surface_layer_list_;
+ // After drawing the |render_surface_layer_list_| the areas in this region
+ // would not be fully covered by opaque content.
+ Region unoccluded_screen_space_region_;
bool contents_textures_purged_;
bool viewport_size_invalid_;
@@ -416,11 +410,9 @@
float top_controls_height_;
- // The up-to-date content offset of the top controls, i.e. the amount that the
- // web contents have been shifted down from the top of the device viewport.
- float top_controls_content_offset_;
- float top_controls_delta_;
- float sent_top_controls_delta_;
+ // The amount that the top controls are shown from 0 (hidden) to 1 (fully
+ // shown).
+ scoped_refptr<SyncedTopControls> top_controls_shown_ratio_;
scoped_ptr<PendingPageScaleAnimation> pending_page_scale_animation_;
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc
index 07dfc29..d3afbe2 100644
--- a/cc/trees/layer_tree_settings.cc
+++ b/cc/trees/layer_tree_settings.cc
@@ -30,6 +30,7 @@
gpu_rasterization_enabled(false),
gpu_rasterization_forced(false),
gpu_rasterization_msaa_sample_count(0),
+ gpu_rasterization_skewport_target_time_in_seconds(0.0f),
threaded_gpu_rasterization_enabled(false),
create_low_res_tiling(false),
scrollbar_animator(NoAnimator),
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 8ba859a..fd108f4 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -38,6 +38,7 @@
bool gpu_rasterization_enabled;
bool gpu_rasterization_forced;
int gpu_rasterization_msaa_sample_count;
+ float gpu_rasterization_skewport_target_time_in_seconds;
bool threaded_gpu_rasterization_enabled;
bool create_low_res_tiling;
diff --git a/cc/trees/occlusion.cc b/cc/trees/occlusion.cc
index 14168f9..6a71496 100644
--- a/cc/trees/occlusion.cc
+++ b/cc/trees/occlusion.cc
@@ -85,4 +85,16 @@
return unoccluded_rect_in_target_surface;
}
+bool Occlusion::IsEqual(const Occlusion& other) const {
+ return draw_transform_ == other.draw_transform_ &&
+ occlusion_from_inside_target_ == other.occlusion_from_inside_target_ &&
+ occlusion_from_outside_target_ == other.occlusion_from_outside_target_;
+}
+
+std::string Occlusion::ToString() const {
+ return draw_transform_.ToString() + "outside(" +
+ occlusion_from_outside_target_.ToString() + ") inside(" +
+ occlusion_from_inside_target_.ToString() + ")";
+}
+
} // namespace cc
diff --git a/cc/trees/occlusion.h b/cc/trees/occlusion.h
index 56f9962..fec4915 100644
--- a/cc/trees/occlusion.h
+++ b/cc/trees/occlusion.h
@@ -5,6 +5,8 @@
#ifndef CC_TREES_OCCLUSION_H_
#define CC_TREES_OCCLUSION_H_
+#include <string>
+
#include "base/basictypes.h"
#include "cc/base/cc_export.h"
#include "cc/base/simple_enclosed_region.h"
@@ -26,6 +28,9 @@
bool IsOccluded(const gfx::Rect& content_rect) const;
gfx::Rect GetUnoccludedContentRect(const gfx::Rect& content_rect) const;
+ bool IsEqual(const Occlusion& other) const;
+ std::string ToString() const;
+
private:
gfx::Rect GetUnoccludedRectInTargetSurface(
const gfx::Rect& content_rect) const;
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc
index bce1fd5..388eb6e 100644
--- a/cc/trees/occlusion_tracker.cc
+++ b/cc/trees/occlusion_tracker.cc
@@ -20,12 +20,12 @@
template <typename LayerType>
OcclusionTracker<LayerType>::OcclusionTracker(
const gfx::Rect& screen_space_clip_rect)
- : screen_space_clip_rect_(screen_space_clip_rect),
- occluding_screen_space_rects_(NULL),
- non_occluding_screen_space_rects_(NULL) {}
+ : screen_space_clip_rect_(screen_space_clip_rect) {
+}
template <typename LayerType>
-OcclusionTracker<LayerType>::~OcclusionTracker() {}
+OcclusionTracker<LayerType>::~OcclusionTracker() {
+}
template <typename LayerType>
Occlusion OcclusionTracker<LayerType>::GetCurrentOcclusionForLayer(
@@ -38,6 +38,21 @@
}
template <typename LayerType>
+Occlusion
+OcclusionTracker<LayerType>::GetCurrentOcclusionForContributingSurface(
+ const gfx::Transform& draw_transform) const {
+ DCHECK(!stack_.empty());
+ if (stack_.size() < 2)
+ return Occlusion();
+ // A contributing surface doesn't get occluded by things inside its own
+ // surface, so only things outside the surface can occlude it. That occlusion
+ // is found just below the top of the stack (if it exists).
+ const StackObject& second_last = stack_[stack_.size() - 2];
+ return Occlusion(draw_transform, second_last.occlusion_from_outside_target,
+ second_last.occlusion_from_inside_target);
+}
+
+template <typename LayerType>
void OcclusionTracker<LayerType>::EnterLayer(
const LayerIteratorPosition<LayerType>& layer_iterator) {
LayerType* render_target = layer_iterator.target_render_surface_layer;
@@ -340,12 +355,15 @@
gfx::Rect unoccluded_surface_rect;
gfx::Rect unoccluded_replica_rect;
if (old_target->background_filters().HasFilterThatMovesPixels()) {
- unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect(
- old_surface->content_rect(), old_surface->draw_transform());
+ Occlusion surface_occlusion = GetCurrentOcclusionForContributingSurface(
+ old_surface->draw_transform());
+ unoccluded_surface_rect =
+ surface_occlusion.GetUnoccludedContentRect(old_surface->content_rect());
if (old_target->has_replica()) {
- unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect(
- old_surface->content_rect(),
+ Occlusion replica_occlusion = GetCurrentOcclusionForContributingSurface(
old_surface->replica_draw_transform());
+ unoccluded_replica_rect = replica_occlusion.GetUnoccludedContentRect(
+ old_surface->content_rect());
}
}
@@ -447,96 +465,7 @@
transformed_rect.height() < minimum_tracking_size_.height())
continue;
stack_.back().occlusion_from_inside_target.Union(transformed_rect);
-
- if (!occluding_screen_space_rects_)
- continue;
-
- // Save the occluding area in screen space for debug visualization.
- bool clipped;
- gfx::QuadF screen_space_quad = MathUtil::MapQuad(
- layer->render_target()->render_surface()->screen_space_transform(),
- gfx::QuadF(transformed_rect), &clipped);
- // TODO(danakj): Store the quad in the debug info instead of the bounding
- // box.
- gfx::Rect screen_space_rect =
- gfx::ToEnclosedRect(screen_space_quad.BoundingBox());
- occluding_screen_space_rects_->push_back(screen_space_rect);
}
-
- if (!non_occluding_screen_space_rects_)
- return;
-
- Region non_opaque_contents(gfx::Rect(layer->content_bounds()));
- non_opaque_contents.Subtract(opaque_contents);
-
- for (Region::Iterator non_opaque_content_rects(non_opaque_contents);
- non_opaque_content_rects.has_rect();
- non_opaque_content_rects.next()) {
- gfx::Rect transformed_rect =
- MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
- layer->draw_transform(), non_opaque_content_rects.rect());
- transformed_rect.Intersect(clip_rect_in_target);
- if (transformed_rect.IsEmpty())
- continue;
-
- bool clipped;
- gfx::QuadF screen_space_quad = MathUtil::MapQuad(
- layer->render_target()->render_surface()->screen_space_transform(),
- gfx::QuadF(transformed_rect),
- &clipped);
- // TODO(danakj): Store the quad in the debug info instead of the bounding
- // box.
- gfx::Rect screen_space_rect =
- gfx::ToEnclosedRect(screen_space_quad.BoundingBox());
- non_occluding_screen_space_rects_->push_back(screen_space_rect);
- }
-}
-
-template <typename LayerType>
-gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect(
- const gfx::Rect& content_rect,
- const gfx::Transform& draw_transform) const {
- if (content_rect.IsEmpty())
- return content_rect;
-
- // A contributing surface doesn't get occluded by things inside its own
- // surface, so only things outside the surface can occlude it. That occlusion
- // is found just below the top of the stack (if it exists).
- bool has_occlusion = stack_.size() > 1;
- if (!has_occlusion)
- return content_rect;
-
- const StackObject& second_last = stack_[stack_.size() - 2];
- if (second_last.occlusion_from_inside_target.IsEmpty() &&
- second_last.occlusion_from_outside_target.IsEmpty())
- return content_rect;
-
- gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
- bool ok = draw_transform.GetInverse(&inverse_draw_transform);
- DCHECK(ok);
-
- // Take the ToEnclosingRect at each step, as we want to contain any unoccluded
- // partial pixels in the resulting Rect.
- gfx::Rect unoccluded_rect_in_target_surface =
- MathUtil::MapEnclosingClippedRect(draw_transform, content_rect);
- DCHECK_LE(second_last.occlusion_from_inside_target.GetRegionComplexity(), 1u);
- DCHECK_LE(second_last.occlusion_from_outside_target.GetRegionComplexity(),
- 1u);
- // These subtract operations are more lossy than if we did both operations at
- // once.
- unoccluded_rect_in_target_surface.Subtract(
- second_last.occlusion_from_inside_target.bounds());
- unoccluded_rect_in_target_surface.Subtract(
- second_last.occlusion_from_outside_target.bounds());
-
- if (unoccluded_rect_in_target_surface.IsEmpty())
- return gfx::Rect();
-
- gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect(
- inverse_draw_transform, unoccluded_rect_in_target_surface);
- unoccluded_rect.Intersect(content_rect);
-
- return unoccluded_rect;
}
template <typename LayerType>
diff --git a/cc/trees/occlusion_tracker.h b/cc/trees/occlusion_tracker.h
index 4d6555a..ff6f18d 100644
--- a/cc/trees/occlusion_tracker.h
+++ b/cc/trees/occlusion_tracker.h
@@ -40,6 +40,8 @@
// and can be used outside of a layer walk to check occlusion.
Occlusion GetCurrentOcclusionForLayer(
const gfx::Transform& draw_transform) const;
+ Occlusion GetCurrentOcclusionForContributingSurface(
+ const gfx::Transform& draw_transform) const;
// Called at the beginning of each step in the LayerIterator's front-to-back
// traversal.
@@ -48,13 +50,6 @@
// traversal.
void LeaveLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
- // Gives an unoccluded sub-rect of |content_rect| in the content space of the
- // render_target owned by the layer. Used when considering occlusion for a
- // contributing surface that is rendering into another target.
- gfx::Rect UnoccludedContributingSurfaceContentRect(
- const gfx::Rect& content_rect,
- const gfx::Transform& draw_transform) const;
-
// Gives the region of the screen that is not occluded by something opaque.
Region ComputeVisibleRegionInScreen() const;
@@ -62,16 +57,6 @@
minimum_tracking_size_ = size;
}
- // The following is used for visualization purposes.
- void set_occluding_screen_space_rects_container(
- std::vector<gfx::Rect>* rects) {
- occluding_screen_space_rects_ = rects;
- }
- void set_non_occluding_screen_space_rects_container(
- std::vector<gfx::Rect>* rects) {
- non_occluding_screen_space_rects_ = rects;
- }
-
protected:
struct StackObject {
StackObject() : target(0) {}
@@ -120,10 +105,6 @@
gfx::Rect screen_space_clip_rect_;
gfx::Size minimum_tracking_size_;
- // This is used for visualizing the occlusion tracking process.
- std::vector<gfx::Rect>* occluding_screen_space_rects_;
- std::vector<gfx::Rect>* non_occluding_screen_space_rects_;
-
DISALLOW_COPY_AND_ASSIGN(OcclusionTracker);
};
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index 172b227..e3639ad 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -101,8 +101,9 @@
gfx::Rect UnoccludedSurfaceContentRect(const LayerType* layer,
const gfx::Rect& content_rect) const {
typename LayerType::RenderSurfaceType* surface = layer->render_surface();
- return this->UnoccludedContributingSurfaceContentRect(
- content_rect, surface->draw_transform());
+ return this->GetCurrentOcclusionForContributingSurface(
+ surface->draw_transform())
+ .GetUnoccludedContentRect(content_rect);
}
};
@@ -2671,6 +2672,53 @@
OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded);
template <class Types>
+class OcclusionTrackerTestBlendModeDoesNotOcclude
+ : public OcclusionTrackerTest<Types> {
+ protected:
+ explicit OcclusionTrackerTestBlendModeDoesNotOcclude(bool opaque_layers)
+ : OcclusionTrackerTest<Types>(opaque_layers) {}
+ void RunMyTest() override {
+ typename Types::ContentLayerType* parent = this->CreateRoot(
+ this->identity_matrix, gfx::PointF(), gfx::Size(100, 100));
+ typename Types::LayerType* blend_mode_layer = this->CreateDrawingLayer(
+ parent, this->identity_matrix, gfx::PointF(0.f, 0.f),
+ gfx::Size(100, 100), true);
+ typename Types::LayerType* top_layer = this->CreateDrawingLayer(
+ parent, this->identity_matrix, gfx::PointF(10.f, 12.f),
+ gfx::Size(20, 22), true);
+
+ // Blend mode makes the layer own a surface.
+ Types::SetForceRenderSurface(blend_mode_layer, true);
+ blend_mode_layer->SetBlendMode(SkXfermode::kMultiply_Mode);
+
+ this->CalcDrawEtc(parent);
+
+ TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
+ gfx::Rect(0, 0, 1000, 1000));
+
+ this->VisitLayer(top_layer, &occlusion);
+ // |top_layer| occludes.
+ EXPECT_EQ(gfx::Rect(10, 12, 20, 22).ToString(),
+ occlusion.occlusion_from_inside_target().ToString());
+ EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
+
+ this->VisitLayer(blend_mode_layer, &occlusion);
+ // |top_layer| occludes but not |blend_mode_layer|.
+ EXPECT_EQ(gfx::Rect(10, 12, 20, 22).ToString(),
+ occlusion.occlusion_from_outside_target().ToString());
+ EXPECT_TRUE(occlusion.occlusion_from_inside_target().IsEmpty());
+
+ this->VisitContributingSurface(blend_mode_layer, &occlusion);
+ // |top_layer| occludes but not |blend_mode_layer|.
+ EXPECT_EQ(gfx::Rect(10, 12, 20, 22).ToString(),
+ occlusion.occlusion_from_inside_target().ToString());
+ EXPECT_TRUE(occlusion.occlusion_from_outside_target().IsEmpty());
+ }
+};
+
+ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestBlendModeDoesNotOcclude);
+
+template <class Types>
class OcclusionTrackerTestMinimumTrackingSize
: public OcclusionTrackerTest<Types> {
protected:
@@ -2816,12 +2864,22 @@
gfx::PointF(),
gfx::Size(200, 400),
true);
+ typename Types::LayerType* top_layer =
+ this->CreateDrawingLayer(root, this->identity_matrix,
+ gfx::PointF(50, 0), gfx::Size(50, 400), true);
this->CalcDrawEtc(root);
TestOcclusionTrackerWithClip<typename Types::LayerType> occlusion(
gfx::Rect(0, 0, 1000, 1000));
+ this->VisitLayer(top_layer, &occlusion);
+ EXPECT_EQ(gfx::Rect().ToString(),
+ occlusion.occlusion_from_outside_target().ToString());
+ EXPECT_EQ(gfx::Rect(50, 0, 50, 400).ToString(),
+ occlusion.occlusion_from_inside_target().ToString());
+
this->VisitLayer(copy_child, &occlusion);
+ // Layers outside the copy request do not occlude.
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
EXPECT_EQ(gfx::Rect(200, 400).ToString(),
@@ -2833,7 +2891,7 @@
// The occlusion from the copy should be kept.
EXPECT_EQ(gfx::Rect().ToString(),
occlusion.occlusion_from_outside_target().ToString());
- EXPECT_EQ(gfx::Rect(100, 0, 200, 400).ToString(),
+ EXPECT_EQ(gfx::Rect(50, 0, 250, 400).ToString(),
occlusion.occlusion_from_inside_target().ToString());
}
};
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 95c2b5a..25d42aa 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -5,6 +5,7 @@
#include <set>
#include "base/logging.h"
+#include "cc/base/math_util.h"
#include "cc/trees/property_tree.h"
namespace cc {
@@ -35,11 +36,16 @@
TransformNodeData::TransformNodeData()
: target_id(-1),
+ content_target_id(-1),
+ needs_local_transform_update(true),
is_invertible(true),
ancestors_are_invertible(true),
is_animated(false),
to_screen_is_animated(false),
- flattens(false) {
+ flattens(false),
+ scrolls(false),
+ needs_sublayer_scale(false),
+ layer_scale_factor(1.0f) {
}
TransformNodeData::~TransformNodeData() {
@@ -79,47 +85,18 @@
transform.Preserves2dAxisAlignment();
}
-void TransformTree::UpdateScreenSpaceTransform(int id) {
- TransformNode* current_node = Node(id);
- TransformNode* parent_node = parent(current_node);
- TransformNode* target_node = Node(current_node->data.target_id);
-
- if (!parent_node) {
- current_node->data.to_screen = current_node->data.to_parent;
- current_node->data.ancestors_are_invertible = true;
- current_node->data.to_screen_is_animated = false;
- } else if (parent_node->data.flattens) {
- // 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
- // screen space transform when flattening is involved we combine three
- // transforms, A * B * C, where A is the screen space transform of the
- // target, B is the flattened draw transform of the layer's parent, and C is
- // the local transform.
- current_node->data.to_screen = target_node->data.to_screen;
- gfx::Transform flattened;
- ComputeTransform(parent_node->id, target_node->id, &flattened);
- flattened.FlattenTo2d();
- current_node->data.to_screen.PreconcatTransform(flattened);
- current_node->data.to_screen.PreconcatTransform(
- current_node->data.to_parent);
- current_node->data.ancestors_are_invertible =
- parent_node->data.ancestors_are_invertible;
- } else {
- current_node->data.to_screen = parent_node->data.to_screen;
- current_node->data.to_screen.PreconcatTransform(
- current_node->data.to_parent);
- current_node->data.ancestors_are_invertible =
- parent_node->data.ancestors_are_invertible;
- }
- if (!current_node->data.to_screen.GetInverse(¤t_node->data.from_screen))
- current_node->data.ancestors_are_invertible = false;
-
- if (parent_node) {
- current_node->data.to_screen_is_animated =
- current_node->data.is_animated ||
- parent_node->data.to_screen_is_animated;
- }
+void TransformTree::UpdateTransforms(int id) {
+ TransformNode* node = Node(id);
+ TransformNode* parent_node = parent(node);
+ TransformNode* target_node = Node(node->data.target_id);
+ if (node->data.needs_local_transform_update)
+ UpdateLocalTransform(node);
+ UpdateLocalTransform(node);
+ UpdateScreenSpaceTransform(node, parent_node, target_node);
+ UpdateSublayerScale(node);
+ UpdateTargetSpaceTransform(node, target_node);
+ UpdateIsAnimated(node, parent_node);
+ UpdateSnapping(node);
}
bool TransformTree::IsDescendant(int desc_id, int source_id) const {
@@ -196,4 +173,123 @@
return all_are_invertible;
}
+void TransformTree::UpdateLocalTransform(TransformNode* node) {
+ gfx::Transform transform = node->data.post_local;
+ transform.Translate(-node->data.scroll_offset.x(),
+ -node->data.scroll_offset.y());
+ transform.PreconcatTransform(node->data.local);
+ transform.PreconcatTransform(node->data.pre_local);
+ node->data.set_to_parent(transform);
+ node->data.needs_local_transform_update = false;
+}
+
+void TransformTree::UpdateScreenSpaceTransform(TransformNode* node,
+ TransformNode* parent_node,
+ TransformNode* target_node) {
+ if (!parent_node) {
+ 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) {
+ // 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
+ // screen space transform when flattening is involved we combine three
+ // transforms, A * B * C, where A is the screen space transform of the
+ // target, B is the flattened draw transform of the layer's parent, and C is
+ // the local transform.
+ node->data.to_screen = target_node->data.to_screen;
+ gfx::Transform flattened;
+ ComputeTransform(parent_node->id, target_node->id, &flattened);
+ flattened.FlattenTo2d();
+ node->data.to_screen.PreconcatTransform(flattened);
+ node->data.to_screen.PreconcatTransform(node->data.to_parent);
+ node->data.ancestors_are_invertible =
+ parent_node->data.ancestors_are_invertible;
+ } else {
+ node->data.to_screen = parent_node->data.to_screen;
+ node->data.to_screen.PreconcatTransform(node->data.to_parent);
+ node->data.ancestors_are_invertible =
+ parent_node->data.ancestors_are_invertible;
+ }
+
+ if (!node->data.to_screen.GetInverse(&node->data.from_screen))
+ node->data.ancestors_are_invertible = false;
+}
+
+void TransformTree::UpdateSublayerScale(TransformNode* node) {
+ // The sublayer scale depends on the screen space transform, so update it too.
+ node->data.sublayer_scale =
+ node->data.needs_sublayer_scale
+ ? MathUtil::ComputeTransform2dScaleComponents(
+ node->data.to_screen, node->data.layer_scale_factor)
+ : gfx::Vector2dF(1.0f, 1.0f);
+}
+
+void TransformTree::UpdateTargetSpaceTransform(TransformNode* node,
+ TransformNode* target_node) {
+ node->data.to_target.MakeIdentity();
+ if (node->data.needs_sublayer_scale) {
+ node->data.to_target.Scale(node->data.sublayer_scale.x(),
+ node->data.sublayer_scale.y());
+ } else {
+ const bool target_is_root_surface = target_node->id == 1;
+ // In order to include the root transform for the root surface, we walk up
+ // to the root of the transform tree in ComputeTransform.
+ int target_id = target_is_root_surface ? 0 : target_node->id;
+ if (target_node) {
+ node->data.to_target.Scale(target_node->data.sublayer_scale.x(),
+ target_node->data.sublayer_scale.y());
+ }
+
+ gfx::Transform unscaled_target_transform;
+ ComputeTransform(node->id, target_id, &unscaled_target_transform);
+ node->data.to_target.PreconcatTransform(unscaled_target_transform);
+ }
+
+ if (!node->data.to_target.GetInverse(&node->data.from_target))
+ node->data.ancestors_are_invertible = false;
+}
+
+void TransformTree::UpdateIsAnimated(TransformNode* node,
+ TransformNode* parent_node) {
+ if (parent_node) {
+ node->data.to_screen_is_animated =
+ node->data.is_animated || parent_node->data.to_screen_is_animated;
+ }
+}
+
+void TransformTree::UpdateSnapping(TransformNode* node) {
+ if (!node->data.scrolls || node->data.to_screen_is_animated ||
+ !node->data.to_target.IsScaleOrTranslation()) {
+ return;
+ }
+
+ // Scroll snapping must be done in target space (the pixels we care about).
+ // This means we effectively snap the target space transform. If TT is the
+ // target space transform and TT' is TT with its translation components
+ // rounded, then what we're after is the scroll delta X, where TT * X = TT'.
+ // I.e., we want a transform that will realize our scroll snap. It follows
+ // that X = TT^-1 * TT'. We cache TT and TT^-1 to make this more efficient.
+ gfx::Transform rounded = node->data.to_target;
+ rounded.RoundTranslationComponents();
+ gfx::Transform delta = node->data.from_target;
+ delta *= rounded;
+ gfx::Transform inverse_delta(gfx::Transform::kSkipInitialization);
+ bool invertible_delta = delta.GetInverse(&inverse_delta);
+
+ // The delta should be a translation, modulo floating point error, and should
+ // therefore be invertible.
+ DCHECK(invertible_delta);
+
+ // Now that we have our scroll delta, we must apply it to each of our
+ // combined, to/from matrices.
+ node->data.to_parent.PreconcatTransform(delta);
+ node->data.from_parent.ConcatTransform(inverse_delta);
+ node->data.to_target.PreconcatTransform(delta);
+ node->data.from_target.ConcatTransform(inverse_delta);
+ node->data.to_screen.PreconcatTransform(delta);
+ node->data.from_screen.ConcatTransform(inverse_delta);
+}
+
} // namespace cc
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index 4c10be1..ef47bce 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -26,13 +26,42 @@
TransformNodeData();
~TransformNodeData();
+ // The local transform information is combined to form to_parent (ignoring
+ // snapping) as follows:
+ //
+ // to_parent = M_post_local * T_scroll * M_local * M_pre_local.
+ //
+ // The pre/post may seem odd when read LTR, but we multiply our points from
+ // the right, so the pre_local matrix affects the result "first". This lines
+ // up with the notions of pre/post used in skia and gfx::Transform.
+ //
+ // TODO(vollick): The values labeled with "will be moved..." take up a lot of
+ // space, but are only necessary for animated or scrolled nodes (otherwise
+ // we'll just use the baked to_parent). These values will be ultimately stored
+ // directly on the transform/scroll display list items when that's possible,
+ // or potentially in a scroll tree.
+ //
+ // TODO(vollick): will be moved when accelerated effects are implemented.
+ gfx::Transform pre_local;
+ gfx::Transform local;
+ gfx::Transform post_local;
+
gfx::Transform to_parent;
gfx::Transform from_parent;
+ gfx::Transform to_target;
+ gfx::Transform from_target;
+
gfx::Transform to_screen;
gfx::Transform from_screen;
int target_id;
+ // This id is used for all content that draws into a render surface associated
+ // with this transform node.
+ int content_target_id;
+
+ // TODO(vollick): will be moved when accelerated effects are implemented.
+ bool needs_local_transform_update;
bool is_invertible;
bool ancestors_are_invertible;
@@ -41,6 +70,16 @@
bool to_screen_is_animated;
bool flattens;
+ bool scrolls;
+
+ bool needs_sublayer_scale;
+ // This is used as a fallback when we either cannot adjust raster scale or if
+ // the raster scale cannot be extracted from the screen space transform.
+ float layer_scale_factor;
+ gfx::Vector2dF sublayer_scale;
+
+ // TODO(vollick): will be moved when accelerated effects are implemented.
+ gfx::Vector2dF scroll_offset;
void set_to_parent(const gfx::Transform& transform) {
to_parent = transform;
@@ -105,9 +144,8 @@
// aligned with respect to one another.
bool Are2DAxisAligned(int source_id, int dest_id) const;
- // This recomputes the screen space transform (and its inverse) for the node
- // at |id|.
- void UpdateScreenSpaceTransform(int id);
+ // Updates the parent, target, and screen space transforms and snapping.
+ void UpdateTransforms(int id);
private:
// Returns true iff the node at |desc_id| is a descendant of the node at
@@ -130,6 +168,16 @@
bool CombineInversesBetween(int source_id,
int dest_id,
gfx::Transform* transform) const;
+
+ void UpdateLocalTransform(TransformNode* node);
+ void UpdateScreenSpaceTransform(TransformNode* node,
+ TransformNode* parent_node,
+ TransformNode* target_node);
+ void UpdateSublayerScale(TransformNode* node);
+ void UpdateTargetSpaceTransform(TransformNode* node,
+ TransformNode* target_node);
+ void UpdateIsAnimated(TransformNode* node, TransformNode* parent_node);
+ void UpdateSnapping(TransformNode* node);
};
class CC_EXPORT ClipTree final : public PropertyTree<ClipNode> {};
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 934e1fc..ae39f03 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -30,6 +30,8 @@
const Layer* page_scale_layer;
float page_scale_factor;
float device_scale_factor;
+ bool in_subtree_of_page_scale_application_layer;
+ const gfx::Transform* device_transform;
};
static Layer* GetTransformParent(const DataForRecursion& data, Layer* layer) {
@@ -165,55 +167,58 @@
return;
}
- if (!is_root) {
- data_for_children->transform_tree->Insert(
- TransformNode(), transform_parent->transform_tree_index());
- }
+ int parent_index = 0;
+ if (transform_parent)
+ parent_index = transform_parent->transform_tree_index();
+
+ data_for_children->transform_tree->Insert(TransformNode(), parent_index);
TransformNode* node = data_for_children->transform_tree->back();
layer->set_transform_tree_index(node->id);
+ node->data.scrolls = is_scrollable;
node->data.flattens = layer->should_flatten_transform();
node->data.target_id =
data_from_ancestor.render_target->transform_tree_index();
+ node->data.content_target_id =
+ data_for_children->render_target->transform_tree_index();
DCHECK_NE(node->data.target_id, -1);
node->data.is_animated = layer->TransformIsAnimating();
- gfx::Transform transform;
- float device_and_page_scale_factors = 1.0f;
- if (is_root)
- device_and_page_scale_factors = data_from_ancestor.device_scale_factor;
- if (is_page_scale_application_layer)
- device_and_page_scale_factors *= data_from_ancestor.page_scale_factor;
-
- transform.Scale(device_and_page_scale_factors, device_and_page_scale_factors);
-
- // TODO(vollick): We've accounted for the scroll offset here but we haven't
- // taken into account snapping to screen space pixels. For the purposes of
- // computing rects we need to record, this should be fine (the visible rects
- // we compute may be slightly different than what we'd compute with snapping,
- // but since we significantly expand the visible rect when determining what to
- // record, the slight difference should be inconsequential).
- gfx::Vector2dF position = layer->position().OffsetFromOrigin();
- if (!layer->scroll_parent()) {
- position -= gfx::Vector2dF(layer->CurrentScrollOffset().x(),
- layer->CurrentScrollOffset().y());
+ float scale_factors = 1.0f;
+ if (is_root) {
+ node->data.post_local = *data_from_ancestor.device_transform;
+ scale_factors = data_from_ancestor.device_scale_factor;
}
- position += parent_offset;
+ if (is_page_scale_application_layer)
+ scale_factors *= data_from_ancestor.page_scale_factor;
- transform.Translate3d(position.x() + layer->transform_origin().x(),
- position.y() + layer->transform_origin().y(),
- layer->transform_origin().z());
- transform.PreconcatTransform(layer->transform());
- transform.Translate3d(-layer->transform_origin().x(),
- -layer->transform_origin().y(),
- -layer->transform_origin().z());
+ if (has_surface && !is_root) {
+ node->data.needs_sublayer_scale = true;
+ node->data.layer_scale_factor = data_from_ancestor.device_scale_factor;
+ if (data_from_ancestor.in_subtree_of_page_scale_application_layer)
+ node->data.layer_scale_factor *= data_from_ancestor.page_scale_factor;
+ }
- node->data.to_parent = transform;
- node->data.is_invertible = transform.GetInverse(&node->data.from_parent);
+ node->data.post_local.Scale(scale_factors, scale_factors);
+ node->data.post_local.Translate3d(
+ layer->position().x() + parent_offset.x() + layer->transform_origin().x(),
+ layer->position().y() + parent_offset.y() + layer->transform_origin().y(),
+ layer->transform_origin().z());
- data_from_ancestor.transform_tree->UpdateScreenSpaceTransform(node->id);
+ if (!layer->scroll_parent()) {
+ node->data.scroll_offset =
+ gfx::ScrollOffsetToVector2dF(layer->CurrentScrollOffset());
+ }
+
+ node->data.local = layer->transform();
+ node->data.pre_local.Translate3d(-layer->transform_origin().x(),
+ -layer->transform_origin().y(),
+ -layer->transform_origin().z());
+
+ node->data.needs_local_transform_update = true;
+ data_from_ancestor.transform_tree->UpdateTransforms(node->id);
layer->set_offset_to_transform_parent(gfx::Vector2dF());
}
@@ -227,6 +232,9 @@
AddTransformNodeIfNeeded(data_from_parent, layer, &data_for_children);
AddClipNodeIfNeeded(data_from_parent, layer, &data_for_children);
+ if (layer == data_from_parent.page_scale_layer)
+ data_for_children.in_subtree_of_page_scale_application_layer = true;
+
for (size_t i = 0; i < layer->children().size(); ++i) {
if (!layer->children()[i]->scroll_parent())
BuildPropertyTreesInternal(layer->children()[i].get(), data_for_children);
@@ -263,19 +271,14 @@
data_for_recursion.page_scale_layer = page_scale_layer;
data_for_recursion.page_scale_factor = page_scale_factor;
data_for_recursion.device_scale_factor = device_scale_factor;
-
- int transform_root_id = transform_tree->Insert(TransformNode(), 0);
+ data_for_recursion.in_subtree_of_page_scale_application_layer = false;
+ data_for_recursion.device_transform = &device_transform;
ClipNode root_clip;
root_clip.data.clip = viewport;
root_clip.data.transform_id = 0;
data_for_recursion.clip_tree_parent = clip_tree->Insert(root_clip, 0);
-
BuildPropertyTreesInternal(root_layer, data_for_recursion);
-
- TransformNode* transform_root = transform_tree->Node(transform_root_id);
- transform_root->data.set_to_parent(device_transform *
- transform_root->data.to_parent);
}
} // namespace cc
diff --git a/cc/trees/property_tree_unittest.cc b/cc/trees/property_tree_unittest.cc
index e6de967..014bfcb 100644
--- a/cc/trees/property_tree_unittest.cc
+++ b/cc/trees/property_tree_unittest.cc
@@ -12,9 +12,9 @@
TEST(PropertyTreeTest, ComputeTransformRoot) {
TransformTree tree;
TransformNode& root = *tree.Node(0);
- root.data.to_parent.Translate(2, 2);
- root.data.from_parent.Translate(-2, -2);
- tree.UpdateScreenSpaceTransform(0);
+ root.data.local.Translate(2, 2);
+ root.data.target_id = 0;
+ tree.UpdateTransforms(0);
gfx::Transform expected;
gfx::Transform transform;
@@ -39,16 +39,16 @@
TEST(PropertyTreeTest, ComputeTransformChild) {
TransformTree tree;
TransformNode& root = *tree.Node(0);
- root.data.to_parent.Translate(2, 2);
- root.data.from_parent.Translate(-2, -2);
- tree.UpdateScreenSpaceTransform(0);
+ root.data.local.Translate(2, 2);
+ root.data.target_id = 0;
+ tree.UpdateTransforms(0);
TransformNode child;
- child.data.to_parent.Translate(3, 3);
- child.data.from_parent.Translate(-3, -3);
+ child.data.local.Translate(3, 3);
+ child.data.target_id = 0;
tree.Insert(child, 0);
- tree.UpdateScreenSpaceTransform(1);
+ tree.UpdateTransforms(1);
gfx::Transform expected;
gfx::Transform transform;
@@ -83,23 +83,23 @@
TEST(PropertyTreeTest, ComputeTransformSibling) {
TransformTree tree;
TransformNode& root = *tree.Node(0);
- root.data.to_parent.Translate(2, 2);
- root.data.from_parent.Translate(-2, -2);
- tree.UpdateScreenSpaceTransform(0);
+ root.data.local.Translate(2, 2);
+ root.data.target_id = 0;
+ tree.UpdateTransforms(0);
TransformNode child;
- child.data.to_parent.Translate(3, 3);
- child.data.from_parent.Translate(-3, -3);
+ child.data.local.Translate(3, 3);
+ child.data.target_id = 0;
TransformNode sibling;
- sibling.data.to_parent.Translate(7, 7);
- sibling.data.from_parent.Translate(-7, -7);
+ sibling.data.local.Translate(7, 7);
+ sibling.data.target_id = 0;
tree.Insert(child, 0);
tree.Insert(sibling, 0);
- tree.UpdateScreenSpaceTransform(1);
- tree.UpdateScreenSpaceTransform(2);
+ tree.UpdateTransforms(1);
+ tree.UpdateTransforms(2);
gfx::Transform expected;
gfx::Transform transform;
@@ -128,32 +128,29 @@
// |sibling|.
TransformTree tree;
TransformNode& root = *tree.Node(0);
- root.data.to_parent.Translate(2, 2);
- root.data.from_parent.Translate(-2, -2);
- tree.UpdateScreenSpaceTransform(0);
+ root.data.local.Translate(2, 2);
+ root.data.target_id = 0;
+ tree.UpdateTransforms(0);
TransformNode singular;
- singular.data.to_parent.matrix().set(2, 2, 0.0);
- singular.data.is_invertible = false;
- singular.data.ancestors_are_invertible = false;
+ singular.data.local.matrix().set(2, 2, 0.0);
+ singular.data.target_id = 0;
TransformNode child;
- child.data.to_parent.Translate(3, 3);
- child.data.from_parent.Translate(-3, -3);
- child.data.ancestors_are_invertible = false;
+ child.data.local.Translate(3, 3);
+ child.data.target_id = 0;
TransformNode sibling;
- sibling.data.to_parent.Translate(7, 7);
- sibling.data.from_parent.Translate(-7, -7);
- sibling.data.ancestors_are_invertible = false;
+ sibling.data.local.Translate(7, 7);
+ sibling.data.target_id = 0;
tree.Insert(singular, 0);
tree.Insert(child, 1);
tree.Insert(sibling, 1);
- tree.UpdateScreenSpaceTransform(1);
- tree.UpdateScreenSpaceTransform(2);
- tree.UpdateScreenSpaceTransform(3);
+ tree.UpdateTransforms(1);
+ tree.UpdateTransforms(2);
+ tree.UpdateTransforms(3);
gfx::Transform expected;
gfx::Transform transform;
@@ -174,16 +171,16 @@
TEST(PropertyTreeTest, MultiplicationOrder) {
TransformTree tree;
TransformNode& root = *tree.Node(0);
- root.data.to_parent.Translate(2, 2);
- root.data.from_parent.Translate(-2, -2);
- tree.UpdateScreenSpaceTransform(0);
+ root.data.local.Translate(2, 2);
+ root.data.target_id = 0;
+ tree.UpdateTransforms(0);
TransformNode child;
- child.data.to_parent.Scale(2, 2);
- child.data.from_parent.Scale(0.5, 0.5);
+ child.data.local.Scale(2, 2);
+ child.data.target_id = 0;
tree.Insert(child, 0);
- tree.UpdateScreenSpaceTransform(1);
+ tree.UpdateTransforms(1);
gfx::Transform expected;
expected.Translate(2, 2);
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 2f181fc..539effe 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -20,14 +20,8 @@
namespace trace_event {
class TracedValue;
}
-
-// TODO(ssid): remove these aliases after the tracing clients are moved to the
-// new trace_event namespace. See crbug.com/451032. ETA: March 2015
-namespace debug {
-using ::base::trace_event::TracedValue;
-}
class SingleThreadTaskRunner;
-} // namespace base
+}
namespace gfx {
class Rect;
@@ -62,6 +56,7 @@
virtual void FinishAllRendering() = 0;
virtual bool IsStarted() const = 0;
+ virtual bool CommitToActiveTree() const = 0;
// Will call LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted
// with the result of this function.
@@ -108,7 +103,7 @@
virtual bool SupportsImplScrolling() const = 0;
- virtual void AsValueInto(base::debug::TracedValue* value) const = 0;
+ virtual void AsValueInto(base::trace_event::TracedValue* value) const = 0;
virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index f913c1f..4a079f3 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -82,6 +82,12 @@
return layer_tree_host_impl_;
}
+bool SingleThreadProxy::CommitToActiveTree() const {
+ // With SingleThreadProxy we skip the pending tree and commit directly to the
+ // active tree.
+ return true;
+}
+
void SingleThreadProxy::SetLayerTreeHostClientReady() {
TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
// Scheduling is controlled by the embedder in the single thread case, so
@@ -240,8 +246,6 @@
layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
- layer_tree_host_impl_->CommitComplete();
-
#if DCHECK_IS_ON()
// In the single-threaded case, the scale and scroll deltas should never be
// touched on the impl layer tree.
@@ -250,18 +254,17 @@
DCHECK(!scroll_info->scrolls.size());
DCHECK_EQ(1.f, scroll_info->page_scale_delta);
#endif
- }
- if (layer_tree_host_->settings().impl_side_painting) {
- // TODO(enne): just commit directly to the active tree.
- //
- // Synchronously activate during commit to satisfy any potential
- // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
- // might not be ready to draw, so DidActivateSyncTree must set
- // the flag to force the tree to not draw until textures are ready.
- NotifyReadyToActivate();
- } else {
- CommitComplete();
+ if (layer_tree_host_->settings().impl_side_painting) {
+ // Commit goes directly to the active tree, but we need to synchronously
+ // "activate" the tree still during commit to satisfy any potential
+ // SetNextCommitWaitsForActivation calls. Unfortunately, the tree
+ // might not be ready to draw, so DidActivateSyncTree must set
+ // the flag to force the tree to not draw until textures are ready.
+ NotifyReadyToActivate();
+ } else {
+ CommitComplete();
+ }
}
}
@@ -270,6 +273,10 @@
<< "Activation is expected to have synchronously occurred by now.";
DCHECK(commit_blocking_task_runner_);
+ // Notify commit complete on the impl side after activate to satisfy any
+ // SetNextCommitWaitsForActivation calls.
+ layer_tree_host_impl_->CommitComplete();
+
DebugScopedSetMainThread main(this);
commit_blocking_task_runner_.reset();
layer_tree_host_->CommitComplete();
@@ -433,8 +440,8 @@
// Non-impl-side painting finishes commit in DoCommit. Impl-side painting
// defers until here to simulate SetNextCommitWaitsForActivation.
if (layer_tree_host_impl_->settings().impl_side_painting) {
- // This is required because NotifyReadyToActivate gets called when
- // the pending tree is not actually ready in the SingleThreadProxy.
+ // This is required because NotifyReadyToActivate gets called immediately
+ // after commit since single thread commits directly to the active tree.
layer_tree_host_impl_->SetRequiresHighResToDraw();
// Synchronously call to CommitComplete. Resetting
@@ -542,7 +549,8 @@
}
}
-void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
+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.
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 132610a..52dd876 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -38,6 +38,7 @@
// Proxy implementation
void FinishAllRendering() override;
bool IsStarted() const override;
+ bool CommitToActiveTree() const override;
void SetOutputSurface(scoped_ptr<OutputSurface>) override;
void SetLayerTreeHostClientReady() override;
void SetVisible(bool visible) override;
@@ -58,7 +59,7 @@
size_t MaxPartialTextureUpdates() const override;
void ForceSerializeOnSwapBuffers() override;
bool SupportsImplScrolling() const override;
- void AsValueInto(base::debug::TracedValue* state) 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 5ee43ab..167cca9 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -153,6 +153,12 @@
return main().started;
}
+bool ThreadProxy::CommitToActiveTree() const {
+ // With ThreadProxy we use a pending tree and activate it once it's ready to
+ // draw.
+ return false;
+}
+
void ThreadProxy::SetLayerTreeHostClientReady() {
TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
Proxy::ImplThreadTaskRunner()->PostTask(
@@ -1232,12 +1238,12 @@
ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
-void ThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
+void ThreadProxy::AsValueInto(base::trace_event::TracedValue* state) const {
CompletionEvent completion;
{
DebugScopedSetMainThreadBlocked main_thread_blocked(
const_cast<ThreadProxy*>(this));
- scoped_refptr<base::debug::TracedValue> state_refptr(state);
+ scoped_refptr<base::trace_event::TracedValue> state_refptr(state);
Proxy::ImplThreadTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&ThreadProxy::AsValueOnImplThread,
@@ -1248,8 +1254,9 @@
}
}
-void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
- base::debug::TracedValue* state) const {
+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();
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index b4050bd..570d240 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -153,6 +153,7 @@
// Proxy implementation
void FinishAllRendering() override;
bool IsStarted() const override;
+ bool CommitToActiveTree() const override;
void SetOutputSurface(scoped_ptr<OutputSurface>) override;
void SetLayerTreeHostClientReady() override;
void SetVisible(bool visible) override;
@@ -174,7 +175,7 @@
void ForceSerializeOnSwapBuffers() override;
bool SupportsImplScrolling() const override;
void SetDebugState(const LayerTreeDebugState& debug_state) override;
- void AsValueInto(base::debug::TracedValue* value) const override;
+ void AsValueInto(base::trace_event::TracedValue* value) const override;
bool MainFrameWillHappenForTesting() override;
void SetChildrenNeedBeginFrames(bool children_need_begin_frames) override;
@@ -277,7 +278,7 @@
void MainFrameWillHappenOnImplThreadForTesting(CompletionEvent* completion,
bool* main_frame_will_happen);
void AsValueOnImplThread(CompletionEvent* completion,
- base::debug::TracedValue* state) const;
+ base::trace_event::TracedValue* state) const;
void SetSwapUsedIncompleteTileOnImplThread(bool used_incomplete_tile);
void MainThreadHasStoppedFlingingOnImplThread();
void SetInputThrottledUntilCommitOnImplThread(bool is_throttled);
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index 6d60f48..632c498 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -297,5 +297,22 @@
'sources': [],
}
]}],
+ ['test_isolation_mode != "noop"', {
+ 'targets': [
+ {
+ 'target_name': 'crypto_unittests_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'crypto_unittests',
+ ],
+ 'includes': [
+ '../build/isolate.gypi',
+ ],
+ 'sources': [
+ 'crypto_unittests.isolate',
+ ],
+ },
+ ],
+ }],
],
}
diff --git a/crypto/crypto_unittests.isolate b/crypto/crypto_unittests.isolate
new file mode 100644
index 0000000..381a1c8
--- /dev/null
+++ b/crypto/crypto_unittests.isolate
@@ -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.
+{
+ 'conditions': [
+ ['OS=="linux"', {
+ 'variables': {
+ 'command': [
+ '../testing/xvfb.py',
+ '<(PRODUCT_DIR)',
+ '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
+ ],
+ 'files': [
+ '../testing/xvfb.py',
+ ],
+ },
+ }],
+ ['OS=="linux" and use_ozone==0', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
+ ],
+ },
+ }],
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'files': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)',
+ ],
+ 'read_only': 1,
+ },
+ }],
+ ['OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--lsan=<(lsan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
+ ],
+ },
+ }],
+ ['OS=="mac" and asan==1 and fastbuild==0', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/crypto_unittests.dSYM/',
+ ],
+ },
+ }],
+ ['OS=="win" and (fastbuild==0 or fastbuild==1)', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/crypto_unittests.exe.pdb',
+ ],
+ },
+ }],
+ ],
+ 'includes': [
+ '../base/base.isolate',
+ ],
+}
diff --git a/examples/sample_app/BUILD.gn b/examples/sample_app/BUILD.gn
index 0297002..e318cc3 100644
--- a/examples/sample_app/BUILD.gn
+++ b/examples/sample_app/BUILD.gn
@@ -34,6 +34,7 @@
deps = [
"//base",
+ "//mojo/common",
"//mojo/public/c/gles2",
"//mojo/public/cpp/environment",
]
diff --git a/examples/sample_app/spinning_cube.cc b/examples/sample_app/spinning_cube.cc
index 691ac20..ae7ef97 100644
--- a/examples/sample_app/spinning_cube.cc
+++ b/examples/sample_app/spinning_cube.cc
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
+#include "mojo/common/common_type_converters.h"
#include "mojo/public/cpp/environment/logging.h"
namespace examples {
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 0896026..e1d5348 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -47,10 +47,10 @@
source_set("test_support") {
testonly = true
sources = [
- "command_buffer/service/gles2_cmd_decoder_mock.cc",
- "command_buffer/service/error_state_mock.cc",
"command_buffer/client/gles2_interface_stub.cc",
"command_buffer/client/gles2_interface_stub.h",
+ "command_buffer/service/error_state_mock.cc",
+ "command_buffer/service/gles2_cmd_decoder_mock.cc",
]
public_deps = [
@@ -156,10 +156,10 @@
"command_buffer/common/id_allocator_test.cc",
"command_buffer/common/trace_event.h",
"command_buffer/common/unittest_main.cc",
- "command_buffer/service/async_pixel_transfer_delegate_mock.h",
"command_buffer/service/async_pixel_transfer_delegate_mock.cc",
- "command_buffer/service/async_pixel_transfer_manager_mock.h",
+ "command_buffer/service/async_pixel_transfer_delegate_mock.h",
"command_buffer/service/async_pixel_transfer_manager_mock.cc",
+ "command_buffer/service/async_pixel_transfer_manager_mock.h",
"command_buffer/service/buffer_manager_unittest.cc",
"command_buffer/service/cmd_parser_test.cc",
"command_buffer/service/command_buffer_service_unittest.cc",
@@ -167,6 +167,8 @@
"command_buffer/service/context_group_unittest.cc",
"command_buffer/service/feature_info_unittest.cc",
"command_buffer/service/framebuffer_manager_unittest.cc",
+ "command_buffer/service/gl_surface_mock.cc",
+ "command_buffer/service/gl_surface_mock.h",
"command_buffer/service/gles2_cmd_decoder_unittest.cc",
"command_buffer/service/gles2_cmd_decoder_unittest.h",
"command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h",
@@ -177,6 +179,7 @@
"command_buffer/service/gles2_cmd_decoder_unittest_3.cc",
"command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h",
"command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc",
+ "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_context_state.cc",
@@ -185,33 +188,30 @@
"command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc",
"command_buffer/service/gles2_cmd_decoder_unittest_programs.cc",
"command_buffer/service/gles2_cmd_decoder_unittest_textures.cc",
- "command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc",
"command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc",
- "command_buffer/service/gl_surface_mock.cc",
- "command_buffer/service/gl_surface_mock.h",
"command_buffer/service/gpu_scheduler_unittest.cc",
"command_buffer/service/gpu_service_test.cc",
"command_buffer/service/gpu_service_test.h",
+ "command_buffer/service/gpu_tracer_unittest.cc",
"command_buffer/service/id_manager_unittest.cc",
"command_buffer/service/mailbox_manager_unittest.cc",
"command_buffer/service/memory_program_cache_unittest.cc",
"command_buffer/service/mocks.cc",
"command_buffer/service/mocks.h",
+ "command_buffer/service/program_cache_unittest.cc",
"command_buffer/service/program_manager_unittest.cc",
- "command_buffer/service/valuebuffer_manager_unittest.cc",
"command_buffer/service/query_manager_unittest.cc",
"command_buffer/service/renderbuffer_manager_unittest.cc",
- "command_buffer/service/program_cache_unittest.cc",
"command_buffer/service/shader_manager_unittest.cc",
- "command_buffer/service/shader_translator_unittest.cc",
"command_buffer/service/shader_translator_cache_unittest.cc",
+ "command_buffer/service/shader_translator_unittest.cc",
"command_buffer/service/test_helper.cc",
"command_buffer/service/test_helper.h",
"command_buffer/service/texture_manager_unittest.cc",
"command_buffer/service/transfer_buffer_manager_unittest.cc",
- "command_buffer/service/vertex_attrib_manager_unittest.cc",
+ "command_buffer/service/valuebuffer_manager_unittest.cc",
"command_buffer/service/vertex_array_manager_unittest.cc",
- "command_buffer/service/gpu_tracer_unittest.cc",
+ "command_buffer/service/vertex_attrib_manager_unittest.cc",
"config/gpu_blacklist_unittest.cc",
"config/gpu_control_list_entry_unittest.cc",
"config/gpu_control_list_number_info_unittest.cc",
@@ -247,6 +247,7 @@
test("gpu_perftests") {
sources = [
+ "perftests/measurements.cc",
"perftests/run_all_tests.cc",
"perftests/texture_upload_perftest.cc",
]
@@ -254,6 +255,7 @@
deps = [
"//base",
"//base/test:test_support",
+ "//gpu/command_buffer/service",
"//testing/gtest",
"//testing/perf",
"//ui/gfx/geometry",
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h
index 9d3a0f9..a36a026 100644
--- a/gpu/GLES2/gl2chromium_autogen.h
+++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -86,7 +86,9 @@
#define glGenTransformFeedbacks GLES2_GET_FUN(GenTransformFeedbacks)
#define glGetActiveAttrib GLES2_GET_FUN(GetActiveAttrib)
#define glGetActiveUniform GLES2_GET_FUN(GetActiveUniform)
+#define glGetActiveUniformBlockiv GLES2_GET_FUN(GetActiveUniformBlockiv)
#define glGetActiveUniformBlockName GLES2_GET_FUN(GetActiveUniformBlockName)
+#define glGetActiveUniformsiv GLES2_GET_FUN(GetActiveUniformsiv)
#define glGetAttachedShaders GLES2_GET_FUN(GetAttachedShaders)
#define glGetAttribLocation GLES2_GET_FUN(GetAttribLocation)
#define glGetBooleanv GLES2_GET_FUN(GetBooleanv)
@@ -110,9 +112,11 @@
#define glGetString GLES2_GET_FUN(GetString)
#define glGetTexParameterfv GLES2_GET_FUN(GetTexParameterfv)
#define glGetTexParameteriv GLES2_GET_FUN(GetTexParameteriv)
+#define glGetTransformFeedbackVarying GLES2_GET_FUN(GetTransformFeedbackVarying)
#define glGetUniformBlockIndex GLES2_GET_FUN(GetUniformBlockIndex)
#define glGetUniformfv GLES2_GET_FUN(GetUniformfv)
#define glGetUniformiv GLES2_GET_FUN(GetUniformiv)
+#define glGetUniformIndices GLES2_GET_FUN(GetUniformIndices)
#define glGetUniformLocation GLES2_GET_FUN(GetUniformLocation)
#define glGetVertexAttribfv GLES2_GET_FUN(GetVertexAttribfv)
#define glGetVertexAttribiv GLES2_GET_FUN(GetVertexAttribiv)
@@ -191,6 +195,7 @@
#define glUniform4iv GLES2_GET_FUN(Uniform4iv)
#define glUniform4ui GLES2_GET_FUN(Uniform4ui)
#define glUniform4uiv GLES2_GET_FUN(Uniform4uiv)
+#define glUniformBlockBinding GLES2_GET_FUN(UniformBlockBinding)
#define glUniformMatrix2fv GLES2_GET_FUN(UniformMatrix2fv)
#define glUniformMatrix2x3fv GLES2_GET_FUN(UniformMatrix2x3fv)
#define glUniformMatrix2x4fv GLES2_GET_FUN(UniformMatrix2x4fv)
@@ -258,6 +263,9 @@
GLES2_GET_FUN(RateLimitOffscreenContextCHROMIUM)
#define glGetProgramInfoCHROMIUM GLES2_GET_FUN(GetProgramInfoCHROMIUM)
#define glGetUniformBlocksCHROMIUM GLES2_GET_FUN(GetUniformBlocksCHROMIUM)
+#define glGetTransformFeedbackVaryingsCHROMIUM \
+ GLES2_GET_FUN(GetTransformFeedbackVaryingsCHROMIUM)
+#define glGetUniformsES3CHROMIUM GLES2_GET_FUN(GetUniformsES3CHROMIUM)
#define glCreateStreamTextureCHROMIUM GLES2_GET_FUN(CreateStreamTextureCHROMIUM)
#define glCreateImageCHROMIUM GLES2_GET_FUN(CreateImageCHROMIUM)
#define glDestroyImageCHROMIUM GLES2_GET_FUN(DestroyImageCHROMIUM)
diff --git a/gpu/blink/webgraphicscontext3d_impl.cc b/gpu/blink/webgraphicscontext3d_impl.cc
index 2681abc..4f728cf 100644
--- a/gpu/blink/webgraphicscontext3d_impl.cc
+++ b/gpu/blink/webgraphicscontext3d_impl.cc
@@ -148,6 +148,22 @@
return gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
}
+#define DELEGATE_TO_GL_10(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, \
+ t9, t10) \
+void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, \
+ t6 a6, t7 a7, t8 a8, t9 a9, \
+ t10 a10) { \
+ gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); \
+}
+
+#define DELEGATE_TO_GL_11(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, \
+ t9, t10, t11) \
+void WebGraphicsContext3DImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, \
+ t6 a6, t7 a7, t8 a8, t9 a9, t10 a10,\
+ t11 a11) { \
+ gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); \
+}
+
WebGraphicsContext3DImpl::WebGraphicsContext3DImpl()
: initialized_(false),
initialize_failed_(false),
@@ -709,23 +725,6 @@
DELEGATE_TO_GL_4(viewport, Viewport,
WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei)
-DELEGATE_TO_GL_2(genBuffers, GenBuffers, WGC3Dsizei, WebGLId*);
-
-DELEGATE_TO_GL_2(genFramebuffers, GenFramebuffers, WGC3Dsizei, WebGLId*);
-
-DELEGATE_TO_GL_2(genRenderbuffers, GenRenderbuffers, WGC3Dsizei, WebGLId*);
-
-DELEGATE_TO_GL_2(genTextures, GenTextures, WGC3Dsizei, WebGLId*);
-
-DELEGATE_TO_GL_2(deleteBuffers, DeleteBuffers, WGC3Dsizei, WebGLId*);
-
-DELEGATE_TO_GL_2(deleteFramebuffers, DeleteFramebuffers, WGC3Dsizei, WebGLId*);
-
-DELEGATE_TO_GL_2(deleteRenderbuffers, DeleteRenderbuffers, WGC3Dsizei,
- WebGLId*);
-
-DELEGATE_TO_GL_2(deleteTextures, DeleteTextures, WGC3Dsizei, WebGLId*);
-
WebGLId WebGraphicsContext3DImpl::createBuffer() {
GLuint o;
gl_->GenBuffers(1, &o);
@@ -974,6 +973,160 @@
RenderbufferStorageMultisampleEXT, WGC3Denum, WGC3Dsizei,
WGC3Denum, WGC3Dsizei, WGC3Dsizei)
+DELEGATE_TO_GL_1(beginTransformFeedback, BeginTransformFeedback, WGC3Denum)
+DELEGATE_TO_GL_3(bindBufferBase, BindBufferBase, WGC3Denum, WGC3Duint,
+ WGC3Duint)
+DELEGATE_TO_GL_5(bindBufferRange, BindBufferRange, WGC3Denum, WGC3Duint,
+ WGC3Duint, WGC3Dintptr, WGC3Dsizeiptr)
+DELEGATE_TO_GL_2(bindSampler, BindSampler, WGC3Duint, WebGLId)
+DELEGATE_TO_GL_2(bindTransformFeedback, BindTransformFeedback, WGC3Denum,
+ WebGLId)
+DELEGATE_TO_GL_4(clearBufferfi, ClearBufferfi, WGC3Denum, WGC3Dint, WGC3Dfloat,
+ WGC3Dint)
+DELEGATE_TO_GL_3(clearBufferfv, ClearBufferfv, WGC3Denum, WGC3Dint,
+ const WGC3Dfloat *)
+DELEGATE_TO_GL_3(clearBufferiv, ClearBufferiv, WGC3Denum, WGC3Dint,
+ const WGC3Dint *)
+DELEGATE_TO_GL_3(clearBufferuiv, ClearBufferuiv, WGC3Denum, WGC3Dint,
+ const WGC3Duint *)
+//DELEGATE_TO_GL_3R(clientWaitSync, ClientWaitSync, WebGLId, WGC3Dbitfield,
+// WGC3Duint64, WGC3Denum)
+//DELEGATE_TO_GL_9(compressedTexImage3D, CompressedTexImage3D, WGC3Denum,
+// WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, WGC3Dsizei,
+// WGC3Dint, WGC3Dsizei, const void *)
+//DELEGATE_TO_GL_11(compressedTexSubImage3D, CompressedTexSubImage3D, WGC3Denum,
+// WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei,
+// WGC3Dsizei, WGC3Dsizei, WGC3Denum, WGC3Dsizei, const void *)
+DELEGATE_TO_GL_5(copyBufferSubData, CopyBufferSubData, WGC3Denum, WGC3Denum,
+ WGC3Dintptr, WGC3Dintptr, WGC3Dsizeiptr)
+DELEGATE_TO_GL_9(copyTexSubImage3D, CopyTexSubImage3D, WGC3Denum, WGC3Dint,
+ WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei,
+ WGC3Dsizei)
+WebGLId WebGraphicsContext3DImpl::createSampler() {
+ GLuint sampler;
+ gl_->GenSamplers(1, &sampler);
+ return sampler;
+}
+WebGLId WebGraphicsContext3DImpl::createTransformFeedback() {
+ GLuint tf;
+ gl_->GenTransformFeedbacks(1, &tf);
+ return tf;
+}
+void WebGraphicsContext3DImpl::deleteSampler(WebGLId sampler) {
+ gl_->DeleteSamplers(1, &sampler);
+}
+//DELEGATE_TO_GL_1(deleteSync, DeleteSync, WebGLId)
+void WebGraphicsContext3DImpl::deleteTransformFeedback(WebGLId tf) {
+ gl_->DeleteTransformFeedbacks(1, &tf);
+}
+DELEGATE_TO_GL(endTransformFeedback, EndTransformFeedback)
+//DELEGATE_TO_GL_2R(fenceSync, FenceSync, WGC3Denum, WGC3Dbitfield, WebGLId)
+DELEGATE_TO_GL_5(framebufferTextureLayer, FramebufferTextureLayer, WGC3Denum,
+ WGC3Denum, WGC3Duint, WGC3Dint, WGC3Dint)
+DELEGATE_TO_GL_5(getActiveUniformBlockName, GetActiveUniformBlockName,
+ WGC3Duint, WGC3Duint, WGC3Dsizei, WGC3Dsizei *, WGC3Dchar *)
+DELEGATE_TO_GL_4(getActiveUniformBlockiv, GetActiveUniformBlockiv, WGC3Duint,
+ WGC3Duint, WGC3Denum, WGC3Dint *)
+//DELEGATE_TO_GL_5(getActiveUniformsiv, GetActiveUniformsiv, WGC3Duint,
+// WGC3Dsizei, const WGC3Duint *, WGC3Denum, WGC3Dint *)
+DELEGATE_TO_GL_2R(getFragDataLocation, GetFragDataLocation, WGC3Duint,
+ const WGC3Dchar *, WGC3Dint)
+DELEGATE_TO_GL_5(getInternalformativ, GetInternalformativ, WGC3Denum, WGC3Denum,
+ WGC3Denum, WGC3Dsizei, WGC3Dint *)
+DELEGATE_TO_GL_3(getSamplerParameterfv, GetSamplerParameterfv, WGC3Duint,
+ WGC3Denum, WGC3Dfloat *)
+DELEGATE_TO_GL_3(getSamplerParameteriv, GetSamplerParameteriv, WGC3Duint,
+ WGC3Denum, WGC3Dint *)
+//DELEGATE_TO_GL_7(getTransformFeedbackVarying, GetTransformFeedbackVarying,
+// WGC3Duint, WGC3Duint, WGC3Dsizei, WGC3Dsizei *, WGC3Dsizei *,
+// WGC3Denum *, WGC3Dchar *)
+DELEGATE_TO_GL_2R(getUniformBlockIndex, GetUniformBlockIndex, WGC3Duint,
+ const WGC3Dchar *, WGC3Duint)
+//DELEGATE_TO_GL_4(getUniformIndices, GetUniformIndices, WGC3Duint, WGC3Dsizei,
+// const WGC3Dchar *const*, WGC3Duint *)
+//DELEGATE_TO_GL_3(getUniformuiv, GetUniformuiv, WGC3Duint, WGC3Dint,
+// WGC3Duint *)
+//DELEGATE_TO_GL_3(getVertexAttribIiv, GetVertexAttribIiv, WGC3Duint,
+// WGC3Denum, WGC3Dint *)
+//DELEGATE_TO_GL_3(getVertexAttribIuiv, GetVertexAttribIuiv, WGC3Duint,
+// WGC3Denum, WGC3Duint *)
+DELEGATE_TO_GL_3(invalidateFramebuffer, InvalidateFramebuffer, WGC3Denum,
+ WGC3Dsizei, const WGC3Denum *)
+DELEGATE_TO_GL_7(invalidateSubFramebuffer, InvalidateSubFramebuffer, WGC3Denum,
+ WGC3Dsizei, const WGC3Denum *, WGC3Dint, WGC3Dint, WGC3Dsizei,
+ WGC3Dsizei)
+DELEGATE_TO_GL_1R(isSampler, IsSampler, WebGLId, WGC3Dboolean)
+//DELEGATE_TO_GL_1R(isSync, IsSync, WebGLId, WGC3Dboolean)
+DELEGATE_TO_GL_1R(isTransformFeedback, IsTransformFeedback, WGC3Duint,
+ WGC3Dboolean)
+DELEGATE_TO_GL(pauseTransformFeedback, PauseTransformFeedback)
+//DELEGATE_TO_GL_3(programParameteri, ProgramParameteri, WGC3Duint, WGC3Denum,
+// WGC3Dint)
+DELEGATE_TO_GL_1(readBuffer, ReadBuffer, WGC3Denum)
+DELEGATE_TO_GL(resumeTransformFeedback, ResumeTransformFeedback)
+DELEGATE_TO_GL_3(samplerParameterf, SamplerParameterf, WGC3Duint, WGC3Denum,
+ WGC3Dfloat)
+DELEGATE_TO_GL_3(samplerParameterfv, SamplerParameterfv, WGC3Duint, WGC3Denum,
+ const WGC3Dfloat *)
+DELEGATE_TO_GL_3(samplerParameteri, SamplerParameteri, WGC3Duint, WGC3Denum,
+ WGC3Dint)
+DELEGATE_TO_GL_3(samplerParameteriv, SamplerParameteriv, WGC3Duint, WGC3Denum,
+ const WGC3Dint *)
+DELEGATE_TO_GL_10(texImage3D, TexImage3D, WGC3Denum, WGC3Dint, WGC3Dint,
+ WGC3Dsizei, WGC3Dsizei, WGC3Dsizei, WGC3Dint, WGC3Denum,
+ WGC3Denum, const void *)
+DELEGATE_TO_GL_6(texStorage3D, TexStorage3D, WGC3Denum, WGC3Dsizei, WGC3Denum,
+ WGC3Dsizei, WGC3Dsizei, WGC3Dsizei)
+DELEGATE_TO_GL_11(texSubImage3D, TexSubImage3D, WGC3Denum, WGC3Dint, WGC3Dint,
+ WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, WGC3Dsizei,
+ WGC3Denum, WGC3Denum, const void *)
+DELEGATE_TO_GL_4(transformFeedbackVaryings, TransformFeedbackVaryings,
+ WGC3Duint, WGC3Dsizei, const WGC3Dchar *const*, WGC3Denum)
+DELEGATE_TO_GL_2(uniform1ui, Uniform1ui, WGC3Dint, WGC3Duint)
+DELEGATE_TO_GL_3(uniform1uiv, Uniform1uiv, WGC3Dint, WGC3Dsizei,
+ const WGC3Duint *)
+DELEGATE_TO_GL_3(uniform2ui, Uniform2ui, WGC3Dint, WGC3Duint, WGC3Duint)
+DELEGATE_TO_GL_3(uniform2uiv, Uniform2uiv, WGC3Dint, WGC3Dsizei,
+ const WGC3Duint *)
+DELEGATE_TO_GL_4(uniform3ui, Uniform3ui, WGC3Dint, WGC3Duint, WGC3Duint,
+ WGC3Duint)
+DELEGATE_TO_GL_3(uniform3uiv, Uniform3uiv, WGC3Dint, WGC3Dsizei,
+ const WGC3Duint *)
+DELEGATE_TO_GL_5(uniform4ui, Uniform4ui, WGC3Dint, WGC3Duint, WGC3Duint,
+ WGC3Duint, WGC3Duint)
+DELEGATE_TO_GL_3(uniform4uiv, Uniform4uiv, WGC3Dint, WGC3Dsizei,
+ const WGC3Duint *)
+DELEGATE_TO_GL_3(uniformBlockBinding, UniformBlockBinding, WGC3Duint, WGC3Duint,
+ WGC3Duint)
+DELEGATE_TO_GL_4(uniformMatrix2x3fv, UniformMatrix2x3fv, WGC3Dint, WGC3Dsizei,
+ WGC3Dboolean, const WGC3Dfloat*)
+DELEGATE_TO_GL_4(uniformMatrix2x4fv, UniformMatrix2x4fv, WGC3Dint, WGC3Dsizei,
+ WGC3Dboolean, const WGC3Dfloat*)
+DELEGATE_TO_GL_4(uniformMatrix3x2fv, UniformMatrix3x2fv, WGC3Dint, WGC3Dsizei,
+ WGC3Dboolean, const WGC3Dfloat*)
+DELEGATE_TO_GL_4(uniformMatrix3x4fv, UniformMatrix3x4fv, WGC3Dint, WGC3Dsizei,
+ WGC3Dboolean, const WGC3Dfloat*)
+DELEGATE_TO_GL_4(uniformMatrix4x2fv, UniformMatrix4x2fv, WGC3Dint, WGC3Dsizei,
+ WGC3Dboolean, const WGC3Dfloat*)
+DELEGATE_TO_GL_4(uniformMatrix4x3fv, UniformMatrix4x3fv, WGC3Dint, WGC3Dsizei,
+ WGC3Dboolean, const WGC3Dfloat*)
+DELEGATE_TO_GL_5(vertexAttribI4i, VertexAttribI4i, WGC3Duint, WGC3Dint,
+ WGC3Dint, WGC3Dint, WGC3Dint)
+DELEGATE_TO_GL_2(vertexAttribI4iv, VertexAttribI4iv, WGC3Duint,
+ const WGC3Dint *)
+DELEGATE_TO_GL_5(vertexAttribI4ui, VertexAttribI4ui, WGC3Duint, WGC3Duint,
+ WGC3Duint, WGC3Duint, WGC3Duint)
+DELEGATE_TO_GL_2(vertexAttribI4uiv, VertexAttribI4uiv, WGC3Duint,
+ const WGC3Duint *)
+void WebGraphicsContext3DImpl::vertexAttribIPointer(
+ WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dsizei stride,
+ WGC3Dintptr offset) {
+ gl_->VertexAttribIPointer(
+ index, size, type, stride,
+ reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+//DELEGATE_TO_GL_3(waitSync, WaitSync, WebGLId, WGC3Dbitfield, WGC3Duint64)
+
GrGLInterface* WebGraphicsContext3DImpl::createGrGLInterface() {
return skia_bindings::CreateCommandBufferSkiaGLBinding();
}
diff --git a/gpu/blink/webgraphicscontext3d_impl.h b/gpu/blink/webgraphicscontext3d_impl.h
index 11a3dc5..ff2ca97 100644
--- a/gpu/blink/webgraphicscontext3d_impl.h
+++ b/gpu/blink/webgraphicscontext3d_impl.h
@@ -37,6 +37,7 @@
using blink::WGC3Dclampf;
using blink::WGC3Dintptr;
using blink::WGC3Dsizeiptr;
+using blink::WGC3Duint64;
namespace gpu_blink {
@@ -371,17 +372,6 @@
virtual void viewport(WGC3Dint x, WGC3Dint y,
WGC3Dsizei width, WGC3Dsizei height);
- // Support for buffer creation and deletion
- virtual void genBuffers(WGC3Dsizei count, WebGLId* ids);
- virtual void genFramebuffers(WGC3Dsizei count, WebGLId* ids);
- virtual void genRenderbuffers(WGC3Dsizei count, WebGLId* ids);
- virtual void genTextures(WGC3Dsizei count, WebGLId* ids);
-
- virtual void deleteBuffers(WGC3Dsizei count, WebGLId* ids);
- virtual void deleteFramebuffers(WGC3Dsizei count, WebGLId* ids);
- virtual void deleteRenderbuffers(WGC3Dsizei count, WebGLId* ids);
- virtual void deleteTextures(WGC3Dsizei count, WebGLId* ids);
-
virtual WebGLId createBuffer();
virtual WebGLId createFramebuffer();
virtual WebGLId createRenderbuffer();
@@ -566,6 +556,147 @@
WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat,
WGC3Dsizei width, 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,
+ // 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 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 void pauseTransformFeedback(void);
+ //virtual void programParameteri(WGC3Duint program, WGC3Denum pname,
+ // WGC3Dint value);
+ virtual void readBuffer(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 GrGLInterface* createGrGLInterface();
::gpu::gles2::GLES2Interface* GetGLInterface() {
diff --git a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
index 386d349..ff83e5a 100644
--- a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
+++ b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.cc
@@ -153,6 +153,10 @@
return context_ && !isContextLost();
}
+void WebGraphicsContext3DInProcessCommandBufferImpl::SetLock(base::Lock* lock) {
+ context_->SetLock(lock);
+}
+
bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() {
return context_lost_reason_ != GL_NO_ERROR;
}
diff --git a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h
index 94816a8..8aba802 100644
--- a/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h
+++ b/gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h
@@ -57,6 +57,7 @@
size_t GetMappedMemoryLimit();
bool InitializeOnCurrentThread();
+ void SetLock(base::Lock* lock);
//----------------------------------------------------------------------
// WebGraphicsContext3D methods
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index dc576d7..ca39150 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1313,6 +1313,37 @@
'GL_MOUSE_POSITION_CHROMIUM',
],
},
+ 'UniformParameter': {
+ 'type': 'GLenum',
+ 'valid': [
+ 'GL_UNIFORM_SIZE',
+ 'GL_UNIFORM_TYPE',
+ 'GL_UNIFORM_NAME_LENGTH',
+ 'GL_UNIFORM_BLOCK_INDEX',
+ 'GL_UNIFORM_OFFSET',
+ 'GL_UNIFORM_ARRAY_STRIDE',
+ 'GL_UNIFORM_MATRIX_STRIDE',
+ 'GL_UNIFORM_IS_ROW_MAJOR',
+ ],
+ 'invalid': [
+ 'GL_UNIFORM_BLOCK_NAME_LENGTH',
+ ],
+ },
+ 'UniformBlockParameter': {
+ 'type': 'GLenum',
+ 'valid': [
+ 'GL_UNIFORM_BLOCK_BINDING',
+ 'GL_UNIFORM_BLOCK_DATA_SIZE',
+ 'GL_UNIFORM_BLOCK_NAME_LENGTH',
+ 'GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS',
+ 'GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES',
+ 'GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER',
+ 'GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER',
+ ],
+ 'invalid': [
+ 'GL_NEAREST',
+ ],
+ },
'VertexAttribType': {
'type': 'GLenum',
'valid': [
@@ -2034,6 +2065,12 @@
'uint32_t type',
],
},
+ 'GetActiveUniformBlockiv': {
+ 'type': 'Custom',
+ 'data_transfer_methods': ['shm'],
+ 'result': ['SizedResult<GLint>'],
+ 'unsafe': True,
+ },
'GetActiveUniformBlockName': {
'type': 'Custom',
'data_transfer_methods': ['shm'],
@@ -2043,6 +2080,15 @@
'result': ['int32_t'],
'unsafe': True,
},
+ 'GetActiveUniformsiv': {
+ 'type': 'Custom',
+ 'data_transfer_methods': ['shm'],
+ 'cmd_args':
+ 'GLidProgram program, uint32_t indices_bucket_id, GLenum pname, '
+ 'GLint* params',
+ 'result': ['SizedResult<GLint>'],
+ 'unsafe': True,
+ },
'GetAttachedShaders': {
'type': 'Custom',
'data_transfer_methods': ['shm'],
@@ -2234,6 +2280,41 @@
'result': ['uint32_t'],
'unsafe': True,
},
+ 'GetUniformsES3CHROMIUM': {
+ 'type': 'Custom',
+ 'expectation': False,
+ 'impl_func': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ 'cmd_args': 'GLidProgram program, uint32_t bucket_id',
+ 'result': ['uint32_t'],
+ 'unsafe': True,
+ },
+ 'GetTransformFeedbackVarying': {
+ 'type': 'Custom',
+ 'data_transfer_methods': ['shm'],
+ 'cmd_args':
+ 'GLidProgram program, GLuint index, uint32_t name_bucket_id, '
+ 'void* result',
+ 'result': [
+ 'int32_t success',
+ 'int32_t size',
+ 'uint32_t type',
+ ],
+ 'unsafe': True,
+ },
+ 'GetTransformFeedbackVaryingsCHROMIUM': {
+ 'type': 'Custom',
+ 'expectation': False,
+ 'impl_func': False,
+ 'extension': True,
+ 'chromium': True,
+ 'client_test': False,
+ 'cmd_args': 'GLidProgram program, uint32_t bucket_id',
+ 'result': ['uint32_t'],
+ 'unsafe': True,
+ },
'GetUniformfv': {
'type': 'Custom',
'data_transfer_methods': ['shm'],
@@ -2244,6 +2325,14 @@
'data_transfer_methods': ['shm'],
'result': ['SizedResult<GLint>'],
},
+ 'GetUniformIndices': {
+ 'type': 'Custom',
+ 'data_transfer_methods': ['shm'],
+ 'result': ['SizedResult<GLuint>'],
+ 'cmd_args': 'GLidProgram program, uint32_t names_bucket_id, '
+ 'GLuint* indices',
+ 'unsafe': True,
+ },
'GetUniformLocation': {
'type': 'Custom',
'data_transfer_methods': ['shm'],
@@ -2735,6 +2824,11 @@
'count': 12,
'unsafe': True,
},
+ 'UniformBlockBinding': {
+ 'type': 'Custom',
+ 'impl_func': False,
+ 'unsafe': True,
+ },
'UnmapBufferCHROMIUM': {
'gen_cmd': False,
'extension': True,
@@ -6480,90 +6574,7 @@
})
for arg in func.GetOriginalArgs():
arg.WriteClientSideValidationCode(file, func)
- size_code_block = """ // Compute the total size.
- base::CheckedNumeric<size_t> total_size = count;
- total_size += 1;
- total_size *= sizeof(GLint);
- if (!total_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow");
- return;
- }
- size_t header_size = total_size.ValueOrDefault(0);
- std::vector<GLint> header(count + 1);
- header[0] = static_cast<GLint>(count);
- for (GLsizei ii = 0; ii < count; ++ii) {
- GLint len = 0;
- if (%(data)s[ii]) {"""
- if length_arg == None:
- size_code_block += """
- len = static_cast<GLint>(strlen(%(data)s[ii]));"""
- else:
- size_code_block += """
- len = (%(length)s && %(length)s[ii] >= 0) ?
- %(length)s[ii] : base::checked_cast<GLint>(strlen(%(data)s[ii]));"""
- size_code_block += """
- }
- total_size += len;
- total_size += 1; // NULL at the end of each char array.
- if (!total_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow");
- return;
- }
- header[ii + 1] = len;
-}
-"""
- file.Write(size_code_block % {
- 'data': data_arg.name,
- 'length': length_arg.name if not length_arg == None else '',
- 'func_name': func.name,
- })
- data_code_block = """ // Pack data into a bucket on the service.
- helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0));
- size_t offset = 0;
- for (GLsizei ii = 0; ii <= count; ++ii) {
- const char* src = (ii == 0) ? reinterpret_cast<const char*>(&header[0]) :
- %(data)s[ii - 1];
- base::CheckedNumeric<size_t> checked_size = (ii == 0) ? header_size :
- static_cast<size_t>(header[ii]);
- if (ii > 0) {
- checked_size += 1; // NULL in the end.
- }
- if (!checked_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "gl%(func_name)s", "overflow");
- return;
- }
- size_t size = checked_size.ValueOrDefault(0);
- while (size) {
- ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
- if (!buffer.valid() || buffer.size() == 0) {
- SetGLError(GL_OUT_OF_MEMORY, "gl%(func_name)s", "too large");
- return;
- }
- size_t copy_size = buffer.size();
- if (ii > 0 && buffer.size() == size)
- --copy_size;
- if (copy_size)
- memcpy(buffer.address(), src, copy_size);
- if (copy_size < buffer.size()) {
- // Append NULL in the end.
- DCHECK(copy_size + 1 == buffer.size());
- char* str = reinterpret_cast<char*>(buffer.address());
- str[copy_size] = 0;
- }
- helper_->SetBucketData(kResultBucketId, offset, buffer.size(),
- buffer.shm_id(), buffer.offset());
- offset += buffer.size();
- src += buffer.size();
- size -= buffer.size();
- }
- }
- DCHECK_EQ(total_size.ValueOrDefault(0), offset);
-"""
- file.Write(data_code_block % {
- 'data': data_arg.name,
- 'length': length_arg.name if not length_arg == None else '',
- 'func_name': func.name,
- })
+
bucket_args = []
for arg in func.GetOriginalArgs():
if arg.name == 'count' or arg == self.__GetLengthArg(func):
@@ -6572,12 +6583,22 @@
bucket_args.append('kResultBucketId')
else:
bucket_args.append(arg.name)
- file.Write(" helper_->%sBucket(%s);\n" %
- (func.name, ", ".join(bucket_args)))
- file.Write(" helper_->SetBucketSize(kResultBucketId, 0);");
- file.Write(" CheckGLError();\n")
- file.Write("}\n")
- file.Write("\n")
+ code_block = """
+ if (!PackStringsToBucket(count, %(data)s, %(length)s, "gl%(func_name)s")) {
+ return;
+ }
+ helper_->%(func_name)sBucket(%(bucket_args)s);
+ helper_->SetBucketSize(kResultBucketId, 0);
+ CheckGLError();
+}
+
+"""
+ file.Write(code_block % {
+ 'data': data_arg.name,
+ 'length': length_arg.name if not length_arg == None else 'NULL',
+ 'func_name': func.name,
+ 'bucket_args': ', '.join(bucket_args),
+ })
def WriteGLES2ImplementationUnitTest(self, func, file):
"""Overrriden from TypeHandler."""
@@ -8009,48 +8030,21 @@
def WriteGetCode(self, file):
"""Overridden from Argument."""
code = """
- const size_t kMinBucketSize = sizeof(GLint);
- // Each string has at least |length| in the header and a NUL character.
- const size_t kMinStringSize = sizeof(GLint) + 1;
Bucket* bucket = GetBucket(c.%(name)s);
if (!bucket) {
return error::kInvalidArguments;
}
- const size_t bucket_size = bucket->size();
- if (bucket_size < kMinBucketSize) {
+ GLsizei count = 0;
+ std::vector<char*> strs;
+ std::vector<GLint> len;
+ if (!bucket->GetAsStrings(&count, &strs, &len)) {
return error::kInvalidArguments;
}
- const char* bucket_data = bucket->GetDataAs<const char*>(0, bucket_size);
- const GLint* header = reinterpret_cast<const GLint*>(bucket_data);
- GLsizei count = static_cast<GLsizei>(header[0]);
- if (count < 0) {
- return error::kInvalidArguments;
- }
- const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize;
- if (max_count < static_cast<size_t>(count)) {
- return error::kInvalidArguments;
- }
- const GLint* length = header + 1;
- scoped_ptr<const char*[]> strs;
- if (count > 0)
- strs.reset(new const char*[count]);
- const char** %(original_name)s = strs.get();
- base::CheckedNumeric<size_t> total_size = sizeof(GLint);
- total_size *= count + 1; // Header size.
- if (!total_size.IsValid())
- return error::kInvalidArguments;
- for (GLsizei ii = 0; ii < count; ++ii) {
- %(original_name)s[ii] = bucket_data + total_size.ValueOrDefault(0);
- total_size += length[ii];
- total_size += 1; // NUL char at the end of each char array.
- if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size ||
- %(original_name)s[ii][length[ii]] != 0) {
- return error::kInvalidArguments;
- }
- }
- if (total_size.ValueOrDefault(0) != bucket_size) {
- return error::kInvalidArguments;
- }
+ const char** %(original_name)s =
+ strs.size() > 0 ? const_cast<const char**>(&strs[0]) : NULL;
+ const GLint* length =
+ len.size() > 0 ? const_cast<const GLint*>(&len[0]) : NULL;
+ (void)length;
"""
file.Write(code % {
'name': self.name,
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn
index 04aa039..2d28d1a 100644
--- a/gpu/command_buffer/client/BUILD.gn
+++ b/gpu/command_buffer/client/BUILD.gn
@@ -70,25 +70,25 @@
"gles2_c_lib.cc",
"gles2_c_lib_autogen.h",
"gles2_c_lib_export.h",
- "gles2_lib.h",
"gles2_lib.cc",
+ "gles2_lib.h",
]
gles2_implementation_source_files = [
"buffer_tracker.cc",
"buffer_tracker.h",
- "client_context_state.h",
"client_context_state.cc",
+ "client_context_state.h",
"client_context_state_autogen.h",
"client_context_state_impl_autogen.h",
"gles2_impl_export.h",
- "gles2_implementation_autogen.h",
"gles2_implementation.cc",
"gles2_implementation.h",
+ "gles2_implementation_autogen.h",
"gles2_implementation_impl_autogen.h",
- "gles2_trace_implementation_autogen.h",
"gles2_trace_implementation.cc",
"gles2_trace_implementation.h",
+ "gles2_trace_implementation_autogen.h",
"gles2_trace_implementation_impl_autogen.h",
"gpu_switches.cc",
"gpu_switches.h",
@@ -148,8 +148,8 @@
component("gl_in_process_context") {
sources = [
- "gl_in_process_context.h",
"gl_in_process_context.cc",
+ "gl_in_process_context.h",
"gl_in_process_context_export.h",
]
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h
index 111c4f4..46e343d 100644
--- a/gpu/command_buffer/client/client_test_helper.h
+++ b/gpu/command_buffer/client/client_test_helper.h
@@ -110,6 +110,7 @@
MOCK_METHOD2(SignalQuery, void(uint32 query, const base::Closure& callback));
MOCK_METHOD1(SetSurfaceVisible, void(bool visible));
MOCK_METHOD1(CreateStreamTexture, uint32(uint32));
+ MOCK_METHOD1(SetLock, void(base::Lock*));
private:
DISALLOW_COPY_AND_ASSIGN(MockClientGpuControl);
diff --git a/gpu/command_buffer/client/gl_in_process_context.cc b/gpu/command_buffer/client/gl_in_process_context.cc
index f10695e..5d8049b 100644
--- a/gpu/command_buffer/client/gl_in_process_context.cc
+++ b/gpu/command_buffer/client/gl_in_process_context.cc
@@ -66,6 +66,7 @@
void SetContextLostCallback(const base::Closure& callback) override;
gles2::GLES2Implementation* GetImplementation() override;
size_t GetMappedMemoryLimit() override;
+ void SetLock(base::Lock* lock) override;
#if defined(OS_ANDROID)
scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
@@ -85,6 +86,7 @@
const GLInProcessContextSharedMemoryLimits mem_limits_;
bool context_lost_;
base::Closure context_lost_callback_;
+ base::Lock* lock_;
DISALLOW_COPY_AND_ASSIGN(GLInProcessContextImpl);
};
@@ -96,7 +98,7 @@
GLInProcessContextImpl::GLInProcessContextImpl(
const GLInProcessContextSharedMemoryLimits& mem_limits)
- : mem_limits_(mem_limits), context_lost_(false) {
+ : mem_limits_(mem_limits), context_lost_(false), lock_(nullptr) {
}
GLInProcessContextImpl::~GLInProcessContextImpl() {
@@ -115,12 +117,20 @@
return mem_limits_.mapped_memory_reclaim_limit;
}
+void GLInProcessContextImpl::SetLock(base::Lock* lock) {
+ command_buffer_->SetLock(lock);
+ lock_ = lock;
+}
+
void GLInProcessContextImpl::SetContextLostCallback(
const base::Closure& callback) {
context_lost_callback_ = callback;
}
void GLInProcessContextImpl::OnContextLost() {
+ scoped_ptr<base::AutoLock> lock;
+ if (lock_)
+ lock.reset(new base::AutoLock(*lock_));
context_lost_ = true;
if (!context_lost_callback_.is_null()) {
context_lost_callback_.Run();
diff --git a/gpu/command_buffer/client/gl_in_process_context.h b/gpu/command_buffer/client/gl_in_process_context.h
index ef1820c..8c3a1c5 100644
--- a/gpu/command_buffer/client/gl_in_process_context.h
+++ b/gpu/command_buffer/client/gl_in_process_context.h
@@ -76,6 +76,8 @@
virtual size_t GetMappedMemoryLimit() = 0;
+ virtual void SetLock(base::Lock* lock) = 0;
+
#if defined(OS_ANDROID)
virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
uint32 stream_id) = 0;
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index dfe7a6a..23d3d6e 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -338,6 +338,12 @@
gles2::GetGLContext()->GetActiveUniform(program, index, bufsize, length, size,
type, name);
}
+void GLES2GetActiveUniformBlockiv(GLuint program,
+ GLuint index,
+ GLenum pname,
+ GLint* params) {
+ gles2::GetGLContext()->GetActiveUniformBlockiv(program, index, pname, params);
+}
void GLES2GetActiveUniformBlockName(GLuint program,
GLuint index,
GLsizei bufsize,
@@ -346,6 +352,14 @@
gles2::GetGLContext()->GetActiveUniformBlockName(program, index, bufsize,
length, name);
}
+void GLES2GetActiveUniformsiv(GLuint program,
+ GLsizei count,
+ const GLuint* indices,
+ GLenum pname,
+ GLint* params) {
+ gles2::GetGLContext()->GetActiveUniformsiv(program, count, indices, pname,
+ params);
+}
void GLES2GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -439,6 +453,16 @@
void GLES2GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
gles2::GetGLContext()->GetTexParameteriv(target, pname, params);
}
+void GLES2GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLsizei* size,
+ GLenum* type,
+ char* name) {
+ gles2::GetGLContext()->GetTransformFeedbackVarying(program, index, bufsize,
+ length, size, type, name);
+}
GLuint GLES2GetUniformBlockIndex(GLuint program, const char* name) {
return gles2::GetGLContext()->GetUniformBlockIndex(program, name);
}
@@ -448,6 +472,12 @@
void GLES2GetUniformiv(GLuint program, GLint location, GLint* params) {
gles2::GetGLContext()->GetUniformiv(program, location, params);
}
+void GLES2GetUniformIndices(GLuint program,
+ GLsizei count,
+ const char* const* names,
+ GLuint* indices) {
+ gles2::GetGLContext()->GetUniformIndices(program, count, names, indices);
+}
GLint GLES2GetUniformLocation(GLuint program, const char* name) {
return gles2::GetGLContext()->GetUniformLocation(program, name);
}
@@ -773,6 +803,9 @@
void GLES2Uniform4uiv(GLint location, GLsizei count, const GLuint* v) {
gles2::GetGLContext()->Uniform4uiv(location, count, v);
}
+void GLES2UniformBlockBinding(GLuint program, GLuint index, GLuint binding) {
+ gles2::GetGLContext()->UniformBlockBinding(program, index, binding);
+}
void GLES2UniformMatrix2fv(GLint location,
GLsizei count,
GLboolean transpose,
@@ -1058,6 +1091,19 @@
void* info) {
gles2::GetGLContext()->GetUniformBlocksCHROMIUM(program, bufsize, size, info);
}
+void GLES2GetTransformFeedbackVaryingsCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) {
+ gles2::GetGLContext()->GetTransformFeedbackVaryingsCHROMIUM(program, bufsize,
+ size, info);
+}
+void GLES2GetUniformsES3CHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) {
+ gles2::GetGLContext()->GetUniformsES3CHROMIUM(program, bufsize, size, info);
+}
GLuint GLES2CreateStreamTextureCHROMIUM(GLuint texture) {
return gles2::GetGLContext()->CreateStreamTextureCHROMIUM(texture);
}
@@ -1559,10 +1605,18 @@
reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniform),
},
{
+ "glGetActiveUniformBlockiv",
+ reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniformBlockiv),
+ },
+ {
"glGetActiveUniformBlockName",
reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniformBlockName),
},
{
+ "glGetActiveUniformsiv",
+ reinterpret_cast<GLES2FunctionPointer>(glGetActiveUniformsiv),
+ },
+ {
"glGetAttachedShaders",
reinterpret_cast<GLES2FunctionPointer>(glGetAttachedShaders),
},
@@ -1652,6 +1706,10 @@
reinterpret_cast<GLES2FunctionPointer>(glGetTexParameteriv),
},
{
+ "glGetTransformFeedbackVarying",
+ reinterpret_cast<GLES2FunctionPointer>(glGetTransformFeedbackVarying),
+ },
+ {
"glGetUniformBlockIndex",
reinterpret_cast<GLES2FunctionPointer>(glGetUniformBlockIndex),
},
@@ -1664,6 +1722,10 @@
reinterpret_cast<GLES2FunctionPointer>(glGetUniformiv),
},
{
+ "glGetUniformIndices",
+ reinterpret_cast<GLES2FunctionPointer>(glGetUniformIndices),
+ },
+ {
"glGetUniformLocation",
reinterpret_cast<GLES2FunctionPointer>(glGetUniformLocation),
},
@@ -1976,6 +2038,10 @@
reinterpret_cast<GLES2FunctionPointer>(glUniform4uiv),
},
{
+ "glUniformBlockBinding",
+ reinterpret_cast<GLES2FunctionPointer>(glUniformBlockBinding),
+ },
+ {
"glUniformMatrix2fv",
reinterpret_cast<GLES2FunctionPointer>(glUniformMatrix2fv),
},
@@ -2228,6 +2294,15 @@
reinterpret_cast<GLES2FunctionPointer>(glGetUniformBlocksCHROMIUM),
},
{
+ "glGetTransformFeedbackVaryingsCHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(
+ glGetTransformFeedbackVaryingsCHROMIUM),
+ },
+ {
+ "glGetUniformsES3CHROMIUM",
+ reinterpret_cast<GLES2FunctionPointer>(glGetUniformsES3CHROMIUM),
+ },
+ {
"glCreateStreamTextureCHROMIUM",
reinterpret_cast<GLES2FunctionPointer>(glCreateStreamTextureCHROMIUM),
},
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index fc0f76d..bda8bb3 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -702,6 +702,18 @@
}
}
+void GetActiveUniformBlockiv(GLuint program,
+ GLuint index,
+ GLenum pname,
+ uint32_t params_shm_id,
+ uint32_t params_shm_offset) {
+ gles2::cmds::GetActiveUniformBlockiv* c =
+ GetCmdSpace<gles2::cmds::GetActiveUniformBlockiv>();
+ if (c) {
+ c->Init(program, index, pname, params_shm_id, params_shm_offset);
+ }
+}
+
void GetActiveUniformBlockName(GLuint program,
GLuint index,
uint32_t name_bucket_id,
@@ -714,6 +726,19 @@
}
}
+void GetActiveUniformsiv(GLuint program,
+ uint32_t indices_bucket_id,
+ GLenum pname,
+ uint32_t params_shm_id,
+ uint32_t params_shm_offset) {
+ gles2::cmds::GetActiveUniformsiv* c =
+ GetCmdSpace<gles2::cmds::GetActiveUniformsiv>();
+ if (c) {
+ c->Init(program, indices_bucket_id, pname, params_shm_id,
+ params_shm_offset);
+ }
+}
+
void GetAttachedShaders(GLuint program,
uint32_t result_shm_id,
uint32_t result_shm_offset,
@@ -933,6 +958,18 @@
}
}
+void GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ uint32_t name_bucket_id,
+ uint32_t result_shm_id,
+ uint32_t result_shm_offset) {
+ gles2::cmds::GetTransformFeedbackVarying* c =
+ GetCmdSpace<gles2::cmds::GetTransformFeedbackVarying>();
+ if (c) {
+ c->Init(program, index, name_bucket_id, result_shm_id, result_shm_offset);
+ }
+}
+
void GetUniformBlockIndex(GLuint program,
uint32_t name_bucket_id,
uint32_t index_shm_id,
@@ -964,6 +1001,17 @@
}
}
+void GetUniformIndices(GLuint program,
+ uint32_t names_bucket_id,
+ uint32_t indices_shm_id,
+ uint32_t indices_shm_offset) {
+ gles2::cmds::GetUniformIndices* c =
+ GetCmdSpace<gles2::cmds::GetUniformIndices>();
+ if (c) {
+ c->Init(program, names_bucket_id, indices_shm_id, indices_shm_offset);
+ }
+}
+
void GetUniformLocation(GLuint program,
uint32_t name_bucket_id,
uint32_t location_shm_id,
@@ -1660,6 +1708,14 @@
}
}
+void UniformBlockBinding(GLuint program, GLuint index, GLuint binding) {
+ gles2::cmds::UniformBlockBinding* c =
+ GetCmdSpace<gles2::cmds::UniformBlockBinding>();
+ if (c) {
+ c->Init(program, index, binding);
+ }
+}
+
void UniformMatrix2fvImmediate(GLint location,
GLsizei count,
const GLfloat* value) {
@@ -2176,6 +2232,22 @@
}
}
+void GetTransformFeedbackVaryingsCHROMIUM(GLuint program, uint32_t bucket_id) {
+ gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM* c =
+ GetCmdSpace<gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM>();
+ if (c) {
+ c->Init(program, bucket_id);
+ }
+}
+
+void GetUniformsES3CHROMIUM(GLuint program, uint32_t bucket_id) {
+ gles2::cmds::GetUniformsES3CHROMIUM* c =
+ GetCmdSpace<gles2::cmds::GetUniformsES3CHROMIUM>();
+ if (c) {
+ c->Init(program, bucket_id);
+ }
+}
+
void GetTranslatedShaderSourceANGLE(GLuint shader, uint32_t bucket_id) {
gles2::cmds::GetTranslatedShaderSourceANGLE* c =
GetCmdSpace<gles2::cmds::GetTranslatedShaderSourceANGLE>();
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 30f9269..e853766 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -1066,6 +1066,52 @@
return loc;
}
+bool GLES2Implementation::GetUniformIndicesHelper(
+ GLuint program, GLsizei count, const char* const* names, GLuint* indices) {
+ typedef cmds::GetUniformIndices::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return false;
+ }
+ result->SetNumResults(0);
+ if (!PackStringsToBucket(count, names, NULL, "glGetUniformIndices")) {
+ return false;
+ }
+ helper_->GetUniformIndices(program, kResultBucketId,
+ GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ if (result->GetNumResults() != count) {
+ return false;
+ }
+ result->CopyResult(indices);
+ return true;
+}
+
+void GLES2Implementation::GetUniformIndices(
+ GLuint program, GLsizei count, const char* const* names, GLuint* indices) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetUniformIndices(" << program
+ << ", " << count << ", " << names << ", " << indices << ")");
+ TRACE_EVENT0("gpu", "GLES2::GetUniformIndices");
+ if (count < 0) {
+ SetGLError(GL_INVALID_VALUE, "glGetUniformIndices", "count < 0");
+ return;
+ }
+ if (count == 0) {
+ return;
+ }
+ bool success = share_group_->program_info_manager()->GetUniformIndices(
+ this, program, count, names, indices);
+ if (success) {
+ GPU_CLIENT_LOG_CODE_BLOCK({
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ GPU_CLIENT_LOG(" " << ii << ": " << indices[ii]);
+ }
+ });
+ }
+ CheckGLError();
+}
+
bool GLES2Implementation::GetProgramivHelper(
GLuint program, GLenum pname, GLint* params) {
bool got_value = share_group_->program_info_manager()->GetProgramiv(
@@ -2363,7 +2409,7 @@
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockName("
<< program << ", " << index << ", " << bufsize << ", "
<< static_cast<const void*>(length) << ", "
- << static_cast<const void*>(name) << ", ");
+ << static_cast<const void*>(name) << ")");
if (bufsize < 0) {
SetGLError(GL_INVALID_VALUE, "glGetActiveUniformBlockName", "bufsize < 0");
return;
@@ -2380,6 +2426,114 @@
CheckGLError();
}
+bool GLES2Implementation::GetActiveUniformBlockivHelper(
+ GLuint program, GLuint index, GLenum pname, GLint* params) {
+ typedef cmds::GetActiveUniformBlockiv::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return false;
+ }
+ result->SetNumResults(0);
+ helper_->GetActiveUniformBlockiv(
+ program, index, pname, GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ if (result->GetNumResults() > 0) {
+ if (params) {
+ result->CopyResult(params);
+ }
+ GPU_CLIENT_LOG_CODE_BLOCK({
+ for (int32_t i = 0; i < result->GetNumResults(); ++i) {
+ GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]);
+ }
+ });
+ return true;
+ }
+ return false;
+}
+
+void GLES2Implementation::GetActiveUniformBlockiv(
+ GLuint program, GLuint index, GLenum pname, GLint* params) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformBlockiv("
+ << program << ", " << index << ", "
+ << GLES2Util::GetStringUniformBlockParameter(pname) << ", "
+ << static_cast<const void*>(params) << ")");
+ TRACE_EVENT0("gpu", "GLES2::GetActiveUniformBlockiv");
+ bool success =
+ share_group_->program_info_manager()->GetActiveUniformBlockiv(
+ this, program, index, pname, params);
+ if (success) {
+ if (params) {
+ // TODO(zmo): For GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, there will
+ // be more than one value returned in params.
+ GPU_CLIENT_LOG(" params: " << params[0]);
+ }
+ }
+ CheckGLError();
+}
+
+bool GLES2Implementation::GetActiveUniformsivHelper(
+ GLuint program, GLsizei count, const GLuint* indices,
+ GLenum pname, GLint* params) {
+ typedef cmds::GetActiveUniformsiv::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return false;
+ }
+ result->SetNumResults(0);
+ base::CheckedNumeric<size_t> bytes = static_cast<size_t>(count);
+ bytes *= sizeof(GLuint);
+ if (!bytes.IsValid()) {
+ SetGLError(GL_INVALID_VALUE, "glGetActiveUniformsiv", "count overflow");
+ return false;
+ }
+ SetBucketContents(kResultBucketId, indices, bytes.ValueOrDefault(0));
+ helper_->GetActiveUniformsiv(
+ program, kResultBucketId, pname, GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ bool success = result->GetNumResults() == count;
+ if (success) {
+ if (params) {
+ result->CopyResult(params);
+ }
+ GPU_CLIENT_LOG_CODE_BLOCK({
+ for (int32_t i = 0; i < result->GetNumResults(); ++i) {
+ GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]);
+ }
+ });
+ }
+ helper_->SetBucketSize(kResultBucketId, 0);
+ return success;
+}
+
+void GLES2Implementation::GetActiveUniformsiv(
+ GLuint program, GLsizei count, const GLuint* indices,
+ GLenum pname, GLint* params) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetActiveUniformsiv("
+ << program << ", " << count << ", "
+ << static_cast<const void*>(indices) << ", "
+ << GLES2Util::GetStringUniformParameter(pname) << ", "
+ << static_cast<const void*>(params) << ")");
+ TRACE_EVENT0("gpu", "GLES2::GetActiveUniformsiv");
+ if (count < 0) {
+ SetGLError(GL_INVALID_VALUE, "glGetActiveUniformsiv", "count < 0");
+ return;
+ }
+ bool success = share_group_->program_info_manager()->GetActiveUniformsiv(
+ this, program, count, indices, pname, params);
+ if (success) {
+ if (params) {
+ GPU_CLIENT_LOG_CODE_BLOCK({
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ GPU_CLIENT_LOG(" " << ii << ": " << params[ii]);
+ }
+ });
+ }
+ }
+ CheckGLError();
+}
+
void GLES2Implementation::GetAttachedShaders(
GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
@@ -2522,6 +2676,84 @@
return result;
}
+bool GLES2Implementation::GetTransformFeedbackVaryingHelper(
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+ GLenum* type, char* name) {
+ // Clear the bucket so if the command fails nothing will be in it.
+ helper_->SetBucketSize(kResultBucketId, 0);
+ typedef cmds::GetTransformFeedbackVarying::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return false;
+ }
+ // Set as failed so if the command fails we'll recover.
+ result->success = false;
+ helper_->GetTransformFeedbackVarying(
+ program, index, kResultBucketId, GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ if (result->success) {
+ if (size) {
+ *size = result->size;
+ }
+ if (type) {
+ *type = result->type;
+ }
+ if (length || name) {
+ std::vector<int8> str;
+ GetBucketContents(kResultBucketId, &str);
+ GLsizei max_size = std::min(bufsize, static_cast<GLsizei>(str.size()));
+ if (max_size > 0) {
+ --max_size;
+ }
+ if (length) {
+ *length = max_size;
+ }
+ if (name) {
+ if (max_size > 0) {
+ memcpy(name, &str[0], max_size);
+ name[max_size] = '\0';
+ } else if (bufsize > 0) {
+ name[0] = '\0';
+ }
+ }
+ }
+ }
+ return result->success != 0;
+}
+
+void GLES2Implementation::GetTransformFeedbackVarying(
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+ GLenum* type, char* name) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetTransformFeedbackVarying("
+ << program << ", " << index << ", " << bufsize << ", "
+ << static_cast<const void*>(length) << ", "
+ << static_cast<const void*>(size) << ", "
+ << static_cast<const void*>(type) << ", "
+ << static_cast<const void*>(name) << ", ");
+ if (bufsize < 0) {
+ SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVarying",
+ "bufsize < 0");
+ return;
+ }
+ TRACE_EVENT0("gpu", "GLES2::GetTransformFeedbackVarying");
+ bool success =
+ share_group_->program_info_manager()->GetTransformFeedbackVarying(
+ this, program, index, bufsize, length, size, type, name);
+ if (success) {
+ if (size) {
+ GPU_CLIENT_LOG(" size: " << *size);
+ }
+ if (type) {
+ GPU_CLIENT_LOG(" type: " << GLES2Util::GetStringEnum(*type));
+ }
+ if (name) {
+ GPU_CLIENT_LOG(" name: " << name);
+ }
+ }
+ CheckGLError();
+}
+
void GLES2Implementation::GetUniformfv(
GLuint program, GLint location, GLfloat* params) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
@@ -3628,11 +3860,11 @@
GPU_CLIENT_SINGLE_THREAD_CHECK();
if (bufsize < 0) {
SetGLError(
- GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "bufsize less than 0.");
+ GL_INVALID_VALUE, "glGetUniformBlocksCHROMIUM", "bufsize less than 0.");
return;
}
if (size == NULL) {
- SetGLError(GL_INVALID_VALUE, "glUniformBlocksCHROMIUM", "size is null.");
+ SetGLError(GL_INVALID_VALUE, "glGetUniformBlocksCHROMIUM", "size is null.");
return;
}
// Make sure they've set size to 0 else the value will be undefined on
@@ -3648,8 +3880,91 @@
return;
}
if (static_cast<size_t>(bufsize) < result.size()) {
+ SetGLError(GL_INVALID_OPERATION, "glGetUniformBlocksCHROMIUM",
+ "bufsize is too small for result.");
+ return;
+ }
+ memcpy(info, &result[0], result.size());
+}
+
+void GLES2Implementation::GetUniformsES3CHROMIUMHelper(
+ GLuint program, std::vector<int8>* result) {
+ DCHECK(result);
+ // Clear the bucket so if the command fails nothing will be in it.
+ helper_->SetBucketSize(kResultBucketId, 0);
+ helper_->GetUniformsES3CHROMIUM(program, kResultBucketId);
+ GetBucketContents(kResultBucketId, result);
+}
+
+void GLES2Implementation::GetUniformsES3CHROMIUM(
+ GLuint program, GLsizei bufsize, GLsizei* size, void* info) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ if (bufsize < 0) {
+ SetGLError(
+ GL_INVALID_VALUE, "glGetUniformsES3CHROMIUM", "bufsize less than 0.");
+ return;
+ }
+ if (size == NULL) {
+ SetGLError(GL_INVALID_VALUE, "glGetUniformsES3CHROMIUM", "size is null.");
+ return;
+ }
+ // Make sure they've set size to 0 else the value will be undefined on
+ // lost context.
+ DCHECK_EQ(0, *size);
+ std::vector<int8> result;
+ GetUniformsES3CHROMIUMHelper(program, &result);
+ if (result.empty()) {
+ return;
+ }
+ *size = result.size();
+ if (!info) {
+ return;
+ }
+ if (static_cast<size_t>(bufsize) < result.size()) {
SetGLError(GL_INVALID_OPERATION,
- "glUniformBlocksCHROMIUM", "bufsize is too small for result.");
+ "glGetUniformsES3CHROMIUM", "bufsize is too small for result.");
+ return;
+ }
+ memcpy(info, &result[0], result.size());
+}
+
+void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUMHelper(
+ GLuint program, std::vector<int8>* result) {
+ DCHECK(result);
+ // Clear the bucket so if the command fails nothing will be in it.
+ helper_->SetBucketSize(kResultBucketId, 0);
+ helper_->GetTransformFeedbackVaryingsCHROMIUM(program, kResultBucketId);
+ GetBucketContents(kResultBucketId, result);
+}
+
+void GLES2Implementation::GetTransformFeedbackVaryingsCHROMIUM(
+ GLuint program, GLsizei bufsize, GLsizei* size, void* info) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ if (bufsize < 0) {
+ SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVaryingsCHROMIUM",
+ "bufsize less than 0.");
+ return;
+ }
+ if (size == NULL) {
+ SetGLError(GL_INVALID_VALUE, "glGetTransformFeedbackVaryingsCHROMIUM",
+ "size is null.");
+ return;
+ }
+ // Make sure they've set size to 0 else the value will be undefined on
+ // lost context.
+ DCHECK_EQ(0, *size);
+ std::vector<int8> result;
+ GetTransformFeedbackVaryingsCHROMIUMHelper(program, &result);
+ if (result.empty()) {
+ return;
+ }
+ *size = result.size();
+ if (!info) {
+ return;
+ }
+ if (static_cast<size_t>(bufsize) < result.size()) {
+ SetGLError(GL_INVALID_OPERATION, "glGetTransformFeedbackVaryingsCHROMIUM",
+ "bufsize is too small for result.");
return;
}
memcpy(info, &result[0], result.size());
@@ -4528,6 +4843,94 @@
return false;
}
+bool GLES2Implementation::PackStringsToBucket(GLsizei count,
+ const char* const* str,
+ const GLint* length,
+ const char* func_name) {
+ DCHECK_LE(0, count);
+ // Compute the total size.
+ base::CheckedNumeric<size_t> total_size = count;
+ total_size += 1;
+ total_size *= sizeof(GLint);
+ if (!total_size.IsValid()) {
+ SetGLError(GL_INVALID_VALUE, func_name, "overflow");
+ return false;
+ }
+ size_t header_size = total_size.ValueOrDefault(0);
+ std::vector<GLint> header(count + 1);
+ header[0] = static_cast<GLint>(count);
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ GLint len = 0;
+ if (str[ii]) {
+ len = (length && length[ii] >= 0)
+ ? length[ii]
+ : base::checked_cast<GLint>(strlen(str[ii]));
+ }
+ total_size += len;
+ total_size += 1; // NULL at the end of each char array.
+ if (!total_size.IsValid()) {
+ SetGLError(GL_INVALID_VALUE, func_name, "overflow");
+ return false;
+ }
+ header[ii + 1] = len;
+ }
+ // Pack data into a bucket on the service.
+ helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0));
+ size_t offset = 0;
+ for (GLsizei ii = 0; ii <= count; ++ii) {
+ const char* src =
+ (ii == 0) ? reinterpret_cast<const char*>(&header[0]) : str[ii - 1];
+ base::CheckedNumeric<size_t> checked_size =
+ (ii == 0) ? header_size : static_cast<size_t>(header[ii]);
+ if (ii > 0) {
+ checked_size += 1; // NULL in the end.
+ }
+ if (!checked_size.IsValid()) {
+ SetGLError(GL_INVALID_VALUE, func_name, "overflow");
+ return false;
+ }
+ size_t size = checked_size.ValueOrDefault(0);
+ while (size) {
+ ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
+ if (!buffer.valid() || buffer.size() == 0) {
+ SetGLError(GL_OUT_OF_MEMORY, func_name, "too large");
+ return false;
+ }
+ size_t copy_size = buffer.size();
+ if (ii > 0 && buffer.size() == size)
+ --copy_size;
+ if (copy_size)
+ memcpy(buffer.address(), src, copy_size);
+ if (copy_size < buffer.size()) {
+ // Append NULL in the end.
+ DCHECK(copy_size + 1 == buffer.size());
+ char* str = reinterpret_cast<char*>(buffer.address());
+ str[copy_size] = 0;
+ }
+ helper_->SetBucketData(kResultBucketId, offset, buffer.size(),
+ buffer.shm_id(), buffer.offset());
+ offset += buffer.size();
+ src += buffer.size();
+ size -= buffer.size();
+ }
+ }
+ DCHECK_EQ(total_size.ValueOrDefault(0), offset);
+ return true;
+}
+
+void GLES2Implementation::UniformBlockBinding(GLuint program,
+ GLuint index,
+ GLuint binding) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUniformBlockBinding(" << program
+ << ", " << index << ", " << binding << ")");
+ share_group_->program_info_manager()->UniformBlockBinding(
+ this, program, index, binding);
+ helper_->UniformBlockBinding(program, index, binding);
+ CheckGLError();
+}
+
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 193fbb8..4e8ae5f 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -222,10 +222,24 @@
GLint* size, GLenum* type, char* name);
void GetUniformBlocksCHROMIUMHelper(
GLuint program, std::vector<int8>* result);
+ void GetUniformsES3CHROMIUMHelper(
+ GLuint program, std::vector<int8>* result);
GLuint GetUniformBlockIndexHelper(GLuint program, const char* name);
bool GetActiveUniformBlockNameHelper(
GLuint program, GLuint index, GLsizei bufsize,
GLsizei* length, char* name);
+ bool GetActiveUniformBlockivHelper(
+ GLuint program, GLuint index, GLenum pname, GLint* params);
+ void GetTransformFeedbackVaryingsCHROMIUMHelper(
+ GLuint program, std::vector<int8>* result);
+ bool GetTransformFeedbackVaryingHelper(
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name);
+ bool GetUniformIndicesHelper(
+ GLuint program, GLsizei count, const char* const* names, GLuint* indices);
+ bool GetActiveUniformsivHelper(
+ GLuint program, GLsizei count, const GLuint* indices,
+ GLenum pname, GLint* params);
void FreeUnusedSharedMemory();
void FreeEverything();
@@ -625,6 +639,13 @@
GLuint buffer_id,
const char* function_name, GLuint offset, GLsizei size);
+ // Pack 2D arrays of char into a bucket.
+ // Helper function for ShaderSource(), TransformFeedbackVaryings(), etc.
+ bool PackStringsToBucket(GLsizei count,
+ const char* const* str,
+ const GLint* length,
+ const char* func_name);
+
const std::string& GetLogPrefix() const;
#if defined(GL_CLIENT_FAIL_GL_ERRORS)
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 3d6009a..9d2d8eb 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -255,12 +255,23 @@
GLenum* type,
char* name) override;
+void GetActiveUniformBlockiv(GLuint program,
+ GLuint index,
+ GLenum pname,
+ GLint* params) override;
+
void GetActiveUniformBlockName(GLuint program,
GLuint index,
GLsizei bufsize,
GLsizei* length,
char* name) override;
+void GetActiveUniformsiv(GLuint program,
+ GLsizei count,
+ const GLuint* indices,
+ GLenum pname,
+ GLint* params) override;
+
void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -333,12 +344,25 @@
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+void GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLsizei* size,
+ GLenum* type,
+ char* name) override;
+
GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
void GetUniformiv(GLuint program, GLint location, GLint* params) override;
+void GetUniformIndices(GLuint program,
+ GLsizei count,
+ const char* const* names,
+ GLuint* indices) override;
+
GLint GetUniformLocation(GLuint program, const char* name) override;
void GetVertexAttribPointerv(GLuint index,
@@ -580,6 +604,8 @@
void Uniform4uiv(GLint location, GLsizei count, const GLuint* v) override;
+void UniformBlockBinding(GLuint program, GLuint index, GLuint binding) override;
+
void UniformMatrix2fv(GLint location,
GLsizei count,
GLboolean transpose,
@@ -794,6 +820,16 @@
GLsizei* size,
void* info) override;
+void GetTransformFeedbackVaryingsCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
+
+void GetUniformsES3CHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
+
GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
GLuint CreateImageCHROMIUM(ClientBuffer buffer,
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index d84c123..625c747 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -1747,73 +1747,10 @@
SetGLError(GL_INVALID_VALUE, "glShaderSource", "count < 0");
return;
}
- // Compute the total size.
- base::CheckedNumeric<size_t> total_size = count;
- total_size += 1;
- total_size *= sizeof(GLint);
- if (!total_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow");
+
+ if (!PackStringsToBucket(count, str, length, "glShaderSource")) {
return;
}
- size_t header_size = total_size.ValueOrDefault(0);
- std::vector<GLint> header(count + 1);
- header[0] = static_cast<GLint>(count);
- for (GLsizei ii = 0; ii < count; ++ii) {
- GLint len = 0;
- if (str[ii]) {
- len = (length && length[ii] >= 0)
- ? length[ii]
- : base::checked_cast<GLint>(strlen(str[ii]));
- }
- total_size += len;
- total_size += 1; // NULL at the end of each char array.
- if (!total_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow");
- return;
- }
- header[ii + 1] = len;
- }
- // Pack data into a bucket on the service.
- helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0));
- size_t offset = 0;
- for (GLsizei ii = 0; ii <= count; ++ii) {
- const char* src =
- (ii == 0) ? reinterpret_cast<const char*>(&header[0]) : str[ii - 1];
- base::CheckedNumeric<size_t> checked_size =
- (ii == 0) ? header_size : static_cast<size_t>(header[ii]);
- if (ii > 0) {
- checked_size += 1; // NULL in the end.
- }
- if (!checked_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "glShaderSource", "overflow");
- return;
- }
- size_t size = checked_size.ValueOrDefault(0);
- while (size) {
- ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
- if (!buffer.valid() || buffer.size() == 0) {
- SetGLError(GL_OUT_OF_MEMORY, "glShaderSource", "too large");
- return;
- }
- size_t copy_size = buffer.size();
- if (ii > 0 && buffer.size() == size)
- --copy_size;
- if (copy_size)
- memcpy(buffer.address(), src, copy_size);
- if (copy_size < buffer.size()) {
- // Append NULL in the end.
- DCHECK(copy_size + 1 == buffer.size());
- char* str = reinterpret_cast<char*>(buffer.address());
- str[copy_size] = 0;
- }
- helper_->SetBucketData(kResultBucketId, offset, buffer.size(),
- buffer.shm_id(), buffer.offset());
- offset += buffer.size();
- src += buffer.size();
- size -= buffer.size();
- }
- }
- DCHECK_EQ(total_size.ValueOrDefault(0), offset);
helper_->ShaderSourceBucket(shader, kResultBucketId);
helper_->SetBucketSize(kResultBucketId, 0);
CheckGLError();
@@ -1990,72 +1927,11 @@
SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "count < 0");
return;
}
- // Compute the total size.
- base::CheckedNumeric<size_t> total_size = count;
- total_size += 1;
- total_size *= sizeof(GLint);
- if (!total_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "overflow");
+
+ if (!PackStringsToBucket(count, varyings, NULL,
+ "glTransformFeedbackVaryings")) {
return;
}
- size_t header_size = total_size.ValueOrDefault(0);
- std::vector<GLint> header(count + 1);
- header[0] = static_cast<GLint>(count);
- for (GLsizei ii = 0; ii < count; ++ii) {
- GLint len = 0;
- if (varyings[ii]) {
- len = static_cast<GLint>(strlen(varyings[ii]));
- }
- total_size += len;
- total_size += 1; // NULL at the end of each char array.
- if (!total_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "overflow");
- return;
- }
- header[ii + 1] = len;
- }
- // Pack data into a bucket on the service.
- helper_->SetBucketSize(kResultBucketId, total_size.ValueOrDefault(0));
- size_t offset = 0;
- for (GLsizei ii = 0; ii <= count; ++ii) {
- const char* src = (ii == 0) ? reinterpret_cast<const char*>(&header[0])
- : varyings[ii - 1];
- base::CheckedNumeric<size_t> checked_size =
- (ii == 0) ? header_size : static_cast<size_t>(header[ii]);
- if (ii > 0) {
- checked_size += 1; // NULL in the end.
- }
- if (!checked_size.IsValid()) {
- SetGLError(GL_INVALID_VALUE, "glTransformFeedbackVaryings", "overflow");
- return;
- }
- size_t size = checked_size.ValueOrDefault(0);
- while (size) {
- ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
- if (!buffer.valid() || buffer.size() == 0) {
- SetGLError(GL_OUT_OF_MEMORY, "glTransformFeedbackVaryings",
- "too large");
- return;
- }
- size_t copy_size = buffer.size();
- if (ii > 0 && buffer.size() == size)
- --copy_size;
- if (copy_size)
- memcpy(buffer.address(), src, copy_size);
- if (copy_size < buffer.size()) {
- // Append NULL in the end.
- DCHECK(copy_size + 1 == buffer.size());
- char* str = reinterpret_cast<char*>(buffer.address());
- str[copy_size] = 0;
- }
- helper_->SetBucketData(kResultBucketId, offset, buffer.size(),
- buffer.shm_id(), buffer.offset());
- offset += buffer.size();
- src += buffer.size();
- size -= buffer.size();
- }
- }
- DCHECK_EQ(total_size.ValueOrDefault(0), offset);
helper_->TransformFeedbackVaryingsBucket(program, kResultBucketId,
buffermode);
helper_->SetBucketSize(kResultBucketId, 0);
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 6dbcdcc..8b02ad9 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -751,7 +751,9 @@
}
// TODO(zmo): Implement unit test for GetActiveAttrib
// TODO(zmo): Implement unit test for GetActiveUniform
+// TODO(zmo): Implement unit test for GetActiveUniformBlockiv
// TODO(zmo): Implement unit test for GetActiveUniformBlockName
+// TODO(zmo): Implement unit test for GetActiveUniformsiv
// TODO(zmo): Implement unit test for GetAttachedShaders
// TODO(zmo): Implement unit test for GetAttribLocation
@@ -984,9 +986,11 @@
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
EXPECT_EQ(static_cast<Result::Type>(1), result);
}
+// TODO(zmo): Implement unit test for GetTransformFeedbackVarying
// TODO(zmo): Implement unit test for GetUniformBlockIndex
// TODO(zmo): Implement unit test for GetUniformfv
// TODO(zmo): Implement unit test for GetUniformiv
+// TODO(zmo): Implement unit test for GetUniformIndices
// TODO(zmo): Implement unit test for GetUniformLocation
TEST_F(GLES2ImplementationTest, GetVertexAttribfv) {
@@ -2032,6 +2036,17 @@
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
+TEST_F(GLES2ImplementationTest, UniformBlockBinding) {
+ struct Cmds {
+ cmds::UniformBlockBinding cmd;
+ };
+ Cmds expected;
+ expected.cmd.Init(1, 2, 3);
+
+ gl_->UniformBlockBinding(1, 2, 3);
+ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+}
+
TEST_F(GLES2ImplementationTest, UniformMatrix2fv) {
GLfloat data[2][4] = {{0}};
struct Cmds {
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h
index 352ff78..990e701 100644
--- a/gpu/command_buffer/client/gles2_interface_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -186,11 +186,20 @@
GLint* size,
GLenum* type,
char* name) = 0;
+virtual void GetActiveUniformBlockiv(GLuint program,
+ GLuint index,
+ GLenum pname,
+ GLint* params) = 0;
virtual void GetActiveUniformBlockName(GLuint program,
GLuint index,
GLsizei bufsize,
GLsizei* length,
char* name) = 0;
+virtual void GetActiveUniformsiv(GLuint program,
+ GLsizei count,
+ const GLuint* indices,
+ GLenum pname,
+ GLint* params) = 0;
virtual void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -245,9 +254,20 @@
GLenum pname,
GLfloat* params) = 0;
virtual void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) = 0;
+virtual void GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLsizei* size,
+ GLenum* type,
+ char* name) = 0;
virtual GLuint GetUniformBlockIndex(GLuint program, const char* name) = 0;
virtual void GetUniformfv(GLuint program, GLint location, GLfloat* params) = 0;
virtual void GetUniformiv(GLuint program, GLint location, GLint* params) = 0;
+virtual void GetUniformIndices(GLuint program,
+ GLsizei count,
+ const char* const* names,
+ GLuint* indices) = 0;
virtual GLint GetUniformLocation(GLuint program, const char* name) = 0;
virtual void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) = 0;
virtual void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) = 0;
@@ -417,6 +437,9 @@
GLuint z,
GLuint w) = 0;
virtual void Uniform4uiv(GLint location, GLsizei count, const GLuint* v) = 0;
+virtual void UniformBlockBinding(GLuint program,
+ GLuint index,
+ GLuint binding) = 0;
virtual void UniformMatrix2fv(GLint location,
GLsizei count,
GLboolean transpose,
@@ -575,6 +598,14 @@
GLsizei bufsize,
GLsizei* size,
void* info) = 0;
+virtual void GetTransformFeedbackVaryingsCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) = 0;
+virtual void GetUniformsES3CHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) = 0;
virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) = 0;
virtual GLuint CreateImageCHROMIUM(ClientBuffer buffer,
GLsizei width,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
index 0ca5199..f020e14 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -185,11 +185,20 @@
GLint* size,
GLenum* type,
char* name) override;
+void GetActiveUniformBlockiv(GLuint program,
+ GLuint index,
+ GLenum pname,
+ GLint* params) override;
void GetActiveUniformBlockName(GLuint program,
GLuint index,
GLsizei bufsize,
GLsizei* length,
char* name) override;
+void GetActiveUniformsiv(GLuint program,
+ GLsizei count,
+ const GLuint* indices,
+ GLenum pname,
+ GLint* params) override;
void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -240,9 +249,20 @@
const GLubyte* GetString(GLenum name) override;
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) override;
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+void GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLsizei* size,
+ GLenum* type,
+ char* name) override;
GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
void GetUniformiv(GLuint program, GLint location, GLint* params) override;
+void GetUniformIndices(GLuint program,
+ GLsizei count,
+ const char* const* names,
+ GLuint* indices) override;
GLint GetUniformLocation(GLuint program, const char* name) override;
void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) override;
void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) override;
@@ -410,6 +430,7 @@
GLuint z,
GLuint w) override;
void Uniform4uiv(GLint location, GLsizei count, const GLuint* v) override;
+void UniformBlockBinding(GLuint program, GLuint index, GLuint binding) override;
void UniformMatrix2fv(GLint location,
GLsizei count,
GLboolean transpose,
@@ -562,6 +583,14 @@
GLsizei bufsize,
GLsizei* size,
void* info) override;
+void GetTransformFeedbackVaryingsCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
+void GetUniformsES3CHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
GLuint CreateImageCHROMIUM(ClientBuffer buffer,
GLsizei width,
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 2a6f88e..15f2912 100644
--- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -286,12 +286,23 @@
GLenum* /* type */,
char* /* name */) {
}
+void GLES2InterfaceStub::GetActiveUniformBlockiv(GLuint /* program */,
+ GLuint /* index */,
+ GLenum /* pname */,
+ GLint* /* params */) {
+}
void GLES2InterfaceStub::GetActiveUniformBlockName(GLuint /* program */,
GLuint /* index */,
GLsizei /* bufsize */,
GLsizei* /* length */,
char* /* name */) {
}
+void GLES2InterfaceStub::GetActiveUniformsiv(GLuint /* program */,
+ GLsizei /* count */,
+ const GLuint* /* indices */,
+ GLenum /* pname */,
+ GLint* /* params */) {
+}
void GLES2InterfaceStub::GetAttachedShaders(GLuint /* program */,
GLsizei /* maxcount */,
GLsizei* /* count */,
@@ -382,6 +393,14 @@
GLenum /* pname */,
GLint* /* params */) {
}
+void GLES2InterfaceStub::GetTransformFeedbackVarying(GLuint /* program */,
+ GLuint /* index */,
+ GLsizei /* bufsize */,
+ GLsizei* /* length */,
+ GLsizei* /* size */,
+ GLenum* /* type */,
+ char* /* name */) {
+}
GLuint GLES2InterfaceStub::GetUniformBlockIndex(GLuint /* program */,
const char* /* name */) {
return 0;
@@ -394,6 +413,11 @@
GLint /* location */,
GLint* /* params */) {
}
+void GLES2InterfaceStub::GetUniformIndices(GLuint /* program */,
+ GLsizei /* count */,
+ const char* const* /* names */,
+ GLuint* /* indices */) {
+}
GLint GLES2InterfaceStub::GetUniformLocation(GLuint /* program */,
const char* /* name */) {
return 0;
@@ -722,6 +746,10 @@
GLsizei /* count */,
const GLuint* /* v */) {
}
+void GLES2InterfaceStub::UniformBlockBinding(GLuint /* program */,
+ GLuint /* index */,
+ GLuint /* binding */) {
+}
void GLES2InterfaceStub::UniformMatrix2fv(GLint /* location */,
GLsizei /* count */,
GLboolean /* transpose */,
@@ -978,6 +1006,17 @@
GLsizei* /* size */,
void* /* info */) {
}
+void GLES2InterfaceStub::GetTransformFeedbackVaryingsCHROMIUM(
+ GLuint /* program */,
+ GLsizei /* bufsize */,
+ GLsizei* /* size */,
+ void* /* info */) {
+}
+void GLES2InterfaceStub::GetUniformsES3CHROMIUM(GLuint /* program */,
+ GLsizei /* bufsize */,
+ GLsizei* /* size */,
+ void* /* info */) {
+}
GLuint GLES2InterfaceStub::CreateStreamTextureCHROMIUM(GLuint /* texture */) {
return 0;
}
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
index da97a87..66deca4 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -185,11 +185,20 @@
GLint* size,
GLenum* type,
char* name) override;
+void GetActiveUniformBlockiv(GLuint program,
+ GLuint index,
+ GLenum pname,
+ GLint* params) override;
void GetActiveUniformBlockName(GLuint program,
GLuint index,
GLsizei bufsize,
GLsizei* length,
char* name) override;
+void GetActiveUniformsiv(GLuint program,
+ GLsizei count,
+ const GLuint* indices,
+ GLenum pname,
+ GLint* params) override;
void GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -240,9 +249,20 @@
const GLubyte* GetString(GLenum name) override;
void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) override;
void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override;
+void GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLsizei* size,
+ GLenum* type,
+ char* name) override;
GLuint GetUniformBlockIndex(GLuint program, const char* name) override;
void GetUniformfv(GLuint program, GLint location, GLfloat* params) override;
void GetUniformiv(GLuint program, GLint location, GLint* params) override;
+void GetUniformIndices(GLuint program,
+ GLsizei count,
+ const char* const* names,
+ GLuint* indices) override;
GLint GetUniformLocation(GLuint program, const char* name) override;
void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) override;
void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) override;
@@ -410,6 +430,7 @@
GLuint z,
GLuint w) override;
void Uniform4uiv(GLint location, GLsizei count, const GLuint* v) override;
+void UniformBlockBinding(GLuint program, GLuint index, GLuint binding) override;
void UniformMatrix2fv(GLint location,
GLsizei count,
GLboolean transpose,
@@ -562,6 +583,14 @@
GLsizei bufsize,
GLsizei* size,
void* info) override;
+void GetTransformFeedbackVaryingsCHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
+void GetUniformsES3CHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) override;
GLuint CreateStreamTextureCHROMIUM(GLuint texture) override;
GLuint CreateImageCHROMIUM(ClientBuffer buffer,
GLsizei width,
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 df03be5..79fd529 100644
--- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -500,6 +500,14 @@
gl_->GetActiveUniform(program, index, bufsize, length, size, type, name);
}
+void GLES2TraceImplementation::GetActiveUniformBlockiv(GLuint program,
+ GLuint index,
+ GLenum pname,
+ GLint* params) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetActiveUniformBlockiv");
+ gl_->GetActiveUniformBlockiv(program, index, pname, params);
+}
+
void GLES2TraceImplementation::GetActiveUniformBlockName(GLuint program,
GLuint index,
GLsizei bufsize,
@@ -509,6 +517,15 @@
gl_->GetActiveUniformBlockName(program, index, bufsize, length, name);
}
+void GLES2TraceImplementation::GetActiveUniformsiv(GLuint program,
+ GLsizei count,
+ const GLuint* indices,
+ GLenum pname,
+ GLint* params) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetActiveUniformsiv");
+ gl_->GetActiveUniformsiv(program, count, indices, pname, params);
+}
+
void GLES2TraceImplementation::GetAttachedShaders(GLuint program,
GLsizei maxcount,
GLsizei* count,
@@ -662,6 +679,19 @@
gl_->GetTexParameteriv(target, pname, params);
}
+void GLES2TraceImplementation::GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLsizei* size,
+ GLenum* type,
+ char* name) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+ "GLES2Trace::GetTransformFeedbackVarying");
+ gl_->GetTransformFeedbackVarying(program, index, bufsize, length, size, type,
+ name);
+}
+
GLuint GLES2TraceImplementation::GetUniformBlockIndex(GLuint program,
const char* name) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformBlockIndex");
@@ -682,6 +712,14 @@
gl_->GetUniformiv(program, location, params);
}
+void GLES2TraceImplementation::GetUniformIndices(GLuint program,
+ GLsizei count,
+ const char* const* names,
+ GLuint* indices) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformIndices");
+ gl_->GetUniformIndices(program, count, names, indices);
+}
+
GLint GLES2TraceImplementation::GetUniformLocation(GLuint program,
const char* name) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformLocation");
@@ -1230,6 +1268,13 @@
gl_->Uniform4uiv(location, count, v);
}
+void GLES2TraceImplementation::UniformBlockBinding(GLuint program,
+ GLuint index,
+ GLuint binding) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UniformBlockBinding");
+ gl_->UniformBlockBinding(program, index, binding);
+}
+
void GLES2TraceImplementation::UniformMatrix2fv(GLint location,
GLsizei count,
GLboolean transpose,
@@ -1675,6 +1720,24 @@
gl_->GetUniformBlocksCHROMIUM(program, bufsize, size, info);
}
+void GLES2TraceImplementation::GetTransformFeedbackVaryingsCHROMIUM(
+ GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) {
+ TRACE_EVENT_BINARY_EFFICIENT0(
+ "gpu", "GLES2Trace::GetTransformFeedbackVaryingsCHROMIUM");
+ gl_->GetTransformFeedbackVaryingsCHROMIUM(program, bufsize, size, info);
+}
+
+void GLES2TraceImplementation::GetUniformsES3CHROMIUM(GLuint program,
+ GLsizei bufsize,
+ GLsizei* size,
+ void* info) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetUniformsES3CHROMIUM");
+ gl_->GetUniformsES3CHROMIUM(program, bufsize, size, info);
+}
+
GLuint GLES2TraceImplementation::CreateStreamTextureCHROMIUM(GLuint texture) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu",
"GLES2Trace::CreateStreamTextureCHROMIUM");
diff --git a/gpu/command_buffer/client/gpu_control.h b/gpu/command_buffer/client/gpu_control.h
index a56bd51..2b303b3 100644
--- a/gpu/command_buffer/client/gpu_control.h
+++ b/gpu/command_buffer/client/gpu_control.h
@@ -17,6 +17,10 @@
extern "C" typedef struct _ClientBuffer* ClientBuffer;
+namespace base {
+class Lock;
+}
+
namespace gfx {
class GpuMemoryBuffer;
}
@@ -75,6 +79,12 @@
// returns a stream identifier.
virtual uint32_t CreateStreamTexture(uint32_t texture_id) = 0;
+ // Sets a lock this will be held on every callback from the GPU
+ // implementation. This lock must be set and must be held on every call into
+ // the GPU implementation if it is to be used from multiple threads. This
+ // may not be supported with all implementations.
+ virtual void SetLock(base::Lock*) = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(GpuControl);
};
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
index 04121aa..779d914 100644
--- a/gpu/command_buffer/client/program_info_manager.cc
+++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -44,6 +44,17 @@
ProgramInfoManager::Program::UniformInfo::~UniformInfo() {
}
+ProgramInfoManager::Program::UniformES3::UniformES3()
+ : block_index(-1),
+ offset(-1),
+ array_stride(-1),
+ matrix_stride(-1),
+ is_row_major(0) {
+}
+
+ProgramInfoManager::Program::UniformES3::~UniformES3() {
+}
+
ProgramInfoManager::Program::UniformBlock::UniformBlock()
: binding(0),
data_size(0),
@@ -54,13 +65,26 @@
ProgramInfoManager::Program::UniformBlock::~UniformBlock() {
}
+ProgramInfoManager::Program::TransformFeedbackVarying::
+TransformFeedbackVarying()
+ : size(0),
+ type(0) {
+}
+
+ProgramInfoManager::Program::TransformFeedbackVarying::
+~TransformFeedbackVarying() {
+}
+
ProgramInfoManager::Program::Program()
: cached_es2_(false),
max_attrib_name_length_(0),
max_uniform_name_length_(0),
link_status_(false),
cached_es3_uniform_blocks_(false),
- active_uniform_block_max_name_length_(0) {
+ active_uniform_block_max_name_length_(0),
+ cached_es3_transform_feedback_varyings_(false),
+ transform_feedback_varying_max_length_(0),
+ cached_es3_uniformsiv_(false) {
}
ProgramInfoManager::Program::~Program() {
@@ -124,6 +148,22 @@
return -1;
}
+GLuint ProgramInfoManager::Program::GetUniformIndex(
+ const std::string& name) const {
+ // TODO(zmo): Maybe build a hashed_map for faster lookup.
+ for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
+ const UniformInfo& info = uniform_infos_[ii];
+ // For an array, either "var" or "var[0]" is considered as a match.
+ // See "OpenGL ES 3.0.0, Section 2.11.3 Program Objects."
+ if (info.name == name ||
+ (info.is_array &&
+ info.name.compare(0, info.name.size() - 3, name) == 0)) {
+ return ii;
+ }
+ }
+ return GL_INVALID_INDEX;
+}
+
GLint ProgramInfoManager::Program::GetFragDataLocation(
const std::string& name) const {
base::hash_map<std::string, GLint>::const_iterator iter =
@@ -162,6 +202,12 @@
case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
*params = static_cast<GLint>(active_uniform_block_max_name_length_);
return true;
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ *params = static_cast<GLint>(transform_feedback_varyings_.size());
+ return true;
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ *params = static_cast<GLint>(transform_feedback_varying_max_length_);
+ return true;
default:
NOTREACHED();
break;
@@ -179,6 +225,98 @@
return GL_INVALID_INDEX;
}
+void ProgramInfoManager::Program::UniformBlockBinding(
+ GLuint index , GLuint binding) {
+ if (index < uniform_blocks_.size()) {
+ uniform_blocks_[index].binding = binding;
+ }
+}
+
+const ProgramInfoManager::Program::TransformFeedbackVarying*
+ProgramInfoManager::Program::GetTransformFeedbackVarying(GLuint index) const {
+ return (index < transform_feedback_varyings_.size()) ?
+ &transform_feedback_varyings_[index] : NULL;
+}
+
+bool ProgramInfoManager::Program::GetUniformsiv(
+ GLsizei count, const GLuint* indices, GLenum pname, GLint* params) {
+ if (count == 0) {
+ // At this point, pname has already been validated.
+ return true;
+ }
+ DCHECK(count > 0 && indices);
+ size_t num_uniforms = uniform_infos_.size();
+ if (num_uniforms == 0) {
+ num_uniforms = uniforms_es3_.size();
+ }
+ if (static_cast<size_t>(count) > num_uniforms) {
+ return false;
+ }
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ if (indices[ii] >= num_uniforms) {
+ return false;
+ }
+ }
+ if (!params) {
+ return true;
+ }
+ switch (pname) {
+ case GL_UNIFORM_SIZE:
+ DCHECK_EQ(num_uniforms, uniform_infos_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = static_cast<GLint>(uniform_infos_[indices[ii]].size);
+ }
+ return true;
+ case GL_UNIFORM_TYPE:
+ DCHECK_EQ(num_uniforms, uniform_infos_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = static_cast<GLint>(uniform_infos_[indices[ii]].type);
+ }
+ return true;
+ case GL_UNIFORM_NAME_LENGTH:
+ DCHECK_EQ(num_uniforms, uniform_infos_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = static_cast<GLint>(
+ uniform_infos_[indices[ii]].name.length() + 1);
+ }
+ return true;
+ case GL_UNIFORM_BLOCK_INDEX:
+ DCHECK_EQ(num_uniforms, uniforms_es3_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = uniforms_es3_[indices[ii]].block_index;
+ }
+ return true;
+ case GL_UNIFORM_OFFSET:
+ DCHECK_EQ(num_uniforms, uniforms_es3_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = uniforms_es3_[indices[ii]].offset;
+ }
+ return true;
+ case GL_UNIFORM_ARRAY_STRIDE:
+ DCHECK_EQ(num_uniforms, uniforms_es3_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = uniforms_es3_[indices[ii]].array_stride;
+ }
+ return true;
+ case GL_UNIFORM_MATRIX_STRIDE:
+ DCHECK_EQ(num_uniforms, uniforms_es3_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = uniforms_es3_[indices[ii]].matrix_stride;
+ }
+ return true;
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ DCHECK_EQ(num_uniforms, uniforms_es3_.size());
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = uniforms_es3_[indices[ii]].is_row_major;
+ }
+ return true;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return false;
+}
+
void ProgramInfoManager::Program::UpdateES2(const std::vector<int8>& result) {
if (cached_es2_) {
return;
@@ -306,12 +444,119 @@
cached_es3_uniform_blocks_ = true;
}
+void ProgramInfoManager::Program::UpdateES3Uniformsiv(
+ const std::vector<int8>& result) {
+ if (cached_es3_uniformsiv_) {
+ return;
+ }
+ if (result.empty()) {
+ // This should only happen on a lost context.
+ return;
+ }
+ uniforms_es3_.clear();
+
+ // |result| comes from GPU process. We consider it trusted data. Therefore,
+ // no need to check for overflows as the GPU side did the checks already.
+ uint32_t header_size = sizeof(UniformsES3Header);
+ DCHECK_GE(result.size(), header_size);
+ const UniformsES3Header* header = LocalGetAs<const UniformsES3Header*>(
+ result, 0, header_size);
+ DCHECK(header);
+ if (header->num_uniforms == 0) {
+ DCHECK_EQ(result.size(), header_size);
+ // TODO(zmo): Here we can't tell if no uniforms are defined, or
+ // the previous link failed.
+ return;
+ }
+ uniforms_es3_.resize(header->num_uniforms);
+
+ uint32_t entry_size = sizeof(UniformES3Info) * header->num_uniforms;
+ DCHECK_EQ(result.size(), header_size + entry_size);
+ const UniformES3Info* entries = LocalGetAs<const UniformES3Info*>(
+ result, header_size, entry_size);
+ DCHECK(entries);
+
+ for (uint32_t ii = 0; ii < header->num_uniforms; ++ii) {
+ uniforms_es3_[ii].block_index = entries[ii].block_index;
+ uniforms_es3_[ii].offset = entries[ii].offset;
+ uniforms_es3_[ii].array_stride = entries[ii].array_stride;
+ uniforms_es3_[ii].matrix_stride = entries[ii].matrix_stride;
+ uniforms_es3_[ii].is_row_major = entries[ii].is_row_major;
+ }
+ cached_es3_uniformsiv_ = true;
+}
+
+void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings(
+ const std::vector<int8>& result) {
+ if (cached_es3_transform_feedback_varyings_) {
+ return;
+ }
+ if (result.empty()) {
+ // This should only happen on a lost context.
+ return;
+ }
+ transform_feedback_varyings_.clear();
+ transform_feedback_varying_max_length_ = 0;
+
+ // |result| comes from GPU process. We consider it trusted data. Therefore,
+ // no need to check for overflows as the GPU side did the checks already.
+ uint32_t header_size = sizeof(TransformFeedbackVaryingsHeader);
+ DCHECK_GE(result.size(), header_size);
+ const TransformFeedbackVaryingsHeader* header =
+ LocalGetAs<const TransformFeedbackVaryingsHeader*>(
+ result, 0, header_size);
+ DCHECK(header);
+ if (header->num_transform_feedback_varyings == 0) {
+ DCHECK_EQ(result.size(), header_size);
+ // TODO(zmo): Here we can't tell if no TransformFeedback varyings are
+ // defined, or the previous link failed.
+ return;
+ }
+ transform_feedback_varyings_.resize(header->num_transform_feedback_varyings);
+
+ uint32_t entry_size = sizeof(TransformFeedbackVaryingInfo) *
+ header->num_transform_feedback_varyings;
+ DCHECK_GE(result.size(), header_size + entry_size);
+ uint32_t data_size = result.size() - header_size - entry_size;
+ DCHECK_LT(0u, data_size);
+ const TransformFeedbackVaryingInfo* entries =
+ LocalGetAs<const TransformFeedbackVaryingInfo*>(
+ result, header_size, entry_size);
+ DCHECK(entries);
+ const char* data = LocalGetAs<const char*>(
+ result, header_size + entry_size, data_size);
+ DCHECK(data);
+
+ uint32_t size = 0;
+ for (uint32_t ii = 0; ii < header->num_transform_feedback_varyings; ++ii) {
+ transform_feedback_varyings_[ii].size =
+ static_cast<GLsizei>(entries[ii].size);
+ transform_feedback_varyings_[ii].type =
+ static_cast<GLenum>(entries[ii].type);
+ DCHECK_LE(1u, entries[ii].name_length);
+ if (entries[ii].name_length > transform_feedback_varying_max_length_) {
+ transform_feedback_varying_max_length_ = entries[ii].name_length;
+ }
+ size += entries[ii].name_length;
+ DCHECK_GE(data_size, size);
+ transform_feedback_varyings_[ii].name =
+ std::string(data, entries[ii].name_length - 1);
+ data += entries[ii].name_length;
+ }
+ DCHECK_EQ(data_size, size);
+ cached_es3_transform_feedback_varyings_ = true;
+}
+
bool ProgramInfoManager::Program::IsCached(ProgramInfoType type) const {
switch (type) {
case kES2:
return cached_es2_;
case kES3UniformBlocks:
return cached_es3_uniform_blocks_;
+ case kES3TransformFeedbackVaryings:
+ return cached_es3_transform_feedback_varyings_;
+ case kES3Uniformsiv:
+ return cached_es3_uniformsiv_;
case kNone:
return true;
default:
@@ -354,12 +599,26 @@
base::AutoUnlock unlock(lock_);
// lock_ can't be held across IPC call or else it may deadlock in
// pepper. http://crbug.com/418651
-
- // TODO(zmo): Uncomment the below line once GetUniformBlocksCHROMIUM
- // command is implemented.
- // gl->GetUniformBlocksCHROMIUMHeler(program, &result);
+ gl->GetUniformBlocksCHROMIUMHelper(program, &result);
}
info->UpdateES3UniformBlocks(result);
+ break;
+ case kES3TransformFeedbackVaryings:
+ {
+ base::AutoUnlock unlock(lock_);
+ // lock_ can't be held across IPC call or else it may deadlock in
+ // pepper. http://crbug.com/418651
+ gl->GetTransformFeedbackVaryingsCHROMIUMHelper(program, &result);
+ }
+ info->UpdateES3TransformFeedbackVaryings(result);
+ case kES3Uniformsiv:
+ {
+ base::AutoUnlock unlock(lock_);
+ // lock_ can't be held across IPC call or else it may deadlock in
+ // pepper. http://crbug.com/418651
+ gl->GetUniformsES3CHROMIUMHelper(program, &result);
+ }
+ info->UpdateES3Uniformsiv(result);
default:
NOTREACHED();
return NULL;
@@ -397,6 +656,10 @@
case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
type = kES3UniformBlocks;
break;
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ type = kES3TransformFeedbackVaryings;
+ break;
default:
return false;
}
@@ -407,6 +670,34 @@
return info->GetProgramiv(pname, params);
}
+bool ProgramInfoManager::GetActiveUniformsiv(
+ GLES2Implementation* gl, GLuint program, GLsizei count,
+ const GLuint* indices, GLenum pname, GLint* params) {
+ base::AutoLock auto_lock(lock_);
+ ProgramInfoType type = kNone;
+ switch (pname) {
+ case GL_UNIFORM_SIZE:
+ case GL_UNIFORM_TYPE:
+ case GL_UNIFORM_NAME_LENGTH:
+ type = kES2;
+ break;
+ case GL_UNIFORM_BLOCK_INDEX:
+ case GL_UNIFORM_OFFSET:
+ case GL_UNIFORM_ARRAY_STRIDE:
+ case GL_UNIFORM_MATRIX_STRIDE:
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ type = kES3Uniformsiv;
+ break;
+ default:
+ return false;
+ }
+ Program* info = GetProgramInfo(gl, program, type);
+ if (info) {
+ return info->GetUniformsiv(count, indices, pname, params);
+ }
+ return gl->GetActiveUniformsivHelper(program, count, indices, pname, params);
+}
+
GLint ProgramInfoManager::GetAttribLocation(
GLES2Implementation* gl, GLuint program, const char* name) {
{
@@ -635,9 +926,73 @@
}
}
}
- return false;
- // TODO(zmo): return gl->GetActiveUniformBlockivHelper(
- // program, index, pname, params);
+ return gl->GetActiveUniformBlockivHelper(program, index, pname, params);
+}
+
+void ProgramInfoManager::UniformBlockBinding(
+ GLES2Implementation* gl, GLuint program, GLuint index, GLuint binding) {
+ GLuint max_bindings =
+ static_cast<GLuint>(gl->capabilities().max_uniform_buffer_bindings);
+ if (binding < max_bindings) {
+ base::AutoLock auto_lock(lock_);
+ // If UniformBlock info haven't been cached yet, skip updating the binding.
+ Program* info = GetProgramInfo(gl, program, kNone);
+ if (info) {
+ info->UniformBlockBinding(index, binding);
+ }
+ }
+}
+
+bool ProgramInfoManager::GetTransformFeedbackVarying(
+ GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, GLsizei* size, GLenum* type, char* name) {
+ {
+ base::AutoLock auto_lock(lock_);
+ Program* info = GetProgramInfo(gl, program, kES3TransformFeedbackVaryings);
+ if (info) {
+ const Program::TransformFeedbackVarying* varying =
+ info->GetTransformFeedbackVarying(index);
+ if (varying) {
+ if (size) {
+ *size = varying->size;
+ }
+ if (type) {
+ *type = varying->type;
+ }
+ if (length || name) {
+ GLsizei max_size = std::min(
+ bufsize - 1, static_cast<GLsizei>(varying->name.size()));
+ if (length) {
+ *length = static_cast<GLsizei>(max_size);
+ }
+ if (name && bufsize > 0) {
+ memcpy(name, varying->name.c_str(), max_size);
+ name[max_size] = '\0';
+ }
+ }
+ return true;
+ }
+ }
+ }
+ return gl->GetTransformFeedbackVaryingHelper(
+ program, index, bufsize, length, size, type, name);
+}
+
+bool ProgramInfoManager::GetUniformIndices(GLES2Implementation* gl,
+ GLuint program, GLsizei count, const char* const* names, GLuint* indices) {
+ {
+ base::AutoLock auto_lock(lock_);
+ Program* info = GetProgramInfo(gl, program, kES2);
+ if (info) {
+ DCHECK_LT(0, count);
+ DCHECK(names && indices);
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ indices[ii] = info->GetUniformIndex(names[ii]);
+ }
+ return true;
+ }
+ }
+ return gl->GetUniformIndicesHelper(program, count, names, indices);
}
} // namespace gles2
diff --git a/gpu/command_buffer/client/program_info_manager.h b/gpu/command_buffer/client/program_info_manager.h
index efbff73..6f8a745 100644
--- a/gpu/command_buffer/client/program_info_manager.h
+++ b/gpu/command_buffer/client/program_info_manager.h
@@ -60,14 +60,39 @@
GLES2Implementation* gl, GLuint program, GLuint index,
GLenum pname, GLint* params);
+ // Attempt to update the |index| uniform block binding.
+ // It's no op if the program does not exist, or the |index| uniform block
+ // is not in the cache, or binding >= GL_MAX_UNIFORM_BUFFER_BINDINGS.
+ void UniformBlockBinding(
+ GLES2Implementation* gl, GLuint program, GLuint index, GLuint binding);
+
+ bool GetTransformFeedbackVarying(
+ GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize,
+ GLsizei* length, GLsizei* size, GLenum* type, char* name);
+
+ bool GetUniformIndices(
+ GLES2Implementation* gl, GLuint program, GLsizei count,
+ const char* const* names, GLuint* indices);
+
+ bool GetActiveUniformsiv(
+ GLES2Implementation* gl, GLuint program, GLsizei count,
+ const GLuint* indices, GLenum pname, GLint* params);
+
private:
friend class ProgramInfoManagerTest;
+ FRIEND_TEST_ALL_PREFIXES(ProgramInfoManagerTest, UpdateES2);
FRIEND_TEST_ALL_PREFIXES(ProgramInfoManagerTest, UpdateES3UniformBlocks);
+ FRIEND_TEST_ALL_PREFIXES(ProgramInfoManagerTest,
+ UpdateES3TransformFeedbackVaryings);
+ FRIEND_TEST_ALL_PREFIXES(ProgramInfoManagerTest,
+ GetActiveUniformsivCached);
enum ProgramInfoType {
kES2,
kES3UniformBlocks,
+ kES3TransformFeedbackVaryings,
+ kES3Uniformsiv,
kNone,
};
@@ -84,6 +109,16 @@
std::string name;
std::vector<GLint> element_locations;
};
+ struct UniformES3 {
+ UniformES3();
+ ~UniformES3();
+
+ GLint block_index;
+ GLint offset;
+ GLint array_stride;
+ GLint matrix_stride;
+ GLint is_row_major;
+ };
struct VertexAttrib {
VertexAttrib(GLsizei _size, GLenum _type, const std::string& _name,
GLint _location);
@@ -105,6 +140,14 @@
GLboolean referenced_by_fragment_shader;
std::string name;
};
+ struct TransformFeedbackVarying {
+ TransformFeedbackVarying();
+ ~TransformFeedbackVarying();
+
+ GLsizei size;
+ GLenum type;
+ std::string name;
+ };
Program();
~Program();
@@ -117,6 +160,11 @@
// Gets the location of a uniform by name.
GLint GetUniformLocation(const std::string& name) const;
+ // Gets the index of a uniform by name. Return INVALID_INDEX in failure.
+ GLuint GetUniformIndex(const std::string& name) const;
+
+ bool GetUniformsiv(
+ GLsizei count, const GLuint* indices, GLenum pname, GLint* params);
GLint GetFragDataLocation(const std::string& name) const;
void CacheFragDataLocation(const std::string& name, GLint loc);
@@ -126,6 +174,11 @@
// Gets the index of a uniform block by name.
GLuint GetUniformBlockIndex(const std::string& name) const;
const UniformBlock* GetUniformBlock(GLuint index) const;
+ // Update the binding if the |index| uniform block is in the cache.
+ void UniformBlockBinding(GLuint index, GLuint binding);
+
+ const TransformFeedbackVarying* GetTransformFeedbackVarying(
+ GLuint index) const;
// Updates the ES2 only program info after a successful link.
void UpdateES2(const std::vector<int8>& result);
@@ -133,6 +186,12 @@
// Updates the ES3 UniformBlock info after a successful link.
void UpdateES3UniformBlocks(const std::vector<int8>& result);
+ // Updates the ES3 Uniformsiv info after a successful link.
+ void UpdateES3Uniformsiv(const std::vector<int8>& result);
+
+ // Updates the ES3 TransformFeedbackVaryings info after a successful link.
+ void UpdateES3TransformFeedbackVaryings(const std::vector<int8>& result);
+
bool IsCached(ProgramInfoType type) const;
private:
@@ -160,6 +219,17 @@
// Uniform blocks by index.
std::vector<UniformBlock> uniform_blocks_;
+ bool cached_es3_transform_feedback_varyings_;
+
+ uint32_t transform_feedback_varying_max_length_;
+
+ // TransformFeedback varyings by index.
+ std::vector<TransformFeedbackVarying> transform_feedback_varyings_;
+
+ bool cached_es3_uniformsiv_;
+
+ std::vector<UniformES3> uniforms_es3_;
+
base::hash_map<std::string, GLint> frag_data_locations_;
};
diff --git a/gpu/command_buffer/client/program_info_manager_unittest.cc b/gpu/command_buffer/client/program_info_manager_unittest.cc
index 6b0576c..f9c6b00 100644
--- a/gpu/command_buffer/client/program_info_manager_unittest.cc
+++ b/gpu/command_buffer/client/program_info_manager_unittest.cc
@@ -27,6 +27,16 @@
protected:
typedef ProgramInfoManager::Program Program;
+ struct ProgramES2Data {
+ // TODO(zmo): Also add attrib data.
+ ProgramInfoHeader header;
+ ProgramInput uniforms[2];
+ int32_t uniform_loc0[1];
+ int32_t uniform_loc1[2];
+ char uniform_name0[4];
+ char uniform_name1[8];
+ };
+
struct UniformBlocksData {
UniformBlocksHeader header;
UniformBlockInfo entry[2];
@@ -36,6 +46,18 @@
uint32_t indices1[1];
};
+ struct UniformsES3Data {
+ UniformsES3Header header;
+ UniformES3Info entry[2];
+ };
+
+ struct TransformFeedbackVaryingsData {
+ TransformFeedbackVaryingsHeader header;
+ TransformFeedbackVaryingInfo entry[2];
+ char name0[4];
+ char name1[8];
+ };
+
void SetUp() override {
program_info_manager_.reset(new ProgramInfoManager);
program_info_manager_->CreateInfo(kClientProgramId);
@@ -49,6 +71,34 @@
void TearDown() override {}
+ void SetupProgramES2Data(ProgramES2Data* data) {
+ // The names needs to be of size 4*k-1 to avoid padding in the struct Data.
+ // This is a testing only problem.
+ const char* kName[] = { "cow", "bull[0]" };
+ data->header.link_status = 1;
+ data->header.num_attribs = 0;
+ data->header.num_uniforms = 2;
+ data->uniforms[0].type = GL_FLOAT;
+ data->uniforms[0].size = 1;
+ data->uniforms[0].location_offset =
+ ComputeOffset(data, &data->uniform_loc0);
+ data->uniforms[0].name_offset =
+ ComputeOffset(data, &data->uniform_name0);
+ data->uniforms[0].name_length = strlen(kName[0]);
+ data->uniforms[1].type = GL_FLOAT_VEC4;
+ data->uniforms[1].size = 2;
+ data->uniforms[1].location_offset =
+ ComputeOffset(data, &data->uniform_loc1);
+ data->uniforms[1].name_offset =
+ ComputeOffset(data, &data->uniform_name1);
+ data->uniforms[1].name_length = strlen(kName[1]);
+ data->uniform_loc0[0] = 1;
+ data->uniform_loc1[0] = 2;
+ data->uniform_loc1[1] = 3;
+ memcpy(data->uniform_name0, kName[0], arraysize(data->uniform_name0));
+ memcpy(data->uniform_name1, kName[1], arraysize(data->uniform_name1));
+ }
+
void SetupUniformBlocksData(UniformBlocksData* data) {
// The names needs to be of size 4*k-1 to avoid padding in the struct Data.
// This is a testing only problem.
@@ -80,10 +130,87 @@
data->indices1[0] = kIndices[1][0];
}
+ void SetupUniformsES3Data(UniformsES3Data* data) {
+ data->header.num_uniforms = 2;
+ data->entry[0].block_index = 1;
+ data->entry[0].offset = 2;
+ data->entry[0].array_stride = 3;
+ data->entry[0].matrix_stride = 4;
+ data->entry[0].is_row_major = 0;
+ data->entry[1].block_index = 5;
+ data->entry[1].offset = 6;
+ data->entry[1].array_stride = 7;
+ data->entry[1].matrix_stride = 8;
+ data->entry[1].is_row_major = 1;
+ }
+
+ void SetupTransformFeedbackVaryingsData(TransformFeedbackVaryingsData* data) {
+ // The names needs to be of size 4*k-1 to avoid padding in the struct Data.
+ // This is a testing only problem.
+ const char* kName[] = { "cow", "chicken" };
+ data->header.num_transform_feedback_varyings = 2;
+ data->entry[0].size = 1;
+ data->entry[0].type = GL_FLOAT_VEC2;
+ data->entry[0].name_offset = ComputeOffset(data, data->name0);
+ data->entry[0].name_length = arraysize(data->name0);
+ data->entry[1].size = 2;
+ data->entry[1].type = GL_FLOAT;
+ data->entry[1].name_offset = ComputeOffset(data, data->name1);
+ data->entry[1].name_length = arraysize(data->name1);
+ memcpy(data->name0, kName[0], arraysize(data->name0));
+ memcpy(data->name1, kName[1], arraysize(data->name1));
+ }
+
scoped_ptr<ProgramInfoManager> program_info_manager_;
Program* program_;
};
+TEST_F(ProgramInfoManagerTest, UpdateES2) {
+ ProgramES2Data data;
+ SetupProgramES2Data(&data);
+ const std::string kNames[] = { data.uniform_name0, data.uniform_name1 };
+ const int32_t* kLocs[] = { data.uniform_loc0, data.uniform_loc1 };
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ EXPECT_FALSE(program_->IsCached(ProgramInfoManager::kES2));
+ program_->UpdateES2(result);
+ EXPECT_TRUE(program_->IsCached(ProgramInfoManager::kES2));
+
+ GLint params = 0;
+ EXPECT_TRUE(program_->GetProgramiv(GL_LINK_STATUS, ¶ms));
+ EXPECT_TRUE(params);
+
+ params = 0;
+ EXPECT_TRUE(program_->GetProgramiv(GL_ACTIVE_ATTRIBUTES, ¶ms));
+ EXPECT_EQ(data.header.num_attribs, static_cast<uint32_t>(params));
+ params = 0;
+ EXPECT_TRUE(program_->GetProgramiv(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, ¶ms));
+ EXPECT_EQ(0, params);
+
+ params = 0;
+ EXPECT_TRUE(program_->GetProgramiv(GL_ACTIVE_UNIFORMS, ¶ms));
+ EXPECT_EQ(data.header.num_uniforms, static_cast<uint32_t>(params));
+ GLint active_uniform_max_length = 0;
+ EXPECT_TRUE(program_->GetProgramiv(
+ GL_ACTIVE_UNIFORM_MAX_LENGTH, &active_uniform_max_length));
+
+ for (uint32_t ii = 0; ii < data.header.num_uniforms; ++ii) {
+ const Program::UniformInfo* info = program_->GetUniformInfo(ii);
+ EXPECT_TRUE(info != NULL);
+ EXPECT_EQ(data.uniforms[ii].type, info->type);
+ EXPECT_EQ(data.uniforms[ii].size, info->size);
+ EXPECT_LT(kNames[0].length(),
+ static_cast<size_t>(active_uniform_max_length));
+ EXPECT_EQ(kNames[ii], info->name);
+ EXPECT_EQ(kNames[ii][kNames[ii].length() - 1] == ']', info->is_array);
+ EXPECT_EQ(data.uniforms[ii].size,
+ static_cast<int32_t>(info->element_locations.size()));
+ for (int32_t uu = 0; uu < data.uniforms[ii].size; ++uu) {
+ EXPECT_EQ(kLocs[ii][uu], info->element_locations[uu]);
+ }
+ }
+}
+
TEST_F(ProgramInfoManagerTest, UpdateES3UniformBlocks) {
UniformBlocksData data;
SetupUniformBlocksData(&data);
@@ -126,6 +253,40 @@
EXPECT_EQ(NULL, program_->GetUniformBlock(data.header.num_uniform_blocks));
}
+TEST_F(ProgramInfoManagerTest, UpdateES3TransformFeedbackVaryings) {
+ TransformFeedbackVaryingsData data;
+ SetupTransformFeedbackVaryingsData(&data);
+ const std::string kName[] = { data.name0, data.name1 };
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ EXPECT_FALSE(program_->IsCached(
+ ProgramInfoManager::kES3TransformFeedbackVaryings));
+ program_->UpdateES3TransformFeedbackVaryings(result);
+ EXPECT_TRUE(program_->IsCached(
+ ProgramInfoManager::kES3TransformFeedbackVaryings));
+
+ GLint transform_feedback_varying_count = 0;
+ EXPECT_TRUE(program_->GetProgramiv(
+ GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varying_count));
+ EXPECT_EQ(data.header.num_transform_feedback_varyings,
+ static_cast<uint32_t>(transform_feedback_varying_count));
+ GLint max_name_length = 0;
+ EXPECT_TRUE(program_->GetProgramiv(
+ GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length));
+ for (uint32_t ii = 0; ii < data.header.num_transform_feedback_varyings;
+ ++ii) {
+ const Program::TransformFeedbackVarying* varying =
+ program_->GetTransformFeedbackVarying(ii);
+ EXPECT_TRUE(varying != NULL);
+ EXPECT_EQ(data.entry[ii].size, static_cast<uint32_t>(varying->size));
+ EXPECT_EQ(data.entry[ii].type, varying->type);
+ EXPECT_EQ(kName[ii], varying->name);
+ EXPECT_GE(max_name_length, static_cast<GLint>(varying->name.size()) + 1);
+ }
+ EXPECT_EQ(NULL, program_->GetTransformFeedbackVarying(
+ data.header.num_transform_feedback_varyings));
+}
+
TEST_F(ProgramInfoManagerTest, GetUniformBlockIndexCached) {
UniformBlocksData data;
SetupUniformBlocksData(&data);
@@ -179,6 +340,210 @@
EXPECT_STREQ(std::string(data.name0).substr(0, length).c_str(), &buffer[0]);
}
+TEST_F(ProgramInfoManagerTest, GetActiveUniformBlockivCached) {
+ UniformBlocksData data;
+ SetupUniformBlocksData(&data);
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ program_->UpdateES3UniformBlocks(result);
+ const char* kName[] = { data.name0, data.name1 };
+ const uint32_t* kIndices[] = { data.indices0, data.indices1 };
+
+ for (uint32_t ii = 0; ii < data.header.num_uniform_blocks; ++ii) {
+ ASSERT_GE(2u, data.entry[ii].active_uniforms);
+ GLint params[2];
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformBlockiv(
+ NULL, kClientProgramId, ii, GL_UNIFORM_BLOCK_BINDING, params));
+ EXPECT_EQ(data.entry[ii].binding, static_cast<uint32_t>(params[0]));
+
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformBlockiv(
+ NULL, kClientProgramId, ii, GL_UNIFORM_BLOCK_DATA_SIZE, params));
+ EXPECT_EQ(data.entry[ii].data_size, static_cast<uint32_t>(params[0]));
+
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformBlockiv(
+ NULL, kClientProgramId, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, params));
+ EXPECT_EQ(strlen(kName[ii]) + 1, static_cast<uint32_t>(params[0]));
+
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformBlockiv(
+ NULL, kClientProgramId, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, params));
+ EXPECT_EQ(data.entry[ii].active_uniforms, static_cast<uint32_t>(params[0]));
+
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformBlockiv(
+ NULL, kClientProgramId, ii,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, params));
+ for (uint32_t uu = 0; uu < data.entry[ii].active_uniforms; ++uu) {
+ EXPECT_EQ(kIndices[ii][uu], static_cast<uint32_t>(params[uu]));
+ }
+
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformBlockiv(
+ NULL, kClientProgramId, ii,
+ GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, params));
+ EXPECT_EQ(data.entry[ii].referenced_by_vertex_shader,
+ static_cast<uint32_t>(params[0]));
+
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformBlockiv(
+ NULL, kClientProgramId, ii,
+ GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, params));
+ EXPECT_EQ(data.entry[ii].referenced_by_fragment_shader,
+ static_cast<uint32_t>(params[0]));
+ }
+}
+
+TEST_F(ProgramInfoManagerTest, GetTransformFeedbackVaryingCached) {
+ TransformFeedbackVaryingsData data;
+ SetupTransformFeedbackVaryingsData(&data);
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ program_->UpdateES3TransformFeedbackVaryings(result);
+ const char* kName[] = { data.name0, data.name1 };
+ GLsizei buf_size = std::max(strlen(kName[0]), strlen(kName[1])) + 1;
+ for (uint32_t ii = 0; ii < data.header.num_transform_feedback_varyings;
+ ++ii) {
+ std::vector<char> buffer(buf_size);
+ GLsizei length = 0;
+ GLsizei size = 0;
+ GLenum type = 0;
+ EXPECT_EQ(true, program_info_manager_->GetTransformFeedbackVarying(
+ NULL, kClientProgramId, ii, buf_size,
+ &length, &size, &type, &buffer[0]));
+ EXPECT_EQ(data.entry[ii].size, static_cast<uint32_t>(size));
+ EXPECT_EQ(data.entry[ii].type, static_cast<uint32_t>(type));
+ EXPECT_STREQ(kName[ii], &buffer[0]);
+ EXPECT_EQ(strlen(kName[ii]), static_cast<size_t>(length));
+ }
+}
+
+TEST_F(ProgramInfoManagerTest, GetUniformIndices) {
+ ProgramES2Data data;
+ SetupProgramES2Data(&data);
+ std::vector<int8> result(sizeof(data));
+ memcpy(&result[0], &data, sizeof(data));
+ program_->UpdateES2(result);
+
+ { // Original order.
+ const char* kNames[] = { data.uniform_name0, data.uniform_name1 };
+ const GLuint kIndices[] = { 0, 1 };
+ const GLsizei kCount = 2;
+ GLuint indices[kCount];
+ EXPECT_TRUE(program_info_manager_->GetUniformIndices(
+ NULL, kClientProgramId, kCount, kNames, indices));
+ for (GLsizei ii = 0; ii < kCount; ++ii) {
+ EXPECT_EQ(kIndices[ii], indices[ii]);
+ }
+ }
+
+ { // Switched order.
+ const char* kNames[] = { data.uniform_name1, data.uniform_name0 };
+ const GLuint kIndices[] = { 1, 0 };
+ const GLsizei kCount = 2;
+ GLuint indices[kCount];
+ EXPECT_TRUE(program_info_manager_->GetUniformIndices(
+ NULL, kClientProgramId, kCount, kNames, indices));
+ for (GLsizei ii = 0; ii < kCount; ++ii) {
+ EXPECT_EQ(kIndices[ii], indices[ii]);
+ }
+ }
+
+ { // With bad names.
+ const char* kNames[] = { data.uniform_name1, "BadName" };
+ const GLuint kIndices[] = { 1, GL_INVALID_INDEX };
+ const GLsizei kCount = 2;
+ GLuint indices[kCount];
+ EXPECT_TRUE(program_info_manager_->GetUniformIndices(
+ NULL, kClientProgramId, kCount, kNames, indices));
+ for (GLsizei ii = 0; ii < kCount; ++ii) {
+ EXPECT_EQ(kIndices[ii], indices[ii]);
+ }
+ }
+
+ { // Both "foo" and "foo[0]" are considered valid names for an array,
+ // but not "foo[1]".
+ const char* kNames[] = { "bull", "bull[0]", "bull[1]" };
+ const GLuint kIndices[] = { 1, 1, GL_INVALID_INDEX };
+ const GLsizei kCount = 3;
+ GLuint indices[kCount];
+ EXPECT_TRUE(program_info_manager_->GetUniformIndices(
+ NULL, kClientProgramId, kCount, kNames, indices));
+ for (GLsizei ii = 0; ii < kCount; ++ii) {
+ EXPECT_EQ(kIndices[ii], indices[ii]);
+ }
+ }
+}
+
+TEST_F(ProgramInfoManagerTest, GetActiveUniformsivCached) {
+ // ES3 only parameters.
+ UniformsES3Data data_es3;
+ SetupUniformsES3Data(&data_es3);
+ std::vector<int8> result(sizeof(data_es3));
+ memcpy(&result[0], &data_es3, sizeof(data_es3));
+ EXPECT_FALSE(program_->IsCached(ProgramInfoManager::kES3Uniformsiv));
+ program_->UpdateES3Uniformsiv(result);
+ EXPECT_TRUE(program_->IsCached(ProgramInfoManager::kES3Uniformsiv));
+
+ uint32_t count = data_es3.header.num_uniforms;
+ std::vector<GLuint> indices(count);
+ for (uint32_t ii = 0; ii < count; ++ii) {
+ indices[ii] = ii;
+ }
+ std::vector<GLint> block_index(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_BLOCK_INDEX, &block_index[0]));
+ std::vector<GLint> offset(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_OFFSET, &offset[0]));
+ std::vector<GLint> array_stride(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_ARRAY_STRIDE, &array_stride[0]));
+ std::vector<GLint> matrix_stride(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_MATRIX_STRIDE, &matrix_stride[0]));
+ std::vector<GLint> is_row_major(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_IS_ROW_MAJOR, &is_row_major[0]));
+
+ for (uint32_t ii = 0; ii < count; ++ii) {
+ EXPECT_EQ(data_es3.entry[ii].block_index, block_index[ii]);
+ EXPECT_EQ(data_es3.entry[ii].offset, offset[ii]);
+ EXPECT_EQ(data_es3.entry[ii].array_stride, array_stride[ii]);
+ EXPECT_EQ(data_es3.entry[ii].matrix_stride, matrix_stride[ii]);
+ EXPECT_EQ(data_es3.entry[ii].is_row_major, is_row_major[ii]);
+ }
+
+ // ES2 parameters.
+ ProgramES2Data data_es2;
+ SetupProgramES2Data(&data_es2);
+ result.resize(sizeof(data_es2));
+ memcpy(&result[0], &data_es2, sizeof(data_es2));
+ EXPECT_FALSE(program_->IsCached(ProgramInfoManager::kES2));
+ program_->UpdateES2(result);
+ EXPECT_TRUE(program_->IsCached(ProgramInfoManager::kES2));
+
+ std::vector<GLint> size(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_SIZE, &size[0]));
+ std::vector<GLint> type(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_TYPE, &type[0]));
+ std::vector<GLint> name_length(count);
+ EXPECT_TRUE(program_info_manager_->GetActiveUniformsiv(
+ NULL, kClientProgramId, static_cast<GLsizei>(count), &indices[0],
+ GL_UNIFORM_NAME_LENGTH, &name_length[0]));
+
+ for (uint32_t ii = 0; ii < count; ++ii) {
+ EXPECT_EQ(data_es2.uniforms[ii].size, size[ii]);
+ EXPECT_EQ(data_es2.uniforms[ii].type, static_cast<uint32_t>(type[ii]));
+ EXPECT_EQ(data_es2.uniforms[ii].name_length + 1,
+ static_cast<uint32_t>(name_length[ii]));
+ }
+}
+
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt
index c415e48..3e8d902 100644
--- a/gpu/command_buffer/cmd_buffer_functions.txt
+++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -77,7 +77,9 @@
GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizeiNotNegative n, GLuint* ids);
GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, GLint* size, GLenum* type, char* name);
GL_APICALL void GL_APIENTRY glGetActiveUniform (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLidProgram program, GLuint index, GLenumUniformBlockParameter pname, GLint* params);
GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLidProgram program, GLsizeiNotNegative count, const GLuint* indices, GLenumUniformParameter pname, GLint* params);
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLidProgram program, GLsizeiNotNegative maxcount, GLsizeiOptional* count, GLuint* shaders);
GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLidProgram program, const char* name);
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenumGLState pname, GLboolean* params);
@@ -100,9 +102,11 @@
GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenumStringType name);
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenumGetTexParamTarget target, GLenumTextureParameter pname, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenumGetTexParamTarget target, GLenumTextureParameter pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLidProgram program, GLuint index, GLsizeiNotNegative bufsize, GLsizeiOptional* length, GLsizei* size, GLenum* type, char* name);
GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLidProgram program, const char* name);
GL_APICALL void GL_APIENTRY glGetUniformfv (GLidProgram program, GLintUniformLocation location, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetUniformiv (GLidProgram program, GLintUniformLocation location, GLint* params);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLidProgram program, GLsizeiNotNegative count, const char* const* names, GLuint* indices);
GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLidProgram program, const char* name);
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenumVertexAttribute pname, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenumVertexAttribute pname, GLint* params);
@@ -181,6 +185,7 @@
GL_APICALL void GL_APIENTRY glUniform4iv (GLintUniformLocation location, GLsizeiNotNegative count, const GLint* v);
GL_APICALL void GL_APIENTRY glUniform4ui (GLintUniformLocation location, GLuint x, GLuint y, GLuint z, GLuint w);
GL_APICALL void GL_APIENTRY glUniform4uiv (GLintUniformLocation location, GLsizeiNotNegative count, const GLuint* v);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLidProgram program, GLuint index, GLuint binding);
GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLintUniformLocation location, GLsizeiNotNegative count, GLbooleanFalseOnly transpose, const GLfloat* value);
GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLintUniformLocation location, GLsizeiNotNegative count, GLbooleanFalseOnly transpose, const GLfloat* value);
GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLintUniformLocation location, GLsizeiNotNegative count, GLbooleanFalseOnly transpose, const GLfloat* value);
@@ -246,6 +251,8 @@
GL_APICALL void GL_APIENTRY glRateLimitOffscreenContextCHROMIUM (void);
GL_APICALL void GL_APIENTRY glGetProgramInfoCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
GL_APICALL void GL_APIENTRY glGetUniformBlocksCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVaryingsCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
+GL_APICALL void GL_APIENTRY glGetUniformsES3CHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info);
GL_APICALL GLuint GL_APIENTRY glCreateStreamTextureCHROMIUM (GLuint texture);
GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM (ClientBuffer buffer, GLsizei width, GLsizei height, GLenum internalformat);
GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM (GLuint image_id);
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h
index e4d38f0..944edfd 100644
--- a/gpu/command_buffer/common/gles2_cmd_format.h
+++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -155,7 +155,7 @@
uint32_t binding; // UNIFORM_BLOCK_BINDING
uint32_t data_size; // UNIFORM_BLOCK_DATA_SIZE
uint32_t name_offset; // offset from UniformBlocksHeader to start of name.
- uint32_t name_length; // UNIFORM_BLOCK_BLOCK_NAME_LENGTH
+ uint32_t name_length; // UNIFORM_BLOCK_NAME_LENGTH
uint32_t active_uniforms; // UNIFORM_BLOCK_ACTIVE_UNIFORMS
// offset from UniformBlocksHeader to |active_uniforms| indices.
uint32_t active_uniform_offset;
@@ -171,6 +171,37 @@
// UniformBlockInfo uniform_blocks[num_uniform_blocks];
};
+// The data for one TransformFeedbackVarying from
+// GetTransformFeedbackVaringCHROMIUM.
+struct TransformFeedbackVaryingInfo {
+ uint32_t size;
+ uint32_t type;
+ uint32_t name_offset; // offset from Header to start of name.
+ uint32_t name_length; // including the null terminator.
+};
+
+// The format of the bucket filled out by GetTransformFeedbackVaryingsCHROMIUM
+struct TransformFeedbackVaryingsHeader {
+ uint32_t num_transform_feedback_varyings;
+ // TransformFeedbackVaryingInfo varyings[num_transform_feedback_varyings];
+};
+
+// Parameters of a uniform that can be queried through glGetActiveUniformsiv,
+// but not through glGetActiveUniform.
+struct UniformES3Info {
+ int32_t block_index;
+ int32_t offset;
+ int32_t array_stride;
+ int32_t matrix_stride;
+ int32_t is_row_major;
+};
+
+// The format of the bucket filled out by GetUniformsivES3CHROMIUM
+struct UniformsES3Header {
+ uint32_t num_uniforms;
+ // UniformES3Info uniforms[num_uniforms];
+};
+
// The format of QuerySync used by EXT_occlusion_query_boolean
struct QuerySync {
void Reset() {
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 12b90c9..cb88581 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -3374,6 +3374,68 @@
"offset of GetActiveUniform Result type should be "
"8");
+struct GetActiveUniformBlockiv {
+ typedef GetActiveUniformBlockiv ValueType;
+ static const CommandId kCmdId = kGetActiveUniformBlockiv;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ typedef SizedResult<GLint> Result;
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _program,
+ GLuint _index,
+ GLenum _pname,
+ uint32_t _params_shm_id,
+ uint32_t _params_shm_offset) {
+ SetHeader();
+ program = _program;
+ index = _index;
+ pname = _pname;
+ params_shm_id = _params_shm_id;
+ params_shm_offset = _params_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ GLuint _index,
+ GLenum _pname,
+ uint32_t _params_shm_id,
+ uint32_t _params_shm_offset) {
+ static_cast<ValueType*>(cmd)
+ ->Init(_program, _index, _pname, _params_shm_id, _params_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t index;
+ uint32_t pname;
+ uint32_t params_shm_id;
+ uint32_t params_shm_offset;
+};
+
+static_assert(sizeof(GetActiveUniformBlockiv) == 24,
+ "size of GetActiveUniformBlockiv should be 24");
+static_assert(offsetof(GetActiveUniformBlockiv, header) == 0,
+ "offset of GetActiveUniformBlockiv header should be 0");
+static_assert(offsetof(GetActiveUniformBlockiv, program) == 4,
+ "offset of GetActiveUniformBlockiv program should be 4");
+static_assert(offsetof(GetActiveUniformBlockiv, index) == 8,
+ "offset of GetActiveUniformBlockiv index should be 8");
+static_assert(offsetof(GetActiveUniformBlockiv, pname) == 12,
+ "offset of GetActiveUniformBlockiv pname should be 12");
+static_assert(offsetof(GetActiveUniformBlockiv, params_shm_id) == 16,
+ "offset of GetActiveUniformBlockiv params_shm_id should be 16");
+static_assert(
+ offsetof(GetActiveUniformBlockiv, params_shm_offset) == 20,
+ "offset of GetActiveUniformBlockiv params_shm_offset should be 20");
+
struct GetActiveUniformBlockName {
typedef GetActiveUniformBlockName ValueType;
static const CommandId kCmdId = kGetActiveUniformBlockName;
@@ -3437,6 +3499,67 @@
offsetof(GetActiveUniformBlockName, result_shm_offset) == 20,
"offset of GetActiveUniformBlockName result_shm_offset should be 20");
+struct GetActiveUniformsiv {
+ typedef GetActiveUniformsiv ValueType;
+ static const CommandId kCmdId = kGetActiveUniformsiv;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ typedef SizedResult<GLint> Result;
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _program,
+ uint32_t _indices_bucket_id,
+ GLenum _pname,
+ uint32_t _params_shm_id,
+ uint32_t _params_shm_offset) {
+ SetHeader();
+ program = _program;
+ indices_bucket_id = _indices_bucket_id;
+ pname = _pname;
+ params_shm_id = _params_shm_id;
+ params_shm_offset = _params_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ uint32_t _indices_bucket_id,
+ GLenum _pname,
+ uint32_t _params_shm_id,
+ uint32_t _params_shm_offset) {
+ static_cast<ValueType*>(cmd)->Init(_program, _indices_bucket_id, _pname,
+ _params_shm_id, _params_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t indices_bucket_id;
+ uint32_t pname;
+ uint32_t params_shm_id;
+ uint32_t params_shm_offset;
+};
+
+static_assert(sizeof(GetActiveUniformsiv) == 24,
+ "size of GetActiveUniformsiv should be 24");
+static_assert(offsetof(GetActiveUniformsiv, header) == 0,
+ "offset of GetActiveUniformsiv header should be 0");
+static_assert(offsetof(GetActiveUniformsiv, program) == 4,
+ "offset of GetActiveUniformsiv program should be 4");
+static_assert(offsetof(GetActiveUniformsiv, indices_bucket_id) == 8,
+ "offset of GetActiveUniformsiv indices_bucket_id should be 8");
+static_assert(offsetof(GetActiveUniformsiv, pname) == 12,
+ "offset of GetActiveUniformsiv pname should be 12");
+static_assert(offsetof(GetActiveUniformsiv, params_shm_id) == 16,
+ "offset of GetActiveUniformsiv params_shm_id should be 16");
+static_assert(offsetof(GetActiveUniformsiv, params_shm_offset) == 20,
+ "offset of GetActiveUniformsiv params_shm_offset should be 20");
+
struct GetAttachedShaders {
typedef GetAttachedShaders ValueType;
static const CommandId kCmdId = kGetAttachedShaders;
@@ -4579,6 +4702,83 @@
static_assert(offsetof(GetTexParameteriv, params_shm_offset) == 16,
"offset of GetTexParameteriv params_shm_offset should be 16");
+struct GetTransformFeedbackVarying {
+ typedef GetTransformFeedbackVarying ValueType;
+ static const CommandId kCmdId = kGetTransformFeedbackVarying;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ struct Result {
+ int32_t success;
+ int32_t size;
+ uint32_t type;
+ };
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _program,
+ GLuint _index,
+ uint32_t _name_bucket_id,
+ uint32_t _result_shm_id,
+ uint32_t _result_shm_offset) {
+ SetHeader();
+ program = _program;
+ index = _index;
+ name_bucket_id = _name_bucket_id;
+ result_shm_id = _result_shm_id;
+ result_shm_offset = _result_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ GLuint _index,
+ uint32_t _name_bucket_id,
+ uint32_t _result_shm_id,
+ uint32_t _result_shm_offset) {
+ static_cast<ValueType*>(cmd)->Init(_program, _index, _name_bucket_id,
+ _result_shm_id, _result_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t index;
+ uint32_t name_bucket_id;
+ uint32_t result_shm_id;
+ uint32_t result_shm_offset;
+};
+
+static_assert(sizeof(GetTransformFeedbackVarying) == 24,
+ "size of GetTransformFeedbackVarying should be 24");
+static_assert(offsetof(GetTransformFeedbackVarying, header) == 0,
+ "offset of GetTransformFeedbackVarying header should be 0");
+static_assert(offsetof(GetTransformFeedbackVarying, program) == 4,
+ "offset of GetTransformFeedbackVarying program should be 4");
+static_assert(offsetof(GetTransformFeedbackVarying, index) == 8,
+ "offset of GetTransformFeedbackVarying index should be 8");
+static_assert(
+ offsetof(GetTransformFeedbackVarying, name_bucket_id) == 12,
+ "offset of GetTransformFeedbackVarying name_bucket_id should be 12");
+static_assert(
+ offsetof(GetTransformFeedbackVarying, result_shm_id) == 16,
+ "offset of GetTransformFeedbackVarying result_shm_id should be 16");
+static_assert(
+ offsetof(GetTransformFeedbackVarying, result_shm_offset) == 20,
+ "offset of GetTransformFeedbackVarying result_shm_offset should be 20");
+static_assert(offsetof(GetTransformFeedbackVarying::Result, success) == 0,
+ "offset of GetTransformFeedbackVarying Result success should be "
+ "0");
+static_assert(offsetof(GetTransformFeedbackVarying::Result, size) == 4,
+ "offset of GetTransformFeedbackVarying Result size should be "
+ "4");
+static_assert(offsetof(GetTransformFeedbackVarying::Result, type) == 8,
+ "offset of GetTransformFeedbackVarying Result type should be "
+ "8");
+
struct GetUniformBlockIndex {
typedef GetUniformBlockIndex ValueType;
static const CommandId kCmdId = kGetUniformBlockIndex;
@@ -4742,6 +4942,61 @@
static_assert(offsetof(GetUniformiv, params_shm_offset) == 16,
"offset of GetUniformiv params_shm_offset should be 16");
+struct GetUniformIndices {
+ typedef GetUniformIndices ValueType;
+ static const CommandId kCmdId = kGetUniformIndices;
+ static const cmd::ArgFlags kArgFlags = cmd::kFixed;
+ static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3);
+
+ typedef SizedResult<GLuint> Result;
+
+ static uint32_t ComputeSize() {
+ return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT
+ }
+
+ void SetHeader() { header.SetCmd<ValueType>(); }
+
+ void Init(GLuint _program,
+ uint32_t _names_bucket_id,
+ uint32_t _indices_shm_id,
+ uint32_t _indices_shm_offset) {
+ SetHeader();
+ program = _program;
+ names_bucket_id = _names_bucket_id;
+ indices_shm_id = _indices_shm_id;
+ indices_shm_offset = _indices_shm_offset;
+ }
+
+ void* Set(void* cmd,
+ GLuint _program,
+ uint32_t _names_bucket_id,
+ uint32_t _indices_shm_id,
+ uint32_t _indices_shm_offset) {
+ static_cast<ValueType*>(cmd)->Init(_program, _names_bucket_id,
+ _indices_shm_id, _indices_shm_offset);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t names_bucket_id;
+ uint32_t indices_shm_id;
+ uint32_t indices_shm_offset;
+};
+
+static_assert(sizeof(GetUniformIndices) == 20,
+ "size of GetUniformIndices should be 20");
+static_assert(offsetof(GetUniformIndices, header) == 0,
+ "offset of GetUniformIndices header should be 0");
+static_assert(offsetof(GetUniformIndices, program) == 4,
+ "offset of GetUniformIndices program should be 4");
+static_assert(offsetof(GetUniformIndices, names_bucket_id) == 8,
+ "offset of GetUniformIndices names_bucket_id should be 8");
+static_assert(offsetof(GetUniformIndices, indices_shm_id) == 12,
+ "offset of GetUniformIndices indices_shm_id should be 12");
+static_assert(offsetof(GetUniformIndices, indices_shm_offset) == 16,
+ "offset of GetUniformIndices indices_shm_offset should be 16");
+
struct GetUniformLocation {
typedef GetUniformLocation ValueType;
static const CommandId kCmdId = kGetUniformLocation;
@@ -8323,6 +8578,47 @@
static_assert(offsetof(Uniform4uivImmediate, count) == 8,
"offset of Uniform4uivImmediate count should be 8");
+struct UniformBlockBinding {
+ typedef UniformBlockBinding ValueType;
+ static const CommandId kCmdId = kUniformBlockBinding;
+ 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(GLuint _program, GLuint _index, GLuint _binding) {
+ SetHeader();
+ program = _program;
+ index = _index;
+ binding = _binding;
+ }
+
+ void* Set(void* cmd, GLuint _program, GLuint _index, GLuint _binding) {
+ static_cast<ValueType*>(cmd)->Init(_program, _index, _binding);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t index;
+ uint32_t binding;
+};
+
+static_assert(sizeof(UniformBlockBinding) == 16,
+ "size of UniformBlockBinding should be 16");
+static_assert(offsetof(UniformBlockBinding, header) == 0,
+ "offset of UniformBlockBinding header should be 0");
+static_assert(offsetof(UniformBlockBinding, program) == 4,
+ "offset of UniformBlockBinding program should be 4");
+static_assert(offsetof(UniformBlockBinding, index) == 8,
+ "offset of UniformBlockBinding index should be 8");
+static_assert(offsetof(UniformBlockBinding, binding) == 12,
+ "offset of UniformBlockBinding binding should be 12");
+
struct UniformMatrix2fvImmediate {
typedef UniformMatrix2fvImmediate ValueType;
static const CommandId kCmdId = kUniformMatrix2fvImmediate;
@@ -10669,6 +10965,87 @@
static_assert(offsetof(GetUniformBlocksCHROMIUM, bucket_id) == 8,
"offset of GetUniformBlocksCHROMIUM bucket_id should be 8");
+struct GetTransformFeedbackVaryingsCHROMIUM {
+ typedef GetTransformFeedbackVaryingsCHROMIUM ValueType;
+ static const CommandId kCmdId = kGetTransformFeedbackVaryingsCHROMIUM;
+ 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(GLuint _program, uint32_t _bucket_id) {
+ SetHeader();
+ program = _program;
+ bucket_id = _bucket_id;
+ }
+
+ void* Set(void* cmd, GLuint _program, uint32_t _bucket_id) {
+ static_cast<ValueType*>(cmd)->Init(_program, _bucket_id);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t bucket_id;
+};
+
+static_assert(sizeof(GetTransformFeedbackVaryingsCHROMIUM) == 12,
+ "size of GetTransformFeedbackVaryingsCHROMIUM should be 12");
+static_assert(
+ offsetof(GetTransformFeedbackVaryingsCHROMIUM, header) == 0,
+ "offset of GetTransformFeedbackVaryingsCHROMIUM header should be 0");
+static_assert(
+ offsetof(GetTransformFeedbackVaryingsCHROMIUM, program) == 4,
+ "offset of GetTransformFeedbackVaryingsCHROMIUM program should be 4");
+static_assert(
+ offsetof(GetTransformFeedbackVaryingsCHROMIUM, bucket_id) == 8,
+ "offset of GetTransformFeedbackVaryingsCHROMIUM bucket_id should be 8");
+
+struct GetUniformsES3CHROMIUM {
+ typedef GetUniformsES3CHROMIUM ValueType;
+ static const CommandId kCmdId = kGetUniformsES3CHROMIUM;
+ 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(GLuint _program, uint32_t _bucket_id) {
+ SetHeader();
+ program = _program;
+ bucket_id = _bucket_id;
+ }
+
+ void* Set(void* cmd, GLuint _program, uint32_t _bucket_id) {
+ static_cast<ValueType*>(cmd)->Init(_program, _bucket_id);
+ return NextCmdAddress<ValueType>(cmd);
+ }
+
+ gpu::CommandHeader header;
+ uint32_t program;
+ uint32_t bucket_id;
+};
+
+static_assert(sizeof(GetUniformsES3CHROMIUM) == 12,
+ "size of GetUniformsES3CHROMIUM should be 12");
+static_assert(offsetof(GetUniformsES3CHROMIUM, header) == 0,
+ "offset of GetUniformsES3CHROMIUM header should be 0");
+static_assert(offsetof(GetUniformsES3CHROMIUM, program) == 4,
+ "offset of GetUniformsES3CHROMIUM program should be 4");
+static_assert(offsetof(GetUniformsES3CHROMIUM, bucket_id) == 8,
+ "offset of GetUniformsES3CHROMIUM bucket_id should be 8");
+
struct GetTranslatedShaderSourceANGLE {
typedef GetTranslatedShaderSourceANGLE ValueType;
static const CommandId kCmdId = kGetTranslatedShaderSourceANGLE;
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 5174384..a89683a 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -1095,6 +1095,24 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetActiveUniformBlockiv) {
+ cmds::GetActiveUniformBlockiv& cmd =
+ *GetBufferAs<cmds::GetActiveUniformBlockiv>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLuint>(12),
+ static_cast<GLenum>(13), static_cast<uint32_t>(14),
+ static_cast<uint32_t>(15));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetActiveUniformBlockiv::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+ EXPECT_EQ(static_cast<GLenum>(13), cmd.pname);
+ EXPECT_EQ(static_cast<uint32_t>(14), cmd.params_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(15), cmd.params_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetActiveUniformBlockName) {
cmds::GetActiveUniformBlockName& cmd =
*GetBufferAs<cmds::GetActiveUniformBlockName>();
@@ -1113,6 +1131,23 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetActiveUniformsiv) {
+ cmds::GetActiveUniformsiv& cmd = *GetBufferAs<cmds::GetActiveUniformsiv>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12),
+ static_cast<GLenum>(13), static_cast<uint32_t>(14),
+ static_cast<uint32_t>(15));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetActiveUniformsiv::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<uint32_t>(12), cmd.indices_bucket_id);
+ EXPECT_EQ(static_cast<GLenum>(13), cmd.pname);
+ EXPECT_EQ(static_cast<uint32_t>(14), cmd.params_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(15), cmd.params_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetAttachedShaders) {
cmds::GetAttachedShaders& cmd = *GetBufferAs<cmds::GetAttachedShaders>();
void* next_cmd =
@@ -1433,6 +1468,24 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetTransformFeedbackVarying) {
+ cmds::GetTransformFeedbackVarying& cmd =
+ *GetBufferAs<cmds::GetTransformFeedbackVarying>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLuint>(12),
+ static_cast<uint32_t>(13), static_cast<uint32_t>(14),
+ static_cast<uint32_t>(15));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetTransformFeedbackVarying::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+ EXPECT_EQ(static_cast<uint32_t>(13), cmd.name_bucket_id);
+ EXPECT_EQ(static_cast<uint32_t>(14), cmd.result_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(15), cmd.result_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetUniformBlockIndex) {
cmds::GetUniformBlockIndex& cmd = *GetBufferAs<cmds::GetUniformBlockIndex>();
void* next_cmd =
@@ -1478,6 +1531,21 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetUniformIndices) {
+ cmds::GetUniformIndices& cmd = *GetBufferAs<cmds::GetUniformIndices>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12),
+ static_cast<uint32_t>(13), static_cast<uint32_t>(14));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetUniformIndices::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<uint32_t>(12), cmd.names_bucket_id);
+ EXPECT_EQ(static_cast<uint32_t>(13), cmd.indices_shm_id);
+ EXPECT_EQ(static_cast<uint32_t>(14), cmd.indices_shm_offset);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetUniformLocation) {
cmds::GetUniformLocation& cmd = *GetBufferAs<cmds::GetUniformLocation>();
void* next_cmd =
@@ -2716,6 +2784,19 @@
// TODO(gman): Check that data was inserted;
}
+TEST_F(GLES2FormatTest, UniformBlockBinding) {
+ cmds::UniformBlockBinding& cmd = *GetBufferAs<cmds::UniformBlockBinding>();
+ void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11),
+ static_cast<GLuint>(12), static_cast<GLuint>(13));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::UniformBlockBinding::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<GLuint>(12), cmd.index);
+ EXPECT_EQ(static_cast<GLuint>(13), cmd.binding);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, UniformMatrix2fvImmediate) {
const int kSomeBaseValueToTestWith = 51;
static GLfloat data[] = {
@@ -3713,6 +3794,33 @@
CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
}
+TEST_F(GLES2FormatTest, GetTransformFeedbackVaryingsCHROMIUM) {
+ cmds::GetTransformFeedbackVaryingsCHROMIUM& cmd =
+ *GetBufferAs<cmds::GetTransformFeedbackVaryingsCHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12));
+ EXPECT_EQ(
+ static_cast<uint32_t>(cmds::GetTransformFeedbackVaryingsCHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<uint32_t>(12), cmd.bucket_id);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
+TEST_F(GLES2FormatTest, GetUniformsES3CHROMIUM) {
+ cmds::GetUniformsES3CHROMIUM& cmd =
+ *GetBufferAs<cmds::GetUniformsES3CHROMIUM>();
+ void* next_cmd =
+ cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12));
+ EXPECT_EQ(static_cast<uint32_t>(cmds::GetUniformsES3CHROMIUM::kCmdId),
+ cmd.header.command);
+ EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u);
+ EXPECT_EQ(static_cast<GLuint>(11), cmd.program);
+ EXPECT_EQ(static_cast<uint32_t>(12), cmd.bucket_id);
+ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd));
+}
+
TEST_F(GLES2FormatTest, GetTranslatedShaderSourceANGLE) {
cmds::GetTranslatedShaderSourceANGLE& cmd =
*GetBufferAs<cmds::GetTranslatedShaderSourceANGLE>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index 76364b7..db67f4f 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -87,198 +87,205 @@
OP(GenTransformFeedbacksImmediate) /* 328 */ \
OP(GetActiveAttrib) /* 329 */ \
OP(GetActiveUniform) /* 330 */ \
- OP(GetActiveUniformBlockName) /* 331 */ \
- OP(GetAttachedShaders) /* 332 */ \
- OP(GetAttribLocation) /* 333 */ \
- OP(GetBooleanv) /* 334 */ \
- OP(GetBufferParameteriv) /* 335 */ \
- OP(GetError) /* 336 */ \
- OP(GetFloatv) /* 337 */ \
- OP(GetFragDataLocation) /* 338 */ \
- OP(GetFramebufferAttachmentParameteriv) /* 339 */ \
- OP(GetIntegerv) /* 340 */ \
- OP(GetInternalformativ) /* 341 */ \
- OP(GetProgramiv) /* 342 */ \
- OP(GetProgramInfoLog) /* 343 */ \
- OP(GetRenderbufferParameteriv) /* 344 */ \
- OP(GetSamplerParameterfv) /* 345 */ \
- OP(GetSamplerParameteriv) /* 346 */ \
- OP(GetShaderiv) /* 347 */ \
- OP(GetShaderInfoLog) /* 348 */ \
- OP(GetShaderPrecisionFormat) /* 349 */ \
- OP(GetShaderSource) /* 350 */ \
- OP(GetString) /* 351 */ \
- OP(GetTexParameterfv) /* 352 */ \
- OP(GetTexParameteriv) /* 353 */ \
- OP(GetUniformBlockIndex) /* 354 */ \
- OP(GetUniformfv) /* 355 */ \
- OP(GetUniformiv) /* 356 */ \
- OP(GetUniformLocation) /* 357 */ \
- OP(GetVertexAttribfv) /* 358 */ \
- OP(GetVertexAttribiv) /* 359 */ \
- OP(GetVertexAttribPointerv) /* 360 */ \
- OP(Hint) /* 361 */ \
- OP(InvalidateFramebufferImmediate) /* 362 */ \
- OP(InvalidateSubFramebufferImmediate) /* 363 */ \
- OP(IsBuffer) /* 364 */ \
- OP(IsEnabled) /* 365 */ \
- OP(IsFramebuffer) /* 366 */ \
- OP(IsProgram) /* 367 */ \
- OP(IsRenderbuffer) /* 368 */ \
- OP(IsSampler) /* 369 */ \
- OP(IsShader) /* 370 */ \
- OP(IsSync) /* 371 */ \
- OP(IsTexture) /* 372 */ \
- OP(IsTransformFeedback) /* 373 */ \
- OP(LineWidth) /* 374 */ \
- OP(LinkProgram) /* 375 */ \
- OP(PauseTransformFeedback) /* 376 */ \
- OP(PixelStorei) /* 377 */ \
- OP(PolygonOffset) /* 378 */ \
- OP(ReadBuffer) /* 379 */ \
- OP(ReadPixels) /* 380 */ \
- OP(ReleaseShaderCompiler) /* 381 */ \
- OP(RenderbufferStorage) /* 382 */ \
- OP(ResumeTransformFeedback) /* 383 */ \
- OP(SampleCoverage) /* 384 */ \
- OP(SamplerParameterf) /* 385 */ \
- OP(SamplerParameterfvImmediate) /* 386 */ \
- OP(SamplerParameteri) /* 387 */ \
- OP(SamplerParameterivImmediate) /* 388 */ \
- OP(Scissor) /* 389 */ \
- OP(ShaderBinary) /* 390 */ \
- OP(ShaderSourceBucket) /* 391 */ \
- OP(StencilFunc) /* 392 */ \
- OP(StencilFuncSeparate) /* 393 */ \
- OP(StencilMask) /* 394 */ \
- OP(StencilMaskSeparate) /* 395 */ \
- OP(StencilOp) /* 396 */ \
- OP(StencilOpSeparate) /* 397 */ \
- OP(TexImage2D) /* 398 */ \
- OP(TexImage3D) /* 399 */ \
- OP(TexParameterf) /* 400 */ \
- OP(TexParameterfvImmediate) /* 401 */ \
- OP(TexParameteri) /* 402 */ \
- OP(TexParameterivImmediate) /* 403 */ \
- OP(TexStorage3D) /* 404 */ \
- OP(TexSubImage2D) /* 405 */ \
- OP(TexSubImage3D) /* 406 */ \
- OP(TransformFeedbackVaryingsBucket) /* 407 */ \
- OP(Uniform1f) /* 408 */ \
- OP(Uniform1fvImmediate) /* 409 */ \
- OP(Uniform1i) /* 410 */ \
- OP(Uniform1ivImmediate) /* 411 */ \
- OP(Uniform1ui) /* 412 */ \
- OP(Uniform1uivImmediate) /* 413 */ \
- OP(Uniform2f) /* 414 */ \
- OP(Uniform2fvImmediate) /* 415 */ \
- OP(Uniform2i) /* 416 */ \
- OP(Uniform2ivImmediate) /* 417 */ \
- OP(Uniform2ui) /* 418 */ \
- OP(Uniform2uivImmediate) /* 419 */ \
- OP(Uniform3f) /* 420 */ \
- OP(Uniform3fvImmediate) /* 421 */ \
- OP(Uniform3i) /* 422 */ \
- OP(Uniform3ivImmediate) /* 423 */ \
- OP(Uniform3ui) /* 424 */ \
- OP(Uniform3uivImmediate) /* 425 */ \
- OP(Uniform4f) /* 426 */ \
- OP(Uniform4fvImmediate) /* 427 */ \
- OP(Uniform4i) /* 428 */ \
- OP(Uniform4ivImmediate) /* 429 */ \
- OP(Uniform4ui) /* 430 */ \
- OP(Uniform4uivImmediate) /* 431 */ \
- OP(UniformMatrix2fvImmediate) /* 432 */ \
- OP(UniformMatrix2x3fvImmediate) /* 433 */ \
- OP(UniformMatrix2x4fvImmediate) /* 434 */ \
- OP(UniformMatrix3fvImmediate) /* 435 */ \
- OP(UniformMatrix3x2fvImmediate) /* 436 */ \
- OP(UniformMatrix3x4fvImmediate) /* 437 */ \
- OP(UniformMatrix4fvImmediate) /* 438 */ \
- OP(UniformMatrix4x2fvImmediate) /* 439 */ \
- OP(UniformMatrix4x3fvImmediate) /* 440 */ \
- OP(UseProgram) /* 441 */ \
- OP(ValidateProgram) /* 442 */ \
- OP(VertexAttrib1f) /* 443 */ \
- OP(VertexAttrib1fvImmediate) /* 444 */ \
- OP(VertexAttrib2f) /* 445 */ \
- OP(VertexAttrib2fvImmediate) /* 446 */ \
- OP(VertexAttrib3f) /* 447 */ \
- OP(VertexAttrib3fvImmediate) /* 448 */ \
- OP(VertexAttrib4f) /* 449 */ \
- OP(VertexAttrib4fvImmediate) /* 450 */ \
- OP(VertexAttribI4i) /* 451 */ \
- OP(VertexAttribI4ivImmediate) /* 452 */ \
- OP(VertexAttribI4ui) /* 453 */ \
- OP(VertexAttribI4uivImmediate) /* 454 */ \
- OP(VertexAttribIPointer) /* 455 */ \
- OP(VertexAttribPointer) /* 456 */ \
- OP(Viewport) /* 457 */ \
- OP(BlitFramebufferCHROMIUM) /* 458 */ \
- OP(RenderbufferStorageMultisampleCHROMIUM) /* 459 */ \
- OP(RenderbufferStorageMultisampleEXT) /* 460 */ \
- OP(FramebufferTexture2DMultisampleEXT) /* 461 */ \
- OP(TexStorage2DEXT) /* 462 */ \
- OP(GenQueriesEXTImmediate) /* 463 */ \
- OP(DeleteQueriesEXTImmediate) /* 464 */ \
- OP(BeginQueryEXT) /* 465 */ \
- OP(BeginTransformFeedback) /* 466 */ \
- OP(EndQueryEXT) /* 467 */ \
- OP(EndTransformFeedback) /* 468 */ \
- OP(InsertEventMarkerEXT) /* 469 */ \
- OP(PushGroupMarkerEXT) /* 470 */ \
- OP(PopGroupMarkerEXT) /* 471 */ \
- OP(GenVertexArraysOESImmediate) /* 472 */ \
- OP(DeleteVertexArraysOESImmediate) /* 473 */ \
- OP(IsVertexArrayOES) /* 474 */ \
- OP(BindVertexArrayOES) /* 475 */ \
- OP(SwapBuffers) /* 476 */ \
- OP(GetMaxValueInBufferCHROMIUM) /* 477 */ \
- OP(EnableFeatureCHROMIUM) /* 478 */ \
- OP(ResizeCHROMIUM) /* 479 */ \
- OP(GetRequestableExtensionsCHROMIUM) /* 480 */ \
- OP(RequestExtensionCHROMIUM) /* 481 */ \
- OP(GetProgramInfoCHROMIUM) /* 482 */ \
- OP(GetUniformBlocksCHROMIUM) /* 483 */ \
- OP(GetTranslatedShaderSourceANGLE) /* 484 */ \
- OP(PostSubBufferCHROMIUM) /* 485 */ \
- OP(TexImageIOSurface2DCHROMIUM) /* 486 */ \
- OP(CopyTextureCHROMIUM) /* 487 */ \
- OP(DrawArraysInstancedANGLE) /* 488 */ \
- OP(DrawElementsInstancedANGLE) /* 489 */ \
- OP(VertexAttribDivisorANGLE) /* 490 */ \
- OP(GenMailboxCHROMIUM) /* 491 */ \
- OP(ProduceTextureCHROMIUMImmediate) /* 492 */ \
- OP(ProduceTextureDirectCHROMIUMImmediate) /* 493 */ \
- OP(ConsumeTextureCHROMIUMImmediate) /* 494 */ \
- OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 495 */ \
- OP(BindUniformLocationCHROMIUMBucket) /* 496 */ \
- OP(GenValuebuffersCHROMIUMImmediate) /* 497 */ \
- OP(DeleteValuebuffersCHROMIUMImmediate) /* 498 */ \
- OP(IsValuebufferCHROMIUM) /* 499 */ \
- OP(BindValuebufferCHROMIUM) /* 500 */ \
- OP(SubscribeValueCHROMIUM) /* 501 */ \
- OP(PopulateSubscribedValuesCHROMIUM) /* 502 */ \
- OP(UniformValuebufferCHROMIUM) /* 503 */ \
- OP(BindTexImage2DCHROMIUM) /* 504 */ \
- OP(ReleaseTexImage2DCHROMIUM) /* 505 */ \
- OP(TraceBeginCHROMIUM) /* 506 */ \
- OP(TraceEndCHROMIUM) /* 507 */ \
- OP(AsyncTexSubImage2DCHROMIUM) /* 508 */ \
- OP(AsyncTexImage2DCHROMIUM) /* 509 */ \
- OP(WaitAsyncTexImage2DCHROMIUM) /* 510 */ \
- OP(WaitAllAsyncTexImage2DCHROMIUM) /* 511 */ \
- OP(DiscardFramebufferEXTImmediate) /* 512 */ \
- OP(LoseContextCHROMIUM) /* 513 */ \
- OP(InsertSyncPointCHROMIUM) /* 514 */ \
- OP(WaitSyncPointCHROMIUM) /* 515 */ \
- OP(DrawBuffersEXTImmediate) /* 516 */ \
- OP(DiscardBackbufferCHROMIUM) /* 517 */ \
- OP(ScheduleOverlayPlaneCHROMIUM) /* 518 */ \
- OP(SwapInterval) /* 519 */ \
- OP(MatrixLoadfCHROMIUMImmediate) /* 520 */ \
- OP(MatrixLoadIdentityCHROMIUM) /* 521 */ \
- OP(BlendBarrierKHR) /* 522 */
+ OP(GetActiveUniformBlockiv) /* 331 */ \
+ OP(GetActiveUniformBlockName) /* 332 */ \
+ OP(GetActiveUniformsiv) /* 333 */ \
+ OP(GetAttachedShaders) /* 334 */ \
+ OP(GetAttribLocation) /* 335 */ \
+ OP(GetBooleanv) /* 336 */ \
+ OP(GetBufferParameteriv) /* 337 */ \
+ OP(GetError) /* 338 */ \
+ OP(GetFloatv) /* 339 */ \
+ OP(GetFragDataLocation) /* 340 */ \
+ OP(GetFramebufferAttachmentParameteriv) /* 341 */ \
+ OP(GetIntegerv) /* 342 */ \
+ OP(GetInternalformativ) /* 343 */ \
+ OP(GetProgramiv) /* 344 */ \
+ OP(GetProgramInfoLog) /* 345 */ \
+ OP(GetRenderbufferParameteriv) /* 346 */ \
+ OP(GetSamplerParameterfv) /* 347 */ \
+ OP(GetSamplerParameteriv) /* 348 */ \
+ OP(GetShaderiv) /* 349 */ \
+ OP(GetShaderInfoLog) /* 350 */ \
+ OP(GetShaderPrecisionFormat) /* 351 */ \
+ OP(GetShaderSource) /* 352 */ \
+ OP(GetString) /* 353 */ \
+ OP(GetTexParameterfv) /* 354 */ \
+ OP(GetTexParameteriv) /* 355 */ \
+ OP(GetTransformFeedbackVarying) /* 356 */ \
+ OP(GetUniformBlockIndex) /* 357 */ \
+ OP(GetUniformfv) /* 358 */ \
+ OP(GetUniformiv) /* 359 */ \
+ OP(GetUniformIndices) /* 360 */ \
+ OP(GetUniformLocation) /* 361 */ \
+ OP(GetVertexAttribfv) /* 362 */ \
+ OP(GetVertexAttribiv) /* 363 */ \
+ OP(GetVertexAttribPointerv) /* 364 */ \
+ OP(Hint) /* 365 */ \
+ OP(InvalidateFramebufferImmediate) /* 366 */ \
+ OP(InvalidateSubFramebufferImmediate) /* 367 */ \
+ OP(IsBuffer) /* 368 */ \
+ OP(IsEnabled) /* 369 */ \
+ OP(IsFramebuffer) /* 370 */ \
+ OP(IsProgram) /* 371 */ \
+ OP(IsRenderbuffer) /* 372 */ \
+ OP(IsSampler) /* 373 */ \
+ OP(IsShader) /* 374 */ \
+ OP(IsSync) /* 375 */ \
+ OP(IsTexture) /* 376 */ \
+ OP(IsTransformFeedback) /* 377 */ \
+ OP(LineWidth) /* 378 */ \
+ OP(LinkProgram) /* 379 */ \
+ OP(PauseTransformFeedback) /* 380 */ \
+ OP(PixelStorei) /* 381 */ \
+ OP(PolygonOffset) /* 382 */ \
+ OP(ReadBuffer) /* 383 */ \
+ OP(ReadPixels) /* 384 */ \
+ OP(ReleaseShaderCompiler) /* 385 */ \
+ OP(RenderbufferStorage) /* 386 */ \
+ OP(ResumeTransformFeedback) /* 387 */ \
+ OP(SampleCoverage) /* 388 */ \
+ OP(SamplerParameterf) /* 389 */ \
+ OP(SamplerParameterfvImmediate) /* 390 */ \
+ OP(SamplerParameteri) /* 391 */ \
+ OP(SamplerParameterivImmediate) /* 392 */ \
+ OP(Scissor) /* 393 */ \
+ OP(ShaderBinary) /* 394 */ \
+ OP(ShaderSourceBucket) /* 395 */ \
+ OP(StencilFunc) /* 396 */ \
+ OP(StencilFuncSeparate) /* 397 */ \
+ OP(StencilMask) /* 398 */ \
+ OP(StencilMaskSeparate) /* 399 */ \
+ OP(StencilOp) /* 400 */ \
+ OP(StencilOpSeparate) /* 401 */ \
+ OP(TexImage2D) /* 402 */ \
+ OP(TexImage3D) /* 403 */ \
+ OP(TexParameterf) /* 404 */ \
+ OP(TexParameterfvImmediate) /* 405 */ \
+ OP(TexParameteri) /* 406 */ \
+ OP(TexParameterivImmediate) /* 407 */ \
+ OP(TexStorage3D) /* 408 */ \
+ OP(TexSubImage2D) /* 409 */ \
+ OP(TexSubImage3D) /* 410 */ \
+ OP(TransformFeedbackVaryingsBucket) /* 411 */ \
+ OP(Uniform1f) /* 412 */ \
+ OP(Uniform1fvImmediate) /* 413 */ \
+ OP(Uniform1i) /* 414 */ \
+ OP(Uniform1ivImmediate) /* 415 */ \
+ OP(Uniform1ui) /* 416 */ \
+ OP(Uniform1uivImmediate) /* 417 */ \
+ OP(Uniform2f) /* 418 */ \
+ OP(Uniform2fvImmediate) /* 419 */ \
+ OP(Uniform2i) /* 420 */ \
+ OP(Uniform2ivImmediate) /* 421 */ \
+ OP(Uniform2ui) /* 422 */ \
+ OP(Uniform2uivImmediate) /* 423 */ \
+ OP(Uniform3f) /* 424 */ \
+ OP(Uniform3fvImmediate) /* 425 */ \
+ OP(Uniform3i) /* 426 */ \
+ OP(Uniform3ivImmediate) /* 427 */ \
+ OP(Uniform3ui) /* 428 */ \
+ OP(Uniform3uivImmediate) /* 429 */ \
+ OP(Uniform4f) /* 430 */ \
+ OP(Uniform4fvImmediate) /* 431 */ \
+ OP(Uniform4i) /* 432 */ \
+ OP(Uniform4ivImmediate) /* 433 */ \
+ OP(Uniform4ui) /* 434 */ \
+ OP(Uniform4uivImmediate) /* 435 */ \
+ OP(UniformBlockBinding) /* 436 */ \
+ OP(UniformMatrix2fvImmediate) /* 437 */ \
+ OP(UniformMatrix2x3fvImmediate) /* 438 */ \
+ OP(UniformMatrix2x4fvImmediate) /* 439 */ \
+ OP(UniformMatrix3fvImmediate) /* 440 */ \
+ OP(UniformMatrix3x2fvImmediate) /* 441 */ \
+ OP(UniformMatrix3x4fvImmediate) /* 442 */ \
+ OP(UniformMatrix4fvImmediate) /* 443 */ \
+ OP(UniformMatrix4x2fvImmediate) /* 444 */ \
+ OP(UniformMatrix4x3fvImmediate) /* 445 */ \
+ OP(UseProgram) /* 446 */ \
+ OP(ValidateProgram) /* 447 */ \
+ OP(VertexAttrib1f) /* 448 */ \
+ OP(VertexAttrib1fvImmediate) /* 449 */ \
+ OP(VertexAttrib2f) /* 450 */ \
+ OP(VertexAttrib2fvImmediate) /* 451 */ \
+ OP(VertexAttrib3f) /* 452 */ \
+ OP(VertexAttrib3fvImmediate) /* 453 */ \
+ OP(VertexAttrib4f) /* 454 */ \
+ OP(VertexAttrib4fvImmediate) /* 455 */ \
+ OP(VertexAttribI4i) /* 456 */ \
+ OP(VertexAttribI4ivImmediate) /* 457 */ \
+ OP(VertexAttribI4ui) /* 458 */ \
+ OP(VertexAttribI4uivImmediate) /* 459 */ \
+ OP(VertexAttribIPointer) /* 460 */ \
+ OP(VertexAttribPointer) /* 461 */ \
+ OP(Viewport) /* 462 */ \
+ OP(BlitFramebufferCHROMIUM) /* 463 */ \
+ OP(RenderbufferStorageMultisampleCHROMIUM) /* 464 */ \
+ OP(RenderbufferStorageMultisampleEXT) /* 465 */ \
+ OP(FramebufferTexture2DMultisampleEXT) /* 466 */ \
+ OP(TexStorage2DEXT) /* 467 */ \
+ OP(GenQueriesEXTImmediate) /* 468 */ \
+ OP(DeleteQueriesEXTImmediate) /* 469 */ \
+ OP(BeginQueryEXT) /* 470 */ \
+ OP(BeginTransformFeedback) /* 471 */ \
+ OP(EndQueryEXT) /* 472 */ \
+ OP(EndTransformFeedback) /* 473 */ \
+ OP(InsertEventMarkerEXT) /* 474 */ \
+ OP(PushGroupMarkerEXT) /* 475 */ \
+ OP(PopGroupMarkerEXT) /* 476 */ \
+ OP(GenVertexArraysOESImmediate) /* 477 */ \
+ OP(DeleteVertexArraysOESImmediate) /* 478 */ \
+ OP(IsVertexArrayOES) /* 479 */ \
+ OP(BindVertexArrayOES) /* 480 */ \
+ OP(SwapBuffers) /* 481 */ \
+ OP(GetMaxValueInBufferCHROMIUM) /* 482 */ \
+ OP(EnableFeatureCHROMIUM) /* 483 */ \
+ OP(ResizeCHROMIUM) /* 484 */ \
+ OP(GetRequestableExtensionsCHROMIUM) /* 485 */ \
+ OP(RequestExtensionCHROMIUM) /* 486 */ \
+ OP(GetProgramInfoCHROMIUM) /* 487 */ \
+ OP(GetUniformBlocksCHROMIUM) /* 488 */ \
+ OP(GetTransformFeedbackVaryingsCHROMIUM) /* 489 */ \
+ OP(GetUniformsES3CHROMIUM) /* 490 */ \
+ OP(GetTranslatedShaderSourceANGLE) /* 491 */ \
+ OP(PostSubBufferCHROMIUM) /* 492 */ \
+ OP(TexImageIOSurface2DCHROMIUM) /* 493 */ \
+ OP(CopyTextureCHROMIUM) /* 494 */ \
+ OP(DrawArraysInstancedANGLE) /* 495 */ \
+ OP(DrawElementsInstancedANGLE) /* 496 */ \
+ OP(VertexAttribDivisorANGLE) /* 497 */ \
+ OP(GenMailboxCHROMIUM) /* 498 */ \
+ OP(ProduceTextureCHROMIUMImmediate) /* 499 */ \
+ OP(ProduceTextureDirectCHROMIUMImmediate) /* 500 */ \
+ OP(ConsumeTextureCHROMIUMImmediate) /* 501 */ \
+ OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 502 */ \
+ OP(BindUniformLocationCHROMIUMBucket) /* 503 */ \
+ OP(GenValuebuffersCHROMIUMImmediate) /* 504 */ \
+ OP(DeleteValuebuffersCHROMIUMImmediate) /* 505 */ \
+ OP(IsValuebufferCHROMIUM) /* 506 */ \
+ OP(BindValuebufferCHROMIUM) /* 507 */ \
+ OP(SubscribeValueCHROMIUM) /* 508 */ \
+ OP(PopulateSubscribedValuesCHROMIUM) /* 509 */ \
+ OP(UniformValuebufferCHROMIUM) /* 510 */ \
+ OP(BindTexImage2DCHROMIUM) /* 511 */ \
+ OP(ReleaseTexImage2DCHROMIUM) /* 512 */ \
+ OP(TraceBeginCHROMIUM) /* 513 */ \
+ OP(TraceEndCHROMIUM) /* 514 */ \
+ OP(AsyncTexSubImage2DCHROMIUM) /* 515 */ \
+ OP(AsyncTexImage2DCHROMIUM) /* 516 */ \
+ OP(WaitAsyncTexImage2DCHROMIUM) /* 517 */ \
+ OP(WaitAllAsyncTexImage2DCHROMIUM) /* 518 */ \
+ OP(DiscardFramebufferEXTImmediate) /* 519 */ \
+ OP(LoseContextCHROMIUM) /* 520 */ \
+ OP(InsertSyncPointCHROMIUM) /* 521 */ \
+ OP(WaitSyncPointCHROMIUM) /* 522 */ \
+ OP(DrawBuffersEXTImmediate) /* 523 */ \
+ OP(DiscardBackbufferCHROMIUM) /* 524 */ \
+ OP(ScheduleOverlayPlaneCHROMIUM) /* 525 */ \
+ OP(SwapInterval) /* 526 */ \
+ OP(MatrixLoadfCHROMIUMImmediate) /* 527 */ \
+ OP(MatrixLoadIdentityCHROMIUM) /* 528 */ \
+ OP(BlendBarrierKHR) /* 529 */
enum CommandId {
kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
index a2f4ca7..17a53db 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -78,6 +78,8 @@
static std::string GetStringTextureWrapMode(uint32_t value);
static std::string GetStringTransformFeedbackBindTarget(uint32_t value);
static std::string GetStringTransformFeedbackPrimitiveMode(uint32_t value);
+static std::string GetStringUniformBlockParameter(uint32_t value);
+static std::string GetStringUniformParameter(uint32_t value);
static std::string GetStringValueBufferTarget(uint32_t value);
static std::string GetStringVertexAttribType(uint32_t value);
static std::string GetStringVertexAttribute(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 db3a6c4..273b1e0 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -5260,6 +5260,38 @@
arraysize(string_table), value);
}
+std::string GLES2Util::GetStringUniformBlockParameter(uint32_t value) {
+ static const EnumToString string_table[] = {
+ {GL_UNIFORM_BLOCK_BINDING, "GL_UNIFORM_BLOCK_BINDING"},
+ {GL_UNIFORM_BLOCK_DATA_SIZE, "GL_UNIFORM_BLOCK_DATA_SIZE"},
+ {GL_UNIFORM_BLOCK_NAME_LENGTH, "GL_UNIFORM_BLOCK_NAME_LENGTH"},
+ {GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, "GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"},
+ {GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
+ "GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"},
+ {GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
+ "GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"},
+ {GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
+ "GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"},
+ };
+ return GLES2Util::GetQualifiedEnumString(string_table,
+ arraysize(string_table), value);
+}
+
+std::string GLES2Util::GetStringUniformParameter(uint32_t value) {
+ static const EnumToString string_table[] = {
+ {GL_UNIFORM_SIZE, "GL_UNIFORM_SIZE"},
+ {GL_UNIFORM_TYPE, "GL_UNIFORM_TYPE"},
+ {GL_UNIFORM_NAME_LENGTH, "GL_UNIFORM_NAME_LENGTH"},
+ {GL_UNIFORM_BLOCK_INDEX, "GL_UNIFORM_BLOCK_INDEX"},
+ {GL_UNIFORM_OFFSET, "GL_UNIFORM_OFFSET"},
+ {GL_UNIFORM_ARRAY_STRIDE, "GL_UNIFORM_ARRAY_STRIDE"},
+ {GL_UNIFORM_MATRIX_STRIDE, "GL_UNIFORM_MATRIX_STRIDE"},
+ {GL_UNIFORM_IS_ROW_MAJOR, "GL_UNIFORM_IS_ROW_MAJOR"},
+ };
+ return GLES2Util::GetQualifiedEnumString(string_table,
+ arraysize(string_table), value);
+}
+
std::string GLES2Util::GetStringValueBufferTarget(uint32_t value) {
static const EnumToString string_table[] = {
{GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM,
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 58c9977..219a4c6 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -9,6 +9,8 @@
sources = [
"async_pixel_transfer_delegate.cc",
"async_pixel_transfer_delegate.h",
+ "async_pixel_transfer_manager.cc",
+ "async_pixel_transfer_manager.h",
"async_pixel_transfer_manager_android.cc",
"async_pixel_transfer_manager_idle.cc",
"async_pixel_transfer_manager_idle.h",
@@ -21,10 +23,8 @@
"async_pixel_transfer_manager_sync.cc",
"async_pixel_transfer_manager_sync.h",
"async_pixel_transfer_manager_win.cc",
- "async_pixel_transfer_manager.cc",
- "async_pixel_transfer_manager.h",
- "buffer_manager.h",
"buffer_manager.cc",
+ "buffer_manager.h",
"cmd_buffer_engine.h",
"cmd_parser.cc",
"cmd_parser.h",
@@ -32,34 +32,34 @@
"command_buffer_service.h",
"common_decoder.cc",
"common_decoder.h",
- "context_group.h",
"context_group.cc",
+ "context_group.h",
+ "context_state.cc",
"context_state.h",
"context_state_autogen.h",
"context_state_impl_autogen.h",
- "context_state.cc",
"error_state.cc",
"error_state.h",
- "feature_info.h",
"feature_info.cc",
- "framebuffer_manager.h",
+ "feature_info.h",
"framebuffer_manager.cc",
- "gles2_cmd_clear_framebuffer.cc",
- "gles2_cmd_clear_framebuffer.h",
- "gles2_cmd_copy_texture_chromium.cc",
- "gles2_cmd_copy_texture_chromium.h",
- "gles2_cmd_decoder.h",
- "gles2_cmd_decoder_autogen.h",
- "gles2_cmd_decoder.cc",
- "gles2_cmd_validation.h",
- "gles2_cmd_validation.cc",
- "gles2_cmd_validation_autogen.h",
- "gles2_cmd_validation_implementation_autogen.h",
+ "framebuffer_manager.h",
"gl_context_virtual.cc",
"gl_context_virtual.h",
"gl_state_restorer_impl.cc",
"gl_state_restorer_impl.h",
"gl_utils.h",
+ "gles2_cmd_clear_framebuffer.cc",
+ "gles2_cmd_clear_framebuffer.h",
+ "gles2_cmd_copy_texture_chromium.cc",
+ "gles2_cmd_copy_texture_chromium.h",
+ "gles2_cmd_decoder.cc",
+ "gles2_cmd_decoder.h",
+ "gles2_cmd_decoder_autogen.h",
+ "gles2_cmd_validation.cc",
+ "gles2_cmd_validation.h",
+ "gles2_cmd_validation_autogen.h",
+ "gles2_cmd_validation_implementation_autogen.h",
"gpu_scheduler.cc",
"gpu_scheduler.h",
"gpu_scheduler_mock.h",
@@ -67,10 +67,12 @@
"gpu_state_tracer.h",
"gpu_switches.cc",
"gpu_switches.h",
+ "gpu_timing.cc",
+ "gpu_timing.h",
"gpu_tracer.cc",
"gpu_tracer.h",
- "id_manager.h",
"id_manager.cc",
+ "id_manager.h",
"image_factory.cc",
"image_factory.h",
"image_manager.cc",
@@ -84,39 +86,39 @@
"mailbox_manager_impl.h",
"mailbox_manager_sync.cc",
"mailbox_manager_sync.h",
- "memory_program_cache.h",
"memory_program_cache.cc",
+ "memory_program_cache.h",
"mocks.h",
- "program_manager.h",
- "program_manager.cc",
- "query_manager.h",
- "query_manager.cc",
- "renderbuffer_manager.h",
- "renderbuffer_manager.cc",
- "program_cache.h",
"program_cache.cc",
- "shader_manager.h",
+ "program_cache.h",
+ "program_manager.cc",
+ "program_manager.h",
+ "query_manager.cc",
+ "query_manager.h",
+ "renderbuffer_manager.cc",
+ "renderbuffer_manager.h",
"shader_manager.cc",
- "shader_translator.h",
+ "shader_manager.h",
"shader_translator.cc",
- "shader_translator_cache.h",
+ "shader_translator.h",
"shader_translator_cache.cc",
- "stream_texture_manager_in_process_android.h",
+ "shader_translator_cache.h",
"stream_texture_manager_in_process_android.cc",
- "sync_point_manager.h",
+ "stream_texture_manager_in_process_android.h",
"sync_point_manager.cc",
- "texture_definition.h",
+ "sync_point_manager.h",
"texture_definition.cc",
- "texture_manager.h",
+ "texture_definition.h",
"texture_manager.cc",
+ "texture_manager.h",
"transfer_buffer_manager.cc",
"transfer_buffer_manager.h",
- "valuebuffer_manager.h",
"valuebuffer_manager.cc",
- "vertex_array_manager.h",
+ "valuebuffer_manager.h",
"vertex_array_manager.cc",
- "vertex_attrib_manager.h",
+ "vertex_array_manager.h",
"vertex_attrib_manager.cc",
+ "vertex_attrib_manager.h",
]
defines = [ "GPU_IMPLEMENTATION" ]
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc
index f40c721..99fdb76 100644
--- a/gpu/command_buffer/service/common_decoder.cc
+++ b/gpu/command_buffer/service/common_decoder.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "gpu/command_buffer/service/common_decoder.h"
+
+#include "base/numerics/safe_math.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
namespace gpu {
@@ -69,6 +71,53 @@
return true;
}
+bool CommonDecoder::Bucket::GetAsStrings(
+ GLsizei* _count, std::vector<char*>* _string, std::vector<GLint>* _length) {
+ const size_t kMinBucketSize = sizeof(GLint);
+ // Each string has at least |length| in the header and a NUL character.
+ const size_t kMinStringSize = sizeof(GLint) + 1;
+ const size_t bucket_size = this->size();
+ if (bucket_size < kMinBucketSize) {
+ return false;
+ }
+ char* bucket_data = this->GetDataAs<char*>(0, bucket_size);
+ GLint* header = reinterpret_cast<GLint*>(bucket_data);
+ GLsizei count = static_cast<GLsizei>(header[0]);
+ if (count < 0) {
+ return false;
+ }
+ const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize;
+ if (max_count < static_cast<size_t>(count)) {
+ return false;
+ }
+ GLint* length = header + 1;
+ std::vector<char*> strs(count);
+ base::CheckedNumeric<size_t> total_size = sizeof(GLint);
+ total_size *= count + 1; // Header size.
+ if (!total_size.IsValid())
+ return false;
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ strs[ii] = bucket_data + total_size.ValueOrDefault(0);
+ total_size += length[ii];
+ total_size += 1; // NUL char at the end of each char array.
+ if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size ||
+ strs[ii][length[ii]] != 0) {
+ return false;
+ }
+ }
+ if (total_size.ValueOrDefault(0) != bucket_size) {
+ return false;
+ }
+ DCHECK(_count && _string && _length);
+ *_count = count;
+ *_string = strs;
+ _length->resize(count);
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ (*_length)[ii] = length[ii];
+ }
+ return true;
+}
+
CommonDecoder::CommonDecoder() : engine_(NULL) {}
CommonDecoder::~CommonDecoder() {}
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h
index fc9ecf2..53de875 100644
--- a/gpu/command_buffer/service/common_decoder.h
+++ b/gpu/command_buffer/service/common_decoder.h
@@ -14,6 +14,10 @@
#include "gpu/command_buffer/service/cmd_parser.h"
#include "gpu/gpu_export.h"
+// Forwardly declare a few GL types to avoid including GL header files.
+typedef int GLsizei;
+typedef int GLint;
+
namespace gpu {
class CommandBufferEngine;
@@ -82,6 +86,13 @@
// is no string.
bool GetAsString(std::string* str);
+ // Gets the bucket data as strings.
+ // On success, the number of strings are in |_count|, the string data are
+ // in |_string|, and string sizes are in |_length|..
+ bool GetAsStrings(GLsizei* _count,
+ std::vector<char*>* _string,
+ std::vector<GLint>* _length);
+
private:
bool OffsetSizeValid(size_t offset, size_t size) const {
size_t temp = offset + size;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 9b8e635..52a9c43 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1684,6 +1684,11 @@
surface_->DeferDraws();
}
+ bool IsRobustnessSupported() {
+ return has_robustness_extension_ &&
+ context_->WasAllocatedUsingRobustnessExtension();
+ }
+
error::Error WillAccessBoundFramebufferForDraw() {
if (ShouldDeferDraws())
return error::kDeferCommandUntilLater;
@@ -1820,8 +1825,8 @@
error::Error current_decoder_error_;
bool use_shader_translator_;
- scoped_refptr<ShaderTranslator> vertex_translator_;
- scoped_refptr<ShaderTranslator> fragment_translator_;
+ scoped_refptr<ShaderTranslatorInterface> vertex_translator_;
+ scoped_refptr<ShaderTranslatorInterface> fragment_translator_;
DisallowedFeatures disallowed_features_;
@@ -5837,15 +5842,7 @@
}
LogClientServiceForInfo(program, program_id, "glLinkProgram");
- ShaderTranslator* vertex_translator = NULL;
- ShaderTranslator* fragment_translator = NULL;
- if (use_shader_translator_) {
- vertex_translator = vertex_translator_.get();
- fragment_translator = fragment_translator_.get();
- }
if (program->Link(shader_manager(),
- vertex_translator,
- fragment_translator,
workarounds().count_all_in_varyings_packing ?
Program::kCountAll : Program::kCountOnlyStaticallyUsed,
shader_cache_callback_)) {
@@ -7091,24 +7088,17 @@
if (!shader) {
return;
}
- ShaderTranslator* translator = NULL;
+
+ scoped_refptr<ShaderTranslatorInterface> translator;
if (use_shader_translator_) {
- translator = shader->shader_type() == GL_VERTEX_SHADER ?
- vertex_translator_.get() : fragment_translator_.get();
+ translator = shader->shader_type() == GL_VERTEX_SHADER ?
+ vertex_translator_ : fragment_translator_;
}
- shader->RequestCompile();
-
- // TODO(dyen): Currently we compile immediately when glCompileShader is
- // requested. Eventually this should be deffered to the linker stage.
- shader->DoCompile(
- translator,
- feature_info_->feature_flags().angle_translated_shader_source ?
- Shader::kANGLE : Shader::kGL);
-
- // CompileShader can be very slow. Exit command processing to allow for
- // context preemption and GPU watchdog checks.
- ExitCommandProcessingEarly();
+ const Shader::TranslatedShaderSourceType source_type =
+ feature_info_->feature_flags().angle_translated_shader_source ?
+ Shader::kANGLE : Shader::kGL;
+ shader->RequestCompile(translator, source_type);
}
void GLES2DecoderImpl::DoGetShaderiv(
@@ -7117,6 +7107,19 @@
if (!shader) {
return;
}
+
+ // Compile now for statuses that require it.
+ switch (pname) {
+ case GL_COMPILE_STATUS:
+ case GL_INFO_LOG_LENGTH:
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ shader->DoCompile();
+ break;
+
+ default:
+ break;
+ }
+
switch (pname) {
case GL_SHADER_SOURCE_LENGTH:
*params = shader->source().size();
@@ -7174,6 +7177,9 @@
return error::kNoError;
}
+ // Make sure translator has been utilized in compile.
+ shader->DoCompile();
+
bucket->SetFromString(shader->translated_source().c_str());
return error::kNoError;
}
@@ -7209,6 +7215,10 @@
bucket->SetFromString("");
return error::kNoError;
}
+
+ // Shader must be compiled in order to get the info log.
+ shader->DoCompile();
+
bucket->SetFromString(shader->log_info().c_str());
return error::kNoError;
}
@@ -8160,6 +8170,58 @@
c.program, c.location_shm_id, c.location_shm_offset, name_str);
}
+error::Error GLES2DecoderImpl::HandleGetUniformIndices(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetUniformIndices& c =
+ *static_cast<const gles2::cmds::GetUniformIndices*>(cmd_data);
+ Bucket* bucket = GetBucket(c.names_bucket_id);
+ if (!bucket) {
+ return error::kInvalidArguments;
+ }
+ GLsizei count = 0;
+ std::vector<char*> names;
+ std::vector<GLint> len;
+ if (!bucket->GetAsStrings(&count, &names, &len) || count <= 0) {
+ return error::kInvalidArguments;
+ }
+ typedef cmds::GetUniformIndices::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>(
+ c.indices_shm_id, c.indices_shm_offset,
+ Result::ComputeSize(static_cast<size_t>(count)));
+ GLuint* indices = result ? result->GetData() : NULL;
+ if (indices == NULL) {
+ return error::kOutOfBounds;
+ }
+ // Check that the client initialized the result.
+ if (result->size != 0) {
+ return error::kInvalidArguments;
+ }
+ Program* program = GetProgramInfoNotShader(c.program, "glGetUniformIndices");
+ if (!program) {
+ return error::kNoError;
+ }
+ GLuint service_id = program->service_id();
+ GLint link_status = GL_FALSE;
+ glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
+ if (link_status != GL_TRUE) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glGetUniformIndices", "program not linked");
+ return error::kNoError;
+ }
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetUniformIndices");
+ glGetUniformIndices(service_id, count, &names[0], indices);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ result->SetNumResults(count);
+ } else {
+ LOCAL_SET_GL_ERROR(error, "GetUniformIndices", "");
+ }
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::GetFragDataLocationHelper(
GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
const std::string& name_str) {
@@ -9730,6 +9792,63 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockiv(
+ uint32 immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetActiveUniformBlockiv& c =
+ *static_cast<const gles2::cmds::GetActiveUniformBlockiv*>(cmd_data);
+ GLuint program_id = c.program;
+ GLuint index = static_cast<GLuint>(c.index);
+ GLenum pname = static_cast<GLenum>(c.pname);
+ Program* program = GetProgramInfoNotShader(
+ program_id, "glGetActiveUniformBlockiv");
+ if (!program) {
+ return error::kNoError;
+ }
+ GLuint service_id = program->service_id();
+ GLint link_status = GL_FALSE;
+ glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
+ if (link_status != GL_TRUE) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glGetActiveActiveUniformBlockiv", "program not linked");
+ return error::kNoError;
+ }
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformBlockiv");
+ GLsizei num_values = 1;
+ if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
+ GLint num = 0;
+ glGetActiveUniformBlockiv(
+ service_id, index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &num);
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR) {
+ // Assume this will the same error if calling with pname.
+ LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
+ return error::kNoError;
+ }
+ num_values = static_cast<GLsizei>(num);
+ }
+ typedef cmds::GetActiveUniformBlockiv::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>(
+ c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values));
+ GLint* params = result ? result->GetData() : NULL;
+ if (params == NULL) {
+ return error::kOutOfBounds;
+ }
+ // Check that the client initialized the result.
+ if (result->size != 0) {
+ return error::kInvalidArguments;
+ }
+ glGetActiveUniformBlockiv(service_id, index, pname, params);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ result->SetNumResults(num_values);
+ } else {
+ LOCAL_SET_GL_ERROR(error, "GetActiveUniformBlockiv", "");
+ }
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleGetActiveUniformBlockName(
uint32 immediate_data_size, const void* cmd_data) {
if (!unsafe_es3_apis_enabled())
@@ -9783,6 +9902,55 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleGetActiveUniformsiv(
+ uint32 immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetActiveUniformsiv& c =
+ *static_cast<const gles2::cmds::GetActiveUniformsiv*>(cmd_data);
+ GLuint program_id = c.program;
+ GLenum pname = static_cast<GLenum>(c.pname);
+ Bucket* bucket = GetBucket(c.indices_bucket_id);
+ if (!bucket) {
+ return error::kInvalidArguments;
+ }
+ GLsizei count = static_cast<GLsizei>(bucket->size() / sizeof(GLuint));
+ const GLuint* indices = bucket->GetDataAs<const GLuint*>(0, bucket->size());
+ typedef cmds::GetActiveUniformsiv::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>(
+ c.params_shm_id, c.params_shm_offset, Result::ComputeSize(count));
+ GLint* params = result ? result->GetData() : NULL;
+ if (params == NULL) {
+ return error::kOutOfBounds;
+ }
+ // Check that the client initialized the result.
+ if (result->size != 0) {
+ return error::kInvalidArguments;
+ }
+ Program* program = GetProgramInfoNotShader(
+ program_id, "glGetActiveUniformsiv");
+ if (!program) {
+ return error::kNoError;
+ }
+ GLuint service_id = program->service_id();
+ GLint link_status = GL_FALSE;
+ glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
+ if (link_status != GL_TRUE) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glGetActiveUniformsiv", "program not linked");
+ return error::kNoError;
+ }
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetActiveUniformsiv");
+ glGetActiveUniformsiv(service_id, count, indices, pname, params);
+ GLenum error = glGetError();
+ if (error == GL_NO_ERROR) {
+ result->SetNumResults(count);
+ } else {
+ LOCAL_SET_GL_ERROR(error, "GetActiveUniformsiv", "");
+ }
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::HandleGetActiveAttrib(uint32 immediate_data_size,
const void* cmd_data) {
const gles2::cmds::GetActiveAttrib& c =
@@ -10136,6 +10304,104 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleGetUniformsES3CHROMIUM(
+ uint32 immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetUniformsES3CHROMIUM& c =
+ *static_cast<const gles2::cmds::GetUniformsES3CHROMIUM*>(cmd_data);
+ GLuint program_id = static_cast<GLuint>(c.program);
+ uint32 bucket_id = c.bucket_id;
+ Bucket* bucket = CreateBucket(bucket_id);
+ bucket->SetSize(sizeof(UniformsES3Header)); // in case we fail.
+ Program* program = NULL;
+ program = GetProgram(program_id);
+ if (!program || !program->IsValid()) {
+ return error::kNoError;
+ }
+ program->GetUniformsES3(bucket);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVarying(
+ uint32 immediate_data_size,
+ const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetTransformFeedbackVarying& c =
+ *static_cast<const gles2::cmds::GetTransformFeedbackVarying*>(cmd_data);
+ GLuint program_id = c.program;
+ GLuint index = c.index;
+ uint32 name_bucket_id = c.name_bucket_id;
+ typedef cmds::GetTransformFeedbackVarying::Result Result;
+ Result* result = GetSharedMemoryAs<Result*>(
+ c.result_shm_id, c.result_shm_offset, sizeof(*result));
+ if (!result) {
+ return error::kOutOfBounds;
+ }
+ // Check that the client initialized the result.
+ if (result->success != 0) {
+ return error::kInvalidArguments;
+ }
+ Program* program = GetProgramInfoNotShader(
+ program_id, "glGetTransformFeedbackVarying");
+ if (!program) {
+ return error::kNoError;
+ }
+ GLuint service_id = program->service_id();
+ GLint link_status = GL_FALSE;
+ glGetProgramiv(service_id, GL_LINK_STATUS, &link_status);
+ if (link_status != GL_TRUE) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glGetTransformFeedbackVarying", "program not linked");
+ return error::kNoError;
+ }
+ GLint max_length = 0;
+ glGetProgramiv(
+ service_id, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_length);
+ max_length = std::max(1, max_length);
+ std::vector<char> buffer(max_length);
+ GLsizei length = 0;
+ GLsizei size = 0;
+ GLenum type = 0;
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetTransformFeedbackVarying");
+ glGetTransformFeedbackVarying(
+ service_id, index, max_length, &length, &size, &type, &buffer[0]);
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR) {
+ LOCAL_SET_GL_ERROR(error, "glGetTransformFeedbackVarying", "");
+ return error::kNoError;
+ }
+ result->success = 1; // true.
+ result->size = static_cast<int32_t>(size);
+ result->type = static_cast<uint32_t>(type);
+ Bucket* bucket = CreateBucket(name_bucket_id);
+ DCHECK(length >= 0 && length < max_length);
+ buffer[length] = '\0'; // Just to be safe.
+ bucket->SetFromString(&buffer[0]);
+ return error::kNoError;
+}
+
+error::Error GLES2DecoderImpl::HandleGetTransformFeedbackVaryingsCHROMIUM(
+ uint32 immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM& c =
+ *static_cast<const gles2::cmds::GetTransformFeedbackVaryingsCHROMIUM*>(
+ cmd_data);
+ GLuint program_id = static_cast<GLuint>(c.program);
+ uint32 bucket_id = c.bucket_id;
+ Bucket* bucket = CreateBucket(bucket_id);
+ bucket->SetSize(sizeof(TransformFeedbackVaryingsHeader)); // in case we fail.
+ Program* program = NULL;
+ program = GetProgram(program_id);
+ if (!program || !program->IsValid()) {
+ return error::kNoError;
+ }
+ program->GetTransformFeedbackVaryings(bucket);
+ return error::kNoError;
+}
+
error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() {
switch (reset_status_) {
case GL_NO_ERROR:
@@ -10172,10 +10438,8 @@
MaybeExitOnContextLost();
return true;
}
- if (context_->WasAllocatedUsingRobustnessExtension()) {
- GLenum status = GL_NO_ERROR;
- if (has_robustness_extension_)
- status = glGetGraphicsResetStatusARB();
+ if (IsRobustnessSupported()) {
+ GLenum status = glGetGraphicsResetStatusARB();
if (status != GL_NO_ERROR) {
// The graphics card was reset. Signal a lost context to the application.
reset_status_ = status;
@@ -10207,7 +10471,7 @@
reset_status = GL_UNKNOWN_CONTEXT_RESET_ARB;
}
} else if (reset_status == GL_UNKNOWN_CONTEXT_RESET_ARB &&
- has_robustness_extension_) {
+ IsRobustnessSupported()) {
// If the reason for the call was a GL error, we can try to determine the
// reset status more accurately.
GLenum driver_status = glGetGraphicsResetStatusARB();
@@ -11772,6 +12036,25 @@
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleUniformBlockBinding(
+ uint32_t immediate_data_size, const void* cmd_data) {
+ if (!unsafe_es3_apis_enabled())
+ return error::kUnknownCommand;
+ const gles2::cmds::UniformBlockBinding& c =
+ *static_cast<const gles2::cmds::UniformBlockBinding*>(cmd_data);
+ GLuint client_id = c.program;
+ GLuint index = static_cast<GLuint>(c.index);
+ GLuint binding = static_cast<GLuint>(c.binding);
+ Program* program = GetProgramInfoNotShader(
+ client_id, "glUniformBlockBinding");
+ if (!program) {
+ return error::kNoError;
+ }
+ GLuint service_id = program->service_id();
+ glUniformBlockBinding(service_id, index, binding);
+ return error::kNoError;
+}
+
void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
TextureRef* texture_ref) {
Texture* texture = texture_ref->texture();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 720d54e..49fa872 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -2432,48 +2432,21 @@
(void)c;
GLuint shader = static_cast<GLuint>(c.shader);
- const size_t kMinBucketSize = sizeof(GLint);
- // Each string has at least |length| in the header and a NUL character.
- const size_t kMinStringSize = sizeof(GLint) + 1;
Bucket* bucket = GetBucket(c.str_bucket_id);
if (!bucket) {
return error::kInvalidArguments;
}
- const size_t bucket_size = bucket->size();
- if (bucket_size < kMinBucketSize) {
+ GLsizei count = 0;
+ std::vector<char*> strs;
+ std::vector<GLint> len;
+ if (!bucket->GetAsStrings(&count, &strs, &len)) {
return error::kInvalidArguments;
}
- const char* bucket_data = bucket->GetDataAs<const char*>(0, bucket_size);
- const GLint* header = reinterpret_cast<const GLint*>(bucket_data);
- GLsizei count = static_cast<GLsizei>(header[0]);
- if (count < 0) {
- return error::kInvalidArguments;
- }
- const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize;
- if (max_count < static_cast<size_t>(count)) {
- return error::kInvalidArguments;
- }
- const GLint* length = header + 1;
- scoped_ptr<const char* []> strs;
- if (count > 0)
- strs.reset(new const char* [count]);
- const char** str = strs.get();
- base::CheckedNumeric<size_t> total_size = sizeof(GLint);
- total_size *= count + 1; // Header size.
- if (!total_size.IsValid())
- return error::kInvalidArguments;
- for (GLsizei ii = 0; ii < count; ++ii) {
- str[ii] = bucket_data + total_size.ValueOrDefault(0);
- total_size += length[ii];
- total_size += 1; // NUL char at the end of each char array.
- if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size ||
- str[ii][length[ii]] != 0) {
- return error::kInvalidArguments;
- }
- }
- if (total_size.ValueOrDefault(0) != bucket_size) {
- return error::kInvalidArguments;
- }
+ const char** str =
+ strs.size() > 0 ? const_cast<const char**>(&strs[0]) : NULL;
+ const GLint* length =
+ len.size() > 0 ? const_cast<const GLint*>(&len[0]) : NULL;
+ (void)length;
DoShaderSource(shader, count, str, length);
return error::kNoError;
}
@@ -2817,48 +2790,21 @@
(void)c;
GLuint program = static_cast<GLuint>(c.program);
- const size_t kMinBucketSize = sizeof(GLint);
- // Each string has at least |length| in the header and a NUL character.
- const size_t kMinStringSize = sizeof(GLint) + 1;
Bucket* bucket = GetBucket(c.varyings_bucket_id);
if (!bucket) {
return error::kInvalidArguments;
}
- const size_t bucket_size = bucket->size();
- if (bucket_size < kMinBucketSize) {
+ GLsizei count = 0;
+ std::vector<char*> strs;
+ std::vector<GLint> len;
+ if (!bucket->GetAsStrings(&count, &strs, &len)) {
return error::kInvalidArguments;
}
- const char* bucket_data = bucket->GetDataAs<const char*>(0, bucket_size);
- const GLint* header = reinterpret_cast<const GLint*>(bucket_data);
- GLsizei count = static_cast<GLsizei>(header[0]);
- if (count < 0) {
- return error::kInvalidArguments;
- }
- const size_t max_count = (bucket_size - kMinBucketSize) / kMinStringSize;
- if (max_count < static_cast<size_t>(count)) {
- return error::kInvalidArguments;
- }
- const GLint* length = header + 1;
- scoped_ptr<const char* []> strs;
- if (count > 0)
- strs.reset(new const char* [count]);
- const char** varyings = strs.get();
- base::CheckedNumeric<size_t> total_size = sizeof(GLint);
- total_size *= count + 1; // Header size.
- if (!total_size.IsValid())
- return error::kInvalidArguments;
- for (GLsizei ii = 0; ii < count; ++ii) {
- varyings[ii] = bucket_data + total_size.ValueOrDefault(0);
- total_size += length[ii];
- total_size += 1; // NUL char at the end of each char array.
- if (!total_size.IsValid() || total_size.ValueOrDefault(0) > bucket_size ||
- varyings[ii][length[ii]] != 0) {
- return error::kInvalidArguments;
- }
- }
- if (total_size.ValueOrDefault(0) != bucket_size) {
- return error::kInvalidArguments;
- }
+ const char** varyings =
+ strs.size() > 0 ? const_cast<const char**>(&strs[0]) : NULL;
+ const GLint* length =
+ len.size() > 0 ? const_cast<const GLint*>(&len[0]) : NULL;
+ (void)length;
GLenum buffermode = static_cast<GLenum>(c.buffermode);
DoTransformFeedbackVaryings(program, count, varyings, buffermode);
return error::kNoError;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
index 381bb0c..80a0ce3 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1.cc
@@ -248,7 +248,7 @@
attach_cmd.Init(client_program_id_, kClientFragmentShaderId);
EXPECT_EQ(error::kNoError, ExecuteCmd(attach_cmd));
- program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
};
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
index 99f26e9..a255fe8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
@@ -1208,8 +1208,12 @@
// TODO(gman): GetActiveUniform
+// TODO(gman): GetActiveUniformBlockiv
+
// TODO(gman): GetActiveUniformBlockName
+// TODO(gman): GetActiveUniformsiv
+
// TODO(gman): GetAttachedShaders
// TODO(gman): GetAttribLocation
@@ -1808,151 +1812,4 @@
// TODO(gman): GetShaderSource
// TODO(gman): GetString
-TEST_P(GLES2DecoderTest1, GetTexParameterfvValidArgs) {
- EXPECT_CALL(*gl_, GetError())
- .WillOnce(Return(GL_NO_ERROR))
- .WillOnce(Return(GL_NO_ERROR))
- .RetiresOnSaturation();
- SpecializedSetup<cmds::GetTexParameterfv, 0>(true);
- typedef cmds::GetTexParameterfv::Result Result;
- Result* result = static_cast<Result*>(shared_memory_address_);
- EXPECT_CALL(*gl_, GetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- result->GetData()));
- result->size = 0;
- cmds::GetTexParameterfv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
- shared_memory_offset_);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(
- decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER),
- result->GetNumResults());
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs0_0) {
- EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
- cmds::GetTexParameterfv::Result* result =
- static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameterfv cmd;
- cmd.Init(GL_PROXY_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
- shared_memory_offset_);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
- EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs1_0) {
- EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
- cmds::GetTexParameterfv::Result* result =
- static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameterfv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_,
- shared_memory_offset_);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
- EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs2_0) {
- EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
- cmds::GetTexParameterfv::Result* result =
- static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameterfv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, kInvalidSharedMemoryId, 0);
- EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterfvInvalidArgs2_1) {
- EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
- cmds::GetTexParameterfv::Result* result =
- static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameterfv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
- kInvalidSharedMemoryOffset);
- EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterivValidArgs) {
- EXPECT_CALL(*gl_, GetError())
- .WillOnce(Return(GL_NO_ERROR))
- .WillOnce(Return(GL_NO_ERROR))
- .RetiresOnSaturation();
- SpecializedSetup<cmds::GetTexParameteriv, 0>(true);
- typedef cmds::GetTexParameteriv::Result Result;
- Result* result = static_cast<Result*>(shared_memory_address_);
- EXPECT_CALL(*gl_, GetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- result->GetData()));
- result->size = 0;
- cmds::GetTexParameteriv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
- shared_memory_offset_);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(
- decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER),
- result->GetNumResults());
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs0_0) {
- EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
- cmds::GetTexParameteriv::Result* result =
- static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameteriv cmd;
- cmd.Init(GL_PROXY_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
- shared_memory_offset_);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
- EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs1_0) {
- EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
- cmds::GetTexParameteriv::Result* result =
- static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameteriv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_,
- shared_memory_offset_);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
- EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_0) {
- EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
- cmds::GetTexParameteriv::Result* result =
- static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameteriv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, kInvalidSharedMemoryId, 0);
- EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
-}
-
-TEST_P(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_1) {
- EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
- SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
- cmds::GetTexParameteriv::Result* result =
- static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
- result->size = 0;
- cmds::GetTexParameteriv cmd;
- cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
- kInvalidSharedMemoryOffset);
- EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
- EXPECT_EQ(0u, result->size);
-}
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index 60d147b..2e60219 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -12,12 +12,163 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
+TEST_P(GLES2DecoderTest2, GetTexParameterfvValidArgs) {
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ SpecializedSetup<cmds::GetTexParameterfv, 0>(true);
+ typedef cmds::GetTexParameterfv::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ EXPECT_CALL(*gl_, GetTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ result->GetData()));
+ result->size = 0;
+ cmds::GetTexParameterfv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(
+ decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER),
+ result->GetNumResults());
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterfvInvalidArgs0_0) {
+ EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
+ cmds::GetTexParameterfv::Result* result =
+ static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameterfv cmd;
+ cmd.Init(GL_PROXY_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterfvInvalidArgs1_0) {
+ EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
+ cmds::GetTexParameterfv::Result* result =
+ static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameterfv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterfvInvalidArgs2_0) {
+ EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
+ cmds::GetTexParameterfv::Result* result =
+ static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameterfv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, kInvalidSharedMemoryId, 0);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterfvInvalidArgs2_1) {
+ EXPECT_CALL(*gl_, GetTexParameterfv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameterfv, 0>(false);
+ cmds::GetTexParameterfv::Result* result =
+ static_cast<cmds::GetTexParameterfv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameterfv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
+ kInvalidSharedMemoryOffset);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterivValidArgs) {
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ SpecializedSetup<cmds::GetTexParameteriv, 0>(true);
+ typedef cmds::GetTexParameteriv::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ EXPECT_CALL(*gl_, GetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ result->GetData()));
+ result->size = 0;
+ cmds::GetTexParameteriv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(
+ decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER),
+ result->GetNumResults());
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterivInvalidArgs0_0) {
+ EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
+ cmds::GetTexParameteriv::Result* result =
+ static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameteriv cmd;
+ cmd.Init(GL_PROXY_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterivInvalidArgs1_0) {
+ EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
+ cmds::GetTexParameteriv::Result* result =
+ static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameteriv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+ EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterivInvalidArgs2_0) {
+ EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
+ cmds::GetTexParameteriv::Result* result =
+ static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameteriv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, kInvalidSharedMemoryId, 0);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+}
+
+TEST_P(GLES2DecoderTest2, GetTexParameterivInvalidArgs2_1) {
+ EXPECT_CALL(*gl_, GetTexParameteriv(_, _, _)).Times(0);
+ SpecializedSetup<cmds::GetTexParameteriv, 0>(false);
+ cmds::GetTexParameteriv::Result* result =
+ static_cast<cmds::GetTexParameteriv::Result*>(shared_memory_address_);
+ result->size = 0;
+ cmds::GetTexParameteriv cmd;
+ cmd.Init(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shared_memory_id_,
+ kInvalidSharedMemoryOffset);
+ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
+ EXPECT_EQ(0u, result->size);
+}
+// TODO(gman): GetTransformFeedbackVarying
+
// TODO(gman): GetUniformBlockIndex
// TODO(gman): GetUniformfv
// TODO(gman): GetUniformiv
+// TODO(gman): GetUniformIndices
+
// TODO(gman): GetUniformLocation
TEST_P(GLES2DecoderTest2, GetVertexAttribfvValidArgs) {
@@ -1217,6 +1368,7 @@
decoder_->set_unsafe_es3_apis_enabled(false);
EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp)));
}
+// TODO(gman): UniformBlockBinding
TEST_P(GLES2DecoderTest2, UniformMatrix2fvImmediateValidArgs) {
cmds::UniformMatrix2fvImmediate& cmd =
@@ -1443,62 +1595,4 @@
EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
-
-TEST_P(GLES2DecoderTest2, VertexAttrib3fValidArgs) {
- EXPECT_CALL(*gl_, VertexAttrib3f(1, 2, 3, 4));
- SpecializedSetup<cmds::VertexAttrib3f, 0>(true);
- cmds::VertexAttrib3f cmd;
- cmd.Init(1, 2, 3, 4);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest2, VertexAttrib3fvImmediateValidArgs) {
- cmds::VertexAttrib3fvImmediate& cmd =
- *GetImmediateAs<cmds::VertexAttrib3fvImmediate>();
- SpecializedSetup<cmds::VertexAttrib3fvImmediate, 0>(true);
- GLfloat temp[3] = {
- 0,
- };
- cmd.Init(1, &temp[0]);
- EXPECT_CALL(*gl_, VertexAttrib3fv(1, reinterpret_cast<GLfloat*>(
- ImmediateDataAddress(&cmd))));
- EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest2, VertexAttrib4fValidArgs) {
- EXPECT_CALL(*gl_, VertexAttrib4f(1, 2, 3, 4, 5));
- SpecializedSetup<cmds::VertexAttrib4f, 0>(true);
- cmds::VertexAttrib4f cmd;
- cmd.Init(1, 2, 3, 4, 5);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest2, VertexAttrib4fvImmediateValidArgs) {
- cmds::VertexAttrib4fvImmediate& cmd =
- *GetImmediateAs<cmds::VertexAttrib4fvImmediate>();
- SpecializedSetup<cmds::VertexAttrib4fvImmediate, 0>(true);
- GLfloat temp[4] = {
- 0,
- };
- cmd.Init(1, &temp[0]);
- EXPECT_CALL(*gl_, VertexAttrib4fv(1, reinterpret_cast<GLfloat*>(
- ImmediateDataAddress(&cmd))));
- EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
-}
-
-TEST_P(GLES2DecoderTest2, VertexAttribI4iValidArgs) {
- EXPECT_CALL(*gl_, VertexAttribI4i(1, 2, 3, 4, 5));
- SpecializedSetup<cmds::VertexAttribI4i, 0>(true);
- cmds::VertexAttribI4i cmd;
- cmd.Init(1, 2, 3, 4, 5);
- decoder_->set_unsafe_es3_apis_enabled(true);
- EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
- EXPECT_EQ(GL_NO_ERROR, GetGLError());
- decoder_->set_unsafe_es3_apis_enabled(false);
- EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
-}
#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
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 6421985..7a58038 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
@@ -12,6 +12,64 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_
+TEST_P(GLES2DecoderTest3, VertexAttrib3fValidArgs) {
+ EXPECT_CALL(*gl_, VertexAttrib3f(1, 2, 3, 4));
+ SpecializedSetup<cmds::VertexAttrib3f, 0>(true);
+ cmds::VertexAttrib3f cmd;
+ cmd.Init(1, 2, 3, 4);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest3, VertexAttrib3fvImmediateValidArgs) {
+ cmds::VertexAttrib3fvImmediate& cmd =
+ *GetImmediateAs<cmds::VertexAttrib3fvImmediate>();
+ SpecializedSetup<cmds::VertexAttrib3fvImmediate, 0>(true);
+ GLfloat temp[3] = {
+ 0,
+ };
+ cmd.Init(1, &temp[0]);
+ EXPECT_CALL(*gl_, VertexAttrib3fv(1, reinterpret_cast<GLfloat*>(
+ ImmediateDataAddress(&cmd))));
+ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest3, VertexAttrib4fValidArgs) {
+ EXPECT_CALL(*gl_, VertexAttrib4f(1, 2, 3, 4, 5));
+ SpecializedSetup<cmds::VertexAttrib4f, 0>(true);
+ cmds::VertexAttrib4f cmd;
+ cmd.Init(1, 2, 3, 4, 5);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest3, VertexAttrib4fvImmediateValidArgs) {
+ cmds::VertexAttrib4fvImmediate& cmd =
+ *GetImmediateAs<cmds::VertexAttrib4fvImmediate>();
+ SpecializedSetup<cmds::VertexAttrib4fvImmediate, 0>(true);
+ GLfloat temp[4] = {
+ 0,
+ };
+ cmd.Init(1, &temp[0]);
+ EXPECT_CALL(*gl_, VertexAttrib4fv(1, reinterpret_cast<GLfloat*>(
+ ImmediateDataAddress(&cmd))));
+ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderTest3, VertexAttribI4iValidArgs) {
+ EXPECT_CALL(*gl_, VertexAttribI4i(1, 2, 3, 4, 5));
+ SpecializedSetup<cmds::VertexAttribI4i, 0>(true);
+ cmds::VertexAttribI4i cmd;
+ cmd.Init(1, 2, 3, 4, 5);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
TEST_P(GLES2DecoderTest3, VertexAttribI4ivImmediateValidArgs) {
cmds::VertexAttribI4ivImmediate& cmd =
*GetImmediateAs<cmds::VertexAttribI4ivImmediate>();
@@ -144,6 +202,10 @@
// TODO(gman): GetUniformBlocksCHROMIUM
+// TODO(gman): GetTransformFeedbackVaryingsCHROMIUM
+
+// TODO(gman): GetUniformsES3CHROMIUM
+
// TODO(gman): GetTranslatedShaderSourceANGLE
// TODO(gman): PostSubBufferCHROMIUM
// TODO(gman): TexImageIOSurface2DCHROMIUM
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 807d488..c3fc9ff 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -570,21 +570,26 @@
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
}
-void GLES2DecoderTestBase::SetBucketAsCString(
- uint32 bucket_id, const char* str) {
- uint32 size = str ? (strlen(str) + 1) : 0;
+void GLES2DecoderTestBase::SetBucketData(
+ uint32_t bucket_id, const void* data, uint32_t data_size) {
+ DCHECK(data || data_size == 0);
cmd::SetBucketSize cmd1;
- cmd1.Init(bucket_id, size);
+ cmd1.Init(bucket_id, data_size);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd1));
- if (str) {
- memcpy(shared_memory_address_, str, size);
+ if (data) {
+ memcpy(shared_memory_address_, data, data_size);
cmd::SetBucketData cmd2;
- cmd2.Init(bucket_id, 0, size, kSharedMemoryId, kSharedMemoryOffset);
+ cmd2.Init(bucket_id, 0, data_size, kSharedMemoryId, kSharedMemoryOffset);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd2));
ClearSharedMemory();
}
}
+void GLES2DecoderTestBase::SetBucketAsCString(
+ uint32 bucket_id, const char* str) {
+ SetBucketData(bucket_id, str, str ? (strlen(str) + 1) : 0);
+}
+
void GLES2DecoderTestBase::SetBucketAsCStrings(
uint32 bucket_id, GLsizei count, const char** str,
GLsizei count_in_header, char str_end) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index 3159483..2160174 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -170,6 +170,7 @@
void DoCreateShader(GLenum shader_type, GLuint client_id, GLuint service_id);
void DoFenceSync(GLuint client_id, GLuint service_id);
+ void SetBucketData(uint32_t bucket_id, const void* data, uint32_t data_size);
void SetBucketAsCString(uint32 bucket_id, const char* str);
// If we want a valid bucket, just set |count_in_header| as |count|,
// and set |str_end| as 0.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
index c0e2364..afb9fc7 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
@@ -43,7 +43,6 @@
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SetArrayArgument;
-using ::testing::SetArgumentPointee;
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::StrictMock;
@@ -122,6 +121,93 @@
EXPECT_EQ(0u, header->num_uniform_blocks);
}
+TEST_P(GLES2DecoderWithShaderTest, GetUniformsES3CHROMIUMValidArgs) {
+ const uint32 kBucketId = 123;
+ GetUniformsES3CHROMIUM cmd;
+ cmd.Init(client_program_id_, kBucketId);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORMS, _))
+ .WillOnce(SetArgPointee<2>(0))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ EXPECT_EQ(sizeof(UniformsES3Header), bucket->size());
+ UniformsES3Header* header =
+ bucket->GetDataAs<UniformsES3Header*>(0, sizeof(UniformsES3Header));
+ EXPECT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_uniforms);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformsES3CHROMIUMInvalidArgs) {
+ const uint32 kBucketId = 123;
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ EXPECT_TRUE(bucket == NULL);
+ GetUniformsES3CHROMIUM cmd;
+ cmd.Init(kInvalidClientId, kBucketId);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ bucket = decoder_->GetBucket(kBucketId);
+ ASSERT_TRUE(bucket != NULL);
+ EXPECT_EQ(sizeof(UniformsES3Header), bucket->size());
+ UniformsES3Header* header =
+ bucket->GetDataAs<UniformsES3Header*>(0, sizeof(UniformsES3Header));
+ ASSERT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_uniforms);
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetTransformFeedbackVaryingsCHROMIUMValidArgs) {
+ const uint32 kBucketId = 123;
+ GetTransformFeedbackVaryingsCHROMIUM cmd;
+ cmd.Init(client_program_id_, kBucketId);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetProgramiv(
+ kServiceProgramId, GL_TRANSFORM_FEEDBACK_VARYINGS, _))
+ .WillOnce(SetArgPointee<2>(0))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ EXPECT_EQ(sizeof(TransformFeedbackVaryingsHeader), bucket->size());
+ TransformFeedbackVaryingsHeader* header =
+ bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(
+ 0, sizeof(TransformFeedbackVaryingsHeader));
+ EXPECT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_transform_feedback_varyings);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetTransformFeedbackVaryingsCHROMIUMInvalidArgs) {
+ const uint32 kBucketId = 123;
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ EXPECT_TRUE(bucket == NULL);
+ GetTransformFeedbackVaryingsCHROMIUM cmd;
+ cmd.Init(kInvalidClientId, kBucketId);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ bucket = decoder_->GetBucket(kBucketId);
+ ASSERT_TRUE(bucket != NULL);
+ EXPECT_EQ(sizeof(TransformFeedbackVaryingsHeader), bucket->size());
+ TransformFeedbackVaryingsHeader* header =
+ bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(
+ 0, sizeof(TransformFeedbackVaryingsHeader));
+ ASSERT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_transform_feedback_varyings);
+}
+
TEST_P(GLES2DecoderWithShaderTest, GetUniformivSucceeds) {
GetUniformiv::Result* result =
static_cast<GetUniformiv::Result*>(shared_memory_address_);
@@ -344,7 +430,7 @@
Result* result = static_cast<Result*>(shared_memory_address_);
result->size = 0;
EXPECT_CALL(*gl_, GetAttachedShaders(kServiceProgramId, 1, _, _)).WillOnce(
- DoAll(SetArgumentPointee<2>(1), SetArgumentPointee<3>(kServiceShaderId)));
+ DoAll(SetArgPointee<2>(1), SetArgPointee<3>(kServiceShaderId)));
cmd.Init(client_program_id_,
shared_memory_id_,
shared_memory_offset_,
@@ -409,7 +495,7 @@
const GLint precision = 16;
EXPECT_CALL(*gl_, GetShaderPrecisionFormat(_, _, _, _))
.WillOnce(DoAll(SetArrayArgument<2>(range, range + 2),
- SetArgumentPointee<3>(precision)))
+ SetArgPointee<3>(precision)))
.RetiresOnSaturation();
cmd.Init(GL_VERTEX_SHADER,
GL_HIGH_FLOAT,
@@ -681,6 +767,175 @@
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockivSucceeds) {
+ GetActiveUniformBlockiv cmd;
+ typedef GetActiveUniformBlockiv::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ GLenum kPname[] {
+ GL_UNIFORM_BLOCK_BINDING,
+ GL_UNIFORM_BLOCK_DATA_SIZE,
+ GL_UNIFORM_BLOCK_NAME_LENGTH,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
+ GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
+ GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
+ };
+ for (size_t ii = 0; ii < arraysize(kPname); ++ii) {
+ result->SetNumResults(0);
+ cmd.Init(client_program_id_,
+ 0,
+ kPname[ii],
+ shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ if (kPname[ii] == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) {
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetActiveUniformBlockiv(kServiceProgramId, 0,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _))
+ .WillOnce(SetArgPointee<3>(1))
+ .RetiresOnSaturation();
+ }
+ EXPECT_CALL(*gl_,
+ GetActiveUniformBlockiv(
+ kServiceProgramId, 0, kPname[ii], _))
+ .WillOnce(SetArgPointee<3>(1976))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(1, result->GetNumResults());
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ EXPECT_EQ(1976, result->GetData()[0]);
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+ }
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetActiveUniformBlockivSucceedsZeroUniforms) {
+ GetActiveUniformBlockiv cmd;
+ typedef GetActiveUniformBlockiv::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->SetNumResults(0);
+ cmd.Init(client_program_id_,
+ 0,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
+ shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetActiveUniformBlockiv(
+ kServiceProgramId, 0, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, _))
+ .WillOnce(SetArgPointee<3>(0))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetActiveUniformBlockiv(kServiceProgramId, 0,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockivUnlinkedProgram) {
+ GetActiveUniformBlockiv cmd;
+ typedef GetActiveUniformBlockiv::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->SetNumResults(0);
+ cmd.Init(client_program_id_,
+ 0,
+ GL_UNIFORM_BLOCK_BINDING,
+ shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_FALSE))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetActiveUniformBlockivResultNotInitFails) {
+ GetActiveUniformBlockiv cmd;
+ typedef GetActiveUniformBlockiv::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->SetNumResults(1); // Should be initialized to 0.
+ cmd.Init(client_program_id_,
+ 0,
+ GL_UNIFORM_BLOCK_BINDING,
+ shared_memory_id_,
+ shared_memory_offset_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformBlockivBadProgramFails) {
+ GetActiveUniformBlockiv cmd;
+ typedef GetActiveUniformBlockiv::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->SetNumResults(0);
+ cmd.Init(kInvalidClientId,
+ 0,
+ GL_UNIFORM_BLOCK_BINDING,
+ shared_memory_id_,
+ shared_memory_offset_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetActiveUniformBlockivBadSharedMemoryFails) {
+ GetActiveUniformBlockiv cmd;
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ cmd.Init(client_program_id_,
+ 0,
+ GL_UNIFORM_BLOCK_BINDING,
+ kInvalidSharedMemoryId,
+ shared_memory_offset_);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(client_program_id_,
+ 0,
+ GL_UNIFORM_BLOCK_BINDING,
+ shared_memory_id_,
+ kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
TEST_P(GLES2DecoderWithShaderTest, GetActiveAttribSucceeds) {
const GLuint kAttribIndex = 1;
const uint32 kBucketId = 123;
@@ -782,6 +1037,306 @@
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesSucceeds) {
+ const uint32 kBucketId = 123;
+ const char kName0[] = "Cow";
+ const char kName1[] = "Chicken";
+ const char* kNames[] = { kName0, kName1 };
+ const size_t kCount = arraysize(kNames);
+ const char kValidStrEnd = 0;
+ const GLuint kIndices[] = { 1, 2 };
+ SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
+ GetUniformIndices::Result* result =
+ static_cast<GetUniformIndices::Result*>(shared_memory_address_);
+ GetUniformIndices cmd;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformIndices(kServiceProgramId, kCount, _, _))
+ .WillOnce(SetArrayArgument<3>(kIndices, kIndices + kCount))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(kCount, static_cast<size_t>(result->GetNumResults()));
+ for (size_t ii = 0; ii < kCount; ++ii) {
+ EXPECT_EQ(kIndices[ii], result->GetData()[ii]);
+ }
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesBadProgramFails) {
+ const uint32 kBucketId = 123;
+ const char kName0[] = "Cow";
+ const char kName1[] = "Chicken";
+ const char* kNames[] = { kName0, kName1 };
+ const size_t kCount = arraysize(kNames);
+ const char kValidStrEnd = 0;
+ SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
+ GetUniformIndices::Result* result =
+ static_cast<GetUniformIndices::Result*>(shared_memory_address_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ GetUniformIndices cmd;
+ // None-existant program
+ cmd.Init(kInvalidClientId,
+ kBucketId,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+ // Unlinked program.
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_FALSE))
+ .RetiresOnSaturation();
+ cmd.Init(client_program_id_,
+ kBucketId,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesBadParamsFails) {
+ const uint32 kBucketId = 123;
+ const char kName0[] = "Cow";
+ const char kName1[] = "Chicken";
+ const char* kNames[] = { kName0, kName1 };
+ const size_t kCount = arraysize(kNames);
+ const char kValidStrEnd = 0;
+ const GLuint kIndices[] = { 1, 2 };
+ SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
+ GetUniformIndices::Result* result =
+ static_cast<GetUniformIndices::Result*>(shared_memory_address_);
+ GetUniformIndices cmd;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetUniformIndices(kServiceProgramId, kCount, _, _))
+ .WillOnce(SetArrayArgument<3>(kIndices, kIndices + kCount))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_INVALID_VALUE))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesResultNotInitFails) {
+ const uint32 kBucketId = 123;
+ const char kName0[] = "Cow";
+ const char kName1[] = "Chicken";
+ const char* kNames[] = { kName0, kName1 };
+ const size_t kCount = arraysize(kNames);
+ const char kValidStrEnd = 0;
+ SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
+ GetUniformIndices::Result* result =
+ static_cast<GetUniformIndices::Result*>(shared_memory_address_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ GetUniformIndices cmd;
+ result->size = 1976; // Any value other than 0.
+ cmd.Init(kInvalidClientId,
+ kBucketId,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetUniformIndicesBadSharedMemoryFails) {
+ const uint32 kBucketId = 123;
+ const char kName0[] = "Cow";
+ const char kName1[] = "Chicken";
+ const char* kNames[] = { kName0, kName1 };
+ const size_t kCount = arraysize(kNames);
+ const char kValidStrEnd = 0;
+ SetBucketAsCStrings(kBucketId, kCount, kNames, kCount, kValidStrEnd);
+ GetUniformIndices::Result* result =
+ static_cast<GetUniformIndices::Result*>(shared_memory_address_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ GetUniformIndices cmd;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ kInvalidSharedMemoryId,
+ kSharedMemoryOffset);
+ result->size = 0;
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(client_program_id_,
+ kBucketId,
+ kSharedMemoryId,
+ kInvalidSharedMemoryOffset);
+ result->size = 0;
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivSucceeds) {
+ const uint32 kBucketId = 123;
+ const GLuint kIndices[] = { 1, 2 };
+ const GLint kResults[] = { 1976, 321 };
+ const size_t kCount = arraysize(kIndices);
+ SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
+ GetActiveUniformsiv::Result* result =
+ static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
+ GetActiveUniformsiv cmd;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ GL_UNIFORM_TYPE,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_CALL(*gl_,
+ GetActiveUniformsiv(
+ kServiceProgramId, kCount, _, GL_UNIFORM_TYPE, _))
+ .WillOnce(SetArrayArgument<4>(kResults, kResults + kCount))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(kCount, static_cast<size_t>(result->GetNumResults()));
+ for (size_t ii = 0; ii < kCount; ++ii) {
+ EXPECT_EQ(kResults[ii], result->GetData()[ii]);
+ }
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivBadProgramFails) {
+ const uint32 kBucketId = 123;
+ const GLuint kIndices[] = { 1, 2 };
+ const size_t kCount = arraysize(kIndices);
+ SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
+ GetActiveUniformsiv::Result* result =
+ static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ GetActiveUniformsiv cmd;
+ // None-existant program
+ cmd.Init(kInvalidClientId,
+ kBucketId,
+ GL_UNIFORM_TYPE,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+ // Unlinked program.
+ cmd.Init(client_program_id_,
+ kBucketId,
+ GL_UNIFORM_TYPE,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_FALSE))
+ .RetiresOnSaturation();
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivBadParamsFails) {
+ const uint32 kBucketId = 123;
+ const GLuint kIndices[] = { 1, 2 };
+ const GLint kResults[] = { 1976, 321 };
+ const size_t kCount = arraysize(kIndices);
+ SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
+ GetActiveUniformsiv::Result* result =
+ static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
+ GetActiveUniformsiv cmd;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ GL_UNIFORM_TYPE,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_CALL(*gl_,
+ GetActiveUniformsiv(
+ kServiceProgramId, kCount, _, GL_UNIFORM_TYPE, _))
+ .WillOnce(SetArrayArgument<4>(kResults, kResults + kCount))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_INVALID_VALUE))
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ result->size = 0;
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->GetNumResults());
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivResultNotInitFails) {
+ const uint32 kBucketId = 123;
+ const GLuint kIndices[] = { 1, 2 };
+ const size_t kCount = arraysize(kIndices);
+ SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
+ GetActiveUniformsiv::Result* result =
+ static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
+ GetActiveUniformsiv cmd;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ GL_UNIFORM_TYPE,
+ kSharedMemoryId,
+ kSharedMemoryOffset);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ result->size = 1976; // Any value other than 0.
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetActiveUniformsivBadSharedMemoryFails) {
+ const uint32 kBucketId = 123;
+ const GLuint kIndices[] = { 1, 2 };
+ const size_t kCount = arraysize(kIndices);
+ SetBucketData(kBucketId, kIndices, sizeof(GLuint) * kCount);
+ GetActiveUniformsiv::Result* result =
+ static_cast<GetActiveUniformsiv::Result*>(shared_memory_address_);
+ GetActiveUniformsiv cmd;
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ result->size = 0;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ GL_UNIFORM_TYPE,
+ kInvalidSharedMemoryId,
+ kSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ result->size = 0;
+ cmd.Init(client_program_id_,
+ kBucketId,
+ GL_UNIFORM_TYPE,
+ kSharedMemoryId,
+ kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
TEST_P(GLES2DecoderWithShaderTest, GetShaderInfoLogValidArgs) {
const char* kInfo = "hello";
const uint32 kBucketId = 123;
@@ -790,13 +1345,13 @@
EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _));
EXPECT_CALL(*gl_, CompileShader(kServiceShaderId));
EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _))
- .WillOnce(SetArgumentPointee<2>(GL_FALSE))
+ .WillOnce(SetArgPointee<2>(GL_FALSE))
.RetiresOnSaturation();
EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_INFO_LOG_LENGTH, _))
- .WillOnce(SetArgumentPointee<2>(strlen(kInfo) + 1))
+ .WillOnce(SetArgPointee<2>(strlen(kInfo) + 1))
.RetiresOnSaturation();
EXPECT_CALL(*gl_, GetShaderInfoLog(kServiceShaderId, strlen(kInfo) + 1, _, _))
- .WillOnce(DoAll(SetArgumentPointee<2>(strlen(kInfo)),
+ .WillOnce(DoAll(SetArgPointee<2>(strlen(kInfo)),
SetArrayArgument<3>(kInfo, kInfo + strlen(kInfo) + 1)));
compile_cmd.Init(client_shader_id_);
cmd.Init(client_shader_id_, kBucketId);
@@ -818,15 +1373,168 @@
EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
}
-TEST_P(GLES2DecoderTest, CompileShaderValidArgs) {
- EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _));
- EXPECT_CALL(*gl_, CompileShader(kServiceShaderId));
- EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _))
- .WillOnce(SetArgumentPointee<2>(GL_TRUE))
+TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingSucceeds) {
+ const GLuint kIndex = 1;
+ const uint32 kBucketId = 123;
+ const char kName[] = "HolyCow";
+ const GLsizei kBufferSize = static_cast<GLsizei>(strlen(kName) + 1);
+ const GLsizei kSize = 2;
+ const GLenum kType = GL_FLOAT_VEC2;
+ GetTransformFeedbackVarying cmd;
+ typedef GetTransformFeedbackVarying::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->success = 0;
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId,
+ GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, _))
+ .WillOnce(SetArgPointee<2>(kBufferSize))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetTransformFeedbackVarying(
+ kServiceProgramId, kIndex, _, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<3>(kBufferSize - 1),
+ SetArgPointee<4>(kSize),
+ SetArgPointee<5>(kType),
+ SetArrayArgument<6>(kName, kName + kBufferSize)))
+ .RetiresOnSaturation();
+ cmd.Init(client_program_id_,
+ kIndex,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_NE(0, result->success);
+ EXPECT_EQ(kSize, static_cast<GLsizei>(result->size));
+ EXPECT_EQ(kType, static_cast<GLenum>(result->type));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ CommonDecoder::Bucket* bucket = decoder_->GetBucket(kBucketId);
+ ASSERT_TRUE(bucket != NULL);
+ EXPECT_EQ(
+ 0, memcmp(bucket->GetData(0, bucket->size()), kName, bucket->size()));
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingNotInitFails) {
+ const GLuint kIndex = 1;
+ const uint32 kBucketId = 123;
+ GetTransformFeedbackVarying cmd;
+ typedef GetTransformFeedbackVarying::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->success = 1;
+ cmd.Init(client_program_id_,
+ kIndex,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingBadProgramFails) {
+ const GLuint kIndex = 1;
+ const uint32 kBucketId = 123;
+ GetTransformFeedbackVarying cmd;
+ typedef GetTransformFeedbackVarying::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->success = 0;
+ cmd.Init(kInvalidClientId,
+ kIndex,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->success);
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest, GetTransformFeedbackVaryingBadParamsFails) {
+ const GLuint kIndex = 1;
+ const uint32 kBucketId = 123;
+ const GLsizei kBufferSize = 10;
+ GetTransformFeedbackVarying cmd;
+ typedef GetTransformFeedbackVarying::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->success = 0;
+ cmd.Init(client_program_id_,
+ kIndex,
+ kBucketId,
+ shared_memory_id_,
+ shared_memory_offset_);
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetProgramiv(kServiceProgramId,
+ GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, _))
+ .WillOnce(SetArgPointee<2>(kBufferSize))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_INVALID_VALUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ GetTransformFeedbackVarying(
+ kServiceProgramId, kIndex, _, _, _, _, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(0, result->success);
+ EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(GLES2DecoderWithShaderTest,
+ GetTransformFeedbackVaryingBadSharedMemoryFails) {
+ const GLuint kIndex = 1;
+ const uint32 kBucketId = 123;
+ GetTransformFeedbackVarying cmd;
+ typedef GetTransformFeedbackVarying::Result Result;
+ Result* result = static_cast<Result*>(shared_memory_address_);
+ result->success = 0;
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ cmd.Init(client_program_id_,
+ kIndex,
+ kBucketId,
+ kInvalidSharedMemoryId,
+ shared_memory_offset_);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+ cmd.Init(client_program_id_,
+ kIndex,
+ kBucketId,
+ shared_memory_id_,
+ kInvalidSharedMemoryOffset);
+ EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
+}
+
+TEST_P(GLES2DecoderTest, CompileShaderValidArgs) {
+ // Compile shader should not actually call any GL calls yet.
CompileShader cmd;
cmd.Init(client_shader_id_);
EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+
+ // Getting the shader compilation state should trigger the actual GL calls.
+ EXPECT_CALL(*gl_, ShaderSource(kServiceShaderId, 1, _, _));
+ EXPECT_CALL(*gl_, CompileShader(kServiceShaderId));
+ EXPECT_CALL(*gl_, GetShaderiv(kServiceShaderId, GL_COMPILE_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GetError())
+ .WillOnce(Return(GL_NO_ERROR))
+ .WillOnce(Return(GL_NO_ERROR))
+ .RetiresOnSaturation();
+
+ GetShaderiv status_cmd;
+ status_cmd.Init(client_shader_id_, GL_COMPILE_STATUS,
+ kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(status_cmd));
}
TEST_P(GLES2DecoderTest, CompileShaderInvalidArgs) {
@@ -1178,6 +1886,18 @@
EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
}
+TEST_P(GLES2DecoderWithShaderTest, UniformBlockBindingValidArgs) {
+ EXPECT_CALL(*gl_, UniformBlockBinding(kServiceProgramId, 2, 3));
+ SpecializedSetup<cmds::UniformBlockBinding, 0>(true);
+ cmds::UniformBlockBinding cmd;
+ cmd.Init(client_program_id_, 2, 3);
+ decoder_->set_unsafe_es3_apis_enabled(true);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ decoder_->set_unsafe_es3_apis_enabled(false);
+ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));
+}
+
TEST_P(GLES2DecoderWithShaderTest, BindUniformLocationCHROMIUMBucket) {
const uint32 kBucketId = 123;
const GLint kLocation = 2;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index 6c9d377..27c61ad 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -78,6 +78,8 @@
ValueValidator<GLenum> texture_wrap_mode;
ValueValidator<GLenum> transform_feedback_bind_target;
ValueValidator<GLenum> transform_feedback_primitive_mode;
+ValueValidator<GLenum> uniform_block_parameter;
+ValueValidator<GLenum> uniform_parameter;
ValueValidator<GLenum> value_buffer_target;
ValueValidator<GLint> vertex_attrib_size;
ValueValidator<GLenum> vertex_attrib_type;
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 1f1211b..97c3cdd 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -552,6 +552,27 @@
GL_TRIANGLES,
};
+static const GLenum valid_uniform_block_parameter_table[] = {
+ GL_UNIFORM_BLOCK_BINDING,
+ GL_UNIFORM_BLOCK_DATA_SIZE,
+ GL_UNIFORM_BLOCK_NAME_LENGTH,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,
+ GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES,
+ GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
+ GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
+};
+
+static const GLenum valid_uniform_parameter_table[] = {
+ GL_UNIFORM_SIZE,
+ GL_UNIFORM_TYPE,
+ GL_UNIFORM_NAME_LENGTH,
+ GL_UNIFORM_BLOCK_INDEX,
+ GL_UNIFORM_OFFSET,
+ GL_UNIFORM_ARRAY_STRIDE,
+ GL_UNIFORM_MATRIX_STRIDE,
+ GL_UNIFORM_IS_ROW_MAJOR,
+};
+
static const GLenum valid_value_buffer_target_table[] = {
GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM,
};
@@ -698,6 +719,10 @@
transform_feedback_primitive_mode(
valid_transform_feedback_primitive_mode_table,
arraysize(valid_transform_feedback_primitive_mode_table)),
+ uniform_block_parameter(valid_uniform_block_parameter_table,
+ arraysize(valid_uniform_block_parameter_table)),
+ uniform_parameter(valid_uniform_parameter_table,
+ arraysize(valid_uniform_parameter_table)),
value_buffer_target(valid_value_buffer_target_table,
arraysize(valid_value_buffer_target_table)),
vertex_attrib_size(valid_vertex_attrib_size_table,
diff --git a/gpu/command_buffer/service/gpu_service_test.cc b/gpu/command_buffer/service/gpu_service_test.cc
index 89740b9..d0b9117 100644
--- a/gpu/command_buffer/service/gpu_service_test.cc
+++ b/gpu/command_buffer/service/gpu_service_test.cc
@@ -51,5 +51,8 @@
testing::Test::TearDown();
}
+gfx::GLContext* GpuServiceTest::GetGLContext() {
+ return context_.get();
+}
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_service_test.h b/gpu/command_buffer/service/gpu_service_test.h
index 539d6ba..7c9c978 100644
--- a/gpu/command_buffer/service/gpu_service_test.h
+++ b/gpu/command_buffer/service/gpu_service_test.h
@@ -28,6 +28,7 @@
void SetUpWithGLVersion(const char* gl_version, const char* gl_extensions);
void SetUp() override;
void TearDown() override;
+ gfx::GLContext* GetGLContext();
scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
@@ -40,4 +41,4 @@
} // namespace gles2
} // namespace gpu
-#endif // GPU_COMMAND_BUFFER_SERVICE_MAILBOX_SYNCHRONIZER_H_
+#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_SERVICE_TEST_H_
diff --git a/gpu/command_buffer/service/gpu_state_tracer.cc b/gpu/command_buffer/service/gpu_state_tracer.cc
index 47938cc..9b8db2a 100644
--- a/gpu/command_buffer/service/gpu_state_tracer.cc
+++ b/gpu/command_buffer/service/gpu_state_tracer.cc
@@ -16,14 +16,14 @@
const int kBytesPerPixel = 4;
-class Snapshot : public base::debug::ConvertableToTraceFormat {
+class Snapshot : public base::trace_event::ConvertableToTraceFormat {
public:
static scoped_refptr<Snapshot> Create(const ContextState* state);
// Save a screenshot of the currently bound framebuffer.
bool SaveScreenshot(const gfx::Size& size);
- // base::debug::ConvertableToTraceFormat implementation.
+ // base::trace_event::ConvertableToTraceFormat implementation.
void AppendAsTraceFormat(std::string* out) const override;
private:
@@ -125,7 +125,7 @@
TRACE_DISABLED_BY_DEFAULT("gpu.debug"),
"gpu::State",
state_,
- scoped_refptr<base::debug::ConvertableToTraceFormat>(snapshot));
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>(snapshot));
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/gpu_timing.cc b/gpu/command_buffer/service/gpu_timing.cc
new file mode 100644
index 0000000..8716448
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_timing.cc
@@ -0,0 +1,145 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/gpu_timing.h"
+
+#include "base/time/time.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_version_info.h"
+
+namespace gpu {
+
+GPUTimer::GPUTimer(GPUTiming* gpu_timing) : gpu_timing_(gpu_timing) {
+ DCHECK(gpu_timing_);
+ memset(queries_, 0, sizeof(queries_));
+ glGenQueriesARB(2, queries_);
+}
+
+GPUTimer::~GPUTimer() {
+ glDeleteQueriesARB(2, queries_);
+}
+
+void GPUTimer::Start() {
+ // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
+ glQueryCounter(queries_[0], GL_TIMESTAMP);
+ offset_ = gpu_timing_->CalculateTimerOffset();
+}
+
+void GPUTimer::End() {
+ end_requested_ = true;
+ glQueryCounter(queries_[1], GL_TIMESTAMP);
+}
+
+bool GPUTimer::IsAvailable() {
+ if (!gpu_timing_->IsAvailable() || !end_requested_) {
+ return false;
+ }
+ GLint done = 0;
+ glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
+ return done != 0;
+}
+
+void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) {
+ DCHECK(start && end);
+ DCHECK(IsAvailable());
+ GLuint64 begin_stamp = 0;
+ GLuint64 end_stamp = 0;
+ // TODO(dsinclair): It's possible for the timer to wrap during the start/end.
+ // We need to detect if the end is less then the start and correct for the
+ // wrapping.
+ glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp);
+ glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp);
+
+ *start = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
+ *end = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
+}
+
+int64 GPUTimer::GetDeltaElapsed() {
+ int64 start = 0;
+ int64 end = 0;
+ GetStartEndTimestamps(&start, &end);
+ return end - start;
+}
+
+GPUTiming::GPUTiming() : cpu_time_for_testing_() {
+}
+
+GPUTiming::~GPUTiming() {
+}
+
+bool GPUTiming::Initialize(gfx::GLContext* gl_context) {
+ DCHECK(gl_context);
+ DCHECK_EQ(kTimerTypeInvalid, timer_type_);
+
+ const gfx::GLVersionInfo* version_info = gl_context->GetVersionInfo();
+ DCHECK(version_info);
+ if (version_info->is_es3 && // glGetInteger64v is supported under ES3.
+ gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) {
+ timer_type_ = kTimerTypeDisjoint;
+ return true;
+ } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
+ timer_type_ = kTimerTypeARB;
+ return true;
+ }
+ return false;
+}
+
+bool GPUTiming::IsAvailable() {
+ return timer_type_ != kTimerTypeInvalid;
+}
+
+const char* GPUTiming::GetTimerTypeName() const {
+ switch (timer_type_) {
+ case kTimerTypeDisjoint:
+ return "GL_EXT_disjoint_timer_query";
+ case kTimerTypeARB:
+ return "GL_ARB_timer_query";
+ default:
+ return "Unknown";
+ }
+}
+
+bool GPUTiming::CheckAndResetTimerErrors() {
+ if (timer_type_ == kTimerTypeDisjoint) {
+ GLint disjoint_value = 0;
+ glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
+ return disjoint_value != 0;
+ } else {
+ return false;
+ }
+}
+
+int64 GPUTiming::CalculateTimerOffset() {
+ if (!offset_valid_) {
+ GLint64 gl_now = 0;
+ glGetInteger64v(GL_TIMESTAMP, &gl_now);
+ int64 now =
+ cpu_time_for_testing_.is_null()
+ ? base::TimeTicks::NowFromSystemTraceTime().ToInternalValue()
+ : cpu_time_for_testing_.Run();
+ offset_ = now - gl_now / base::Time::kNanosecondsPerMicrosecond;
+ offset_valid_ = timer_type_ == kTimerTypeARB;
+ }
+ return offset_;
+}
+
+void GPUTiming::InvalidateTimerOffset() {
+ offset_valid_ = false;
+}
+
+void GPUTiming::SetCpuTimeForTesting(
+ const base::Callback<int64(void)>& cpu_time) {
+ cpu_time_for_testing_ = cpu_time;
+}
+
+void GPUTiming::SetOffsetForTesting(int64 offset, bool cache_it) {
+ offset_ = offset;
+ offset_valid_ = cache_it;
+}
+
+void GPUTiming::SetTimerTypeForTesting(TimerType type) {
+ timer_type_ = type;
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_timing.h b/gpu/command_buffer/service/gpu_timing.h
new file mode 100644
index 0000000..1d9ecf6
--- /dev/null
+++ b/gpu/command_buffer/service/gpu_timing.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "gpu/gpu_export.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace gpu {
+
+class GPUTiming;
+
+// Class to compute the amount of time it takes to fully
+// complete a set of GL commands
+class GPU_EXPORT GPUTimer {
+ public:
+ // gpu_timing must outlive GPUTimer instance we're creating.
+ explicit GPUTimer(GPUTiming* gpu_timing);
+ ~GPUTimer();
+
+ void Start();
+ void End();
+ bool IsAvailable();
+
+ void GetStartEndTimestamps(int64* start, int64* end);
+ int64 GetDeltaElapsed();
+
+ private:
+ GLuint queries_[2];
+ int64 offset_ = 0;
+ bool end_requested_ = false;
+ GPUTiming* gpu_timing_;
+
+ DISALLOW_COPY_AND_ASSIGN(GPUTimer);
+};
+
+// GPUTiming contains all the gl timing logic that is not specific
+// to a single GPUTimer.
+class GPU_EXPORT GPUTiming {
+ public:
+ enum TimerType {
+ kTimerTypeInvalid = -1,
+
+ kTimerTypeARB, // ARB_timer_query
+ kTimerTypeDisjoint // EXT_disjoint_timer_query
+ };
+
+ GPUTiming();
+ virtual ~GPUTiming();
+
+ bool Initialize(gfx::GLContext* context);
+ bool IsAvailable();
+
+ // CheckAndResetTimerErrors has to be called before reading timestamps
+ // from GPUTimers instances and after making sure all the timers
+ // were available.
+ // If the returned value is false, all the previous timers should be
+ // discarded.
+ bool CheckAndResetTimerErrors();
+
+ const char* GetTimerTypeName() const;
+
+ // Returns the offset between the current gpu time and the cpu time.
+ int64 CalculateTimerOffset();
+ void InvalidateTimerOffset();
+
+ void SetCpuTimeForTesting(const base::Callback<int64(void)>& cpu_time);
+ void SetOffsetForTesting(int64 offset, bool cache_it);
+ void SetTimerTypeForTesting(TimerType type);
+
+ private:
+ TimerType timer_type_ = kTimerTypeInvalid;
+ int64 offset_ = 0; // offset cache when timer_type_ == kTimerTypeARB
+ bool offset_valid_ = false;
+ base::Callback<int64(void)> cpu_time_for_testing_;
+ friend class GPUTimer;
+ DISALLOW_COPY_AND_ASSIGN(GPUTiming);
+};
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GPU_TIMING_H_
diff --git a/gpu/command_buffer/service/gpu_tracer.cc b/gpu/command_buffer/service/gpu_tracer.cc
index 72b29dd..6bedb7f 100644
--- a/gpu/command_buffer/service/gpu_tracer.cc
+++ b/gpu/command_buffer/service/gpu_tracer.cc
@@ -20,16 +20,6 @@
static const unsigned int kProcessInterval = 16;
static TraceOutputter* g_outputter_thread = NULL;
-CPUTime::CPUTime() {
-}
-
-int64 CPUTime::GetCurrentTime() {
- return base::TimeTicks::NowFromSystemTraceTime().ToInternalValue();
-}
-
-CPUTime::~CPUTime() {
-}
-
TraceMarker::TraceMarker(const std::string& category, const std::string& name)
: category_(category),
name_(name),
@@ -90,122 +80,53 @@
}
GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter,
- scoped_refptr<CPUTime> cpu_time,
+ gpu::GPUTiming* gpu_timing,
const std::string& category,
const std::string& name,
- int64 offset,
- GpuTracerType tracer_type)
+ const bool enabled)
: category_(category),
name_(name),
outputter_(outputter),
- cpu_time_(cpu_time),
- offset_(offset),
- start_time_(0),
- end_time_(0),
- tracer_type_(tracer_type),
- end_requested_(false) {
- memset(queries_, 0, sizeof(queries_));
- switch (tracer_type_) {
- case kTracerTypeARBTimer:
- case kTracerTypeDisjointTimer:
- glGenQueriesARB(2, queries_);
- break;
-
- default:
- tracer_type_ = kTracerTypeInvalid;
+ enabled_(enabled) {
+ if (gpu_timing->IsAvailable()) {
+ gpu_timer_.reset(new GPUTimer(gpu_timing));
}
}
GPUTrace::~GPUTrace() {
- switch (tracer_type_) {
- case kTracerTypeInvalid:
- break;
-
- case kTracerTypeARBTimer:
- case kTracerTypeDisjointTimer:
- glDeleteQueriesARB(2, queries_);
- break;
- }
}
void GPUTrace::Start(bool trace_service) {
if (trace_service) {
outputter_->TraceServiceBegin(category_, name_);
}
-
- switch (tracer_type_) {
- case kTracerTypeInvalid:
- break;
-
- case kTracerTypeDisjointTimer:
- // For the disjoint timer, GPU idle time does not seem to increment the
- // internal counter. We must calculate the offset before any query.
- // glGetInteger64v is supported under ES3 which we check for before using
- // the kTracerTypeDisjointTimer.
- {
- GLint64 gl_now = 0;
- glGetInteger64v(GL_TIMESTAMP, &gl_now);
- offset_ = cpu_time_->GetCurrentTime() -
- gl_now / base::Time::kNanosecondsPerMicrosecond;
- }
- // Intentionally fall through to kTracerTypeARBTimer case.xs
- case kTracerTypeARBTimer:
- // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
- glQueryCounter(queries_[0], GL_TIMESTAMP);
- break;
+ if (gpu_timer_.get()) {
+ gpu_timer_->Start();
}
}
void GPUTrace::End(bool tracing_service) {
- end_requested_ = true;
- switch (tracer_type_) {
- case kTracerTypeInvalid:
- break;
-
- case kTracerTypeARBTimer:
- case kTracerTypeDisjointTimer:
- // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
- glQueryCounter(queries_[1], GL_TIMESTAMP);
- break;
+ if (gpu_timer_.get()) {
+ gpu_timer_->End();
}
-
if (tracing_service) {
outputter_->TraceServiceEnd(category_, name_);
}
}
bool GPUTrace::IsAvailable() {
- if (tracer_type_ != kTracerTypeInvalid) {
- if (!end_requested_)
- return false;
-
- GLint done = 0;
- glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
- return !!done;
- }
-
- return true;
+ return !gpu_timer_.get() || gpu_timer_->IsAvailable();
}
void GPUTrace::Process() {
- if (tracer_type_ == kTracerTypeInvalid)
- return;
+ if (gpu_timer_.get()) {
+ DCHECK(IsAvailable());
- DCHECK(IsAvailable());
-
- GLuint64 begin_stamp = 0;
- GLuint64 end_stamp = 0;
-
- // TODO(dsinclair): It's possible for the timer to wrap during the start/end.
- // We need to detect if the end is less then the start and correct for the
- // wrapping.
- glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp);
- glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp);
-
- start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) +
- offset_;
- end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
- outputter_->TraceDevice(category_, name_, start_time_, end_time_);
+ int64 start = 0;
+ int64 end = 0;
+ gpu_timer_->GetStartEndTimestamps(&start, &end);
+ outputter_->TraceDevice(category_, name_, start, end);
+ }
}
GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder)
@@ -214,9 +135,7 @@
gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
TRACE_DISABLED_BY_DEFAULT("gpu.device"))),
decoder_(decoder),
- timer_offset_(0),
- tracer_type_(kTracerTypeInvalid),
- gpu_timing_synced_(false),
+ gpu_timing_(),
gpu_executing_(false),
process_posted_(false) {
}
@@ -229,43 +148,25 @@
return false;
if (outputter_ == NULL) {
- tracer_type_ = DetermineTracerType();
- const char* tracer_type_name = "Unknown";
- switch (tracer_type_) {
- case kTracerTypeDisjointTimer:
- tracer_type_name = "GL_EXT_disjoint_timer_query";
- break;
- case kTracerTypeARBTimer:
- tracer_type_name = "GL_ARB_timer_query";
- break;
-
- default:
- break;
- }
-
- outputter_ = CreateOutputter(tracer_type_name);
+ outputter_ = CreateOutputter(gpu_timing_.GetTimerTypeName());
+ gpu_timing_.Initialize(decoder_->GetGLContext());
}
- if (cpu_time_ == NULL) {
- cpu_time_ = CreateCPUTime();
+ if (*gpu_trace_dev_category == '\0') {
+ // If GPU device category is off, invalidate timing sync.
+ gpu_timing_.InvalidateTimerOffset();
}
- CalculateTimerOffset();
gpu_executing_ = true;
-
if (IsTracing()) {
- // Reset disjoint bit for the disjoint timer.
- if (tracer_type_ == kTracerTypeDisjointTimer) {
- GLint disjoint_value = 0;
- glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
- }
-
+ gpu_timing_.CheckAndResetTimerErrors();
// Begin a Trace for all active markers
for (int n = 0; n < NUM_TRACER_SOURCES; n++) {
for (size_t i = 0; i < markers_[n].size(); i++) {
TraceMarker& trace_marker = markers_[n][i];
- trace_marker.trace_ = CreateTrace(trace_marker.category_,
- trace_marker.name_);
+ trace_marker.trace_ =
+ new GPUTrace(outputter_, &gpu_timing_, trace_marker.category_,
+ trace_marker.name_, *gpu_trace_dev_category != 0);
trace_marker.trace_->Start(*gpu_trace_srv_category != 0);
}
}
@@ -313,7 +214,8 @@
// Create trace
if (IsTracing()) {
- scoped_refptr<GPUTrace> trace = CreateTrace(category, name);
+ scoped_refptr<GPUTrace> trace = new GPUTrace(
+ outputter_, &gpu_timing_, category, name, *gpu_trace_dev_category != 0);
trace->Start(*gpu_trace_srv_category != 0);
markers_[source].back().trace_ = trace;
}
@@ -367,38 +269,10 @@
return base::EmptyString();
}
-scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category,
- const std::string& name) {
- GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ :
- kTracerTypeInvalid;
-
- return new GPUTrace(outputter_, cpu_time_, category, name,
- timer_offset_, tracer_type);
-}
-
scoped_refptr<Outputter> GPUTracer::CreateOutputter(const std::string& name) {
return TraceOutputter::Create(name);
}
-scoped_refptr<CPUTime> GPUTracer::CreateCPUTime() {
- return new CPUTime();
-}
-
-GpuTracerType GPUTracer::DetermineTracerType() {
- ContextGroup* context_group = decoder_->GetContextGroup();
- const gpu::gles2::FeatureInfo* feature_info = context_group->feature_info();
- const gfx::GLVersionInfo& version_info = feature_info->gl_version_info();
-
- if (version_info.is_es3 &&
- gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) {
- return kTracerTypeDisjointTimer;
- } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
- return kTracerTypeARBTimer;
- }
-
- return kTracerTypeInvalid;
-}
-
void GPUTracer::PostTask() {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
@@ -413,7 +287,7 @@
}
void GPUTracer::ProcessTraces() {
- if (tracer_type_ == kTracerTypeInvalid) {
+ if (!gpu_timing_.IsAvailable()) {
traces_.clear();
return;
}
@@ -427,13 +301,10 @@
return;
}
- // Check if disjoint operation has occurred, discard ongoing traces if so.
- if (tracer_type_ == kTracerTypeDisjointTimer) {
- GLint disjoint_value = 0;
- glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
- if (disjoint_value)
- traces_.clear();
- }
+ // Check if timers are still valid (e.g: a disjoint operation
+ // might have occurred.)
+ if (gpu_timing_.CheckAndResetTimerErrors())
+ traces_.clear();
while (!traces_.empty() && traces_.front()->IsAvailable()) {
traces_.front()->Process();
@@ -446,24 +317,6 @@
traces_.clear();
}
-void GPUTracer::CalculateTimerOffset() {
- if (tracer_type_ != kTracerTypeInvalid) {
- if (*gpu_trace_dev_category == '\0') {
- // If GPU device category is off, invalidate timing sync.
- gpu_timing_synced_ = false;
- } else if (!gpu_timing_synced_ && tracer_type_ == kTracerTypeARBTimer) {
- TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset");
-
- // ARB Timer is written for OpenGL 3.2 which contains glGetInteger64v().
- GLint64 gl_now = 0;
- glGetInteger64v(GL_TIMESTAMP, &gl_now);
- timer_offset_ = cpu_time_->GetCurrentTime() -
- gl_now / base::Time::kNanosecondsPerMicrosecond;
- gpu_timing_synced_ = true;
- }
- }
-}
-
void GPUTracer::IssueProcessTask() {
if (traces_.empty() || process_posted_)
return;
diff --git a/gpu/command_buffer/service/gpu_tracer.h b/gpu/command_buffer/service/gpu_tracer.h
index 594a98e..c8ac9d7 100644
--- a/gpu/command_buffer/service/gpu_tracer.h
+++ b/gpu/command_buffer/service/gpu_tracer.h
@@ -6,13 +6,16 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_TRACER_H_
#define GPU_COMMAND_BUFFER_SERVICE_GPU_TRACER_H_
+#include <deque>
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/command_buffer/service/gpu_timing.h"
#include "gpu/gpu_export.h"
#include "ui/gl/gl_bindings.h"
@@ -33,28 +36,6 @@
NUM_TRACER_SOURCES
};
-enum GpuTracerType {
- kTracerTypeInvalid = -1,
-
- kTracerTypeARBTimer,
- kTracerTypeDisjointTimer
-};
-
-// Central accesser to CPU Time
-class GPU_EXPORT CPUTime
- : public base::RefCounted<CPUTime> {
- public:
- CPUTime();
-
- virtual int64 GetCurrentTime();
-
- protected:
- virtual ~CPUTime();
- friend class base::RefCounted<CPUTime>;
-
- DISALLOW_COPY_AND_ASSIGN(CPUTime);
-};
-
// Marker structure for a Trace.
struct TraceMarker {
TraceMarker(const std::string& category, const std::string& name);
@@ -94,35 +75,27 @@
protected:
// Trace Processing.
- scoped_refptr<GPUTrace> CreateTrace(const std::string& category,
- const std::string& name);
virtual scoped_refptr<Outputter> CreateOutputter(const std::string& name);
- virtual scoped_refptr<CPUTime> CreateCPUTime();
- virtual GpuTracerType DetermineTracerType();
virtual void PostTask();
void Process();
void ProcessTraces();
- void CalculateTimerOffset();
void IssueProcessTask();
scoped_refptr<Outputter> outputter_;
- scoped_refptr<CPUTime> cpu_time_;
std::vector<TraceMarker> markers_[NUM_TRACER_SOURCES];
std::deque<scoped_refptr<GPUTrace> > traces_;
const unsigned char* gpu_trace_srv_category;
const unsigned char* gpu_trace_dev_category;
gles2::GLES2Decoder* decoder_;
+ gpu::GPUTiming gpu_timing_;
- int64 timer_offset_;
-
- GpuTracerType tracer_type_;
- bool gpu_timing_synced_;
bool gpu_executing_;
bool process_posted_;
+ private:
DISALLOW_COPY_AND_ASSIGN(GPUTracer);
};
@@ -166,6 +139,7 @@
base::Thread named_thread_;
uint64 local_trace_id_;
+ private:
DISALLOW_COPY_AND_ASSIGN(TraceOutputter);
};
@@ -173,17 +147,15 @@
: public base::RefCounted<GPUTrace> {
public:
GPUTrace(scoped_refptr<Outputter> outputter,
- scoped_refptr<CPUTime> cpu_time,
+ gpu::GPUTiming* gpu_timing,
const std::string& category,
const std::string& name,
- int64 offset,
- GpuTracerType tracer_type);
-
- bool IsEnabled() { return tracer_type_ != kTracerTypeInvalid; }
+ const bool enabled);
void Start(bool trace_service);
void End(bool tracing_service);
bool IsAvailable();
+ bool IsEnabled() { return enabled_; }
void Process();
private:
@@ -196,35 +168,27 @@
std::string category_;
std::string name_;
scoped_refptr<Outputter> outputter_;
- scoped_refptr<CPUTime> cpu_time_;
-
- int64 offset_;
- int64 start_time_;
- int64 end_time_;
- GpuTracerType tracer_type_;
- bool end_requested_;
-
- GLuint queries_[2];
+ scoped_ptr<gpu::GPUTimer> gpu_timer_;
+ const bool enabled_ = false;
DISALLOW_COPY_AND_ASSIGN(GPUTrace);
};
class ScopedGPUTrace {
- public:
- ScopedGPUTrace(GPUTracer* gpu_tracer, GpuTracerSource source,
- const std::string& category, const std::string& name)
- : gpu_tracer_(gpu_tracer),
- source_(source) {
- gpu_tracer_->Begin(category, name, source_);
- }
+ public:
+ ScopedGPUTrace(GPUTracer* gpu_tracer,
+ GpuTracerSource source,
+ const std::string& category,
+ const std::string& name)
+ : gpu_tracer_(gpu_tracer), source_(source) {
+ gpu_tracer_->Begin(category, name, source_);
+ }
- ~ScopedGPUTrace() {
- gpu_tracer_->End(source_);
- }
+ ~ScopedGPUTrace() { gpu_tracer_->End(source_); }
- private:
- GPUTracer* gpu_tracer_;
- GpuTracerSource source_;
+ private:
+ GPUTracer* gpu_tracer_;
+ GpuTracerSource source_;
};
} // namespace gles2
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc
index 1b10fc6..9005421 100644
--- a/gpu/command_buffer/service/gpu_tracer_unittest.cc
+++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -5,43 +5,30 @@
#include <map>
#include <set>
+#include "base/bind.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
#include "gpu/command_buffer/service/gpu_service_test.h"
+#include "gpu/command_buffer/service/gpu_timing.h"
#include "gpu/command_buffer/service/gpu_tracer.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gl/gl_context_stub.h"
#include "ui/gl/gl_mock.h"
-#include "ui/gl/gl_surface_stub.h"
namespace gpu {
namespace gles2 {
+namespace {
using ::testing::_;
using ::testing::AtLeast;
+using ::testing::AtMost;
using ::testing::Exactly;
using ::testing::Invoke;
using ::testing::NotNull;
using ::testing::Return;
-class FakeCPUTime : public CPUTime {
- public:
- FakeCPUTime()
- : current_cpu_time_(0) {
- }
-
- int64 GetCurrentTime() override {
- return current_cpu_time_;
- }
-
- void SetFakeCPUTime(int64 cpu_time) {
- current_cpu_time_ = cpu_time;
- }
-
- protected:
- ~FakeCPUTime() override {}
-
- int64 current_cpu_time_;
-};
+int64 g_fakeCPUTime = 0;
+int64 FakeCpuTime() {
+ return g_fakeCPUTime;
+}
class MockOutputter : public Outputter {
public:
@@ -154,19 +141,19 @@
}
protected:
- bool disjointed_;
- GLint64 current_time_;
- GLuint next_query_id_;
+ bool disjointed_ = false;
+ GLint64 current_time_ = 0;
+ GLuint next_query_id_ = 0;
std::set<GLuint> alloced_queries_;
std::map<GLuint, GLint64> query_timestamp_;
};
class GPUTracerTester : public GPUTracer {
public:
- GPUTracerTester(GpuTracerType tracer_type, gles2::GLES2Decoder* decoder)
- : GPUTracer(decoder),
- tracing_enabled_(0),
- test_tracer_type_(tracer_type) {
+ explicit GPUTracerTester(gles2::GLES2Decoder* decoder)
+ : GPUTracer(decoder), tracing_enabled_(0) {
+ gpu_timing_.SetCpuTimeForTesting(base::Bind(&FakeCpuTime));
+
// Force tracing to be dependent on our mock variable here.
gpu_trace_srv_category = &tracing_enabled_;
gpu_trace_dev_category = &tracing_enabled_;
@@ -182,10 +169,6 @@
set_outputter_ = outputter;
}
- void SetCPUTime(scoped_refptr<CPUTime> cputime) {
- set_cputime_ = cputime;
- }
-
protected:
scoped_refptr<Outputter> CreateOutputter(const std::string& name) override {
if (set_outputter_.get()) {
@@ -194,72 +177,52 @@
return new MockOutputter();
}
- scoped_refptr<CPUTime> CreateCPUTime() override {
- if (set_cputime_.get()) {
- return set_cputime_;
- }
- return new FakeCPUTime();
- }
-
- GpuTracerType DetermineTracerType() override {
- return test_tracer_type_;
- }
-
void PostTask() override {
// Process synchronously.
Process();
}
unsigned char tracing_enabled_;
- GpuTracerType test_tracer_type_;
scoped_refptr<Outputter> set_outputter_;
- scoped_refptr<CPUTime> set_cputime_;
};
class BaseGpuTest : public GpuServiceTest {
public:
- BaseGpuTest(GpuTracerType test_tracer_type)
- : test_tracer_type_(test_tracer_type) {
+ explicit BaseGpuTest(GPUTiming::TimerType test_timer_type)
+ : test_timer_type_(test_timer_type) {
+ gpu_timing_.SetCpuTimeForTesting(base::Bind(&FakeCpuTime));
+ gpu_timing_.SetTimerTypeForTesting(test_timer_type);
}
protected:
void SetUp() override {
+ g_fakeCPUTime = 0;
const char* gl_version = "3.2";
- const char* extensions = nullptr;
- if (GetTracerType() == kTracerTypeDisjointTimer) {
+ const char* extensions = "";
+ if (GetTimerType() == GPUTiming::kTimerTypeDisjoint) {
gl_version = "opengl es 3.0";
extensions = "GL_EXT_disjoint_timer_query";
- } else if (GetTracerType() == kTracerTypeARBTimer) {
+ } else if (GetTimerType() == GPUTiming::kTimerTypeARB) {
// TODO(sievers): The tracer should not depend on ARB_occlusion_query.
// Try merge Query APIs (core, ARB, EXT) into a single binding each.
extensions = "GL_ARB_timer_query GL_ARB_occlusion_query";
}
GpuServiceTest::SetUpWithGLVersion(gl_version, extensions);
gl_fake_queries_.Reset();
- gl_surface_ = new gfx::GLSurfaceStub();
- gl_context_ = new gfx::GLContextStub();
- gl_context_->MakeCurrent(gl_surface_.get());
outputter_ref_ = new MockOutputter();
- cpu_time_ref_ = new FakeCPUTime;
}
void TearDown() override {
outputter_ref_ = NULL;
- cpu_time_ref_ = NULL;
- gl_context_->ReleaseCurrent(gl_surface_.get());
- gl_context_ = NULL;
- gl_surface_ = NULL;
-
- gl_.reset();
gl_fake_queries_.Reset();
GpuServiceTest::TearDown();
}
void ExpectTraceQueryMocks() {
- if (GetTracerType() != kTracerTypeInvalid) {
+ if (GetTimerType() != GPUTiming::kTimerTypeInvalid) {
// Delegate query APIs used by GPUTrace to a GlFakeQueries
EXPECT_CALL(*gl_, GenQueriesARB(2, NotNull())).Times(AtLeast(1))
.WillRepeatedly(
@@ -270,7 +233,7 @@
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectivARB));
- if (GetTracerType() == kTracerTypeDisjointTimer) {
+ if (GetTimerType() == GPUTiming::kTimerTypeDisjoint) {
EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, _))
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::GetInteger64v));
@@ -323,14 +286,14 @@
const std::string& name, int64 expect_start_time,
int64 expect_end_time) {
ExpectOutputterBeginMocks(outputter, category, name);
- ExpectOutputterEndMocks(outputter, category, name,
- expect_start_time, expect_end_time,
- GetTracerType() != kTracerTypeInvalid);
+ ExpectOutputterEndMocks(outputter, category, name, expect_start_time,
+ expect_end_time,
+ GetTimerType() != GPUTiming::kTimerTypeInvalid);
}
void ExpectTracerOffsetQueryMocks() {
// Disjoint check should only be called by kTracerTypeDisjointTimer type.
- if (GetTracerType() == kTracerTypeDisjointTimer) {
+ if (GetTimerType() == GPUTiming::kTimerTypeDisjoint) {
EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(AtLeast(1))
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::GetIntegerv));
@@ -338,36 +301,31 @@
EXPECT_CALL(*gl_, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(Exactly(0));
}
- // Timer offset calculation should only happen for the regular timer.
- if (GetTracerType() != kTracerTypeARBTimer) {
+ if (GetTimerType() != GPUTiming::kTimerTypeARB) {
EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull()))
.Times(Exactly(0));
} else {
EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull()))
- .Times(AtLeast(1))
+ .Times(AtMost(1))
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::GetInteger64v));
}
}
- GpuTracerType GetTracerType() { return test_tracer_type_; }
+ GPUTiming::TimerType GetTimerType() { return test_timer_type_; }
- GpuTracerType test_tracer_type_;
+ GPUTiming::TimerType test_timer_type_;
GlFakeQueries gl_fake_queries_;
+ GPUTiming gpu_timing_;
scoped_refptr<MockOutputter> outputter_ref_;
- scoped_refptr<FakeCPUTime> cpu_time_ref_;
-
- scoped_refptr<gfx::GLSurface> gl_surface_;
- scoped_refptr<gfx::GLContext> gl_context_;
};
// Test GPUTrace calls all the correct gl calls.
class BaseGpuTraceTest : public BaseGpuTest {
public:
- BaseGpuTraceTest(GpuTracerType test_tracer_type)
- : BaseGpuTest(test_tracer_type) {
- }
+ explicit BaseGpuTraceTest(GPUTiming::TimerType test_timer_type)
+ : BaseGpuTest(test_timer_type) {}
void DoTraceTest() {
// Expected results
@@ -386,12 +344,14 @@
ExpectOutputterMocks(outputter_ref_.get(), category_name, trace_name,
expect_start_time, expect_end_time);
- scoped_refptr<GPUTrace> trace =
- new GPUTrace(outputter_ref_, cpu_time_ref_, category_name, trace_name,
- offset_time, GetTracerType());
+ scoped_refptr<GPUTrace> trace = new GPUTrace(
+ outputter_ref_, &gpu_timing_, category_name, trace_name, true);
+
+ gpu_timing_.SetOffsetForTesting(
+ offset_time, test_timer_type_ == GPUTiming::kTimerTypeARB);
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
- cpu_time_ref_->SetFakeCPUTime(expect_start_time);
+ g_fakeCPUTime = expect_start_time;
trace->Start(true);
// Shouldn't be available before End() call
@@ -413,22 +373,18 @@
trace->Process();
outputter_ref_ = NULL;
- cpu_time_ref_ = NULL;
}
};
class GpuARBTimerTraceTest : public BaseGpuTraceTest {
public:
- GpuARBTimerTraceTest()
- : BaseGpuTraceTest(kTracerTypeARBTimer) {
- }
+ GpuARBTimerTraceTest() : BaseGpuTraceTest(GPUTiming::kTimerTypeARB) {}
};
class GpuDisjointTimerTraceTest : public BaseGpuTraceTest {
public:
GpuDisjointTimerTraceTest()
- : BaseGpuTraceTest(kTracerTypeDisjointTimer) {
- }
+ : BaseGpuTraceTest(GPUTiming::kTimerTypeDisjoint) {}
};
TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTest) {
@@ -442,25 +398,23 @@
// Test GPUTracer calls all the correct gl calls.
class BaseGpuTracerTest : public BaseGpuTest {
public:
- BaseGpuTracerTest(GpuTracerType test_tracer_type)
- : BaseGpuTest(test_tracer_type) {
- }
+ explicit BaseGpuTracerTest(GPUTiming::TimerType test_timer_type)
+ : BaseGpuTest(test_timer_type) {}
void DoBasicTracerTest() {
ExpectTracerOffsetQueryMocks();
MockGLES2Decoder decoder;
- GPUTracerTester tracer(test_tracer_type_, &decoder);
+ EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
+ GPUTracerTester tracer(&decoder);
tracer.SetTracingEnabled(true);
tracer.SetOutputter(outputter_ref_);
- tracer.SetCPUTime(cpu_time_ref_);
ASSERT_TRUE(tracer.BeginDecoding());
ASSERT_TRUE(tracer.EndDecoding());
outputter_ref_ = NULL;
- cpu_time_ref_ = NULL;
}
void DoTracerMarkersTest() {
@@ -482,14 +436,14 @@
(end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
MockGLES2Decoder decoder;
- GPUTracerTester tracer(test_tracer_type_, &decoder);
+ EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
+ GPUTracerTester tracer(&decoder);
tracer.SetTracingEnabled(true);
tracer.SetOutputter(outputter_ref_);
- tracer.SetCPUTime(cpu_time_ref_);
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
- cpu_time_ref_->SetFakeCPUTime(expect_start_time);
+ g_fakeCPUTime = expect_start_time;
ASSERT_TRUE(tracer.BeginDecoding());
@@ -501,7 +455,7 @@
gl_fake_queries_.SetCurrentGLTime(
start_timestamp +
(i * base::Time::kNanosecondsPerMicrosecond));
- cpu_time_ref_->SetFakeCPUTime(expect_start_time + i);
+ g_fakeCPUTime = expect_start_time + i;
// Each trace name should be different to differentiate.
const char num_char = static_cast<char>('0' + i);
@@ -520,7 +474,7 @@
gl_fake_queries_.SetCurrentGLTime(
end_timestamp +
(i * base::Time::kNanosecondsPerMicrosecond));
- cpu_time_ref_->SetFakeCPUTime(expect_end_time + i);
+ g_fakeCPUTime = expect_start_time + i;
// Each trace name should be different to differentiate.
const char num_char = static_cast<char>('0' + i);
@@ -528,9 +482,9 @@
std::string source_trace_name = trace_name + num_char;
ExpectOutputterEndMocks(outputter_ref_.get(), source_category,
- source_trace_name,
- expect_start_time + i, expect_end_time + i,
- GetTracerType() != kTracerTypeInvalid);
+ source_trace_name, expect_start_time + i,
+ expect_end_time + i,
+ GetTimerType() != GPUTiming::kTimerTypeInvalid);
const GpuTracerSource source = static_cast<GpuTracerSource>(i);
@@ -544,7 +498,6 @@
ASSERT_TRUE(tracer.EndDecoding());
outputter_ref_ = NULL;
- cpu_time_ref_ = NULL;
}
void DoDisjointTest() {
@@ -568,14 +521,14 @@
(end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
MockGLES2Decoder decoder;
- GPUTracerTester tracer(test_tracer_type_, &decoder);
+ EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
+ GPUTracerTester tracer(&decoder);
tracer.SetTracingEnabled(true);
tracer.SetOutputter(outputter_ref_);
- tracer.SetCPUTime(cpu_time_ref_);
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
- cpu_time_ref_->SetFakeCPUTime(expect_start_time);
+ g_fakeCPUTime = expect_start_time;
ASSERT_TRUE(tracer.BeginDecoding());
@@ -586,7 +539,7 @@
ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
gl_fake_queries_.SetCurrentGLTime(end_timestamp);
- cpu_time_ref_->SetFakeCPUTime(expect_end_time);
+ g_fakeCPUTime = expect_end_time;
gl_fake_queries_.SetDisjoint();
ExpectOutputterEndMocks(outputter_ref_.get(), category_name, trace_name,
@@ -596,29 +549,23 @@
ASSERT_TRUE(tracer.EndDecoding());
outputter_ref_ = NULL;
- cpu_time_ref_ = NULL;
}
};
class InvalidTimerTracerTest : public BaseGpuTracerTest {
public:
- InvalidTimerTracerTest()
- : BaseGpuTracerTest(kTracerTypeInvalid) {
- }
+ InvalidTimerTracerTest() : BaseGpuTracerTest(GPUTiming::kTimerTypeInvalid) {}
};
class GpuARBTimerTracerTest : public BaseGpuTracerTest {
public:
- GpuARBTimerTracerTest()
- : BaseGpuTracerTest(kTracerTypeARBTimer) {
- }
+ GpuARBTimerTracerTest() : BaseGpuTracerTest(GPUTiming::kTimerTypeARB) {}
};
class GpuDisjointTimerTracerTest : public BaseGpuTracerTest {
public:
GpuDisjointTimerTracerTest()
- : BaseGpuTracerTest(kTracerTypeDisjointTimer) {
- }
+ : BaseGpuTracerTest(GPUTiming::kTimerTypeDisjoint) {}
};
TEST_F(InvalidTimerTracerTest, InvalidTimerBasicTracerTest) {
@@ -649,38 +596,53 @@
DoDisjointTest();
}
+class GPUTracerTest : public GpuServiceTest {
+ protected:
+ void SetUp() override {
+ g_fakeCPUTime = 0;
+ GpuServiceTest::SetUpWithGLVersion("3.2", "");
+ decoder_.reset(new MockGLES2Decoder());
+ EXPECT_CALL(*decoder_, GetGLContext())
+ .Times(AtMost(1))
+ .WillRepeatedly(Return(GetGLContext()));
+ tracer_tester_.reset(new GPUTracerTester(decoder_.get()));
+ }
+
+ void TearDown() override {
+ tracer_tester_ = nullptr;
+ decoder_ = nullptr;
+ GpuServiceTest::TearDown();
+ }
+ scoped_ptr<MockGLES2Decoder> decoder_;
+ scoped_ptr<GPUTracerTester> tracer_tester_;
+};
+
+TEST_F(GPUTracerTest, IsTracingTest) {
+ EXPECT_FALSE(tracer_tester_->IsTracing());
+ tracer_tester_->SetTracingEnabled(true);
+ EXPECT_TRUE(tracer_tester_->IsTracing());
+}
// Test basic functionality of the GPUTracerTester.
-TEST(GPUTracerTester, IsTracingTest) {
- MockGLES2Decoder decoder;
- GPUTracerTester tracer_tester(kTracerTypeInvalid, &decoder);
- EXPECT_FALSE(tracer_tester.IsTracing());
- tracer_tester.SetTracingEnabled(true);
- EXPECT_TRUE(tracer_tester.IsTracing());
+TEST_F(GPUTracerTest, DecodeTest) {
+ ASSERT_TRUE(tracer_tester_->BeginDecoding());
+ EXPECT_FALSE(tracer_tester_->BeginDecoding());
+ ASSERT_TRUE(tracer_tester_->EndDecoding());
+ EXPECT_FALSE(tracer_tester_->EndDecoding());
}
-TEST(GPUTracerTester, DecodeTest) {
- MockGLES2Decoder decoder;
- GPUTracerTester tracer_tester(kTracerTypeInvalid, &decoder);
- ASSERT_TRUE(tracer_tester.BeginDecoding());
- EXPECT_FALSE(tracer_tester.BeginDecoding());
- ASSERT_TRUE(tracer_tester.EndDecoding());
- EXPECT_FALSE(tracer_tester.EndDecoding());
-}
-
-TEST(GPUTracerTester, TraceDuringDecodeTest) {
- MockGLES2Decoder decoder;
- GPUTracerTester tracer_tester(kTracerTypeInvalid, &decoder);
+TEST_F(GPUTracerTest, TraceDuringDecodeTest) {
const std::string category_name("trace_category");
const std::string trace_name("trace_test");
- EXPECT_FALSE(tracer_tester.Begin(category_name, trace_name,
- kTraceGroupMarker));
+ EXPECT_FALSE(
+ tracer_tester_->Begin(category_name, trace_name, kTraceGroupMarker));
- ASSERT_TRUE(tracer_tester.BeginDecoding());
- EXPECT_TRUE(tracer_tester.Begin(category_name, trace_name,
- kTraceGroupMarker));
- ASSERT_TRUE(tracer_tester.EndDecoding());
+ ASSERT_TRUE(tracer_tester_->BeginDecoding());
+ EXPECT_TRUE(
+ tracer_tester_->Begin(category_name, trace_name, kTraceGroupMarker));
+ ASSERT_TRUE(tracer_tester_->EndDecoding());
}
+} // namespace
} // namespace gles2
} // namespace gpu
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 5db80b0..c4fa167 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -31,6 +31,7 @@
#include "gpu/command_buffer/service/mailbox_manager_sync.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/query_manager.h"
+#include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h"
#include "gpu/command_buffer/service/valuebuffer_manager.h"
#include "ui/gfx/geometry/size.h"
@@ -130,60 +131,64 @@
base::WaitableEvent* event_;
};
-class SyncPointManager {
+// This wrapper adds the WaitSyncPoint which allows waiting on a sync point
+// on the service thread, implemented using a condition variable.
+class SyncPointManagerWrapper {
public:
- SyncPointManager();
- ~SyncPointManager();
+ SyncPointManagerWrapper();
uint32 GenerateSyncPoint();
void RetireSyncPoint(uint32 sync_point);
+ void AddSyncPointCallback(uint32 sync_point, const base::Closure& callback);
- bool IsSyncPointPassed(uint32 sync_point);
void WaitSyncPoint(uint32 sync_point);
-private:
- // This lock protects access to pending_sync_points_ and next_sync_point_ and
- // is used with the ConditionVariable to signal when a sync point is retired.
- base::Lock lock_;
- std::set<uint32> pending_sync_points_;
- uint32 next_sync_point_;
- base::ConditionVariable cond_var_;
+ private:
+ void OnSyncPointRetired();
+
+ const scoped_refptr<SyncPointManager> manager_;
+ base::Lock retire_lock_;
+ base::ConditionVariable retire_cond_var_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncPointManagerWrapper);
};
-SyncPointManager::SyncPointManager() : next_sync_point_(1), cond_var_(&lock_) {}
-
-SyncPointManager::~SyncPointManager() {
- DCHECK_EQ(pending_sync_points_.size(), 0U);
+SyncPointManagerWrapper::SyncPointManagerWrapper()
+ : manager_(SyncPointManager::Create(true)),
+ retire_cond_var_(&retire_lock_) {
}
-uint32 SyncPointManager::GenerateSyncPoint() {
- base::AutoLock lock(lock_);
- uint32 sync_point = next_sync_point_++;
- DCHECK_EQ(pending_sync_points_.count(sync_point), 0U);
- pending_sync_points_.insert(sync_point);
+uint32 SyncPointManagerWrapper::GenerateSyncPoint() {
+ uint32 sync_point = manager_->GenerateSyncPoint();
+ manager_->AddSyncPointCallback(
+ sync_point, base::Bind(&SyncPointManagerWrapper::OnSyncPointRetired,
+ base::Unretained(this)));
return sync_point;
}
-void SyncPointManager::RetireSyncPoint(uint32 sync_point) {
- base::AutoLock lock(lock_);
- DCHECK(pending_sync_points_.count(sync_point));
- pending_sync_points_.erase(sync_point);
- cond_var_.Broadcast();
+void SyncPointManagerWrapper::RetireSyncPoint(uint32 sync_point) {
+ manager_->RetireSyncPoint(sync_point);
}
-bool SyncPointManager::IsSyncPointPassed(uint32 sync_point) {
- base::AutoLock lock(lock_);
- return pending_sync_points_.count(sync_point) == 0;
+void SyncPointManagerWrapper::AddSyncPointCallback(
+ uint32 sync_point,
+ const base::Closure& callback) {
+ manager_->AddSyncPointCallback(sync_point, callback);
}
-void SyncPointManager::WaitSyncPoint(uint32 sync_point) {
- base::AutoLock lock(lock_);
- while (pending_sync_points_.count(sync_point)) {
- cond_var_.Wait();
+void SyncPointManagerWrapper::WaitSyncPoint(uint32 sync_point) {
+ base::AutoLock lock(retire_lock_);
+ while (!manager_->IsSyncPointRetired(sync_point)) {
+ retire_cond_var_.Wait();
}
}
-base::LazyInstance<SyncPointManager> g_sync_point_manager =
+void SyncPointManagerWrapper::OnSyncPointRetired() {
+ base::AutoLock lock(retire_lock_);
+ retire_cond_var_.Broadcast();
+}
+
+base::LazyInstance<SyncPointManagerWrapper> g_sync_point_manager =
LAZY_INSTANCE_INITIALIZER;
base::SharedMemoryHandle ShareToGpuThread(
@@ -858,15 +863,7 @@
void InProcessCommandBuffer::SignalSyncPointOnGpuThread(
unsigned sync_point,
const base::Closure& callback) {
- if (g_sync_point_manager.Get().IsSyncPointPassed(sync_point)) {
- callback.Run();
- } else {
- service_->ScheduleIdleWork(
- base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread,
- gpu_thread_weak_ptr_,
- sync_point,
- callback));
- }
+ g_sync_point_manager.Get().AddSyncPointCallback(sync_point, callback);
}
void InProcessCommandBuffer::SignalQuery(unsigned query_id,
@@ -906,6 +903,9 @@
return stream_id;
}
+void InProcessCommandBuffer::SetLock(base::Lock*) {
+}
+
uint32 InProcessCommandBuffer::CreateStreamTextureOnGpuThread(
uint32 client_texture_id) {
#if defined(OS_ANDROID)
diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h
index 3be3602..b3f6eb8 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.h
+++ b/gpu/command_buffer/service/in_process_command_buffer.h
@@ -120,6 +120,7 @@
void SignalQuery(uint32 query_id, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
+ void SetLock(base::Lock*) override;
// The serializer interface to the GPU service (i.e. thread).
class Service {
diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc
index 1e8e11b..16509e5 100644
--- a/gpu/command_buffer/service/memory_program_cache.cc
+++ b/gpu/command_buffer/service/memory_program_cache.cc
@@ -15,7 +15,6 @@
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/shader_manager.h"
-#include "gpu/command_buffer/service/shader_translator.h"
#include "ui/gl/gl_bindings.h"
namespace {
@@ -173,9 +172,7 @@
ProgramCache::ProgramLoadResult MemoryProgramCache::LoadLinkedProgram(
GLuint program,
Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) {
char a_sha[kHashLength];
@@ -183,9 +180,9 @@
DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
shader_b && !shader_b->last_compiled_source().empty());
ComputeShaderHash(
- shader_a->last_compiled_source(), translator_a, a_sha);
+ shader_a->last_compiled_signature(), a_sha);
ComputeShaderHash(
- shader_b->last_compiled_source(), translator_b, b_sha);
+ shader_b->last_compiled_signature(), b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
@@ -235,9 +232,7 @@
void MemoryProgramCache::SaveLinkedProgram(
GLuint program,
const Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) {
GLenum format;
@@ -259,9 +254,9 @@
DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
shader_b && !shader_b->last_compiled_source().empty());
ComputeShaderHash(
- shader_a->last_compiled_source(), translator_a, a_sha);
+ shader_a->last_compiled_signature(), a_sha);
ComputeShaderHash(
- shader_b->last_compiled_source(), translator_b, b_sha);
+ shader_b->last_compiled_signature(), b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
diff --git a/gpu/command_buffer/service/memory_program_cache.h b/gpu/command_buffer/service/memory_program_cache.h
index 7560d01..b5862d2 100644
--- a/gpu/command_buffer/service/memory_program_cache.h
+++ b/gpu/command_buffer/service/memory_program_cache.h
@@ -14,7 +14,6 @@
#include "base/memory/scoped_ptr.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/program_cache.h"
-#include "gpu/command_buffer/service/shader_translator.h"
namespace gpu {
namespace gles2 {
@@ -29,16 +28,12 @@
ProgramLoadResult LoadLinkedProgram(
GLuint program,
Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) override;
void SaveLinkedProgram(GLuint program,
const Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) override;
diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc
index 8f8c430..795b0af 100644
--- a/gpu/command_buffer/service/memory_program_cache_unittest.cc
+++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc
@@ -190,16 +190,14 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->last_compiled_source(),
- NULL,
- fragment_shader_->last_compiled_source(),
- NULL,
+ vertex_shader_->last_compiled_signature(),
+ fragment_shader_->last_compiled_signature(),
NULL));
EXPECT_EQ(1, shader_cache_count());
}
@@ -215,16 +213,14 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->last_compiled_source(),
- NULL,
- fragment_shader_->last_compiled_source(),
- NULL,
+ vertex_shader_->last_compiled_signature(),
+ fragment_shader_->last_compiled_signature(),
NULL));
EXPECT_EQ(1, shader_cache_count());
@@ -232,10 +228,8 @@
cache_->LoadProgram(shader_cache_shader());
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->last_compiled_source(),
- NULL,
- fragment_shader_->last_compiled_source(),
- NULL,
+ vertex_shader_->last_compiled_signature(),
+ fragment_shader_->last_compiled_signature(),
NULL));
}
@@ -250,8 +244,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(1, shader_cache_count());
@@ -275,10 +269,8 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
@@ -305,8 +297,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(1, shader_cache_count());
@@ -333,10 +325,8 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
@@ -363,8 +353,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -372,10 +362,8 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -391,8 +379,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -402,10 +390,8 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
@@ -416,10 +402,8 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -439,9 +423,7 @@
binding_map["test"] = 512;
cache_->SaveLinkedProgram(kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
- NULL,
&binding_map,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -450,19 +432,15 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
- NULL,
&binding_map,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -479,8 +457,8 @@
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -488,7 +466,7 @@
const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1;
// save old source and modify for new program
- const std::string& old_source = fragment_shader_->last_compiled_source();
+ const std::string& old_sig = fragment_shader_->last_compiled_signature();
fragment_shader_->set_source("al sdfkjdk");
TestHelper::SetShaderStates(gl_.get(), fragment_shader_, true);
@@ -504,24 +482,18 @@
SetExpectationsForSaveLinkedProgram(kEvictingProgramId, &emulator2);
cache_->SaveLinkedProgram(kEvictingProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->last_compiled_source(),
- NULL,
- fragment_shader_->last_compiled_source(),
- NULL,
+ vertex_shader_->last_compiled_signature(),
+ fragment_shader_->last_compiled_signature(),
NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
- old_source,
- NULL,
- fragment_shader_->last_compiled_source(),
- NULL,
+ old_sig,
+ fragment_shader_->last_compiled_signature(),
NULL));
}
@@ -537,16 +509,14 @@
vertex_shader_->set_source("different!");
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->last_compiled_source(),
- NULL,
- fragment_shader_->last_compiled_source(),
- NULL,
+ vertex_shader_->last_compiled_signature(),
+ fragment_shader_->last_compiled_signature(),
NULL));
}
@@ -561,16 +531,14 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
- vertex_shader_->last_compiled_source(),
- NULL,
- fragment_shader_->last_compiled_source(),
- NULL,
+ vertex_shader_->last_compiled_signature(),
+ fragment_shader_->last_compiled_signature(),
NULL));
SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
@@ -579,10 +547,8 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
@@ -598,8 +564,8 @@
ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -610,8 +576,8 @@
}
ProgramBinaryEmulator emulator2(kBinaryLength, kFormat, test_binary2);
SetExpectationsForSaveLinkedProgram(kProgramId, &emulator2);
- cache_->SaveLinkedProgram(kProgramId, vertex_shader_, NULL,
- fragment_shader_, NULL, NULL,
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_,
+ fragment_shader_, NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this)));
@@ -619,10 +585,8 @@
EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
kProgramId,
vertex_shader_,
- NULL,
fragment_shader_,
NULL,
- NULL,
base::Bind(&MemoryProgramCacheTest::ShaderCacheCb,
base::Unretained(this))));
}
diff --git a/gpu/command_buffer/service/mocks.h b/gpu/command_buffer/service/mocks.h
index 87b3136..d5cff51 100644
--- a/gpu/command_buffer/service/mocks.h
+++ b/gpu/command_buffer/service/mocks.h
@@ -88,7 +88,6 @@
class MockShaderTranslator : public ShaderTranslatorInterface {
public:
MockShaderTranslator();
- virtual ~MockShaderTranslator();
MOCK_METHOD5(Init, bool(
sh::GLenum shader_type,
@@ -106,6 +105,8 @@
NameMap* name_map));
MOCK_CONST_METHOD0(
GetStringForOptionsThatWouldAffectCompilation, std::string());
+ private:
+ ~MockShaderTranslator() override;
};
class MockProgramCache : public ProgramCache {
@@ -113,21 +114,17 @@
MockProgramCache();
virtual ~MockProgramCache();
- MOCK_METHOD7(LoadLinkedProgram, ProgramLoadResult(
+ MOCK_METHOD5(LoadLinkedProgram, ProgramLoadResult(
GLuint program,
Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& callback));
- MOCK_METHOD7(SaveLinkedProgram, void(
+ MOCK_METHOD5(SaveLinkedProgram, void(
GLuint program,
const Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& callback));
MOCK_METHOD1(LoadProgram, void(const std::string&));
diff --git a/gpu/command_buffer/service/program_cache.cc b/gpu/command_buffer/service/program_cache.cc
index abdcfc0..b219086 100644
--- a/gpu/command_buffer/service/program_cache.cc
+++ b/gpu/command_buffer/service/program_cache.cc
@@ -20,15 +20,13 @@
}
ProgramCache::LinkedProgramStatus ProgramCache::GetLinkedProgramStatus(
- const std::string& untranslated_a,
- const ShaderTranslatorInterface* translator_a,
- const std::string& untranslated_b,
- const ShaderTranslatorInterface* translator_b,
+ const std::string& shader_signature_a,
+ const std::string& shader_signature_b,
const std::map<std::string, GLint>* bind_attrib_location_map) const {
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(untranslated_a, translator_a, a_sha);
- ComputeShaderHash(untranslated_b, translator_b, b_sha);
+ ComputeShaderHash(shader_signature_a, a_sha);
+ ComputeShaderHash(shader_signature_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
@@ -46,15 +44,13 @@
}
void ProgramCache::LinkedProgramCacheSuccess(
- const std::string& shader_a,
- const ShaderTranslatorInterface* translator_a,
- const std::string& shader_b,
- const ShaderTranslatorInterface* translator_b,
+ const std::string& shader_signature_a,
+ const std::string& shader_signature_b,
const LocationMap* bind_attrib_location_map) {
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(shader_a, translator_a, a_sha);
- ComputeShaderHash(shader_b, translator_b, b_sha);
+ ComputeShaderHash(shader_signature_a, a_sha);
+ ComputeShaderHash(shader_signature_b, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
b_sha,
@@ -71,13 +67,9 @@
void ProgramCache::ComputeShaderHash(
const std::string& str,
- const ShaderTranslatorInterface* translator,
char* result) const {
- std::string s((
- translator ? translator->GetStringForOptionsThatWouldAffectCompilation() :
- std::string()) + str);
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(s.c_str()),
- s.length(), reinterpret_cast<unsigned char*>(result));
+ base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
+ str.length(), reinterpret_cast<unsigned char*>(result));
}
void ProgramCache::Evict(const std::string& program_hash) {
diff --git a/gpu/command_buffer/service/program_cache.h b/gpu/command_buffer/service/program_cache.h
index 3fb5687..624c436 100644
--- a/gpu/command_buffer/service/program_cache.h
+++ b/gpu/command_buffer/service/program_cache.h
@@ -18,7 +18,6 @@
namespace gles2 {
class Shader;
-class ShaderTranslator;
// Program cache base class for caching linked gpu programs
class GPU_EXPORT ProgramCache {
@@ -41,10 +40,8 @@
virtual ~ProgramCache();
LinkedProgramStatus GetLinkedProgramStatus(
- const std::string& untranslated_shader_a,
- const ShaderTranslatorInterface* translator_a,
- const std::string& untranslated_shader_b,
- const ShaderTranslatorInterface* translator_b,
+ const std::string& shader_signature_a,
+ const std::string& shader_signature_b,
const LocationMap* bind_attrib_location_map) const;
// Loads the linked program from the cache. If the program is not found or
@@ -52,9 +49,7 @@
virtual ProgramLoadResult LoadLinkedProgram(
GLuint program,
Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) = 0;
@@ -63,9 +58,7 @@
virtual void SaveLinkedProgram(
GLuint program,
const Shader* shader_a,
- const ShaderTranslatorInterface* translator_a,
const Shader* shader_b,
- const ShaderTranslatorInterface* translator_b,
const LocationMap* bind_attrib_location_map,
const ShaderCacheCallback& shader_callback) = 0;
@@ -75,10 +68,8 @@
void Clear();
// Only for testing
- void LinkedProgramCacheSuccess(const std::string& shader_a,
- const ShaderTranslatorInterface* translator_a,
- const std::string& shader_b,
- const ShaderTranslatorInterface* translator_b,
+ void LinkedProgramCacheSuccess(const std::string& shader_signature_a,
+ const std::string& shader_signature_b,
const LocationMap* bind_attrib_location_map);
protected:
@@ -87,7 +78,6 @@
// result is not null terminated
void ComputeShaderHash(const std::string& shader,
- const ShaderTranslatorInterface* translator,
char* result) const;
// result is not null terminated. hashed shaders are expected to be
diff --git a/gpu/command_buffer/service/program_cache_unittest.cc b/gpu/command_buffer/service/program_cache_unittest.cc
index 525fea1..7a4cbcd 100644
--- a/gpu/command_buffer/service/program_cache_unittest.cc
+++ b/gpu/command_buffer/service/program_cache_unittest.cc
@@ -18,18 +18,14 @@
ProgramLoadResult LoadLinkedProgram(
GLuint /* program */,
Shader* /* shader_a */,
- const ShaderTranslatorInterface* /* translator_a */,
Shader* /* shader_b */,
- const ShaderTranslatorInterface* /* translator_b */,
const LocationMap* /* bind_attrib_location_map */,
const ShaderCacheCallback& /* callback */) override {
return PROGRAM_LOAD_SUCCESS;
}
void SaveLinkedProgram(GLuint /* program */,
const Shader* /* shader_a */,
- const ShaderTranslatorInterface* /* translator_b */,
const Shader* /* shader_b */,
- const ShaderTranslatorInterface* /* translator_b */,
const LocationMap* /* bind_attrib_location_map */,
const ShaderCacheCallback& /* callback */) override {}
@@ -38,14 +34,12 @@
void ClearBackend() override {}
void SaySuccessfullyCached(const std::string& shader1,
- const ShaderTranslatorInterface* translator_1,
const std::string& shader2,
- const ShaderTranslatorInterface* translator_2,
std::map<std::string, GLint>* attrib_map) {
char a_sha[kHashLength];
char b_sha[kHashLength];
- ComputeShaderHash(shader1, translator_1, a_sha);
- ComputeShaderHash(shader2, translator_2, b_sha);
+ ComputeShaderHash(shader1, a_sha);
+ ComputeShaderHash(shader2, b_sha);
char sha[kHashLength];
ComputeProgramHash(a_sha,
@@ -58,9 +52,8 @@
}
void ComputeShaderHash(const std::string& shader,
- const ShaderTranslatorInterface* translator,
char* result) const {
- ProgramCache::ComputeShaderHash(shader, translator, result);
+ ProgramCache::ComputeShaderHash(shader, result);
}
void ComputeProgramHash(const char* hashed_shader_0,
@@ -95,8 +88,8 @@
std::string shader_b = shader2;
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
cache_->GetLinkedProgramStatus(
- shader_a, NULL, shader_b, NULL, NULL));
- cache_->SaySuccessfullyCached(shader_a, NULL, shader_b, NULL, NULL);
+ shader_a, shader_b, NULL));
+ cache_->SaySuccessfullyCached(shader_a, shader_b, NULL);
shader_a.clear();
shader_b.clear();
@@ -104,37 +97,37 @@
// make sure it was copied
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED,
cache_->GetLinkedProgramStatus(
- shader1, NULL, shader2, NULL, NULL));
+ shader1, shader2, NULL));
}
TEST_F(ProgramCacheTest, LinkUnknownOnFragmentSourceChange) {
const std::string shader1 = "abcd1234";
std::string shader2 = "abcda sda b1~#4 bbbbb1234";
- cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
+ cache_->SaySuccessfullyCached(shader1, shader2, NULL);
shader2 = "different!";
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
}
TEST_F(ProgramCacheTest, LinkUnknownOnVertexSourceChange) {
std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
- cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
+ cache_->SaySuccessfullyCached(shader1, shader2, NULL);
shader1 = "different!";
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
}
TEST_F(ProgramCacheTest, StatusEviction) {
const std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
- cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
+ cache_->SaySuccessfullyCached(shader1, shader2, NULL);
char a_sha[ProgramCache::kHashLength];
char b_sha[ProgramCache::kHashLength];
- cache_->ComputeShaderHash(shader1, NULL, a_sha);
- cache_->ComputeShaderHash(shader2, NULL, b_sha);
+ cache_->ComputeShaderHash(shader1, a_sha);
+ cache_->ComputeShaderHash(shader2, b_sha);
char sha[ProgramCache::kHashLength];
cache_->ComputeProgramHash(a_sha,
@@ -143,22 +136,22 @@
sha);
cache_->Evict(std::string(sha, ProgramCache::kHashLength));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
}
TEST_F(ProgramCacheTest, EvictionWithReusedShader) {
const std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
const std::string shader3 = "asbjbbjj239a";
- cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
- cache_->SaySuccessfullyCached(shader1, NULL, shader3, NULL, NULL);
+ cache_->SaySuccessfullyCached(shader1, shader2, NULL);
+ cache_->SaySuccessfullyCached(shader1, shader3, NULL);
char a_sha[ProgramCache::kHashLength];
char b_sha[ProgramCache::kHashLength];
char c_sha[ProgramCache::kHashLength];
- cache_->ComputeShaderHash(shader1, NULL, a_sha);
- cache_->ComputeShaderHash(shader2, NULL, b_sha);
- cache_->ComputeShaderHash(shader3, NULL, c_sha);
+ cache_->ComputeShaderHash(shader1, a_sha);
+ cache_->ComputeShaderHash(shader2, b_sha);
+ cache_->ComputeShaderHash(shader3, c_sha);
char sha[ProgramCache::kHashLength];
cache_->ComputeProgramHash(a_sha,
@@ -167,9 +160,9 @@
sha);
cache_->Evict(std::string(sha, ProgramCache::kHashLength));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
EXPECT_EQ(ProgramCache::LINK_SUCCEEDED,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader3, NULL));
cache_->ComputeProgramHash(a_sha,
@@ -178,22 +171,22 @@
sha);
cache_->Evict(std::string(sha, ProgramCache::kHashLength));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader3, NULL));
}
TEST_F(ProgramCacheTest, StatusClear) {
const std::string shader1 = "abcd1234";
const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
const std::string shader3 = "asbjbbjj239a";
- cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL);
- cache_->SaySuccessfullyCached(shader1, NULL, shader3, NULL, NULL);
+ cache_->SaySuccessfullyCached(shader1, shader2, NULL);
+ cache_->SaySuccessfullyCached(shader1, shader3, NULL);
cache_->Clear();
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader2, NULL));
EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
- cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL));
+ cache_->GetLinkedProgramStatus(shader1, shader3, NULL));
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 1f6b2d4..aef7e44 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -24,7 +24,6 @@
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/program_cache.h"
#include "gpu/command_buffer/service/shader_manager.h"
-#include "gpu/command_buffer/service/shader_translator.h"
#include "third_party/re2/re2/re2.h"
using base::TimeDelta;
@@ -515,48 +514,14 @@
}
bool Program::Link(ShaderManager* manager,
- ShaderTranslator* vertex_translator,
- ShaderTranslator* fragment_translator,
Program::VaryingsPackingOption varyings_packing_option,
const ShaderCacheCallback& shader_callback) {
ClearLinkStatus();
- if (!CanLink()) {
+
+ if (!AttachedShadersExist()) {
set_log_info("missing shaders");
return false;
}
- if (DetectAttribLocationBindingConflicts()) {
- set_log_info("glBindAttribLocation() conflicts");
- return false;
- }
- std::string conflicting_name;
- if (DetectUniformsMismatch(&conflicting_name)) {
- std::string info_log = "Uniforms with the same name but different "
- "type/precision: " + conflicting_name;
- set_log_info(ProcessLogInfo(info_log).c_str());
- return false;
- }
- if (DetectVaryingsMismatch(&conflicting_name)) {
- std::string info_log = "Varyings with the same name but different type, "
- "or statically used varyings in fragment shader are "
- "not declared in vertex shader: " + conflicting_name;
- set_log_info(ProcessLogInfo(info_log).c_str());
- return false;
- }
- if (DetectBuiltInInvariantConflicts()) {
- set_log_info("Invariant settings for certain built-in varyings "
- "have to match");
- return false;
- }
- if (DetectGlobalNameConflicts(&conflicting_name)) {
- std::string info_log = "Name conflicts between an uniform and an "
- "attribute: " + conflicting_name;
- set_log_info(ProcessLogInfo(info_log).c_str());
- return false;
- }
- if (!CheckVaryingsPacking(varyings_packing_option)) {
- set_log_info("Varyings over maximum register limit");
- return false;
- }
TimeTicks before_time = TimeTicks::Now();
bool link = true;
@@ -565,19 +530,15 @@
DCHECK(!attached_shaders_[0]->last_compiled_source().empty() &&
!attached_shaders_[1]->last_compiled_source().empty());
ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
- attached_shaders_[0]->last_compiled_source(),
- vertex_translator,
- attached_shaders_[1]->last_compiled_source(),
- fragment_translator,
+ attached_shaders_[0]->last_compiled_signature(),
+ attached_shaders_[1]->last_compiled_signature(),
&bind_attrib_location_map_);
if (status == ProgramCache::LINK_SUCCEEDED) {
ProgramCache::ProgramLoadResult success =
cache->LoadLinkedProgram(service_id(),
attached_shaders_[0].get(),
- vertex_translator,
attached_shaders_[1].get(),
- fragment_translator,
&bind_attrib_location_map_,
shader_callback);
link = success != ProgramCache::PROGRAM_LOAD_SUCCESS;
@@ -586,6 +547,47 @@
}
if (link) {
+ CompileAttachedShaders();
+
+ if (!CanLink()) {
+ set_log_info("invalid shaders");
+ return false;
+ }
+ if (DetectAttribLocationBindingConflicts()) {
+ set_log_info("glBindAttribLocation() conflicts");
+ return false;
+ }
+ std::string conflicting_name;
+ if (DetectUniformsMismatch(&conflicting_name)) {
+ std::string info_log = "Uniforms with the same name but different "
+ "type/precision: " + conflicting_name;
+ set_log_info(ProcessLogInfo(info_log).c_str());
+ return false;
+ }
+ if (DetectVaryingsMismatch(&conflicting_name)) {
+ std::string info_log = "Varyings with the same name but different type, "
+ "or statically used varyings in fragment shader "
+ "are not declared in vertex shader: " +
+ conflicting_name;
+ set_log_info(ProcessLogInfo(info_log).c_str());
+ return false;
+ }
+ if (DetectBuiltInInvariantConflicts()) {
+ set_log_info("Invariant settings for certain built-in varyings "
+ "have to match");
+ return false;
+ }
+ if (DetectGlobalNameConflicts(&conflicting_name)) {
+ std::string info_log = "Name conflicts between an uniform and an "
+ "attribute: " + conflicting_name;
+ set_log_info(ProcessLogInfo(info_log).c_str());
+ return false;
+ }
+ if (!CheckVaryingsPacking(varyings_packing_option)) {
+ set_log_info("Varyings over maximum register limit");
+ return false;
+ }
+
ExecuteBindAttribLocationCalls();
before_time = TimeTicks::Now();
if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
@@ -604,9 +606,7 @@
if (cache) {
cache->SaveLinkedProgram(service_id(),
attached_shaders_[0].get(),
- vertex_translator,
attached_shaders_[1].get(),
- fragment_translator,
&bind_attrib_location_map_,
shader_callback);
}
@@ -1001,6 +1001,23 @@
}
}
+void Program::CompileAttachedShaders() {
+ for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
+ Shader* shader = attached_shaders_[ii].get();
+ if (shader) {
+ shader->DoCompile();
+ }
+ }
+}
+
+bool Program::AttachedShadersExist() const {
+ for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
+ if (!attached_shaders_[ii].get())
+ return false;
+ }
+ return true;
+}
+
bool Program::CanLink() const {
for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->valid()) {
@@ -1303,6 +1320,7 @@
GLuint program = service_id();
uint32_t header_size = sizeof(UniformBlocksHeader);
+ bucket->SetSize(header_size); // In case we fail.
uint32_t num_uniform_blocks = 0;
GLint param = GL_FALSE;
@@ -1316,10 +1334,6 @@
if (num_uniform_blocks == 0) {
// Although spec allows an implementation to return uniform block info
// even if a link fails, for consistency, we disallow that.
- bucket->SetSize(header_size);
- UniformBlocksHeader* header =
- bucket->GetDataAs<UniformBlocksHeader*>(0, header_size);
- header->num_uniform_blocks = 0;
return true;
}
@@ -1390,7 +1404,7 @@
bucket->SetSize(total_size);
UniformBlocksHeader* header =
- bucket->GetDataAs<UniformBlocksHeader*>(0, total_size);
+ bucket->GetDataAs<UniformBlocksHeader*>(0, header_size);
UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>(
header_size, entry_size);
char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
@@ -1405,8 +1419,8 @@
std::vector<GLint> params;
for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
// Get active uniform name.
- memcpy(data, names[ii].c_str(), blocks[ii].name_length);
- data += blocks[ii].name_length;
+ memcpy(data, names[ii].c_str(), names[ii].length() + 1);
+ data += names[ii].length() + 1;
// Get active uniform indices.
if (params.size() < blocks[ii].active_uniforms)
@@ -1425,6 +1439,170 @@
return true;
}
+bool Program::GetTransformFeedbackVaryings(
+ CommonDecoder::Bucket* bucket) const {
+ // The data is packed into the bucket in the following order
+ // 1) header
+ // 2) N entries of varying data (except for name)
+ // 3) name1, name2, ..., nameN
+ //
+ // We query all the data directly through GL calls, assuming they are
+ // cheap through MANGLE.
+
+ DCHECK(bucket);
+ GLuint program = service_id();
+
+ uint32_t header_size = sizeof(TransformFeedbackVaryingsHeader);
+ bucket->SetSize(header_size); // In case we fail.
+
+ uint32_t num_transform_feedback_varyings = 0;
+ GLint param = GL_FALSE;
+ // We assume program is a valid program service id.
+ glGetProgramiv(program, GL_LINK_STATUS, ¶m);
+ if (param == GL_TRUE) {
+ param = 0;
+ glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, ¶m);
+ num_transform_feedback_varyings = static_cast<uint32_t>(param);
+ }
+ if (num_transform_feedback_varyings == 0) {
+ return true;
+ }
+
+ std::vector<TransformFeedbackVaryingInfo> varyings(
+ num_transform_feedback_varyings);
+ base::CheckedNumeric<uint32_t> size = sizeof(TransformFeedbackVaryingInfo);
+ size *= num_transform_feedback_varyings;
+ uint32_t entry_size = size.ValueOrDefault(0);
+ size += header_size;
+ std::vector<std::string> names(num_transform_feedback_varyings);
+ GLint max_name_length = 0;
+ glGetProgramiv(
+ program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length);
+ if (max_name_length < 1)
+ max_name_length = 1;
+ std::vector<char> buffer(max_name_length);
+ for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
+ GLsizei var_size = 0;
+ GLsizei var_name_length = 0;
+ GLenum var_type = 0;
+ glGetTransformFeedbackVarying(
+ program, ii, max_name_length,
+ &var_name_length, &var_size, &var_type, &buffer[0]);
+ varyings[ii].size = static_cast<uint32_t>(var_size);
+ varyings[ii].type = static_cast<uint32_t>(var_type);
+ varyings[ii].name_offset = static_cast<uint32_t>(size.ValueOrDefault(0));
+ DCHECK_GT(max_name_length, var_name_length);
+ names[ii] = std::string(&buffer[0], var_name_length);
+ // TODO(zmo): optimize the name mapping lookup.
+ const std::string* original_name = GetOriginalNameFromHashedName(names[ii]);
+ if (original_name)
+ names[ii] = *original_name;
+ varyings[ii].name_length = names[ii].size() + 1;
+ size += names[ii].size();
+ size += 1;
+ }
+ if (!size.IsValid())
+ return false;
+ uint32_t total_size = size.ValueOrDefault(0);
+ DCHECK_LE(header_size + entry_size, total_size);
+ uint32_t data_size = total_size - header_size - entry_size;
+
+ bucket->SetSize(total_size);
+ TransformFeedbackVaryingsHeader* header =
+ bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(0, header_size);
+ TransformFeedbackVaryingInfo* entries =
+ bucket->GetDataAs<TransformFeedbackVaryingInfo*>(header_size, entry_size);
+ char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
+ DCHECK(header);
+ DCHECK(entries);
+ DCHECK(data);
+
+ // Copy over data for the header and entries.
+ header->num_transform_feedback_varyings = num_transform_feedback_varyings;
+ memcpy(entries, &varyings[0], entry_size);
+
+ for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
+ memcpy(data, names[ii].c_str(), names[ii].length() + 1);
+ data += names[ii].length() + 1;
+ }
+ DCHECK_EQ(ComputeOffset(header, data), total_size);
+ return true;
+}
+
+bool Program::GetUniformsES3(CommonDecoder::Bucket* bucket) const {
+ // The data is packed into the bucket in the following order
+ // 1) header
+ // 2) N entries of UniformES3Info
+ //
+ // We query all the data directly through GL calls, assuming they are
+ // cheap through MANGLE.
+
+ DCHECK(bucket);
+ GLuint program = service_id();
+
+ uint32_t header_size = sizeof(UniformsES3Header);
+ bucket->SetSize(header_size); // In case we fail.
+
+ GLsizei count = 0;
+ GLint param = GL_FALSE;
+ // We assume program is a valid program service id.
+ glGetProgramiv(program, GL_LINK_STATUS, ¶m);
+ if (param == GL_TRUE) {
+ param = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count);
+ }
+ if (count == 0) {
+ return true;
+ }
+
+ base::CheckedNumeric<uint32_t> size = sizeof(UniformES3Info);
+ size *= count;
+ uint32_t entry_size = size.ValueOrDefault(0);
+ size += header_size;
+ if (!size.IsValid())
+ return false;
+ uint32_t total_size = size.ValueOrDefault(0);
+ bucket->SetSize(total_size);
+ UniformsES3Header* header =
+ bucket->GetDataAs<UniformsES3Header*>(0, header_size);
+ DCHECK(header);
+ header->num_uniforms = static_cast<uint32_t>(count);
+
+ // Instead of GetDataAs<UniformES3Info*>, we do GetDataAs<int32_t>. This is
+ // because struct UniformES3Info is defined as five int32_t.
+ // By doing this, we can fill the structs through loops.
+ int32_t* entries =
+ bucket->GetDataAs<int32_t*>(header_size, entry_size);
+ DCHECK(entries);
+ const size_t kStride = sizeof(UniformES3Info) / sizeof(int32_t);
+
+ const GLenum kPname[] = {
+ GL_UNIFORM_BLOCK_INDEX,
+ GL_UNIFORM_OFFSET,
+ GL_UNIFORM_ARRAY_STRIDE,
+ GL_UNIFORM_MATRIX_STRIDE,
+ GL_UNIFORM_IS_ROW_MAJOR,
+ };
+ const GLint kDefaultValue[] = { -1, -1, -1, -1, 0 };
+ const size_t kNumPnames = arraysize(kPname);
+ std::vector<GLuint> indices(count);
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ indices[ii] = ii;
+ }
+ std::vector<GLint> params(count);
+ for (size_t pname_index = 0; pname_index < kNumPnames; ++pname_index) {
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ params[ii] = kDefaultValue[pname_index];
+ }
+ glGetActiveUniformsiv(
+ program, count, &indices[0], kPname[pname_index], ¶ms[0]);
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ entries[kStride * ii + pname_index] = params[ii];
+ }
+ }
+ return true;
+}
+
Program::~Program() {
if (manager_) {
if (manager_->have_context_) {
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index 6f7e3a9..b8b2d2d 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -24,7 +24,6 @@
class ProgramManager;
class Shader;
class ShaderManager;
-class ShaderTranslator;
// This is used to track which attributes a particular program needs
// so we can verify at glDrawXXX time that every attribute is either disabled
@@ -153,6 +152,15 @@
// Return false on overflow.
bool GetUniformBlocks(CommonDecoder::Bucket* bucket) const;
+ // Gets all the TransformFeedbackVarying info.
+ // Return false on overflow.
+ bool GetTransformFeedbackVaryings(CommonDecoder::Bucket* bucket) const;
+
+ // Gather all info through glGetActiveUniformsiv, except for size, type,
+ // name_length, which we gather through glGetActiveUniform in
+ // glGetProgramInfoCHROMIUM.
+ bool GetUniformsES3(CommonDecoder::Bucket* bucket) const;
+
// Sets the sampler values for a uniform.
// This is safe to call for any location. If the location is not
// a sampler uniform nothing will happen.
@@ -175,12 +183,12 @@
bool AttachShader(ShaderManager* manager, Shader* shader);
bool DetachShader(ShaderManager* manager, Shader* shader);
+ void CompileAttachedShaders();
+ bool AttachedShadersExist() const;
bool CanLink() const;
// Performs glLinkProgram and related activities.
bool Link(ShaderManager* manager,
- ShaderTranslator* vertex_translator,
- ShaderTranslator* fragment_shader,
VaryingsPackingOption varyings_packing_option,
const ShaderCacheCallback& shader_callback);
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc
index 7d9ea9d..99678f4 100644
--- a/gpu/command_buffer/service/program_manager_unittest.cc
+++ b/gpu/command_buffer/service/program_manager_unittest.cc
@@ -242,7 +242,7 @@
program_->AttachShader(&shader_manager_, vertex_shader);
program_->AttachShader(&shader_manager_, fragment_shader);
- program_->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program_->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
}
@@ -272,7 +272,7 @@
SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
service_id);
}
- program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
GLint link_status;
program->GetProgramiv(GL_LINK_STATUS, &link_status);
@@ -715,7 +715,7 @@
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
- program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
GLint value = 0;
program->GetProgramiv(GL_ACTIVE_ATTRIBUTES, &value);
@@ -784,7 +784,7 @@
ASSERT_TRUE(program != NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
- program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
// Check that we get the correct locations.
@@ -880,7 +880,7 @@
ASSERT_TRUE(program!= NULL);
EXPECT_TRUE(program->AttachShader(&shader_manager_, vshader));
EXPECT_TRUE(program->AttachShader(&shader_manager_, fshader));
- program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
// Check that we got the good type, not the bad.
// Check Attribs
@@ -1227,6 +1227,199 @@
EXPECT_EQ(0, memcmp(&data, bucket_data, sizeof(Data)));
}
+TEST_F(ProgramManagerWithShaderTest,
+ ProgramInfoGetTransformFeedbackVaryingsNone) {
+ CommonDecoder::Bucket bucket;
+ const Program* program = manager_.GetProgram(kClientProgramId);
+ ASSERT_TRUE(program != NULL);
+ // The program's previous link failed.
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_FALSE))
+ .RetiresOnSaturation();
+ EXPECT_TRUE(program->GetTransformFeedbackVaryings(&bucket));
+ EXPECT_EQ(sizeof(TransformFeedbackVaryingsHeader), bucket.size());
+ TransformFeedbackVaryingsHeader* header =
+ bucket.GetDataAs<TransformFeedbackVaryingsHeader*>(
+ 0, sizeof(TransformFeedbackVaryingsHeader));
+ EXPECT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_transform_feedback_varyings);
+ // Zero uniform blocks.
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(
+ kServiceProgramId, GL_TRANSFORM_FEEDBACK_VARYINGS, _))
+ .WillOnce(SetArgPointee<2>(0))
+ .RetiresOnSaturation();
+ EXPECT_TRUE(program->GetTransformFeedbackVaryings(&bucket));
+ EXPECT_EQ(sizeof(TransformFeedbackVaryingsHeader), bucket.size());
+ header = bucket.GetDataAs<TransformFeedbackVaryingsHeader*>(
+ 0, sizeof(TransformFeedbackVaryingsHeader));
+ EXPECT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_transform_feedback_varyings);
+}
+
+TEST_F(ProgramManagerWithShaderTest,
+ ProgramInfoGetTransformFeedbackVaryingsValid) {
+ CommonDecoder::Bucket bucket;
+ const Program* program = manager_.GetProgram(kClientProgramId);
+ ASSERT_TRUE(program != NULL);
+ struct Data {
+ TransformFeedbackVaryingsHeader header;
+ TransformFeedbackVaryingInfo entry[2];
+ char name0[4];
+ char name1[8];
+ };
+ Data data;
+ // The names needs to be of size 4*k-1 to avoid padding in the struct Data.
+ // This is a testing only problem.
+ const char* kName[] = { "cow", "chicken" };
+ data.header.num_transform_feedback_varyings = 2;
+ data.entry[0].size = 1;
+ data.entry[0].type = GL_FLOAT_VEC2;
+ data.entry[0].name_offset = ComputeOffset(&data, data.name0);
+ data.entry[0].name_length = arraysize(data.name0);
+ data.entry[1].size = 2;
+ data.entry[1].type = GL_FLOAT;
+ data.entry[1].name_offset = ComputeOffset(&data, data.name1);
+ data.entry[1].name_length = arraysize(data.name1);
+ memcpy(data.name0, kName[0], arraysize(data.name0));
+ memcpy(data.name1, kName[1], arraysize(data.name1));
+
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(
+ kServiceProgramId, GL_TRANSFORM_FEEDBACK_VARYINGS, _))
+ .WillOnce(SetArgPointee<2>(data.header.num_transform_feedback_varyings))
+ .RetiresOnSaturation();
+ GLsizei max_length = 1 + std::max(strlen(kName[0]), strlen(kName[1]));
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId,
+ GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, _))
+ .WillOnce(SetArgPointee<2>(max_length))
+ .RetiresOnSaturation();
+ for (uint32_t ii = 0; ii < data.header.num_transform_feedback_varyings;
+ ++ii) {
+ EXPECT_CALL(*(gl_.get()),
+ GetTransformFeedbackVarying(
+ kServiceProgramId, ii, max_length, _, _, _, _))
+ .WillOnce(DoAll(
+ SetArgPointee<3>(data.entry[ii].name_length - 1),
+ SetArgPointee<4>(data.entry[ii].size),
+ SetArgPointee<5>(data.entry[ii].type),
+ SetArrayArgument<6>(
+ kName[ii], kName[ii] + data.entry[ii].name_length)))
+ .RetiresOnSaturation();
+ }
+ program->GetTransformFeedbackVaryings(&bucket);
+ EXPECT_EQ(sizeof(Data), bucket.size());
+ Data* bucket_data = bucket.GetDataAs<Data*>(0, sizeof(Data));
+ EXPECT_TRUE(bucket_data != NULL);
+ EXPECT_EQ(0, memcmp(&data, bucket_data, sizeof(Data)));
+}
+
+TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformsES3None) {
+ CommonDecoder::Bucket bucket;
+ const Program* program = manager_.GetProgram(kClientProgramId);
+ ASSERT_TRUE(program != NULL);
+ // The program's previous link failed.
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_FALSE))
+ .RetiresOnSaturation();
+ EXPECT_TRUE(program->GetUniformsES3(&bucket));
+ EXPECT_EQ(sizeof(UniformsES3Header), bucket.size());
+ UniformsES3Header* header =
+ bucket.GetDataAs<UniformsES3Header*>(0, sizeof(UniformsES3Header));
+ EXPECT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_uniforms);
+ // Zero uniform blocks.
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORMS, _))
+ .WillOnce(SetArgPointee<2>(0))
+ .RetiresOnSaturation();
+ EXPECT_TRUE(program->GetUniformsES3(&bucket));
+ EXPECT_EQ(sizeof(UniformsES3Header), bucket.size());
+ header =
+ bucket.GetDataAs<UniformsES3Header*>(0, sizeof(UniformsES3Header));
+ EXPECT_TRUE(header != NULL);
+ EXPECT_EQ(0u, header->num_uniforms);
+}
+
+TEST_F(ProgramManagerWithShaderTest, ProgramInfoGetUniformsES3Valid) {
+ CommonDecoder::Bucket bucket;
+ const Program* program = manager_.GetProgram(kClientProgramId);
+ ASSERT_TRUE(program != NULL);
+ struct Data {
+ UniformsES3Header header;
+ UniformES3Info entry[2];
+ };
+ Data data;
+ const GLint kBlockIndex[] = { -1, 2 };
+ const GLint kOffset[] = { 3, 4 };
+ const GLint kArrayStride[] = { 7, 8 };
+ const GLint kMatrixStride[] = { 9, 10 };
+ const GLint kIsRowMajor[] = { 0, 1 };
+ data.header.num_uniforms = 2;
+ for (uint32_t ii = 0; ii < data.header.num_uniforms; ++ii) {
+ data.entry[ii].block_index = kBlockIndex[ii];
+ data.entry[ii].offset = kOffset[ii];
+ data.entry[ii].array_stride = kArrayStride[ii];
+ data.entry[ii].matrix_stride = kMatrixStride[ii];
+ data.entry[ii].is_row_major = kIsRowMajor[ii];
+ }
+
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_LINK_STATUS, _))
+ .WillOnce(SetArgPointee<2>(GL_TRUE))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*(gl_.get()),
+ GetProgramiv(kServiceProgramId, GL_ACTIVE_UNIFORMS, _))
+ .WillOnce(SetArgPointee<2>(data.header.num_uniforms))
+ .RetiresOnSaturation();
+
+ const GLenum kPname[] = {
+ GL_UNIFORM_BLOCK_INDEX,
+ GL_UNIFORM_OFFSET,
+ GL_UNIFORM_ARRAY_STRIDE,
+ GL_UNIFORM_MATRIX_STRIDE,
+ GL_UNIFORM_IS_ROW_MAJOR,
+ };
+ const GLint* kParams[] = {
+ kBlockIndex,
+ kOffset,
+ kArrayStride,
+ kMatrixStride,
+ kIsRowMajor,
+ };
+ const size_t kNumIterations = arraysize(kPname);
+ for (size_t ii = 0; ii < kNumIterations; ++ii) {
+ EXPECT_CALL(*(gl_.get()),
+ GetActiveUniformsiv(
+ kServiceProgramId, data.header.num_uniforms, _,
+ kPname[ii], _))
+ .WillOnce(SetArrayArgument<4>(
+ kParams[ii], kParams[ii] + data.header.num_uniforms))
+ .RetiresOnSaturation();
+ }
+
+ program->GetUniformsES3(&bucket);
+ EXPECT_EQ(sizeof(Data), bucket.size());
+ Data* bucket_data = bucket.GetDataAs<Data*>(0, sizeof(Data));
+ EXPECT_TRUE(bucket_data != NULL);
+ EXPECT_EQ(0, memcmp(&data, bucket_data, sizeof(Data)));
+}
+
// Some drivers optimize out unused uniform array elements, so their
// location would be -1.
TEST_F(ProgramManagerWithShaderTest, UnusedUniformArrayElements) {
@@ -1631,7 +1824,7 @@
const size_t kNumUniforms = arraysize(kUniforms);
SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
kServiceProgramId);
- program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
SetupExpectationsForClearingUniforms(kUniforms, kNumUniforms);
manager_.ClearUniforms(program);
@@ -1704,7 +1897,7 @@
const size_t kNumUniforms = arraysize(kUniforms);
SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms,
kServiceProgramId);
- program->Link(NULL, NULL, NULL, Program::kCountOnlyStaticallyUsed,
+ program->Link(NULL, Program::kCountOnlyStaticallyUsed,
base::Bind(&ShaderCacheCb));
EXPECT_EQ(kUniform1DesiredLocation,
@@ -1765,9 +1958,7 @@
void SetProgramCached() {
cache_->LinkedProgramCacheSuccess(
vertex_shader_->source(),
- NULL,
fragment_shader_->source(),
- NULL,
&program_->bind_attrib_location_map());
}
@@ -1784,9 +1975,7 @@
EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
program->service_id(),
vertex_shader,
- NULL,
fragment_shader,
- NULL,
&program->bind_attrib_location_map(),
_)).Times(1);
}
@@ -1804,9 +1993,7 @@
EXPECT_CALL(*cache_.get(), SaveLinkedProgram(
program->service_id(),
vertex_shader,
- NULL,
fragment_shader,
- NULL,
&program->bind_attrib_location_map(),
_)).Times(0);
}
@@ -1828,9 +2015,7 @@
EXPECT_CALL(*cache_.get(),
LoadLinkedProgram(service_program_id,
vertex_shader,
- NULL,
fragment_shader,
- NULL,
&program->bind_attrib_location_map(),
_))
.WillOnce(Return(result));
@@ -1921,8 +2106,8 @@
SetShadersCompiled();
SetExpectationsForProgramLink();
SetExpectationsForProgramCached();
- EXPECT_TRUE(program_->Link(NULL, NULL, NULL,
- Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb)));
+ EXPECT_TRUE(program_->Link(NULL, Program::kCountOnlyStaticallyUsed,
+ base::Bind(&ShaderCacheCb)));
}
TEST_F(ProgramManagerWithCacheTest, LoadProgramOnProgramCacheHit) {
@@ -1935,8 +2120,8 @@
SetExpectationsForNotCachingProgram();
SetExpectationsForProgramLoadSuccess();
- EXPECT_TRUE(program_->Link(NULL, NULL, NULL,
- Program::kCountOnlyStaticallyUsed, base::Bind(&ShaderCacheCb)));
+ EXPECT_TRUE(program_->Link(NULL, Program::kCountOnlyStaticallyUsed,
+ base::Bind(&ShaderCacheCb)));
}
} // namespace gles2
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc
index 90b1576..055cd70 100644
--- a/gpu/command_buffer/service/shader_manager.cc
+++ b/gpu/command_buffer/service/shader_manager.cc
@@ -29,19 +29,22 @@
shader_state_(kShaderStateWaiting),
service_id_(service_id),
shader_type_(shader_type),
+ source_type_(kANGLE),
valid_(false) {
}
Shader::~Shader() {
}
-void Shader::RequestCompile() {
+void Shader::RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator,
+ TranslatedShaderSourceType type) {
shader_state_ = kShaderStateCompileRequested;
+ translator_ = translator;
+ source_type_ = type;
last_compiled_source_ = source_;
}
-void Shader::DoCompile(ShaderTranslatorInterface* translator,
- TranslatedShaderSourceType type) {
+void Shader::DoCompile() {
// We require that RequestCompile() must be called before DoCompile(),
// so we can return early if the shader state is not what we expect.
if (shader_state_ != kShaderStateCompileRequested) {
@@ -51,19 +54,21 @@
// Signify the shader has been compiled, whether or not it is valid
// is dependent on the |valid_| member variable.
shader_state_ = kShaderStateCompiled;
+ valid_ = false;
// Translate GL ES 2.0 shader to Desktop GL shader and pass that to
// glShaderSource and then glCompileShader.
const char* source_for_driver = last_compiled_source_.c_str();
+ ShaderTranslatorInterface* translator = translator_.get();
if (translator) {
- valid_ = translator->Translate(last_compiled_source_,
- &log_info_,
- &translated_source_,
- &attrib_map_,
- &uniform_map_,
- &varying_map_,
- &name_map_);
- if (!valid_) {
+ bool success = translator->Translate(last_compiled_source_,
+ &log_info_,
+ &translated_source_,
+ &attrib_map_,
+ &uniform_map_,
+ &varying_map_,
+ &name_map_);
+ if (!success) {
return;
}
source_for_driver = translated_source_.c_str();
@@ -71,7 +76,7 @@
glShaderSource(service_id_, 1, &source_for_driver, NULL);
glCompileShader(service_id_);
- if (type == kANGLE) {
+ if (source_type_ == kANGLE) {
GLint max_len = 0;
glGetShaderiv(service_id_,
GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
@@ -84,11 +89,14 @@
DCHECK(max_len == 0 || len < max_len);
DCHECK(len == 0 || translated_source_[len] == '\0');
translated_source_.resize(len);
+ source_for_driver = translated_source_.c_str();
}
GLint status = GL_FALSE;
glGetShaderiv(service_id_, GL_COMPILE_STATUS, &status);
- if (status != GL_TRUE) {
+ if (status == GL_TRUE) {
+ valid_ = true;
+ } else {
// 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.
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index 11f567d..82fd288 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -35,10 +35,10 @@
kShaderStateCompiled, // Signifies compile happened, not valid compile.
};
- void RequestCompile();
+ void RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator,
+ TranslatedShaderSourceType type);
- void DoCompile(ShaderTranslatorInterface* translator,
- TranslatedShaderSourceType type);
+ void DoCompile();
ShaderState shader_state() const {
return shader_state_;
@@ -64,7 +64,15 @@
return translated_source_;
}
- const std::string& last_compiled_source() const {
+ std::string last_compiled_source() const {
+ return last_compiled_source_;
+ }
+
+ std::string last_compiled_signature() const {
+ if (translator_.get()) {
+ return last_compiled_source_ +
+ translator_->GetStringForOptionsThatWouldAffectCompilation();
+ }
return last_compiled_source_;
}
@@ -152,6 +160,12 @@
// Type of shader - GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
GLenum shader_type_;
+ // Translated source type when shader was last requested to be compiled.
+ TranslatedShaderSourceType source_type_;
+
+ // Translator to use, set when shader was last requested to be compiled.
+ scoped_refptr<ShaderTranslatorInterface> translator_;
+
// True if compilation succeeded.
bool valid_;
diff --git a/gpu/command_buffer/service/shader_manager_unittest.cc b/gpu/command_buffer/service/shader_manager_unittest.cc
index f5f6206..c46b734 100644
--- a/gpu/command_buffer/service/shader_manager_unittest.cc
+++ b/gpu/command_buffer/service/shader_manager_unittest.cc
@@ -140,14 +140,14 @@
EXPECT_TRUE(shader1->last_compiled_source().empty());
// Check that DoCompile() will not work if RequestCompile() was not called.
- MockShaderTranslator translator;
- shader1->DoCompile(&translator, Shader::kANGLE);
+ shader1->DoCompile();
EXPECT_EQ(Shader::kShaderStateWaiting, shader1->shader_state());
EXPECT_FALSE(shader1->valid());
// Check RequestCompile() will update the state and last compiled source, but
// still keep the actual compile state invalid.
- shader1->RequestCompile();
+ scoped_refptr<ShaderTranslatorInterface> translator(new MockShaderTranslator);
+ shader1->RequestCompile(translator, Shader::kANGLE);
EXPECT_EQ(Shader::kShaderStateCompileRequested, shader1->shader_state());
EXPECT_STREQ(kClient1Source, shader1->last_compiled_source().c_str());
EXPECT_FALSE(shader1->valid());
diff --git a/gpu/command_buffer/service/shader_translator.h b/gpu/command_buffer/service/shader_translator.h
index ef25ebb..818be5d 100644
--- a/gpu/command_buffer/service/shader_translator.h
+++ b/gpu/command_buffer/service/shader_translator.h
@@ -27,8 +27,10 @@
// Translates a GLSL ES 2.0 shader to desktop GLSL shader, or just
// validates GLSL ES 2.0 shaders on a true GLSL ES implementation.
-class ShaderTranslatorInterface {
+class ShaderTranslatorInterface
+ : public base::RefCounted<ShaderTranslatorInterface> {
public:
+ ShaderTranslatorInterface() {}
enum GlslImplementationType {
kGlsl,
kGlslES
@@ -62,12 +64,15 @@
protected:
virtual ~ShaderTranslatorInterface() {}
+
+ private:
+ friend class base::RefCounted<ShaderTranslatorInterface>;
+ DISALLOW_COPY_AND_ASSIGN(ShaderTranslatorInterface);
};
// Implementation of ShaderTranslatorInterface
class GPU_EXPORT ShaderTranslator
- : public base::RefCounted<ShaderTranslator>,
- NON_EXPORTED_BASE(public ShaderTranslatorInterface) {
+ : NON_EXPORTED_BASE(public ShaderTranslatorInterface) {
public:
class DestructionObserver {
public:
@@ -104,17 +109,14 @@
void RemoveDestructionObserver(DestructionObserver* observer);
private:
- friend class base::RefCounted<ShaderTranslator>;
-
~ShaderTranslator() override;
+
int GetCompileOptions() const;
ShHandle compiler_;
bool implementation_is_glsl_es_;
ShCompileOptions driver_bug_workarounds_;
ObserverList<DestructionObserver> destruction_observers_;
-
- DISALLOW_COPY_AND_ASSIGN(ShaderTranslator);
};
} // namespace gles2
diff --git a/gpu/command_buffer/service/sync_point_manager.cc b/gpu/command_buffer/service/sync_point_manager.cc
index cd8c490..aa91bf1 100644
--- a/gpu/command_buffer/service/sync_point_manager.cc
+++ b/gpu/command_buffer/service/sync_point_manager.cc
@@ -8,16 +8,26 @@
#include "base/logging.h"
#include "base/rand_util.h"
+#include "base/sequence_checker.h"
namespace gpu {
static const int kMaxSyncBase = INT_MAX;
-SyncPointManager::SyncPointManager()
+// static
+SyncPointManager* SyncPointManager::Create(bool allow_threaded_calls) {
+ return new SyncPointManager(allow_threaded_calls);
+}
+
+SyncPointManager::SyncPointManager(bool allow_threaded_calls)
: next_sync_point_(base::RandInt(1, kMaxSyncBase)) {
// To reduce the risk that a sync point created in a previous GPU process
// will be in flight in the next GPU process, randomize the starting sync
// point number. http://crbug.com/373452
+
+ if (!allow_threaded_calls) {
+ sequence_checker_.reset(new base::SequenceChecker);
+ }
}
SyncPointManager::~SyncPointManager() {
@@ -41,7 +51,7 @@
}
void SyncPointManager::RetireSyncPoint(uint32 sync_point) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ CheckSequencedThread();
ClosureList list;
{
base::AutoLock lock(lock_);
@@ -60,7 +70,7 @@
void SyncPointManager::AddSyncPointCallback(uint32 sync_point,
const base::Closure& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ CheckSequencedThread();
{
base::AutoLock lock(lock_);
SyncPointMap::iterator it = sync_point_map_.find(sync_point);
@@ -73,7 +83,7 @@
}
bool SyncPointManager::IsSyncPointRetired(uint32 sync_point) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ CheckSequencedThread();
{
base::AutoLock lock(lock_);
SyncPointMap::iterator it = sync_point_map_.find(sync_point);
@@ -81,4 +91,9 @@
}
}
+void SyncPointManager::CheckSequencedThread() {
+ DCHECK(!sequence_checker_ ||
+ sequence_checker_->CalledOnValidSequencedThread());
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/service/sync_point_manager.h b/gpu/command_buffer/service/sync_point_manager.h
index 8cbf8a8..001ab17 100644
--- a/gpu/command_buffer/service/sync_point_manager.h
+++ b/gpu/command_buffer/service/sync_point_manager.h
@@ -10,10 +10,14 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
#include "gpu/gpu_export.h"
+namespace base {
+class SequenceChecker;
+}
+
namespace gpu {
// This class manages the sync points, which allow cross-channel
@@ -21,7 +25,10 @@
class GPU_EXPORT SyncPointManager
: public base::RefCountedThreadSafe<SyncPointManager> {
public:
- SyncPointManager();
+ // InProcessCommandBuffer allows threaded calls since it can call into
+ // SyncPointManager from client threads, or from multiple service threads
+ // used in Android WebView.
+ static SyncPointManager* Create(bool allow_threaded_calls);
// Generates a sync point, returning its ID. This can me called on any thread.
// IDs start at a random number. Never return 0.
@@ -44,9 +51,11 @@
typedef std::vector<base::Closure> ClosureList;
typedef base::hash_map<uint32, ClosureList> SyncPointMap;
+ explicit SyncPointManager(bool allow_threaded_calls);
~SyncPointManager();
+ void CheckSequencedThread();
- base::ThreadChecker thread_checker_;
+ scoped_ptr<base::SequenceChecker> sequence_checker_;
// Protects the 2 fields below. Note: callbacks shouldn't be called with this
// held.
diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc
index 6cd0acf..096a60c 100644
--- a/gpu/command_buffer/service/test_helper.cc
+++ b/gpu/command_buffer/service/test_helper.cc
@@ -761,14 +761,15 @@
const NameMap* name_map = (expected_name_map && expected_valid) ?
expected_name_map : &empty_name_map;
- MockShaderTranslator translator;
- EXPECT_CALL(translator, Translate(_,
- NotNull(), // log_info
- NotNull(), // translated_source
- NotNull(), // attrib_map
- NotNull(), // uniform_map
- NotNull(), // varying_map
- NotNull())) // name_map
+ MockShaderTranslator* mock_translator = new MockShaderTranslator;
+ scoped_refptr<ShaderTranslatorInterface> translator(mock_translator);
+ EXPECT_CALL(*mock_translator, Translate(_,
+ NotNull(), // log_info
+ NotNull(), // translated_source
+ NotNull(), // attrib_map
+ NotNull(), // uniform_map
+ NotNull(), // varying_map
+ NotNull())) // name_map
.WillOnce(DoAll(SetArgumentPointee<1>(*log_info),
SetArgumentPointee<2>(*translated_source),
SetArgumentPointee<3>(*attrib_map),
@@ -790,8 +791,8 @@
.WillOnce(SetArgumentPointee<2>(GL_TRUE))
.RetiresOnSaturation();
}
- shader->RequestCompile();
- shader->DoCompile(&translator, Shader::kGL);
+ shader->RequestCompile(translator, Shader::kGL);
+ shader->DoCompile();
}
// static
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 8f4b330..43120b9 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -429,4 +429,8 @@
return 0;
}
+void GLManager::SetLock(base::Lock*) {
+ NOTIMPLEMENTED();
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h
index cad1469..c163ac0 100644
--- a/gpu/command_buffer/tests/gl_manager.h
+++ b/gpu/command_buffer/tests/gl_manager.h
@@ -119,6 +119,7 @@
void SignalQuery(uint32 query, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
+ void SetLock(base::Lock*) override;
private:
void PumpCommands();
diff --git a/gpu/command_buffer/tests/gl_program_unittest.cc b/gpu/command_buffer/tests/gl_program_unittest.cc
index 186b28b..d243994 100644
--- a/gpu/command_buffer/tests/gl_program_unittest.cc
+++ b/gpu/command_buffer/tests/gl_program_unittest.cc
@@ -4,7 +4,9 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/tests/gl_manager.h"
#include "gpu/command_buffer/tests/gl_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -187,5 +189,67 @@
GLTestHelper::CheckGLError("no errors", __LINE__);
}
+TEST_F(GLProgramTest, DeferCompileWithExt) {
+ // This test must have extensions enabled.
+ gles2::ContextGroup* context_group = gl_.decoder()->GetContextGroup();
+ gles2::FeatureInfo* feature_info = context_group->feature_info();
+ const gles2::FeatureInfo::FeatureFlags& flags = feature_info->feature_flags();
+ if (!flags.ext_frag_depth)
+ return;
+
+ static const char* v_shdr_str = R"(
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+ )";
+ static const char* f_shdr_str = R"(
+ #extension GL_EXT_frag_depth : enable
+ void main()
+ {
+ gl_FragDepthEXT = 1.0;
+ }
+ )";
+
+ // First compile and link to be shader compiles.
+ GLuint vs_good = GLTestHelper::CompileShader(GL_VERTEX_SHADER, v_shdr_str);
+ GLuint fs_good = GLTestHelper::CompileShader(GL_FRAGMENT_SHADER, f_shdr_str);
+ GLuint program_good = GLTestHelper::LinkProgram(vs_good, fs_good);
+ GLint linked_good = 0;
+ glGetProgramiv(program_good, GL_LINK_STATUS, &linked_good);
+ EXPECT_NE(0, linked_good);
+
+ // Disable extension and be sure shader no longer compiles.
+ ASSERT_TRUE(glEnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation"));
+ GLuint vs_bad = GLTestHelper::CompileShader(GL_VERTEX_SHADER, v_shdr_str);
+ GLuint fs_bad = GLTestHelper::CompileShader(GL_FRAGMENT_SHADER, f_shdr_str);
+ GLuint program_bad = GLTestHelper::LinkProgram(vs_bad, fs_bad);
+ GLint linked_bad = 0;
+ glGetProgramiv(program_bad, GL_LINK_STATUS, &linked_bad);
+ EXPECT_EQ(0, linked_bad);
+
+ // Relinking good compilations without extension disabled should still link.
+ GLuint program_defer_good = GLTestHelper::LinkProgram(vs_good, fs_good);
+ GLint linked_defer_good = 0;
+ glGetProgramiv(program_defer_good, GL_LINK_STATUS, &linked_defer_good);
+ EXPECT_NE(0, linked_defer_good);
+
+ // linking bad compilations with extension enabled should still not link.
+ GLuint vs_bad2 = GLTestHelper::CompileShader(GL_VERTEX_SHADER, v_shdr_str);
+ GLuint fs_bad2 = GLTestHelper::CompileShader(GL_FRAGMENT_SHADER, f_shdr_str);
+ glRequestExtensionCHROMIUM("GL_EXT_frag_depth");
+ GLuint program_bad2 = GLTestHelper::LinkProgram(vs_bad2, fs_bad2);
+ GLint linked_bad2 = 0;
+ glGetProgramiv(program_bad2, GL_LINK_STATUS, &linked_bad2);
+ EXPECT_EQ(0, linked_bad2);
+
+ // Be sure extension was actually turned on by recompiling.
+ GLuint vs_good2 = GLTestHelper::LoadShader(GL_VERTEX_SHADER, v_shdr_str);
+ GLuint fs_good2 = GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, f_shdr_str);
+ GLuint program_good2 = GLTestHelper::SetupProgram(vs_good2, fs_good2);
+ EXPECT_NE(0u, program_good2);
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc
index d3272ca..7582a5d 100644
--- a/gpu/command_buffer/tests/gl_test_utils.cc
+++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -31,12 +31,19 @@
return success;
}
-GLuint GLTestHelper::LoadShader(GLenum type, const char* shaderSrc) {
+GLuint GLTestHelper::CompileShader(GLenum type, const char* shaderSrc) {
GLuint shader = glCreateShader(type);
// Load the shader source
glShaderSource(shader, 1, &shaderSrc, NULL);
// Compile the shader
glCompileShader(shader);
+
+ return shader;
+}
+
+GLuint GLTestHelper::LoadShader(GLenum type, const char* shaderSrc) {
+ GLuint shader = CompileShader(type, shaderSrc);
+
// Check the compile status
GLint value = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
@@ -52,7 +59,7 @@
return shader;
}
-GLuint GLTestHelper::SetupProgram(
+GLuint GLTestHelper::LinkProgram(
GLuint vertex_shader, GLuint fragment_shader) {
// Create the program object
GLuint program = glCreateProgram();
@@ -60,6 +67,13 @@
glAttachShader(program, fragment_shader);
// Link the program
glLinkProgram(program);
+
+ return program;
+}
+
+GLuint GLTestHelper::SetupProgram(
+ GLuint vertex_shader, GLuint fragment_shader) {
+ GLuint program = LinkProgram(vertex_shader, fragment_shader);
// Check the link status
GLint linked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
diff --git a/gpu/command_buffer/tests/gl_test_utils.h b/gpu/command_buffer/tests/gl_test_utils.h
index 15a726e..802d54d 100644
--- a/gpu/command_buffer/tests/gl_test_utils.h
+++ b/gpu/command_buffer/tests/gl_test_utils.h
@@ -18,11 +18,19 @@
static bool CheckGLError(const char* msg, int line);
// Compiles a shader.
- // Returns shader, 0 on failure..
+ // Does not check for errors, always returns shader.
+ static GLuint CompileShader(GLenum type, const char* shaderSrc);
+
+ // Compiles a shader and checks for compilation errors.
+ // Returns shader, 0 on failure.
static GLuint LoadShader(GLenum type, const char* shaderSrc);
// Attaches 2 shaders and links them to a program.
- // Returns program, 0 on failure..
+ // Does not check for errors, always returns program.
+ static GLuint LinkProgram(GLuint vertex_shader, GLuint fragment_shader);
+
+ // Attaches 2 shaders, links them to a program, and checks for errors.
+ // Returns program, 0 on failure.
static GLuint SetupProgram(GLuint vertex_shader, GLuint fragment_shader);
// Compiles 2 shaders, attaches and links them to a program
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi
index 358317c..5cb2a45 100644
--- a/gpu/command_buffer_service.gypi
+++ b/gpu/command_buffer_service.gypi
@@ -27,6 +27,8 @@
'sources': [
'command_buffer/service/async_pixel_transfer_delegate.cc',
'command_buffer/service/async_pixel_transfer_delegate.h',
+ 'command_buffer/service/async_pixel_transfer_manager.cc',
+ 'command_buffer/service/async_pixel_transfer_manager.h',
'command_buffer/service/async_pixel_transfer_manager_android.cc',
'command_buffer/service/async_pixel_transfer_manager_idle.cc',
'command_buffer/service/async_pixel_transfer_manager_idle.h',
@@ -39,10 +41,8 @@
'command_buffer/service/async_pixel_transfer_manager_sync.cc',
'command_buffer/service/async_pixel_transfer_manager_sync.h',
'command_buffer/service/async_pixel_transfer_manager_win.cc',
- 'command_buffer/service/async_pixel_transfer_manager.cc',
- 'command_buffer/service/async_pixel_transfer_manager.h',
- 'command_buffer/service/buffer_manager.h',
'command_buffer/service/buffer_manager.cc',
+ 'command_buffer/service/buffer_manager.h',
'command_buffer/service/cmd_buffer_engine.h',
'command_buffer/service/cmd_parser.cc',
'command_buffer/service/cmd_parser.h',
@@ -50,34 +50,34 @@
'command_buffer/service/command_buffer_service.h',
'command_buffer/service/common_decoder.cc',
'command_buffer/service/common_decoder.h',
- 'command_buffer/service/context_group.h',
'command_buffer/service/context_group.cc',
+ 'command_buffer/service/context_group.h',
+ 'command_buffer/service/context_state.cc',
'command_buffer/service/context_state.h',
'command_buffer/service/context_state_autogen.h',
'command_buffer/service/context_state_impl_autogen.h',
- 'command_buffer/service/context_state.cc',
'command_buffer/service/error_state.cc',
'command_buffer/service/error_state.h',
- 'command_buffer/service/feature_info.h',
'command_buffer/service/feature_info.cc',
- 'command_buffer/service/framebuffer_manager.h',
+ 'command_buffer/service/feature_info.h',
'command_buffer/service/framebuffer_manager.cc',
- 'command_buffer/service/gles2_cmd_clear_framebuffer.cc',
- 'command_buffer/service/gles2_cmd_clear_framebuffer.h',
- 'command_buffer/service/gles2_cmd_copy_texture_chromium.cc',
- 'command_buffer/service/gles2_cmd_copy_texture_chromium.h',
- 'command_buffer/service/gles2_cmd_decoder.h',
- 'command_buffer/service/gles2_cmd_decoder_autogen.h',
- 'command_buffer/service/gles2_cmd_decoder.cc',
- 'command_buffer/service/gles2_cmd_validation.h',
- 'command_buffer/service/gles2_cmd_validation.cc',
- 'command_buffer/service/gles2_cmd_validation_autogen.h',
- 'command_buffer/service/gles2_cmd_validation_implementation_autogen.h',
+ 'command_buffer/service/framebuffer_manager.h',
'command_buffer/service/gl_context_virtual.cc',
'command_buffer/service/gl_context_virtual.h',
'command_buffer/service/gl_state_restorer_impl.cc',
'command_buffer/service/gl_state_restorer_impl.h',
'command_buffer/service/gl_utils.h',
+ 'command_buffer/service/gles2_cmd_clear_framebuffer.cc',
+ 'command_buffer/service/gles2_cmd_clear_framebuffer.h',
+ 'command_buffer/service/gles2_cmd_copy_texture_chromium.cc',
+ 'command_buffer/service/gles2_cmd_copy_texture_chromium.h',
+ 'command_buffer/service/gles2_cmd_decoder.cc',
+ 'command_buffer/service/gles2_cmd_decoder.h',
+ 'command_buffer/service/gles2_cmd_decoder_autogen.h',
+ 'command_buffer/service/gles2_cmd_validation.cc',
+ 'command_buffer/service/gles2_cmd_validation.h',
+ 'command_buffer/service/gles2_cmd_validation_autogen.h',
+ 'command_buffer/service/gles2_cmd_validation_implementation_autogen.h',
'command_buffer/service/gpu_scheduler.cc',
'command_buffer/service/gpu_scheduler.h',
'command_buffer/service/gpu_scheduler_mock.h',
@@ -85,10 +85,12 @@
'command_buffer/service/gpu_state_tracer.h',
'command_buffer/service/gpu_switches.cc',
'command_buffer/service/gpu_switches.h',
+ 'command_buffer/service/gpu_timing.cc',
+ 'command_buffer/service/gpu_timing.h',
'command_buffer/service/gpu_tracer.cc',
'command_buffer/service/gpu_tracer.h',
- 'command_buffer/service/id_manager.h',
'command_buffer/service/id_manager.cc',
+ 'command_buffer/service/id_manager.h',
'command_buffer/service/image_factory.cc',
'command_buffer/service/image_factory.h',
'command_buffer/service/image_manager.cc',
@@ -102,39 +104,39 @@
'command_buffer/service/mailbox_manager_impl.h',
'command_buffer/service/mailbox_manager_sync.cc',
'command_buffer/service/mailbox_manager_sync.h',
- 'command_buffer/service/memory_program_cache.h',
'command_buffer/service/memory_program_cache.cc',
+ 'command_buffer/service/memory_program_cache.h',
'command_buffer/service/mocks.h',
- 'command_buffer/service/program_manager.h',
- 'command_buffer/service/program_manager.cc',
- 'command_buffer/service/query_manager.h',
- 'command_buffer/service/query_manager.cc',
- 'command_buffer/service/renderbuffer_manager.h',
- 'command_buffer/service/renderbuffer_manager.cc',
- 'command_buffer/service/program_cache.h',
'command_buffer/service/program_cache.cc',
- 'command_buffer/service/shader_manager.h',
+ 'command_buffer/service/program_cache.h',
+ 'command_buffer/service/program_manager.cc',
+ 'command_buffer/service/program_manager.h',
+ 'command_buffer/service/query_manager.cc',
+ 'command_buffer/service/query_manager.h',
+ 'command_buffer/service/renderbuffer_manager.cc',
+ 'command_buffer/service/renderbuffer_manager.h',
'command_buffer/service/shader_manager.cc',
- 'command_buffer/service/shader_translator.h',
+ 'command_buffer/service/shader_manager.h',
'command_buffer/service/shader_translator.cc',
- 'command_buffer/service/shader_translator_cache.h',
+ 'command_buffer/service/shader_translator.h',
'command_buffer/service/shader_translator_cache.cc',
- 'command_buffer/service/stream_texture_manager_in_process_android.h',
+ 'command_buffer/service/shader_translator_cache.h',
'command_buffer/service/stream_texture_manager_in_process_android.cc',
- 'command_buffer/service/sync_point_manager.h',
+ 'command_buffer/service/stream_texture_manager_in_process_android.h',
'command_buffer/service/sync_point_manager.cc',
- 'command_buffer/service/texture_definition.h',
+ 'command_buffer/service/sync_point_manager.h',
'command_buffer/service/texture_definition.cc',
- 'command_buffer/service/texture_manager.h',
+ 'command_buffer/service/texture_definition.h',
'command_buffer/service/texture_manager.cc',
+ 'command_buffer/service/texture_manager.h',
'command_buffer/service/transfer_buffer_manager.cc',
'command_buffer/service/transfer_buffer_manager.h',
- 'command_buffer/service/valuebuffer_manager.h',
'command_buffer/service/valuebuffer_manager.cc',
- 'command_buffer/service/vertex_array_manager.h',
+ 'command_buffer/service/valuebuffer_manager.h',
'command_buffer/service/vertex_array_manager.cc',
- 'command_buffer/service/vertex_attrib_manager.h',
+ 'command_buffer/service/vertex_array_manager.h',
'command_buffer/service/vertex_attrib_manager.cc',
+ 'command_buffer/service/vertex_attrib_manager.h',
],
'conditions': [
['ui_compositor_image_transport==1', {
diff --git a/gpu/config/BUILD.gn b/gpu/config/BUILD.gn
index be7a444..1d86e69 100644
--- a/gpu/config/BUILD.gn
+++ b/gpu/config/BUILD.gn
@@ -15,17 +15,19 @@
"dx_diag_node.h",
"gpu_blacklist.cc",
"gpu_blacklist.h",
- "gpu_control_list_jsons.h",
"gpu_control_list.cc",
"gpu_control_list.h",
- "gpu_driver_bug_list_json.cc",
+ "gpu_control_list_jsons.h",
"gpu_driver_bug_list.cc",
"gpu_driver_bug_list.h",
+ "gpu_driver_bug_list_json.cc",
"gpu_driver_bug_workaround_type.h",
"gpu_dx_diagnostics_win.cc",
"gpu_feature_type.h",
"gpu_info.cc",
"gpu_info.h",
+ "gpu_info_collector.cc",
+ "gpu_info_collector.h",
"gpu_info_collector_android.cc",
"gpu_info_collector_linux.cc",
"gpu_info_collector_linux.h",
@@ -33,8 +35,6 @@
"gpu_info_collector_ozone.cc",
"gpu_info_collector_win.cc",
"gpu_info_collector_x11.cc",
- "gpu_info_collector.cc",
- "gpu_info_collector.h",
"gpu_performance_stats.h",
"gpu_test_config.cc",
"gpu_test_config.h",
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 382bcba..53361eb 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
- "version": "7.15",
+ "version": "7.16",
"entries": [
{
"id": 1,
@@ -1134,6 +1134,31 @@
"features": [
"ignore_egl_sync_failures"
]
+ },
+ {
+ "id": 100,
+ "description": "Disable Direct3D11 on systems with AMD switchable graphics",
+ "cr_bugs": [451420],
+ "os": {
+ "type": "win"
+ },
+ "multi_gpu_style": "amd_switchable",
+ "features": [
+ "disable_d3d11"
+ ]
+ },
+ {
+ "id": 101,
+ "description": "The Mali-Txxx driver hangs when reading from currently displayed buffer",
+ "cr_bugs": [457511],
+ "os": {
+ "type": "chromeos"
+ },
+ "gl_vendor": "ARM.*",
+ "gl_renderer": "Mali-T.*",
+ "features": [
+ "disable_post_sub_buffers_for_onscreen_surfaces"
+ ]
}
]
}
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index fd1ff8b..521f2cd 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -112,6 +112,7 @@
bool supports_robustness =
gpu_info->gl_extensions.find("GL_EXT_robustness") != std::string::npos ||
+ gpu_info->gl_extensions.find("GL_KHR_robustness") != std::string::npos ||
gpu_info->gl_extensions.find("GL_ARB_robustness") != std::string::npos;
if (supports_robustness) {
glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc
index a5686a9..4deee7c 100644
--- a/gpu/config/gpu_info_collector_win.cc
+++ b/gpu/config/gpu_info_collector_win.cc
@@ -407,8 +407,18 @@
{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
// create device info for the display device
- HDEVINFO device_info =
- SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT);
+ HDEVINFO device_info;
+ if (base::win::GetVersion() <= base::win::VERSION_XP) {
+ // Collection of information on all adapters is much slower on XP (almost
+ // 100ms), and not very useful (as it's not going to use the GPU anyway), so
+ // just collect information on the current device. http://crbug.com/456178
+ device_info =
+ SetupDiGetClassDevsW(NULL, device_id.c_str(), NULL,
+ DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
+ } else {
+ device_info =
+ SetupDiGetClassDevsW(&display_class, NULL, NULL, DIGCF_PRESENT);
+ }
if (device_info == INVALID_HANDLE_VALUE) {
LOG(ERROR) << "Creating device info failed";
return kCollectInfoNonFatalFailure;
diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc
index 228e4c1..bd17250 100644
--- a/gpu/gles2_conform_support/egl/display.cc
+++ b/gpu/gles2_conform_support/egl/display.cc
@@ -335,4 +335,8 @@
return 0;
}
+void Display::SetLock(base::Lock*) {
+ NOTIMPLEMENTED();
+}
+
} // namespace egl
diff --git a/gpu/gles2_conform_support/egl/display.h b/gpu/gles2_conform_support/egl/display.h
index 651ab1a..9b349bd 100644
--- a/gpu/gles2_conform_support/egl/display.h
+++ b/gpu/gles2_conform_support/egl/display.h
@@ -92,6 +92,7 @@
void SignalQuery(uint32 query, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
+ void SetLock(base::Lock*) override;
private:
EGLNativeDisplayType display_id_;
diff --git a/gpu/gles2_conform_support/gles2_conform.gypi b/gpu/gles2_conform_support/gles2_conform.gypi
index 41e0f28..6dcf277 100644
--- a/gpu/gles2_conform_support/gles2_conform.gypi
+++ b/gpu/gles2_conform_support/gles2_conform.gypi
@@ -47,12 +47,12 @@
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestPointSizeArray.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestPointSprite.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestPointSprite.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRGB8RGBA8.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRGB8RGBA8.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestReadFormat.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestReadFormat.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRequiredInternalformat.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRequiredInternalformat.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRGB8RGBA8.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRGB8RGBA8.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil1.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil1.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil4.c',
@@ -200,34 +200,40 @@
'gtf_es_sources': [
# Bootstrapping files commented out. We have different bootstrapping
# files for each platform.
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/egl_config_select.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/egl_config_select.h',
- #'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglu.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglu.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglut.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglut.h',
# Note: FilesDATA.h, FilesDATA.c, and FilesTOC.c are generated
# by GTF_ES/glsl/GTF/mergeTestFilesToCSource.pl
- '<(SHARED_INTERMEDIATE_DIR)/gles2_conform_test_embedded_data/FilesDATA.c',
- '<(SHARED_INTERMEDIATE_DIR)/gles2_conform_test_embedded_data/FilesDATA.h',
- '<(SHARED_INTERMEDIATE_DIR)/gles2_conform_test_embedded_data/FilesTOC.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/FilesTOC.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/gl2ext_missing.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/gl2Native.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/gl2Native.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFAttDataGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFAttDataGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFDepthRangeParamGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFDepthRangeParamGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFModelDataGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFModelDataGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFPointParamGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFPointParamGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFReadPixelsGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFReadPixelsGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderDataGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderDataGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderTextGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderTextGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFStateDataGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFStateDataGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexDataGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexDataGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexParamGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexParamGL.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFUniDataGL.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFUniDataGL.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFArguments.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFArguments.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFCoverageDict.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFCoverageGL.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFCoverageGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFCoverageDict.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFDict.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFDictBase.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFFileReader.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFFileReader.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFgl.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFgl.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFInitEGL.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFLog.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFLog.h',
@@ -273,34 +279,28 @@
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFVecBase.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFVector.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFVersion.h',
- #'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/main.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFgl.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GTFgl.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/MIMG.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/MIMG.h',
#'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/Win32Console.h',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/XmlUtils.c',
'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/XmlUtils.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFAttDataGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFAttDataGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFDepthRangeParamGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFDepthRangeParamGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFModelDataGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFModelDataGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFPointParamGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFPointParamGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFReadPixelsGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFReadPixelsGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderDataGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderDataGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderTextGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFShaderTextGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFStateDataGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFStateDataGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexDataGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexDataGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexParamGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFTexParamGL.h',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFUniDataGL.c',
- '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/GL/GTFUniDataGL.h',
+ #'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglNative.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/egl_config_select.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/egl_config_select.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglu.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglu.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglut.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/eglut.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/gl2Native.c',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/gl2Native.h',
+ '<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/gl2ext_missing.h',
+ #'<(DEPTH)/third_party/gles2_conform/GTF_ES/glsl/GTF/Source/main.c',
+ '<(SHARED_INTERMEDIATE_DIR)/gles2_conform_test_embedded_data/FilesDATA.c',
+ '<(SHARED_INTERMEDIATE_DIR)/gles2_conform_test_embedded_data/FilesDATA.h',
+ '<(SHARED_INTERMEDIATE_DIR)/gles2_conform_test_embedded_data/FilesTOC.c',
'<@(gl2_extension_test_sources)',
'<@(gl2_fixed_test_sources)',
'<@(gl2_test_sources)',
diff --git a/gpu/gles2_conform_support/gles2_conform_support.gyp b/gpu/gles2_conform_support/gles2_conform_support.gyp
index 928b152..6bf8510 100644
--- a/gpu/gles2_conform_support/gles2_conform_support.gyp
+++ b/gpu/gles2_conform_support/gles2_conform_support.gyp
@@ -14,8 +14,8 @@
'conditions': [
['OS=="linux"', {
'bootstrap_sources_native': [
- 'native/egl_native_aura.cc',
'native/egl_native.cc',
+ 'native/egl_native_aura.cc',
'native/egl_native_x11.cc',
],
}],
@@ -84,9 +84,9 @@
'../../third_party/khronos/khronos.gyp:khronos_headers',
],
'sources': [
- 'native/main.cc',
'native/egl_native.cc',
'native/egl_native_windowless.cc',
+ 'native/main.cc',
'<@(bootstrap_sources_native)',
],
'defines': [
diff --git a/gpu/gles2_conform_support/gles2_conform_test.gyp b/gpu/gles2_conform_support/gles2_conform_test.gyp
index 4cbb35b..1f23efa 100644
--- a/gpu/gles2_conform_support/gles2_conform_test.gyp
+++ b/gpu/gles2_conform_support/gles2_conform_test.gyp
@@ -137,12 +137,9 @@
4018, # signed/unsigned mismatch
4101, # unreferenced local variable
4715, # not all control paths return a value
+ 4267, # size_t/unsigned int conversion
],
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- 'AdditionalOptions': ['/UNOMINMAX'],
- },
- },
+ 'defines!': [ 'NOMINMAX' ],
}],
['OS=="mac"', {
'defines': [
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 73a1059..70e99c8 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -54,8 +54,8 @@
'GL_IN_PROCESS_CONTEXT_IMPLEMENTATION',
],
'sources': [
- 'command_buffer/client/gl_in_process_context.h',
'command_buffer/client/gl_in_process_context.cc',
+ 'command_buffer/client/gl_in_process_context.h',
'command_buffer/client/gl_in_process_context_export.h',
],
},
@@ -194,10 +194,10 @@
'command_buffer/common/id_allocator_test.cc',
'command_buffer/common/trace_event.h',
'command_buffer/common/unittest_main.cc',
- 'command_buffer/service/async_pixel_transfer_delegate_mock.h',
'command_buffer/service/async_pixel_transfer_delegate_mock.cc',
- 'command_buffer/service/async_pixel_transfer_manager_mock.h',
+ 'command_buffer/service/async_pixel_transfer_delegate_mock.h',
'command_buffer/service/async_pixel_transfer_manager_mock.cc',
+ 'command_buffer/service/async_pixel_transfer_manager_mock.h',
'command_buffer/service/buffer_manager_unittest.cc',
'command_buffer/service/cmd_parser_test.cc',
'command_buffer/service/command_buffer_service_unittest.cc',
@@ -205,6 +205,8 @@
'command_buffer/service/context_group_unittest.cc',
'command_buffer/service/feature_info_unittest.cc',
'command_buffer/service/framebuffer_manager_unittest.cc',
+ 'command_buffer/service/gl_surface_mock.cc',
+ 'command_buffer/service/gl_surface_mock.h',
'command_buffer/service/gles2_cmd_decoder_unittest.cc',
'command_buffer/service/gles2_cmd_decoder_unittest.h',
'command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h',
@@ -215,6 +217,7 @@
'command_buffer/service/gles2_cmd_decoder_unittest_3.cc',
'command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h',
'command_buffer/service/gles2_cmd_decoder_unittest_async_pixel.cc',
+ '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_context_state.cc',
@@ -224,33 +227,30 @@
'command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc',
'command_buffer/service/gles2_cmd_decoder_unittest_programs.cc',
'command_buffer/service/gles2_cmd_decoder_unittest_textures.cc',
- 'command_buffer/service/gles2_cmd_decoder_unittest_attribs.cc',
'command_buffer/service/gles2_cmd_decoder_unittest_valuebuffer.cc',
- 'command_buffer/service/gl_surface_mock.cc',
- 'command_buffer/service/gl_surface_mock.h',
'command_buffer/service/gpu_scheduler_unittest.cc',
'command_buffer/service/gpu_service_test.cc',
'command_buffer/service/gpu_service_test.h',
+ 'command_buffer/service/gpu_tracer_unittest.cc',
'command_buffer/service/id_manager_unittest.cc',
'command_buffer/service/mailbox_manager_unittest.cc',
'command_buffer/service/memory_program_cache_unittest.cc',
'command_buffer/service/mocks.cc',
'command_buffer/service/mocks.h',
+ 'command_buffer/service/program_cache_unittest.cc',
'command_buffer/service/program_manager_unittest.cc',
'command_buffer/service/query_manager_unittest.cc',
'command_buffer/service/renderbuffer_manager_unittest.cc',
- 'command_buffer/service/program_cache_unittest.cc',
'command_buffer/service/shader_manager_unittest.cc',
- 'command_buffer/service/shader_translator_unittest.cc',
'command_buffer/service/shader_translator_cache_unittest.cc',
+ 'command_buffer/service/shader_translator_unittest.cc',
'command_buffer/service/test_helper.cc',
'command_buffer/service/test_helper.h',
'command_buffer/service/texture_manager_unittest.cc',
'command_buffer/service/transfer_buffer_manager_unittest.cc',
'command_buffer/service/valuebuffer_manager_unittest.cc',
- 'command_buffer/service/vertex_attrib_manager_unittest.cc',
'command_buffer/service/vertex_array_manager_unittest.cc',
- 'command_buffer/service/gpu_tracer_unittest.cc',
+ 'command_buffer/service/vertex_attrib_manager_unittest.cc',
'config/gpu_blacklist_unittest.cc',
'config/gpu_control_list_entry_unittest.cc',
'config/gpu_control_list_number_info_unittest.cc',
@@ -291,8 +291,10 @@
'../testing/perf/perf_test.gyp:perf_test',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gl/gl.gyp:gl',
+ 'command_buffer_service',
],
'sources': [
+ 'perftests/measurements.cc',
'perftests/run_all_tests.cc',
'perftests/texture_upload_perftest.cc',
],
@@ -386,10 +388,10 @@
'..',
],
'sources': [
- 'command_buffer/service/gles2_cmd_decoder_mock.cc',
- 'command_buffer/service/error_state_mock.cc',
'command_buffer/client/gles2_interface_stub.cc',
'command_buffer/client/gles2_interface_stub.h',
+ 'command_buffer/service/error_state_mock.cc',
+ 'command_buffer/service/gles2_cmd_decoder_mock.cc',
],
},
],
diff --git a/gpu/gpu_common.gypi b/gpu/gpu_common.gypi
index 5ff16da..b66d5ea 100644
--- a/gpu/gpu_common.gypi
+++ b/gpu/gpu_common.gypi
@@ -12,8 +12,8 @@
'command_buffer/client/gles2_c_lib.cc',
'command_buffer/client/gles2_c_lib_autogen.h',
'command_buffer/client/gles2_c_lib_export.h',
- 'command_buffer/client/gles2_lib.h',
'command_buffer/client/gles2_lib.cc',
+ 'command_buffer/client/gles2_lib.h',
],
# These are defined here because we need to build this library twice. Once
# with without support for client side arrays and once with for pepper and
@@ -21,19 +21,19 @@
'gles2_implementation_source_files': [
'command_buffer/client/buffer_tracker.cc',
'command_buffer/client/buffer_tracker.h',
- 'command_buffer/client/client_context_state.h',
'command_buffer/client/client_context_state.cc',
+ 'command_buffer/client/client_context_state.h',
'command_buffer/client/client_context_state_autogen.h',
'command_buffer/client/client_context_state_impl_autogen.h',
'command_buffer/client/gles2_impl_export.h',
- 'command_buffer/client/gles2_implementation_autogen.h',
'command_buffer/client/gles2_implementation.cc',
'command_buffer/client/gles2_implementation.h',
+ 'command_buffer/client/gles2_implementation_autogen.h',
'command_buffer/client/gles2_implementation_impl_autogen.h',
'command_buffer/client/gles2_interface.h',
- 'command_buffer/client/gles2_trace_implementation_autogen.h',
'command_buffer/client/gles2_trace_implementation.cc',
'command_buffer/client/gles2_trace_implementation.h',
+ 'command_buffer/client/gles2_trace_implementation_autogen.h',
'command_buffer/client/gles2_trace_implementation_impl_autogen.h',
'command_buffer/client/gpu_switches.cc',
'command_buffer/client/gpu_switches.h',
diff --git a/gpu/gpu_config.gypi b/gpu/gpu_config.gypi
index 98b19aa..f1915f3 100644
--- a/gpu/gpu_config.gypi
+++ b/gpu/gpu_config.gypi
@@ -16,17 +16,19 @@
'config/dx_diag_node.h',
'config/gpu_blacklist.cc',
'config/gpu_blacklist.h',
- 'config/gpu_control_list_jsons.h',
'config/gpu_control_list.cc',
'config/gpu_control_list.h',
- 'config/gpu_driver_bug_list_json.cc',
+ 'config/gpu_control_list_jsons.h',
'config/gpu_driver_bug_list.cc',
'config/gpu_driver_bug_list.h',
+ 'config/gpu_driver_bug_list_json.cc',
'config/gpu_driver_bug_workaround_type.h',
'config/gpu_dx_diagnostics_win.cc',
'config/gpu_feature_type.h',
'config/gpu_info.cc',
'config/gpu_info.h',
+ 'config/gpu_info_collector.cc',
+ 'config/gpu_info_collector.h',
'config/gpu_info_collector_android.cc',
'config/gpu_info_collector_linux.cc',
'config/gpu_info_collector_linux.h',
@@ -34,8 +36,6 @@
'config/gpu_info_collector_ozone.cc',
'config/gpu_info_collector_win.cc',
'config/gpu_info_collector_x11.cc',
- 'config/gpu_info_collector.cc',
- 'config/gpu_info_collector.h',
'config/gpu_performance_stats.h',
'config/gpu_test_config.cc',
'config/gpu_test_config.h',
diff --git a/gpu/gpu_unittests.isolate b/gpu/gpu_unittests.isolate
index 48fb1c5..e64633c 100644
--- a/gpu/gpu_unittests.isolate
+++ b/gpu/gpu_unittests.isolate
@@ -58,6 +58,13 @@
],
},
}],
+ ['OS=="mac" and asan==1 and fastbuild==0', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/gpu_unittests.dSYM/',
+ ],
+ },
+ }],
['OS=="win" and (fastbuild==0 or fastbuild==1)', {
'variables': {
'files': [
diff --git a/gpu/khronos_glcts_support/khronos_glcts.gypi b/gpu/khronos_glcts_support/khronos_glcts.gypi
index ebd8919..07d9cd1 100644
--- a/gpu/khronos_glcts_support/khronos_glcts.gypi
+++ b/gpu/khronos_glcts_support/khronos_glcts.gypi
@@ -53,23 +53,23 @@
],
'gtf_core_srcs': [
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFArguments.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTest.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestDriver.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/MIMG.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFFileReader.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFLog.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/XmlUtils.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFMemFile.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFModelData.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFPort.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFStringUtils.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTest.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestCompareGL.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestDriver.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestElement.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestUtil.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFgl.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/MIMG.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/XmlUtils.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/eglu.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/eglut.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/gl2Native.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFgl.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFPort.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFModelData.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFStringUtils.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestElement.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFFileReader.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestUtil.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestCompareGL.c',
],
'gtf_gl_core_srcs': [
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFAttDataGL.c',
@@ -80,19 +80,18 @@
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFShaderDataGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFShaderTextGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFStateDataGL.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFTestTextureFloatBase.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFTexDataGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFTexParamGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFUniDataGL.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL/GTFTestTextureFloatBase.c',
],
'gtf_gles2_srcs': [
# Base
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestGL2Test.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestAttributeGL.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestDetachGL.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestCreateObjectGL.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestUniformQueryGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestBindAllAttributes.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestCreateObjectGL.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestDetachGL.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestFixedDataType.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestFramebufferObjects.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestGetAttachedObjects.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestGetAttributeLocation.c',
@@ -108,10 +107,11 @@
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestMultipleShaders.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestRelinkProgram.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestUniform.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestUniformQueryGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestVertexAttribPointer.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestVertexAttributes.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestVertexProgramPointSize.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2Tests/GTFGL2TestFixedDataType.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestGL2Test.c',
# Build
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestBuildGL.c',
@@ -127,11 +127,10 @@
# Coverage
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFCoverageDict.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestCoverageGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFCoverageGL.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestCoverageGL.c',
# Fixed-function
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestFixedGL.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestBlend.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestBufferClear.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestBufferColor.c',
@@ -143,7 +142,6 @@
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestDepthBufferClear.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestDepthBufferFunctions.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestDither.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestUserClipPlanes.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestDivideByZero.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestGets.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestMipmapsInterpolation.c',
@@ -160,51 +158,53 @@
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestTransformViewport.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestTriangleRasterization.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestTriangleTiling.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestUserClipPlanes.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestVertexOrder.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedTestViewportClamp.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedUtilg.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2FixedTests/GTFFixedUtilr.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestFixedGL.c',
# Extensions
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestExtension.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestFramebufferObject.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil8.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestConditionalQuery.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestDataType1010102.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestDebug.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestDepth24.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestDepth32.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestDepthTexture.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestDepthTextureCubeMap.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestElementIndexUINT.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestFBORenderMipmap.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestFragmentPrecisionHigh.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestFramebufferObject.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestMapBuffer.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestOcclusionQuery.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestPackedDepthStencil.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestPointSizeArray.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestPointSprite.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestReadFormat.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil1.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil4.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil8.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestTexture3D.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestTextureCompressionASTCLDR.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestTextureFloat.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestTextureFloatLinear.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestTextureNPOT.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestUtilp.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestOcclusionQuery.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestConditionalQuery.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestPackedDepthStencil.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestVertexArrayObject.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestTextureCompressionASTCLDR.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestDepthTextureCubeMap.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil1.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestStencil4.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestVertexHalfFloat.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestReadFormat.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GTFTestExtension.c',
],
'gtf_gles2_es_only_srcs': [
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestCompressedPalettedTexture.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestCompressedETC1RGB8Texture.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRGB8RGBA8.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestEGLImage.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestSurfacelessContext.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestEGLImageExternal.c',
- '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRequiredInternalformat.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestCompressedPalettedTexture.c',
'<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestEGLCreateContext.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestEGLImage.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestEGLImageExternal.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRGB8RGBA8.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestRequiredInternalformat.c',
+ '<(DEPTH)/third_party/khronos_glcts/GTF_ES/glsl/GTF/Source/GL2ExtensionTests/GTFExtensionTestSurfacelessContext.c',
],
'glcts_common_sources': [
'<(DEPTH)/third_party/khronos_glcts/cts/common/glcConfigList.cpp',
@@ -425,10 +425,10 @@
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/deMemPool.h',
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolArray.c',
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolArray.h',
- '<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHashArray.c',
- '<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHashArray.h',
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHash.c',
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHash.h',
+ '<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHashArray.c',
+ '<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHashArray.h',
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHashSet.c',
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHashSet.h',
'<(DEPTH)/third_party/khronos_glcts/framework/delibs/depool/dePoolHeap.c',
diff --git a/gpu/perftests/measurements.cc b/gpu/perftests/measurements.cc
new file mode 100644
index 0000000..270e459
--- /dev/null
+++ b/gpu/perftests/measurements.cc
@@ -0,0 +1,99 @@
+// 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/perftests/measurements.h"
+
+#include "testing/perf/perf_test.h"
+
+namespace gpu {
+
+Measurement::Measurement() : name(), wall_time(), cpu_time(), gpu_time() {
+}
+Measurement::Measurement(const Measurement& m)
+ : name(m.name),
+ wall_time(m.wall_time),
+ cpu_time(m.cpu_time),
+ gpu_time(m.gpu_time) {
+}
+Measurement::Measurement(const std::string& name,
+ const base::TimeDelta wall_time,
+ const base::TimeDelta cpu_time,
+ const base::TimeDelta gpu_time)
+ : name(name), wall_time(wall_time), cpu_time(cpu_time), gpu_time(gpu_time) {
+}
+
+void Measurement::PrintResult() const {
+ perf_test::PrintResult(name, "_wall", "", wall_time.InMillisecondsF(), "ms",
+ true);
+ if (cpu_time.InMicroseconds() >= 0) {
+ perf_test::PrintResult(name, "_cpu", "", cpu_time.InMillisecondsF(), "ms",
+ true);
+ }
+ if (gpu_time.InMicroseconds() >= 0) {
+ perf_test::PrintResult(name, "_gpu", "", gpu_time.InMillisecondsF(), "ms",
+ true);
+ }
+}
+
+Measurement& Measurement::Increment(const Measurement& m) {
+ wall_time += m.wall_time;
+ cpu_time += m.cpu_time;
+ gpu_time += m.gpu_time;
+ return *this;
+}
+
+Measurement Measurement::Divide(int a) const {
+ return Measurement(name, wall_time / a, cpu_time / a, gpu_time / a);
+}
+
+Measurement::~Measurement() {
+}
+
+MeasurementTimers::MeasurementTimers(GPUTiming* gpu_timing)
+ : wall_time_start_(), cpu_time_start_(), gpu_timer_() {
+ DCHECK(gpu_timing);
+ wall_time_start_ = base::TimeTicks::NowFromSystemTraceTime();
+ if (base::TimeTicks::IsThreadNowSupported()) {
+ cpu_time_start_ = base::TimeTicks::ThreadNow();
+ } else {
+ static bool logged_once = false;
+ LOG_IF(WARNING, !logged_once) << "ThreadNow not supported.";
+ logged_once = true;
+ }
+
+ if (gpu_timing->IsAvailable()) {
+ gpu_timer_.reset(new GPUTimer(gpu_timing));
+ gpu_timer_->Start();
+ }
+}
+
+void MeasurementTimers::Record() {
+ wall_time_ = base::TimeTicks::NowFromSystemTraceTime() - wall_time_start_;
+ if (base::TimeTicks::IsThreadNowSupported()) {
+ cpu_time_ = base::TimeTicks::ThreadNow() - cpu_time_start_;
+ }
+ if (gpu_timer_.get()) {
+ gpu_timer_->End();
+ }
+}
+
+Measurement MeasurementTimers::GetAsMeasurement(const std::string& name) {
+ DCHECK_NE(base::TimeDelta(),
+ wall_time_); // At least wall_time_ has been set.
+
+ if (!base::TimeTicks::IsThreadNowSupported()) {
+ cpu_time_ = base::TimeDelta::FromMicroseconds(-1);
+ }
+ int64 gpu_time = -1;
+ if (gpu_timer_.get() != nullptr && gpu_timer_->IsAvailable()) {
+ gpu_time = gpu_timer_->GetDeltaElapsed();
+ }
+ return Measurement(name, wall_time_, cpu_time_,
+ base::TimeDelta::FromMicroseconds(gpu_time));
+}
+
+MeasurementTimers::~MeasurementTimers() {
+}
+
+} // namespace gpu
diff --git a/gpu/perftests/measurements.h b/gpu/perftests/measurements.h
new file mode 100644
index 0000000..15be422
--- /dev/null
+++ b/gpu/perftests/measurements.h
@@ -0,0 +1,56 @@
+// 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 GPU_PERFTESTS_MEASUREMENTS_H_
+#define GPU_PERFTESTS_MEASUREMENTS_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "gpu/command_buffer/service/gpu_timing.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace gpu {
+struct Measurement {
+ Measurement();
+ Measurement(const Measurement& m);
+ Measurement(const std::string& name,
+ const base::TimeDelta wall_time,
+ const base::TimeDelta cpu_time,
+ const base::TimeDelta gpu_time);
+ ~Measurement();
+
+ void PrintResult() const;
+ Measurement& Increment(const Measurement& m);
+ Measurement Divide(int a) const;
+
+ std::string name;
+ base::TimeDelta wall_time;
+ base::TimeDelta cpu_time;
+ base::TimeDelta gpu_time;
+};
+
+// Class to measure wall, cpu and gpu time deltas.
+// The deltas are measured from the time of the object
+// creation up to when Record is called.
+class MeasurementTimers {
+ public:
+ explicit MeasurementTimers(GPUTiming* gpu_timing);
+ void Record();
+ Measurement GetAsMeasurement(const std::string& name);
+ ~MeasurementTimers();
+
+ private:
+ base::TimeTicks wall_time_start_;
+ base::TimeTicks cpu_time_start_;
+ scoped_ptr<gpu::GPUTimer> gpu_timer_;
+
+ base::TimeDelta wall_time_;
+ base::TimeDelta cpu_time_;
+};
+
+} // namespace gpu
+
+#endif // GPU_PERFTESTS_MEASUREMENTS_H_
diff --git a/gpu/perftests/texture_upload_perftest.cc b/gpu/perftests/texture_upload_perftest.cc
index 7166c2a..f691c9e 100644
--- a/gpu/perftests/texture_upload_perftest.cc
+++ b/gpu/perftests/texture_upload_perftest.cc
@@ -8,10 +8,8 @@
#include "base/containers/small_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "base/timer/elapsed_timer.h"
+#include "gpu/perftests/measurements.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
@@ -103,9 +101,18 @@
surface_.get(),
gfx::PreferIntegratedGpu);
+ ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
+ if (gpu_timing_.Initialize(gl_context_.get())) {
+ LOG(INFO) << "Gpu timing initialized with timer type: "
+ << gpu_timing_.GetTimerTypeName();
+ gpu_timing_.CheckAndResetTimerErrors();
+ gpu_timing_.InvalidateTimerOffset();
+ } else {
+ LOG(WARNING) << "Can't initialize gpu timing";
+ }
+
// Prepare a simple program and a vertex buffer that will be
// used to draw a quad on the offscreen surface.
- ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
vertex_shader_ = LoadShader(GL_VERTEX_SHADER, kVertexShader);
fragment_shader_ = LoadShader(GL_FRAGMENT_SHADER, kFragmentShader);
program_object_ = glCreateProgram();
@@ -153,26 +160,18 @@
}
protected:
- struct Measurement {
- Measurement() : name(), wall_time(){};
- Measurement(const std::string& name, const base::TimeDelta wall_time)
- : name(name), wall_time(wall_time){};
- std::string name;
- base::TimeDelta wall_time;
- };
// 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 std::vector<uint8>& pixels,
const GLenum format,
const GLenum type) {
- std::vector<Measurement> measurements;
ui::ScopedMakeCurrent smc(gl_context_.get(), surface_.get());
- base::ElapsedTimer total_timer;
+ MeasurementTimers total_timers(&gpu_timing_);
GLuint texture_id = 0;
- base::ElapsedTimer tex_timer;
+ MeasurementTimers tex_timers(&gpu_timing_);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
@@ -184,9 +183,9 @@
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();
- measurements.push_back(Measurement("teximage2d", tex_timer.Elapsed()));
+ tex_timers.Record();
- base::ElapsedTimer draw_timer;
+ MeasurementTimers draw_timers(&gpu_timing_);
glUseProgram(program_object_);
glUniform1i(sampler_location_, 0);
@@ -195,13 +194,13 @@
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- measurements.push_back(Measurement("drawarrays", draw_timer.Elapsed()));
+ draw_timers.Record();
- base::ElapsedTimer finish_timer;
+ MeasurementTimers finish_timers(&gpu_timing_);
glFinish();
CheckNoGlError();
- measurements.push_back(Measurement("finish", finish_timer.Elapsed()));
- measurements.push_back(Measurement("total", total_timer.Elapsed()));
+ finish_timers.Record();
+ total_timers.Record();
glDeleteTextures(1, &texture_id);
@@ -214,12 +213,19 @@
// the appropriate format conversion.
EXPECT_EQ(static_cast<GLenum>(GL_RGBA), format);
EXPECT_EQ(pixels, pixels_rendered);
+
+ std::vector<Measurement> measurements;
+ 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"));
return measurements;
}
const gfx::Size size_; // for the offscreen surface and the texture
scoped_refptr<gfx::GLContext> gl_context_;
scoped_refptr<gfx::GLSurface> surface_;
+ GPUTiming gpu_timing_;
GLuint vertex_shader_ = 0;
GLuint fragment_shader_ = 0;
@@ -241,16 +247,14 @@
for (const Measurement& m : run) {
auto& agg = aggregates[m.name];
agg.name = m.name;
- agg.wall_time += m.wall_time;
+ agg.Increment(m);
}
}
}
for (const auto& entry : aggregates) {
- const auto& m = entry.second;
- perf_test::PrintResult(
- m.name, "", "", (m.wall_time / kUploadPerfTestRuns).InMillisecondsF(),
- "ms", true);
+ const auto m = entry.second.Divide(kUploadPerfTestRuns);
+ m.PrintResult();
}
}
diff --git a/gpu/tools/tools.gyp b/gpu/tools/tools.gyp
index f659d72..73ef754 100644
--- a/gpu/tools/tools.gyp
+++ b/gpu/tools/tools.gyp
@@ -25,11 +25,11 @@
],
'sources': [
'compositor_model_bench/compositor_model_bench.cc',
+ 'compositor_model_bench/forward_render_model.cc',
+ 'compositor_model_bench/render_model_utils.cc',
+ 'compositor_model_bench/render_models.cc',
'compositor_model_bench/render_tree.cc',
'compositor_model_bench/shaders.cc',
- 'compositor_model_bench/render_models.cc',
- 'compositor_model_bench/render_model_utils.cc',
- 'compositor_model_bench/forward_render_model.cc',
],
},
],
diff --git a/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java b/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java
index 49ffd48..4af9a28 100644
--- a/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java
+++ b/mojo/android/javatests/src/org/chromium/mojo/MojoTestCase.java
@@ -9,6 +9,7 @@
import org.chromium.base.JNINamespace;
import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
/**
* Base class to test mojo. Setup the environment.
@@ -24,7 +25,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- LibraryLoader.ensureInitialized();
+ LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
nativeInitApplicationContext(getInstrumentation().getTargetContext());
mTestEnvironmentPointer = nativeSetupTestEnvironment();
}
diff --git a/mojo/cc/context_provider_mojo.cc b/mojo/cc/context_provider_mojo.cc
index 9d57e52..3a32a5e 100644
--- a/mojo/cc/context_provider_mojo.cc
+++ b/mojo/cc/context_provider_mojo.cc
@@ -46,6 +46,13 @@
return capabilities_;
}
+void ContextProviderMojo::SetupLock() {
+}
+
+base::Lock* ContextProviderMojo::GetLock() {
+ return &context_lock_;
+}
+
bool ContextProviderMojo::IsContextLost() {
return context_lost_;
}
diff --git a/mojo/cc/context_provider_mojo.h b/mojo/cc/context_provider_mojo.h
index 014b973..9b55a85 100644
--- a/mojo/cc/context_provider_mojo.h
+++ b/mojo/cc/context_provider_mojo.h
@@ -6,6 +6,7 @@
#define MOJO_CC_CONTEXT_PROVIDER_MOJO_H_
#include "base/macros.h"
+#include "base/synchronization/lock.h"
#include "cc/output/context_provider.h"
#include "mojo/public/c/gles2/gles2.h"
#include "mojo/public/cpp/system/core.h"
@@ -31,6 +32,8 @@
void SetMemoryPolicyChangedCallback(
const MemoryPolicyChangedCallback& memory_policy_changed_callback)
override {}
+ void SetupLock() override;
+ base::Lock* GetLock() override;
protected:
friend class base::RefCountedThreadSafe<ContextProviderMojo>;
@@ -47,6 +50,8 @@
MojoGLES2Context context_;
bool context_lost_;
+ base::Lock context_lock_;
+
DISALLOW_COPY_AND_ASSIGN(ContextProviderMojo);
};
diff --git a/mojo/common/trace_controller_impl.cc b/mojo/common/trace_controller_impl.cc
index 4409b30..a5b0ea1 100644
--- a/mojo/common/trace_controller_impl.cc
+++ b/mojo/common/trace_controller_impl.cc
@@ -24,16 +24,16 @@
DCHECK(!collector_.get());
collector_ = collector.Pass();
std::string categories_str = categories.To<std::string>();
- base::debug::TraceLog::GetInstance()->SetEnabled(
- base::debug::CategoryFilter(categories_str),
- base::debug::TraceLog::RECORDING_MODE,
- base::debug::TraceOptions(base::debug::RECORD_UNTIL_FULL));
+ base::trace_event::TraceLog::GetInstance()->SetEnabled(
+ base::trace_event::CategoryFilter(categories_str),
+ base::trace_event::TraceLog::RECORDING_MODE,
+ base::trace_event::TraceOptions(base::trace_event::RECORD_UNTIL_FULL));
}
void TraceControllerImpl::StopTracing() {
- base::debug::TraceLog::GetInstance()->SetDisabled();
+ base::trace_event::TraceLog::GetInstance()->SetDisabled();
- base::debug::TraceLog::GetInstance()->Flush(
+ base::trace_event::TraceLog::GetInstance()->Flush(
base::Bind(&TraceControllerImpl::SendChunk, base::Unretained(this)));
}
diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc
index 494ff3d..8a93546 100644
--- a/mojo/gles2/command_buffer_client_impl.cc
+++ b/mojo/gles2/command_buffer_client_impl.cc
@@ -330,4 +330,7 @@
last_state_ = state.To<State>();
}
+void CommandBufferClientImpl::SetLock(base::Lock* lock) {
+}
+
} // namespace gles2
diff --git a/mojo/gles2/command_buffer_client_impl.h b/mojo/gles2/command_buffer_client_impl.h
index 6bcacb2..1b5c871 100644
--- a/mojo/gles2/command_buffer_client_impl.h
+++ b/mojo/gles2/command_buffer_client_impl.h
@@ -71,6 +71,7 @@
void SignalQuery(uint32 query, const base::Closure& callback) override;
void SetSurfaceVisible(bool visible) override;
uint32 CreateStreamTexture(uint32 texture_id) override;
+ void SetLock(base::Lock*) override;
private:
class SyncClientImpl;
diff --git a/mojo/tools/roll/cc_strip_video.patch b/mojo/tools/roll/cc_strip_video.patch
index 4540a2a..2d3fb51 100644
--- a/mojo/tools/roll/cc_strip_video.patch
+++ b/mojo/tools/roll/cc_strip_video.patch
@@ -128,10 +128,11 @@
-
-#endif // CC_LAYERS_VIDEO_FRAME_PROVIDER_H_
diff --git a/cc/layers/video_frame_provider_client_impl.cc b/cc/layers/video_frame_provider_client_impl.cc
-index 2b12567..e69de29 100644
+deleted file mode 100644
+index 4bbd92f..0000000
--- a/cc/layers/video_frame_provider_client_impl.cc
-+++ b/cc/layers/video_frame_provider_client_impl.cc
-@@ -1,95 +0,0 @@
++++ /dev/null
+@@ -1,116 +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.
@@ -173,15 +174,32 @@
- 0.0, 0.0, 0.0, 1.0);
-}
-
+-void VideoFrameProviderClientImpl::SetActiveVideoLayer(
+- VideoLayerImpl* video_layer) {
+- DCHECK(thread_checker_.CalledOnValidThread());
+- DCHECK(video_layer);
+- active_video_layer_ = video_layer;
+-}
+-
-void VideoFrameProviderClientImpl::Stop() {
+- // It's called when the main thread is blocked, so lock isn't needed.
- if (!provider_)
- return;
+- DCHECK(thread_checker_.CalledOnValidThread());
- provider_->SetVideoFrameProviderClient(nullptr);
- provider_ = nullptr;
-}
-
+-bool VideoFrameProviderClientImpl::Stopped() {
+- DCHECK(thread_checker_.CalledOnValidThread());
+- // |provider_| is changed while the main thread is blocked, and not changed
+- // thereafter, so lock isn't needed.
+- return !provider_;
+-}
+-
-scoped_refptr<media::VideoFrame>
-VideoFrameProviderClientImpl::AcquireLockAndCurrentFrame() {
+- DCHECK(thread_checker_.CalledOnValidThread());
- provider_lock_.Acquire(); // Balanced by call to ReleaseLock().
- if (!provider_)
- return nullptr;
@@ -191,11 +209,13 @@
-
-void VideoFrameProviderClientImpl::PutCurrentFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
+- DCHECK(thread_checker_.CalledOnValidThread());
- provider_lock_.AssertAcquired();
- provider_->PutCurrentFrame(frame);
-}
-
-void VideoFrameProviderClientImpl::ReleaseLock() {
+- DCHECK(thread_checker_.CalledOnValidThread());
- provider_lock_.AssertAcquired();
- provider_lock_.Release();
-}
@@ -212,11 +232,13 @@
- "VideoFrameProviderClientImpl::DidReceiveFrame",
- "active_video_layer",
- !!active_video_layer_);
+- DCHECK(thread_checker_.CalledOnValidThread());
- if (active_video_layer_)
- active_video_layer_->SetNeedsRedraw();
-}
-
-void VideoFrameProviderClientImpl::DidUpdateMatrix(const float* matrix) {
+- DCHECK(thread_checker_.CalledOnValidThread());
- stream_texture_matrix_ = gfx::Transform(
- matrix[0], matrix[4], matrix[8], matrix[12],
- matrix[1], matrix[5], matrix[9], matrix[13],
@@ -228,7 +250,7 @@
-
-} // namespace cc
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
-index 45d98b6..5a15efa 100644
+index a394a1a..2612f10 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -13,7 +13,6 @@
@@ -240,7 +262,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 d503cc4..c7582fe 100644
+index 36765ce..d7d1211 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -12,7 +12,6 @@
@@ -706,7 +728,7 @@
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 61f11a2..7ad0ba4 100644
+index 99ed7e2..d57d56f 100644
--- a/cc/quads/yuv_video_draw_quad.h
+++ b/cc/quads/yuv_video_draw_quad.h
@@ -8,7 +8,6 @@
@@ -718,7 +740,7 @@
namespace cc {
diff --git a/cc/resources/drawing_display_item.cc b/cc/resources/drawing_display_item.cc
-index 29cc2d3..351fade 100644
+index 0fe86f4..1ef149f 100644
--- a/cc/resources/drawing_display_item.cc
+++ b/cc/resources/drawing_display_item.cc
@@ -6,6 +6,7 @@
@@ -730,7 +752,7 @@
#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 cb33686..b016fff 100644
+index aa46125..07fb048 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -27,7 +27,6 @@
@@ -773,7 +795,7 @@
}
LayerTreeSettings DefaultSettings() {
-@@ -5312,18 +5307,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
+@@ -5489,18 +5484,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
root_layer->SetBounds(gfx::Size(10, 10));
root_layer->SetHasRenderSurface(true);
@@ -792,7 +814,7 @@
scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
io_surface_layer->SetBounds(gfx::Size(10, 10));
-@@ -6403,16 +6386,6 @@ TEST_F(LayerTreeHostImplTest,
+@@ -6580,16 +6563,6 @@ TEST_F(LayerTreeHostImplTest,
scoped_ptr<SolidColorLayerImpl> root_layer =
SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
@@ -810,7 +832,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 a3c37ed..d4bfb6e 100644
+index bb315e7..bb6dc17 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -18,7 +18,6 @@
@@ -829,7 +851,7 @@
#include "cc/test/geometry_test_utils.h"
#include "cc/test/impl_side_painting_settings.h"
#include "cc/test/layer_tree_test.h"
-@@ -4200,28 +4198,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest {
+@@ -4202,28 +4200,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest {
int num_draws_;
};
@@ -859,7 +881,7 @@
// to the compositor thread, even though no resources are updated in
// response to that invalidation.
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc
-index 56e52ad..fb0c9c8 100644
+index 596adc0..fb0c9c8 100644
--- a/cc/trees/layer_tree_host_unittest_context.cc
+++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -15,8 +15,6 @@
@@ -897,7 +919,7 @@
}
void LoseContext() {
-@@ -1057,43 +1050,6 @@ class LayerTreeHostContextTestDontUseLostResources
+@@ -1057,41 +1050,6 @@ class LayerTreeHostContextTestDontUseLostResources
layer_with_mask->SetMaskLayer(mask.get());
root->AddChild(layer_with_mask);
@@ -925,14 +947,12 @@
- make_scoped_ptr(
- new gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point)),
- media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
-- gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(),
-- VideoFrame::ReadPixelsCB(), false);
+- gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(), false);
- scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
- make_scoped_ptr(
- new gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point)),
- media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
-- gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta(),
-- VideoFrame::ReadPixelsCB(), false);
+- gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta(), false);
-
- color_frame_provider_.set_frame(color_video_frame_);
- hw_frame_provider_.set_frame(hw_video_frame_);
@@ -941,7 +961,7 @@
if (!delegating_renderer()) {
// TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
-@@ -1123,14 +1079,6 @@ class LayerTreeHostContextTestDontUseLostResources
+@@ -1121,14 +1079,6 @@ class LayerTreeHostContextTestDontUseLostResources
void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
@@ -956,7 +976,7 @@
}
DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
-@@ -1179,14 +1127,6 @@ class LayerTreeHostContextTestDontUseLostResources
+@@ -1177,14 +1127,6 @@ class LayerTreeHostContextTestDontUseLostResources
scoped_refptr<DelegatedFrameResourceCollection>
delegated_resource_collection_;
scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
diff --git a/mojo/tools/roll/skia_build.patch b/mojo/tools/roll/skia_build.patch
index 1fdf63f..a252691 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 9aeaa0d..83c4d8b 100644
+index c793e0b..85ccce7 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
-@@ -11,18 +11,6 @@ if (cpu_arch == "arm") {
+@@ -12,18 +12,6 @@ if (cpu_arch == "arm") {
skia_support_gpu = !is_ios
skia_support_pdf = !is_ios && (enable_basic_printing || enable_print_preview)
@@ -21,13 +21,13 @@
# The list of Skia defines that are to be set for chromium.
gypi_skia_defines =
exec_script("//build/gypi_to_gn.py",
-@@ -126,8 +114,7 @@ config("skia_config") {
- "//third_party/skia/src/lazy",
+@@ -133,8 +121,7 @@ config("skia_config") {
+ "//third_party/skia/src/core",
]
- defines = gypi_blink_skia_defines.blink_skia_defines
- defines += gypi_skia_defines.skia_for_chromium_defines
+ defines = gypi_skia_defines.skia_for_chromium_defines
- defines += [
- "SK_ENABLE_INST_COUNT=0",
+ defines += []
+
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 6be160e..cf1d98e 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -113,8 +113,8 @@
sources -= [
"http/http_auth_gssapi_posix.cc",
"http/http_auth_gssapi_posix.h",
- "http/http_auth_handler_negotiate.h",
"http/http_auth_handler_negotiate.cc",
+ "http/http_auth_handler_negotiate.h",
]
}
@@ -130,12 +130,12 @@
sources -= [
"base/directory_lister.cc",
"base/directory_lister.h",
+ "url_request/file_protocol_handler.cc",
+ "url_request/file_protocol_handler.h",
"url_request/url_request_file_dir_job.cc",
"url_request/url_request_file_dir_job.h",
"url_request/url_request_file_job.cc",
"url_request/url_request_file_job.h",
- "url_request/file_protocol_handler.cc",
- "url_request/file_protocol_handler.h",
]
}
@@ -398,10 +398,10 @@
"websockets/websocket_frame.h",
"websockets/websocket_frame_parser.cc",
"websockets/websocket_frame_parser.h",
- "websockets/websocket_handshake_constants.cc",
- "websockets/websocket_handshake_constants.h",
"websockets/websocket_handshake_challenge.cc",
"websockets/websocket_handshake_challenge.h",
+ "websockets/websocket_handshake_constants.cc",
+ "websockets/websocket_handshake_constants.h",
"websockets/websocket_handshake_request_info.cc",
"websockets/websocket_handshake_request_info.h",
"websockets/websocket_handshake_response_info.cc",
@@ -477,10 +477,10 @@
"cert/test_root_certs_nss.cc",
"cert/x509_util_nss.cc",
"cert/x509_util_nss.h",
- "proxy/proxy_resolver_mac.cc",
- "proxy/proxy_server_mac.cc",
"ocsp/nss_ocsp.cc",
"ocsp/nss_ocsp.h",
+ "proxy/proxy_resolver_mac.cc",
+ "proxy/proxy_server_mac.cc",
]
set_sources_assignment_filter(sources_assignment_filter)
@@ -503,11 +503,11 @@
# are needed.
set_sources_assignment_filter([])
sources += [
- "base/platform_mime_util_linux.cc",
"base/address_tracker_linux.cc",
"base/address_tracker_linux.h",
"base/net_util_linux.cc",
"base/net_util_linux.h",
+ "base/platform_mime_util_linux.cc",
]
set_sources_assignment_filter(sources_assignment_filter)
@@ -593,8 +593,8 @@
"tools/dump_cache/simple_cache_dumper.h",
"tools/dump_cache/url_to_filename_encoder.cc",
"tools/dump_cache/url_to_filename_encoder.h",
- "tools/dump_cache/url_utilities.h",
"tools/dump_cache/url_utilities.cc",
+ "tools/dump_cache/url_utilities.h",
]
configs += [ ":net_win_size_truncation" ]
@@ -670,10 +670,10 @@
"test/python_utils.h",
"test/spawned_test_server/base_test_server.cc",
"test/spawned_test_server/base_test_server.h",
- "test/spawned_test_server/local_test_server_posix.cc",
- "test/spawned_test_server/local_test_server_win.cc",
"test/spawned_test_server/local_test_server.cc",
"test/spawned_test_server/local_test_server.h",
+ "test/spawned_test_server/local_test_server_posix.cc",
+ "test/spawned_test_server/local_test_server_win.cc",
"test/spawned_test_server/remote_test_server.cc",
"test/spawned_test_server/remote_test_server.h",
"test/spawned_test_server/spawned_test_server.h",
@@ -794,6 +794,35 @@
}
}
+if (use_v8_in_net && !is_android) {
+ source_set("net_browser_services") {
+ sources = [
+ "dns/mojo_host_resolver_impl.cc",
+ "dns/mojo_host_resolver_impl.h",
+ ]
+
+ public_deps = [
+ ":mojo_type_converters",
+ ":net",
+ "//net/interfaces",
+ "//mojo/public/cpp/bindings",
+ ]
+ }
+
+ source_set("mojo_type_converters") {
+ sources = [
+ "dns/mojo_type_converters.cc",
+ "dns/mojo_type_converters.h",
+ ]
+
+ public_deps = [
+ ":net",
+ "//net/interfaces",
+ "//mojo/public/cpp/bindings",
+ ]
+ }
+}
+
if (!is_ios && !is_android) {
executable("crash_cache") {
testonly = true
@@ -938,20 +967,20 @@
sources = [
"tools/dump_cache/url_to_filename_encoder.cc",
"tools/dump_cache/url_to_filename_encoder.h",
- "tools/dump_cache/url_utilities.h",
"tools/dump_cache/url_utilities.cc",
- "tools/flip_server/acceptor_thread.h",
+ "tools/dump_cache/url_utilities.h",
"tools/flip_server/acceptor_thread.cc",
+ "tools/flip_server/acceptor_thread.h",
+ "tools/flip_server/constants.h",
"tools/flip_server/create_listener.cc",
"tools/flip_server/create_listener.h",
- "tools/flip_server/constants.h",
"tools/flip_server/flip_config.cc",
"tools/flip_server/flip_config.h",
"tools/flip_server/http_interface.cc",
"tools/flip_server/http_interface.h",
"tools/flip_server/loadtime_measurement.h",
- "tools/flip_server/mem_cache.h",
"tools/flip_server/mem_cache.cc",
+ "tools/flip_server/mem_cache.h",
"tools/flip_server/output_ordering.cc",
"tools/flip_server/output_ordering.h",
"tools/flip_server/ring_buffer.cc",
@@ -959,10 +988,10 @@
"tools/flip_server/sm_connection.cc",
"tools/flip_server/sm_connection.h",
"tools/flip_server/sm_interface.h",
- "tools/flip_server/spdy_ssl.cc",
- "tools/flip_server/spdy_ssl.h",
"tools/flip_server/spdy_interface.cc",
"tools/flip_server/spdy_interface.h",
+ "tools/flip_server/spdy_ssl.cc",
+ "tools/flip_server/spdy_ssl.h",
"tools/flip_server/spdy_util.cc",
"tools/flip_server/spdy_util.h",
"tools/flip_server/streamer_interface.cc",
@@ -1017,8 +1046,8 @@
"tools/quic/quic_client_session.h",
"tools/quic/quic_default_packet_writer.cc",
"tools/quic/quic_default_packet_writer.h",
- "tools/quic/quic_dispatcher.h",
"tools/quic/quic_dispatcher.cc",
+ "tools/quic/quic_dispatcher.h",
"tools/quic/quic_epoll_clock.cc",
"tools/quic/quic_epoll_clock.h",
"tools/quic/quic_epoll_connection_helper.cc",
@@ -1039,8 +1068,8 @@
"tools/quic/quic_spdy_client_stream.h",
"tools/quic/quic_spdy_server_stream.cc",
"tools/quic/quic_spdy_server_stream.h",
- "tools/quic/quic_time_wait_list_manager.h",
"tools/quic/quic_time_wait_list_manager.cc",
+ "tools/quic/quic_time_wait_list_manager.h",
]
deps = [
":balsa",
@@ -1268,8 +1297,8 @@
"websockets/websocket_deflate_predictor_impl_test.cc",
"websockets/websocket_deflate_stream_test.cc",
"websockets/websocket_deflater_test.cc",
- "websockets/websocket_errors_test.cc",
"websockets/websocket_end_to_end_test.cc",
+ "websockets/websocket_errors_test.cc",
"websockets/websocket_extension_parser_test.cc",
"websockets/websocket_frame_parser_test.cc",
"websockets/websocket_frame_test.cc",
@@ -1321,11 +1350,21 @@
deps += [ ":net_with_v8" ]
} else {
sources -= [
- "proxy/proxy_resolver_v8_unittest.cc",
"proxy/proxy_resolver_v8_tracing_unittest.cc",
+ "proxy/proxy_resolver_v8_unittest.cc",
]
}
+ if (use_v8_in_net && !is_android) {
+ deps += [
+ ":net_browser_services",
+ "//mojo/environment:chromium",
+ "//mojo/edk/system",
+ ]
+ } else {
+ sources -= [ "dns/mojo_host_resolver_impl_unittest.cc" ]
+ }
+
if (!enable_mdns) {
sources -= [
"dns/mdns_cache_unittest.cc",
diff --git a/net/DEPS b/net/DEPS
index dc5c1b9..f916d6e 100644
--- a/net/DEPS
+++ b/net/DEPS
@@ -4,6 +4,7 @@
"+jni",
"+third_party/apple_apsl",
"+third_party/libevent",
+ "+third_party/mojo/src/mojo/public",
"+third_party/nss",
"+third_party/zlib",
"+sdch/open-vcdiff",
@@ -50,6 +51,10 @@
"ftp_directory_listing_parser\.cc": [
"+base/i18n",
],
+
+ "run_all_unittests\.cc": [
+ "+third_party/mojo/src/mojo/edk",
+ ],
}
skip_child_includes = [
diff --git a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
index b59246e..064bfc8 100644
--- a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
+++ b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierTest.java
@@ -15,6 +15,7 @@
import org.chromium.base.ApplicationState;
import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.test.util.Feature;
import org.chromium.net.NetworkChangeNotifierAutoDetect.NetworkState;
@@ -100,7 +101,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- LibraryLoader.ensureInitialized();
+ LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
createTestNotifier(WatchForChanges.ONLY_WHEN_APP_IN_FOREGROUND);
}
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc
index 99a6cc2..f623b14 100644
--- a/net/android/network_change_notifier_delegate_android.cc
+++ b/net/android/network_change_notifier_delegate_android.cc
@@ -97,7 +97,7 @@
const ConnectionType actual_connection_type = ConvertConnectionType(
new_connection_type);
SetCurrentConnectionType(actual_connection_type);
- observers_->Notify(&Observer::OnConnectionTypeChanged);
+ observers_->Notify(FROM_HERE, &Observer::OnConnectionTypeChanged);
}
jint NetworkChangeNotifierDelegateAndroid::GetConnectionType(JNIEnv*,
@@ -113,7 +113,8 @@
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(new_max_bandwidth != GetCurrentMaxBandwidth());
SetCurrentMaxBandwidth(new_max_bandwidth);
- observers_->Notify(&Observer::OnMaxBandwidthChanged, new_max_bandwidth);
+ observers_->Notify(FROM_HERE, &Observer::OnMaxBandwidthChanged,
+ new_max_bandwidth);
}
void NetworkChangeNotifierDelegateAndroid::AddObserver(
diff --git a/net/base/file_stream_context.cc b/net/base/file_stream_context.cc
index fc2af1b..69741e5 100644
--- a/net/base/file_stream_context.cc
+++ b/net/base/file_stream_context.cc
@@ -77,12 +77,6 @@
orphaned_ = true;
-#if defined(OS_WIN)
- // Clean up weak pointers here to ensure that they are destroyed on the
- // same thread where they were created.
- weak_ptr_factory_.InvalidateWeakPtrs();
-#endif
-
if (!async_in_progress_) {
CloseAndDelete();
} else if (file_.IsValid()) {
@@ -221,7 +215,10 @@
}
void FileStream::Context::CloseAndDelete() {
- DCHECK(!async_in_progress_);
+ // TODO(ananta)
+ // Replace this CHECK with a DCHECK once we figure out the root cause of
+ // http://crbug.com/455066
+ CHECK(!async_in_progress_);
if (file_.IsValid()) {
bool posted = task_runner_.get()->PostTask(
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h
index 4f01d9d..cb1b7aa 100644
--- a/net/base/file_stream_context.h
+++ b/net/base/file_stream_context.h
@@ -161,12 +161,19 @@
DWORD bytes_read,
DWORD error) override;
+ // Invokes the user callback.
+ void InvokeUserCallback();
+
+ // Deletes an orphaned context.
+ void DeleteOrphanedContext();
+
// The ReadFile call on Windows can execute synchonously at times.
// http://support.microsoft.com/kb/156932. This ends up blocking the calling
// thread which is undesirable. To avoid this we execute the ReadFile call
// on a worker thread.
- // The |context| parameter is a weak pointer instance passed to the worker
- // pool.
+ // The |context| parameter is a pointer to the current Context instance. It
+ // is safe to pass this as is to the pool as the Context instance should
+ // remain valid until the pending Read operation completes.
// The |file| parameter is the handle to the file being read.
// The |buf| parameter is the buffer where we want the ReadFile to read the
// data into.
@@ -176,7 +183,7 @@
// The |origin_thread_loop| is a MessageLoopProxy instance used to post tasks
// back to the originating thread.
static void ReadAsync(
- const base::WeakPtr<FileStream::Context>& context,
+ FileStream::Context* context,
HANDLE file,
scoped_refptr<net::IOBuffer> buf,
int buf_len,
@@ -185,9 +192,13 @@
// This callback executes on the main calling thread. It informs the caller
// about the result of the ReadFile call.
+ // The |read_file_ret| parameter contains the return value of the ReadFile
+ // call.
+ // The |bytes_read| contains the number of bytes read from the file, if
+ // ReadFile succeeds.
// The |os_error| parameter contains the value of the last error returned by
// the ReadFile API.
- void ReadAsyncResult(DWORD os_error);
+ void ReadAsyncResult(BOOL read_file_ret, DWORD bytes_read, DWORD os_error);
#elif defined(OS_POSIX)
// ReadFileImpl() is a simple wrapper around read() that handles EINTR
@@ -209,8 +220,18 @@
base::MessageLoopForIO::IOContext io_context_;
CompletionCallback callback_;
scoped_refptr<IOBuffer> in_flight_buf_;
- // WeakPtrFactory for posting tasks back to |this|.
- base::WeakPtrFactory<Context> weak_ptr_factory_;
+ // This flag is set to true when we receive a Read request which is queued to
+ // the thread pool.
+ bool async_read_initiated_;
+ // This flag is set to true when we receive a notification ReadAsyncResult()
+ // on the calling thread which indicates that the asynchronous Read
+ // operation is complete.
+ bool async_read_completed_;
+ // This flag is set to true when we receive an IO completion notification for
+ // an asynchonously initiated Read operaton. OnIOComplete().
+ bool io_complete_for_read_received_;
+ // Tracks the result of the IO completion operation. Set in OnIOComplete.
+ int result_;
#endif
DISALLOW_COPY_AND_ASSIGN(Context);
diff --git a/net/base/file_stream_context_win.cc b/net/base/file_stream_context_win.cc
index d225ee3..a41a74c 100644
--- a/net/base/file_stream_context_win.cc
+++ b/net/base/file_stream_context_win.cc
@@ -11,7 +11,6 @@
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
-#include "base/profiler/scoped_tracker.h"
#include "base/task_runner.h"
#include "base/threading/worker_pool.h"
#include "net/base/io_buffer.h"
@@ -41,7 +40,10 @@
async_in_progress_(false),
orphaned_(false),
task_runner_(task_runner),
- weak_ptr_factory_(this) {
+ async_read_initiated_(false),
+ async_read_completed_(false),
+ io_complete_for_read_received_(false),
+ result_(0) {
io_context_.handler = this;
memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
}
@@ -53,7 +55,10 @@
async_in_progress_(false),
orphaned_(false),
task_runner_(task_runner),
- weak_ptr_factory_(this) {
+ async_read_initiated_(false),
+ async_read_completed_(false),
+ io_complete_for_read_received_(false),
+ result_(0) {
io_context_.handler = this;
memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
if (file_.IsValid()) {
@@ -68,28 +73,32 @@
int FileStream::Context::Read(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
- // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 FileStream::Context::Read"));
-
- DCHECK(!async_in_progress_);
+ CHECK(!async_in_progress_);
+ DCHECK(!async_read_initiated_);
+ DCHECK(!async_read_completed_);
+ DCHECK(!io_complete_for_read_received_);
IOCompletionIsPending(callback, buf);
- base::WorkerPool::PostTask(
- FROM_HERE,
- base::Bind(&FileStream::Context::ReadAsync,
- weak_ptr_factory_.GetWeakPtr(), file_.GetPlatformFile(),
- make_scoped_refptr(buf), buf_len, &io_context_.overlapped,
- base::MessageLoop::current()->message_loop_proxy()),
- false);
+ async_read_initiated_ = true;
+ result_ = 0;
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&FileStream::Context::ReadAsync, base::Unretained(this),
+ file_.GetPlatformFile(), make_scoped_refptr(buf), buf_len,
+ &io_context_.overlapped,
+ base::MessageLoop::current()->message_loop_proxy()));
return ERR_IO_PENDING;
}
int FileStream::Context::Write(IOBuffer* buf,
int buf_len,
const CompletionCallback& callback) {
+ CHECK(!async_in_progress_);
+
+ result_ = 0;
+
DWORD bytes_written = 0;
if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len,
&bytes_written, &io_context_.overlapped)) {
@@ -140,58 +149,100 @@
DCHECK(!callback_.is_null());
DCHECK(async_in_progress_);
- async_in_progress_ = false;
+ if (!async_read_initiated_)
+ async_in_progress_ = false;
+
if (orphaned_) {
- callback_.Reset();
- in_flight_buf_ = NULL;
- CloseAndDelete();
+ io_complete_for_read_received_ = true;
+ // If we are called due to a pending read and the asynchronous read task
+ // has not completed we have to keep the context around until it completes.
+ if (async_read_initiated_ && !async_read_completed_)
+ return;
+ DeleteOrphanedContext();
return;
}
- int result;
if (error == ERROR_HANDLE_EOF) {
- result = 0;
+ result_ = 0;
} else if (error) {
IOResult error_result = IOResult::FromOSError(error);
- result = static_cast<int>(error_result.result);
+ result_ = static_cast<int>(error_result.result);
} else {
- result = bytes_read;
+ if (result_)
+ DCHECK_EQ(result_, static_cast<int>(bytes_read));
+ result_ = bytes_read;
IncrementOffset(&io_context_.overlapped, bytes_read);
}
+ if (async_read_initiated_)
+ io_complete_for_read_received_ = true;
+
+ InvokeUserCallback();
+}
+
+void FileStream::Context::InvokeUserCallback() {
+ // For an asynchonous Read operation don't invoke the user callback until
+ // we receive the IO completion notification and the asynchronous Read
+ // completion notification.
+ if (async_read_initiated_) {
+ if (!io_complete_for_read_received_ || !async_read_completed_)
+ return;
+ async_read_initiated_ = false;
+ io_complete_for_read_received_ = false;
+ async_read_completed_ = false;
+ async_in_progress_ = false;
+ }
CompletionCallback temp_callback = callback_;
callback_.Reset();
scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
in_flight_buf_ = NULL;
- temp_callback.Run(result);
+ temp_callback.Run(result_);
+}
+
+void FileStream::Context::DeleteOrphanedContext() {
+ async_in_progress_ = false;
+ callback_.Reset();
+ in_flight_buf_ = NULL;
+ CloseAndDelete();
}
// static
void FileStream::Context::ReadAsync(
- const base::WeakPtr<FileStream::Context>& context,
+ FileStream::Context* context,
HANDLE file,
scoped_refptr<net::IOBuffer> buf,
int buf_len,
OVERLAPPED* overlapped,
scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
DWORD bytes_read = 0;
- if (!ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped)) {
- origin_thread_loop->PostTask(
- FROM_HERE, base::Bind(&FileStream::Context::ReadAsyncResult, context,
- ::GetLastError()));
- }
+ BOOL ret = ::ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped);
+ origin_thread_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&FileStream::Context::ReadAsyncResult,
+ base::Unretained(context), ret, bytes_read, ::GetLastError()));
}
-void FileStream::Context::ReadAsyncResult(DWORD os_error) {
+void FileStream::Context::ReadAsyncResult(BOOL read_file_ret,
+ DWORD bytes_read,
+ DWORD os_error) {
+ // If the context is orphaned and we already received the io completion
+ // notification then we should delete the context and get out.
+ if (orphaned_ && io_complete_for_read_received_) {
+ DeleteOrphanedContext();
+ return;
+ }
+
+ async_read_completed_ = true;
+ if (read_file_ret) {
+ result_ = bytes_read;
+ InvokeUserCallback();
+ return;
+ }
+
IOResult error = IOResult::FromOSError(os_error);
- if (error.os_error == ERROR_HANDLE_EOF) {
- // Report EOF by returning 0 bytes read.
- OnIOCompleted(&io_context_, 0, error.os_error);
- } else if (error.os_error != ERROR_IO_PENDING) {
- // We don't need to inform the caller about ERROR_PENDING_IO as that was
- // already done when the ReadFile call was queued to the worker pool.
- if (error.os_error)
- LOG(WARNING) << "ReadFile failed: " << error.os_error;
+ if (error.os_error == ERROR_IO_PENDING) {
+ InvokeUserCallback();
+ } else {
OnIOCompleted(&io_context_, 0, error.os_error);
}
}
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index e9b4e1a..7b51b41 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -142,15 +142,16 @@
// Returns true if |codec| refers to a proprietary codec.
bool IsCodecProprietary(Codec codec) const;
- // Returns true and sets |*default_codec| if |mime_type| has a
- // default codec associated with it.
- // Returns false otherwise and the value of |*default_codec| is undefined.
- bool GetDefaultCodec(const std::string& mime_type,
- Codec* default_codec) const;
+ // Returns true and sets |*default_codec| if |mime_type| has a default codec
+ // associated with it. Returns false otherwise and the value of
+ // |*default_codec| is undefined.
+ bool GetDefaultCodecLowerCase(const std::string& mime_type_lower_case,
+ Codec* default_codec) const;
- // Returns true if |mime_type| has a default codec associated with it
- // and IsCodecSupported() returns true for that particular codec.
- bool IsDefaultCodecSupported(const std::string& mime_type) const;
+ // Returns true if |mime_type_lower_case| has a default codec associated with
+ // it and IsCodecSupported() returns true for that particular codec.
+ bool IsDefaultCodecSupportedLowerCase(
+ const std::string& mime_type_lower_case) const;
MimeMappings image_map_;
MimeMappings media_map_;
@@ -476,9 +477,8 @@
return base::android::BuildInfo::GetInstance()->sdk_int() >= 19;
case MimeUtil::OPUS:
- // TODO(vigneshv): Change this similar to the VP9 check once Opus is
- // supported on Android (http://crbug.com/318436).
- return false;
+ // Opus is supported only in Lollipop+ (API Level 21).
+ return base::android::BuildInfo::GetInstance()->sdk_int() >= 21;
case MimeUtil::THEORA:
return false;
@@ -528,23 +528,29 @@
"mp4a.40.05,mp4a.40.29";
static const MediaFormatStrict format_codec_mappings[] = {
- { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" },
- { "audio/webm", "opus,vorbis" },
- { "audio/wav", "1" },
- { "audio/x-wav", "1" },
- { "video/ogg", "opus,theora,vorbis" },
- { "audio/ogg", "opus,vorbis" },
- { "application/ogg", "opus,theora,vorbis" },
- { "audio/mpeg", "mp3" },
- { "audio/mp3", "" },
- { "audio/x-mp3", "" },
- { "audio/mp4", kMP4AudioCodecsExpression },
- { "audio/x-m4a", kMP4AudioCodecsExpression },
- { "video/mp4", kMP4VideoCodecsExpression },
- { "video/x-m4v", kMP4VideoCodecsExpression },
- { "application/x-mpegurl", kMP4VideoCodecsExpression },
- { "application/vnd.apple.mpegurl", kMP4VideoCodecsExpression }
-};
+ {"video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0"},
+ {"audio/webm", "opus,vorbis"},
+ {"audio/wav", "1"},
+ {"audio/x-wav", "1"},
+// Android does not support Opus in Ogg container.
+#if defined(OS_ANDROID)
+ {"video/ogg", "theora,vorbis"},
+ {"audio/ogg", "vorbis"},
+ {"application/ogg", "theora,vorbis"},
+#else
+ {"video/ogg", "opus,theora,vorbis"},
+ {"audio/ogg", "opus,vorbis"},
+ {"application/ogg", "opus,theora,vorbis"},
+#endif
+ {"audio/mpeg", "mp3"},
+ {"audio/mp3", ""},
+ {"audio/x-mp3", ""},
+ {"audio/mp4", kMP4AudioCodecsExpression},
+ {"audio/x-m4a", kMP4AudioCodecsExpression},
+ {"video/mp4", kMP4VideoCodecsExpression},
+ {"video/x-m4v", kMP4VideoCodecsExpression},
+ {"application/x-mpegurl", kMP4VideoCodecsExpression},
+ {"application/vnd.apple.mpegurl", kMP4VideoCodecsExpression}};
struct CodecIDMappings {
const char* const codec_id;
@@ -689,23 +695,27 @@
}
bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const {
- return image_map_.find(mime_type) != image_map_.end();
+ return image_map_.find(base::StringToLowerASCII(mime_type)) !=
+ image_map_.end();
}
bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const {
- return media_map_.find(mime_type) != media_map_.end();
+ return media_map_.find(base::StringToLowerASCII(mime_type)) !=
+ media_map_.end();
}
bool MimeUtil::IsSupportedNonImageMimeType(const std::string& mime_type) const {
- return non_image_map_.find(mime_type) != non_image_map_.end() ||
- (mime_type.compare(0, 5, "text/") == 0 &&
- !IsUnsupportedTextMimeType(mime_type)) ||
- (mime_type.compare(0, 12, "application/") == 0 &&
- MatchesMimeType("application/*+json", mime_type));
+ return non_image_map_.find(base::StringToLowerASCII(mime_type)) !=
+ non_image_map_.end() ||
+ (StartsWithASCII(mime_type, "text/", false /* case insensitive */) &&
+ !IsUnsupportedTextMimeType(mime_type)) ||
+ (StartsWithASCII(mime_type, "application/", false) &&
+ MatchesMimeType("application/*+json", mime_type));
}
bool MimeUtil::IsUnsupportedTextMimeType(const std::string& mime_type) const {
- return unsupported_text_map_.find(mime_type) != unsupported_text_map_.end();
+ return unsupported_text_map_.find(base::StringToLowerASCII(mime_type)) !=
+ unsupported_text_map_.end();
}
bool MimeUtil::IsSupportedJavascriptMimeType(
@@ -715,7 +725,7 @@
// Mirrors WebViewImpl::CanShowMIMEType()
bool MimeUtil::IsSupportedMimeType(const std::string& mime_type) const {
- return (mime_type.compare(0, 6, "image/") == 0 &&
+ return (StartsWithASCII(mime_type, "image/", false) &&
IsSupportedImageMimeType(mime_type)) ||
IsSupportedNonImageMimeType(mime_type);
}
@@ -723,29 +733,52 @@
// Tests for MIME parameter equality. Each parameter in the |mime_type_pattern|
// must be matched by a parameter in the |mime_type|. If there are no
// parameters in the pattern, the match is a success.
+//
+// According rfc2045 keys of parameters are case-insensitive, while values may
+// or may not be case-sensitive, but they are usually case-sensitive. So, this
+// function matches values in *case-sensitive* manner, however note that this
+// may produce some false negatives.
bool MatchesMimeTypeParameters(const std::string& mime_type_pattern,
const std::string& mime_type) {
+ typedef std::map<std::string, std::string> StringPairMap;
+
const std::string::size_type semicolon = mime_type_pattern.find(';');
const std::string::size_type test_semicolon = mime_type.find(';');
if (semicolon != std::string::npos) {
if (test_semicolon == std::string::npos)
return false;
- std::vector<std::string> pattern_parameters;
- base::SplitString(mime_type_pattern.substr(semicolon + 1),
- ';', &pattern_parameters);
+ base::StringPairs pattern_parameters;
+ base::SplitStringIntoKeyValuePairs(mime_type_pattern.substr(semicolon + 1),
+ '=', ';', &pattern_parameters);
+ base::StringPairs test_parameters;
+ base::SplitStringIntoKeyValuePairs(mime_type.substr(test_semicolon + 1),
+ '=', ';', &test_parameters);
- std::vector<std::string> test_parameters;
- base::SplitString(mime_type.substr(test_semicolon + 1),
- ';', &test_parameters);
+ // Put the parameters to maps with the keys converted to lower case.
+ StringPairMap pattern_parameter_map;
+ for (const auto& pair : pattern_parameters) {
+ pattern_parameter_map[base::StringToLowerASCII(pair.first)] = pair.second;
+ }
- sort(pattern_parameters.begin(), pattern_parameters.end());
- sort(test_parameters.begin(), test_parameters.end());
- std::vector<std::string> difference =
- base::STLSetDifference<std::vector<std::string> >(pattern_parameters,
- test_parameters);
- return difference.size() == 0;
+ StringPairMap test_parameter_map;
+ for (const auto& pair : test_parameters) {
+ test_parameter_map[base::StringToLowerASCII(pair.first)] = pair.second;
+ }
+
+ if (pattern_parameter_map.size() > test_parameter_map.size())
+ return false;
+
+ for (const auto& parameter_pair : pattern_parameter_map) {
+ const auto& test_parameter_pair_it =
+ test_parameter_map.find(parameter_pair.first);
+ if (test_parameter_pair_it == test_parameter_map.end())
+ return false;
+ if (parameter_pair.second != test_parameter_pair_it->second)
+ return false;
+ }
}
+
return true;
}
@@ -759,10 +792,6 @@
// in the tested type for a match to succeed.
bool MimeUtil::MatchesMimeType(const std::string& mime_type_pattern,
const std::string& mime_type) const {
- // Verify caller is passing lowercase strings.
- DCHECK_EQ(base::StringToLowerASCII(mime_type_pattern), mime_type_pattern);
- DCHECK_EQ(base::StringToLowerASCII(mime_type), mime_type);
-
if (mime_type_pattern.empty())
return false;
@@ -776,10 +805,13 @@
const std::string::size_type star = base_pattern.find('*');
if (star == std::string::npos) {
- if (base_pattern == base_type)
+ if (base_pattern.size() == base_type.size() &&
+ base::strncasecmp(base_pattern.c_str(), base_type.c_str(),
+ base_pattern.size()) == 0) {
return MatchesMimeTypeParameters(mime_type_pattern, mime_type);
- else
+ } else {
return false;
+ }
}
// Test length to prevent overlap between |left| and |right|.
@@ -789,11 +821,10 @@
const std::string left(base_pattern.substr(0, star));
const std::string right(base_pattern.substr(star + 1));
- if (base_type.find(left) != 0)
+ if (!StartsWithASCII(base_type, left, false))
return false;
- if (!right.empty() &&
- base_type.rfind(right) != base_type.length() - right.length())
+ if (!right.empty() && !EndsWith(base_type, right, false))
return false;
return MatchesMimeTypeParameters(mime_type_pattern, mime_type);
@@ -874,30 +905,34 @@
}
bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
- return strict_format_map_.find(mime_type) != strict_format_map_.end();
+ return strict_format_map_.find(base::StringToLowerASCII(mime_type)) !=
+ strict_format_map_.end();
}
SupportsType MimeUtil::IsSupportedStrictMediaMimeType(
const std::string& mime_type,
const std::vector<std::string>& codecs) const {
+ const std::string mime_type_lower_case = base::StringToLowerASCII(mime_type);
StrictMappings::const_iterator it_strict_map =
- strict_format_map_.find(mime_type);
+ strict_format_map_.find(mime_type_lower_case);
if (it_strict_map == strict_format_map_.end())
return codecs.empty() ? MayBeSupported : IsNotSupported;
if (it_strict_map->second.empty()) {
// We get here if the mimetype does not expect a codecs parameter.
- return (codecs.empty() && IsDefaultCodecSupported(mime_type)) ?
- IsSupported : IsNotSupported;
+ return (codecs.empty() &&
+ IsDefaultCodecSupportedLowerCase(mime_type_lower_case))
+ ? IsSupported
+ : IsNotSupported;
}
if (codecs.empty()) {
// We get here if the mimetype expects to get a codecs parameter,
- // but didn't get one. If |mime_type| does not have a default codec
- // the best we can do is say "maybe" because we don't have enough
+ // but didn't get one. If |mime_type_lower_case| does not have a default
+ // codec the best we can do is say "maybe" because we don't have enough
// information.
Codec default_codec = INVALID_CODEC;
- if (!GetDefaultCodec(mime_type, &default_codec))
+ if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec))
return MayBeSupported;
return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported;
@@ -1053,11 +1088,11 @@
return true;
}
-bool MimeUtil::GetDefaultCodec(const std::string& mime_type,
- Codec* default_codec) const {
- if (mime_type == "audio/mpeg" ||
- mime_type == "audio/mp3" ||
- mime_type == "audio/x-mp3") {
+bool MimeUtil::GetDefaultCodecLowerCase(const std::string& mime_type_lower_case,
+ Codec* default_codec) const {
+ if (mime_type_lower_case == "audio/mpeg" ||
+ mime_type_lower_case == "audio/mp3" ||
+ mime_type_lower_case == "audio/x-mp3") {
*default_codec = MimeUtil::MP3;
return true;
}
@@ -1065,10 +1100,10 @@
return false;
}
-
-bool MimeUtil::IsDefaultCodecSupported(const std::string& mime_type) const {
+bool MimeUtil::IsDefaultCodecSupportedLowerCase(
+ const std::string& mime_type_lower_case) const {
Codec default_codec = Codec::INVALID_CODEC;
- if (!GetDefaultCodec(mime_type, &default_codec))
+ if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec))
return false;
return IsCodecSupported(default_codec);
}
@@ -1292,7 +1327,8 @@
iter != source->end(); ++iter, ++i)
(*target)[old_target_size + i] = *iter;
}
-}
+
+} // namespace
void GetExtensionsForMimeType(
const std::string& unsafe_mime_type,
@@ -1303,7 +1339,7 @@
const std::string mime_type = base::StringToLowerASCII(unsafe_mime_type);
base::hash_set<base::FilePath::StringType> unique_extensions;
- if (EndsWith(mime_type, "/*", true)) {
+ if (EndsWith(mime_type, "/*", false)) {
std::string leading_mime_type = mime_type.substr(0, mime_type.length() - 1);
// Find the matching StandardType from within kStandardTypes, or fall
@@ -1349,8 +1385,10 @@
// Don't create a map, there is only one entry in the table,
// except on Android.
for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) {
- if (mime_type == net::supported_certificate_types[i].mime_type)
+ if (base::strcasecmp(mime_type.c_str(),
+ net::supported_certificate_types[i].mime_type) == 0) {
return net::supported_certificate_types[i].cert_type;
+ }
}
return CERTIFICATE_MIME_TYPE_UNKNOWN;
}
diff --git a/net/base/mime_util.h b/net/base/mime_util.h
index f3901ba..09a3c7e 100644
--- a/net/base/mime_util.h
+++ b/net/base/mime_util.h
@@ -5,6 +5,18 @@
#ifndef NET_BASE_MIME_UTIL_H__
#define NET_BASE_MIME_UTIL_H__
+// This file defines MIME utility functions. All of them assume the MIME type
+// to be of the format specified by rfc2045. According to it, MIME types are
+// case strongly insensitive except parameter values, which may or may not be
+// case sensitive.
+//
+// These utilities perform a *case-sensitive* matching for parameter values,
+// which may produce some false negatives. Except that, matching is
+// case-insensitive.
+//
+// All constants in mime_util.cc must be written in lower case, except parameter
+// values, which can be any case.
+
#include <string>
#include <vector>
@@ -50,8 +62,7 @@
NET_EXPORT bool IsSupportedMimeType(const std::string& mime_type);
// Returns true if this the mime_type_pattern matches a given mime-type.
-// Checks for absolute matching and wildcards. mime-types should be in
-// lower case.
+// Checks for absolute matching and wildcards. MIME types are case insensitive.
NET_EXPORT bool MatchesMimeType(const std::string& mime_type_pattern,
const std::string& mime_type);
@@ -125,9 +136,9 @@
const std::string& mime_type,
const std::vector<std::string>& codecs);
-// Get the extensions associated with the given mime type. This should be passed
-// in lower case. There could be multiple extensions for a given mime type, like
-// "html,htm" for "text/html", or "txt,text,html,..." for "text/*".
+// Get the extensions associated with the given mime type. There could be
+// multiple extensions for a given mime type, like "html,htm" for "text/html",
+// or "txt,text,html,..." for "text/*".
// Note that we do not erase the existing elements in the the provided vector.
// Instead, we append the result to it.
NET_EXPORT void GetExtensionsForMimeType(
diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc
index b5335b6..1b29aff 100644
--- a/net/base/mime_util_unittest.cc
+++ b/net/base/mime_util_unittest.cc
@@ -20,14 +20,15 @@
const char* const mime_type;
bool valid;
} tests[] = {
- { FILE_PATH_LITERAL("png"), "image/png", true },
- { FILE_PATH_LITERAL("css"), "text/css", true },
- { FILE_PATH_LITERAL("pjp"), "image/jpeg", true },
- { FILE_PATH_LITERAL("pjpeg"), "image/jpeg", true },
+ {FILE_PATH_LITERAL("png"), "image/png", true},
+ {FILE_PATH_LITERAL("PNG"), "image/png", true},
+ {FILE_PATH_LITERAL("css"), "text/css", true},
+ {FILE_PATH_LITERAL("pjp"), "image/jpeg", true},
+ {FILE_PATH_LITERAL("pjpeg"), "image/jpeg", true},
#if defined(OS_ANDROID)
- { FILE_PATH_LITERAL("m3u8"), "application/x-mpegurl", true },
+ {FILE_PATH_LITERAL("m3u8"), "application/x-mpegurl", true},
#endif
- { FILE_PATH_LITERAL("not an extension / for sure"), "", false },
+ {FILE_PATH_LITERAL("not an extension / for sure"), "", false},
};
std::string mime_type;
@@ -47,12 +48,13 @@
const char* const mime_type;
bool valid;
} tests[] = {
- { FILE_PATH_LITERAL("c:\\foo\\bar.css"), "text/css", true },
- { FILE_PATH_LITERAL("c:\\blah"), "", false },
- { FILE_PATH_LITERAL("/usr/local/bin/mplayer"), "", false },
- { FILE_PATH_LITERAL("/home/foo/bar.css"), "text/css", true },
- { FILE_PATH_LITERAL("/blah."), "", false },
- { FILE_PATH_LITERAL("c:\\blah."), "", false },
+ {FILE_PATH_LITERAL("c:\\foo\\bar.css"), "text/css", true},
+ {FILE_PATH_LITERAL("c:\\foo\\bar.CSS"), "text/css", true},
+ {FILE_PATH_LITERAL("c:\\blah"), "", false},
+ {FILE_PATH_LITERAL("/usr/local/bin/mplayer"), "", false},
+ {FILE_PATH_LITERAL("/home/foo/bar.css"), "text/css", true},
+ {FILE_PATH_LITERAL("/blah."), "", false},
+ {FILE_PATH_LITERAL("c:\\blah."), "", false},
};
std::string mime_type;
@@ -72,13 +74,17 @@
EXPECT_TRUE(IsUnsupportedTextMimeType("text/vcard"));
EXPECT_TRUE(IsSupportedImageMimeType("image/jpeg"));
+ EXPECT_TRUE(IsSupportedImageMimeType("Image/JPEG"));
EXPECT_FALSE(IsSupportedImageMimeType("image/lolcat"));
+ EXPECT_FALSE(IsSupportedImageMimeType("Image/LolCat"));
EXPECT_TRUE(IsSupportedNonImageMimeType("text/html"));
EXPECT_TRUE(IsSupportedNonImageMimeType("text/css"));
EXPECT_TRUE(IsSupportedNonImageMimeType("text/"));
EXPECT_TRUE(IsSupportedNonImageMimeType("text/banana"));
+ EXPECT_TRUE(IsSupportedNonImageMimeType("Text/Banana"));
EXPECT_FALSE(IsSupportedNonImageMimeType("text/vcard"));
EXPECT_FALSE(IsSupportedNonImageMimeType("application/virus"));
+ EXPECT_FALSE(IsSupportedNonImageMimeType("Application/VIRUS"));
EXPECT_TRUE(IsSupportedNonImageMimeType("application/x-x509-user-cert"));
EXPECT_TRUE(IsSupportedNonImageMimeType("application/json"));
EXPECT_TRUE(IsSupportedNonImageMimeType("application/+json"));
@@ -89,20 +95,26 @@
EXPECT_TRUE(IsSupportedNonImageMimeType("application/x-pkcs12"));
EXPECT_TRUE(IsSupportedMediaMimeType("application/vnd.apple.mpegurl"));
EXPECT_TRUE(IsSupportedMediaMimeType("application/x-mpegurl"));
+ EXPECT_TRUE(IsSupportedMediaMimeType("Application/X-MPEGURL"));
#endif
EXPECT_TRUE(IsSupportedMimeType("image/jpeg"));
EXPECT_FALSE(IsSupportedMimeType("image/lolcat"));
+ EXPECT_FALSE(IsSupportedMimeType("Image/LOLCAT"));
EXPECT_TRUE(IsSupportedMimeType("text/html"));
EXPECT_TRUE(IsSupportedMimeType("text/banana"));
+ EXPECT_TRUE(IsSupportedMimeType("Text/BANANA"));
EXPECT_FALSE(IsSupportedMimeType("text/vcard"));
EXPECT_FALSE(IsSupportedMimeType("application/virus"));
EXPECT_FALSE(IsSupportedMimeType("application/x-json"));
+ EXPECT_FALSE(IsSupportedMimeType("Application/X-JSON"));
EXPECT_FALSE(IsSupportedNonImageMimeType("application/vnd.doc;x=y+json"));
+ EXPECT_FALSE(IsSupportedNonImageMimeType("Application/VND.DOC;X=Y+JSON"));
}
TEST(MimeUtilTest, StrictMediaMimeType) {
EXPECT_TRUE(IsStrictMediaMimeType("video/webm"));
+ EXPECT_TRUE(IsStrictMediaMimeType("Video/WEBM"));
EXPECT_TRUE(IsStrictMediaMimeType("audio/webm"));
EXPECT_TRUE(IsStrictMediaMimeType("audio/wav"));
@@ -125,12 +137,17 @@
EXPECT_TRUE(IsStrictMediaMimeType("application/vnd.apple.mpegurl"));
EXPECT_FALSE(IsStrictMediaMimeType("video/unknown"));
+ EXPECT_FALSE(IsStrictMediaMimeType("Video/UNKNOWN"));
EXPECT_FALSE(IsStrictMediaMimeType("audio/unknown"));
EXPECT_FALSE(IsStrictMediaMimeType("application/unknown"));
EXPECT_FALSE(IsStrictMediaMimeType("unknown/unknown"));
}
TEST(MimeUtilTest, MatchesMimeType) {
+ // MIME types are case insensitive.
+ EXPECT_TRUE(MatchesMimeType("VIDEO/*", "video/x-mpeg"));
+ EXPECT_TRUE(MatchesMimeType("video/*", "VIDEO/X-MPEG"));
+
EXPECT_TRUE(MatchesMimeType("*", "video/x-mpeg"));
EXPECT_TRUE(MatchesMimeType("video/*", "video/x-mpeg"));
EXPECT_TRUE(MatchesMimeType("video/*", "video/*"));
@@ -143,6 +160,7 @@
EXPECT_TRUE(MatchesMimeType("aaa*aaa", "aaaaaa"));
EXPECT_TRUE(MatchesMimeType("*", std::string()));
EXPECT_FALSE(MatchesMimeType("video/", "video/x-mpeg"));
+ EXPECT_FALSE(MatchesMimeType("VIDEO/", "Video/X-MPEG"));
EXPECT_FALSE(MatchesMimeType(std::string(), "video/x-mpeg"));
EXPECT_FALSE(MatchesMimeType(std::string(), std::string()));
EXPECT_FALSE(MatchesMimeType("video/x-mpeg", std::string()));
@@ -154,10 +172,14 @@
EXPECT_FALSE(MatchesMimeType("aaa*aaa", "aaaaa"));
EXPECT_TRUE(MatchesMimeType("*", "video/x-mpeg;param=val"));
+ EXPECT_TRUE(MatchesMimeType("*", "Video/X-MPEG;PARAM=VAL"));
EXPECT_TRUE(MatchesMimeType("video/*", "video/x-mpeg;param=val"));
EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/mpeg"));
+ EXPECT_FALSE(MatchesMimeType("Video/*;PARAM=VAL", "VIDEO/Mpeg"));
EXPECT_FALSE(MatchesMimeType("video/*;param=val", "video/mpeg;param=other"));
EXPECT_TRUE(MatchesMimeType("video/*;param=val", "video/mpeg;param=val"));
+ EXPECT_TRUE(MatchesMimeType("Video/*;PARAM=Val", "VIDEO/Mpeg;Param=Val"));
+ EXPECT_FALSE(MatchesMimeType("Video/*;PARAM=VAL", "VIDEO/Mpeg;Param=Val"));
EXPECT_TRUE(MatchesMimeType("video/x-mpeg", "video/x-mpeg;param=val"));
EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val",
"video/x-mpeg;param=val"));
@@ -167,8 +189,14 @@
"video/x-mpeg;param2=val"));
EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val",
"video/x-mpeg;param=val;param2=val2"));
- EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param=val;param2=val2",
- "video/x-mpeg;param=val;param2=val2"));
+ EXPECT_TRUE(MatchesMimeType("Video/X-Mpeg;Param=Val",
+ "VIDEO/X-MPEG;PARAM=Val;PARAM2=val2"));
+ EXPECT_TRUE(MatchesMimeType("Video/X-Mpeg;Param=VAL",
+ "VIDEO/X-MPEG;PARAM=VAL;PARAM2=val2"));
+ EXPECT_FALSE(MatchesMimeType("Video/X-Mpeg;Param=val",
+ "VIDEO/X-MPEG;PARAM=VAL;PARAM2=val2"));
+ EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param=VAL;param2=val2",
+ "video/x-mpeg;param=val;param2=val2"));
EXPECT_TRUE(MatchesMimeType("video/x-mpeg;param2=val2;param=val",
"video/x-mpeg;param=val;param2=val2"));
EXPECT_FALSE(MatchesMimeType("video/x-mpeg;param3=val3;param=val",
@@ -412,6 +440,8 @@
TEST(MimeUtilTest, TestGetCertificateMimeTypeForMimeType) {
EXPECT_EQ(CERTIFICATE_MIME_TYPE_X509_USER_CERT,
GetCertificateMimeTypeForMimeType("application/x-x509-user-cert"));
+ EXPECT_EQ(CERTIFICATE_MIME_TYPE_X509_USER_CERT,
+ GetCertificateMimeTypeForMimeType("Application/X-X509-USER-CERT"));
#if defined(OS_ANDROID)
// Only Android supports CA Certs and PKCS12 archives.
EXPECT_EQ(CERTIFICATE_MIME_TYPE_X509_CA_CERT,
diff --git a/net/base/net_util.h b/net/base/net_util.h
index 9e9dbad..c7d1715 100644
--- a/net/base/net_util.h
+++ b/net/base/net_util.h
@@ -496,6 +496,11 @@
NET_EXPORT bool GetNetworkList(NetworkInterfaceList* networks,
int policy);
+// Gets the SSID of the currently associated WiFi access point if there is one.
+// Otherwise, returns empty string.
+// Currently only implemented on Linux, ChromeOS and Android.
+NET_EXPORT std::string GetWifiSSID();
+
// General category of the IEEE 802.11 (wifi) physical layer operating mode.
enum WifiPHYLayerProtocol {
// No wifi support or no associated AP.
diff --git a/net/base/net_util_linux.cc b/net/base/net_util_linux.cc
index a348912..8342597 100644
--- a/net/base/net_util_linux.cc
+++ b/net/base/net_util_linux.cc
@@ -18,7 +18,6 @@
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
@@ -69,7 +68,11 @@
namespace internal {
inline const unsigned char* GetIPAddressData(const IPAddressNumber& ip) {
- return vector_as_array(&ip);
+#if defined(OS_ANDROID)
+ return ip.begin();
+#else
+ return ip.data();
+#endif
}
// Gets the connection type for interface |ifname| by checking for wireless
@@ -100,6 +103,21 @@
return NetworkChangeNotifier::CONNECTION_UNKNOWN;
}
+std::string GetInterfaceSSID(const std::string& ifname) {
+ base::ScopedFD ioctl_socket(socket(AF_INET, SOCK_DGRAM, 0));
+ if (!ioctl_socket.is_valid())
+ return "";
+ struct iwreq wreq = {};
+ strncpy(wreq.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
+
+ char ssid[IW_ESSID_MAX_SIZE + 1] = {0};
+ wreq.u.essid.pointer = ssid;
+ wreq.u.essid.length = IW_ESSID_MAX_SIZE;
+ if (ioctl(ioctl_socket.get(), SIOCGIWESSID, &wreq) != -1)
+ return ssid;
+ return "";
+}
+
bool GetNetworkListImpl(
NetworkInterfaceList* networks,
int policy,
@@ -169,6 +187,23 @@
return true;
}
+std::string GetWifiSSIDFromInterfaceListInternal(
+ const NetworkInterfaceList& interfaces,
+ internal::GetInterfaceSSIDFunction get_interface_ssid) {
+ std::string connected_ssid;
+ for (size_t i = 0; i < interfaces.size(); ++i) {
+ if (interfaces[i].type != NetworkChangeNotifier::CONNECTION_WIFI)
+ return "";
+ std::string ssid = get_interface_ssid(interfaces[i].name);
+ if (i == 0) {
+ connected_ssid = ssid;
+ } else if (ssid != connected_ssid) {
+ return "";
+ }
+ }
+ return connected_ssid;
+}
+
} // namespace internal
bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
@@ -183,4 +218,13 @@
&internal::AddressTrackerLinux::GetInterfaceName);
}
+std::string GetWifiSSID() {
+ NetworkInterfaceList networks;
+ if (GetNetworkList(&networks, net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
+ return internal::GetWifiSSIDFromInterfaceListInternal(
+ networks, internal::GetInterfaceSSID);
+ }
+ return "";
+}
+
} // namespace net
diff --git a/net/base/net_util_linux.h b/net/base/net_util_linux.h
index fb5b6f4..0b556bc 100644
--- a/net/base/net_util_linux.h
+++ b/net/base/net_util_linux.h
@@ -8,6 +8,8 @@
// This file is only used to expose some of the internals
// of net_util_linux.cc to address_tracker_linux and tests.
+#include <string>
+
#include "base/containers/hash_tables.h"
#include "net/base/address_tracker_linux.h"
#include "net/base/net_util.h"
@@ -17,6 +19,8 @@
typedef char* (*GetInterfaceNameFunction)(int interface_index, char* ifname);
+typedef std::string (*GetInterfaceSSIDFunction)(const std::string& ifname);
+
NET_EXPORT bool GetNetworkListImpl(
NetworkInterfaceList* networks,
int policy,
@@ -24,6 +28,15 @@
const internal::AddressTrackerLinux::AddressMap& address_map,
GetInterfaceNameFunction get_interface_name);
+// Gets the current Wi-Fi SSID based on |interfaces|. Returns
+// empty string if there are no interfaces or if two interfaces have different
+// connection types. Otherwise returns the SSID of all interfaces if they have
+// the same SSID. This is adapted from
+// NetworkChangeNotifier::ConnectionTypeFromInterfaceList.
+NET_EXPORT std::string GetWifiSSIDFromInterfaceListInternal(
+ const NetworkInterfaceList& interfaces,
+ internal::GetInterfaceSSIDFunction get_interface_ssid);
+
} // namespace internal
} // namespace net
diff --git a/net/base/net_util_mac.cc b/net/base/net_util_mac.cc
index 5dd4630..b227fbc 100644
--- a/net/base/net_util_mac.cc
+++ b/net/base/net_util_mac.cc
@@ -243,4 +243,9 @@
return result;
}
+std::string GetWifiSSID() {
+ NOTIMPLEMENTED();
+ return "";
+}
+
} // namespace net
diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc
index b8e7195..86709d6 100644
--- a/net/base/net_util_posix.cc
+++ b/net/base/net_util_posix.cc
@@ -63,6 +63,11 @@
NOTIMPLEMENTED();
return false;
}
+
+std::string GetWifiSSID() {
+ NOTIMPLEMENTED();
+ return "";
+}
#endif // OS_NACL
WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc
index e9cd79b..fa2a60b 100644
--- a/net/base/net_util_unittest.cc
+++ b/net/base/net_util_unittest.cc
@@ -65,6 +65,15 @@
const char* const expected;
};
+#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
+const char kWiFiSSID[] = "TestWiFi";
+const char kInterfaceWithDifferentSSID[] = "wlan999";
+
+std::string TestGetInterfaceSSID(const std::string& ifname) {
+ return (ifname == kInterfaceWithDifferentSSID) ? "AnotherSSID" : kWiFiSSID;
+}
+#endif
+
// Fills in sockaddr for the given 32-bit address (IPv4.)
// |bytes| should be an array of length 4.
void MakeIPv4Address(const uint8* bytes, int port, SockaddrStorage* storage) {
@@ -1306,6 +1315,56 @@
#endif // !OS_MACOSX && !OS_WIN && !OS_NACL
+TEST(NetUtilTest, GetWifiSSID) {
+ // We can't check the result of GetWifiSSID() directly, since the result
+ // will differ across machines. Simply exercise the code path and hope that it
+ // doesn't crash.
+ EXPECT_NE((const char*)NULL, GetWifiSSID().c_str());
+}
+
+#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS)
+TEST(NetUtilTest, GetWifiSSIDFromInterfaceList) {
+ NetworkInterfaceList list;
+ EXPECT_EQ(std::string(), net::internal::GetWifiSSIDFromInterfaceListInternal(
+ list, TestGetInterfaceSSID));
+
+ NetworkInterface interface1;
+ interface1.name = "wlan0";
+ interface1.type = NetworkChangeNotifier::CONNECTION_WIFI;
+ list.push_back(interface1);
+ ASSERT_EQ(1u, list.size());
+ EXPECT_EQ(std::string(kWiFiSSID),
+ net::internal::GetWifiSSIDFromInterfaceListInternal(
+ list, TestGetInterfaceSSID));
+
+ NetworkInterface interface2;
+ interface2.name = "wlan1";
+ interface2.type = NetworkChangeNotifier::CONNECTION_WIFI;
+ list.push_back(interface2);
+ ASSERT_EQ(2u, list.size());
+ EXPECT_EQ(std::string(kWiFiSSID),
+ net::internal::GetWifiSSIDFromInterfaceListInternal(
+ list, TestGetInterfaceSSID));
+
+ NetworkInterface interface3;
+ interface3.name = kInterfaceWithDifferentSSID;
+ interface3.type = NetworkChangeNotifier::CONNECTION_WIFI;
+ list.push_back(interface3);
+ ASSERT_EQ(3u, list.size());
+ EXPECT_EQ(std::string(), net::internal::GetWifiSSIDFromInterfaceListInternal(
+ list, TestGetInterfaceSSID));
+
+ list.pop_back();
+ NetworkInterface interface4;
+ interface4.name = "eth0";
+ interface4.type = NetworkChangeNotifier::CONNECTION_ETHERNET;
+ list.push_back(interface4);
+ ASSERT_EQ(3u, list.size());
+ EXPECT_EQ(std::string(), net::internal::GetWifiSSIDFromInterfaceListInternal(
+ list, TestGetInterfaceSSID));
+}
+#endif // OS_LINUX
+
namespace {
#if defined(OS_WIN)
diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc
index ec40233..6658358 100644
--- a/net/base/net_util_win.cc
+++ b/net/base/net_util_win.cc
@@ -320,4 +320,9 @@
return scoped_ptr<ScopedWifiOptions>(new WifiOptionSetter(options));
}
+std::string GetWifiSSID() {
+ NOTIMPLEMENTED();
+ return "";
+}
+
} // namespace net
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index ec45a4e..3ec6369 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -949,29 +949,31 @@
}
void NetworkChangeNotifier::NotifyObserversOfIPAddressChangeImpl() {
- ip_address_observer_list_->Notify(&IPAddressObserver::OnIPAddressChanged);
+ ip_address_observer_list_->Notify(FROM_HERE,
+ &IPAddressObserver::OnIPAddressChanged);
}
void NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeImpl(
ConnectionType type) {
connection_type_observer_list_->Notify(
- &ConnectionTypeObserver::OnConnectionTypeChanged, type);
+ FROM_HERE, &ConnectionTypeObserver::OnConnectionTypeChanged, type);
}
void NetworkChangeNotifier::NotifyObserversOfNetworkChangeImpl(
ConnectionType type) {
network_change_observer_list_->Notify(
- &NetworkChangeObserver::OnNetworkChanged, type);
+ FROM_HERE, &NetworkChangeObserver::OnNetworkChanged, type);
}
void NetworkChangeNotifier::NotifyObserversOfDNSChangeImpl() {
- resolver_state_observer_list_->Notify(&DNSObserver::OnDNSChanged);
+ resolver_state_observer_list_->Notify(FROM_HERE, &DNSObserver::OnDNSChanged);
}
void NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeImpl(
double max_bandwidth_mbps) {
max_bandwidth_observer_list_->Notify(
- &MaxBandwidthObserver::OnMaxBandwidthChanged, max_bandwidth_mbps);
+ FROM_HERE, &MaxBandwidthObserver::OnMaxBandwidthChanged,
+ max_bandwidth_mbps);
}
NetworkChangeNotifier::DisableForTest::DisableForTest()
diff --git a/net/base/trace_net_log_observer.cc b/net/base/trace_net_log_observer.cc
index 905ec66..bbee970 100644
--- a/net/base/trace_net_log_observer.cc
+++ b/net/base/trace_net_log_observer.cc
@@ -22,7 +22,7 @@
// TraceLog category for NetLog events.
const char kNetLogTracingCategory[] = TRACE_DISABLED_BY_DEFAULT("netlog");
-class TracedValue : public base::debug::ConvertableToTraceFormat {
+class TracedValue : public base::trace_event::ConvertableToTraceFormat {
public:
explicit TracedValue(scoped_ptr<base::Value> value) : value_(value.Pass()) {}
@@ -58,26 +58,26 @@
switch (entry.phase()) {
case NetLog::PHASE_BEGIN:
TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
- kNetLogTracingCategory,
- NetLog::EventTypeToString(entry.type()), entry.source().id,
- "source_type", NetLog::SourceTypeToString(entry.source().type),
- "params", scoped_refptr<base::debug::ConvertableToTraceFormat>(
+ kNetLogTracingCategory, NetLog::EventTypeToString(entry.type()),
+ entry.source().id, "source_type",
+ NetLog::SourceTypeToString(entry.source().type), "params",
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
new TracedValue(params.Pass())));
break;
case NetLog::PHASE_END:
TRACE_EVENT_NESTABLE_ASYNC_END2(
- kNetLogTracingCategory,
- NetLog::EventTypeToString(entry.type()), entry.source().id,
- "source_type", NetLog::SourceTypeToString(entry.source().type),
- "params", scoped_refptr<base::debug::ConvertableToTraceFormat>(
+ kNetLogTracingCategory, NetLog::EventTypeToString(entry.type()),
+ entry.source().id, "source_type",
+ NetLog::SourceTypeToString(entry.source().type), "params",
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
new TracedValue(params.Pass())));
break;
case NetLog::PHASE_NONE:
TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(
- kNetLogTracingCategory,
- NetLog::EventTypeToString(entry.type()), entry.source().id,
- "source_type", NetLog::SourceTypeToString(entry.source().type),
- "params", scoped_refptr<base::debug::ConvertableToTraceFormat>(
+ kNetLogTracingCategory, NetLog::EventTypeToString(entry.type()),
+ entry.source().id, "source_type",
+ NetLog::SourceTypeToString(entry.source().type), "params",
+ scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
new TracedValue(params.Pass())));
break;
}
@@ -87,13 +87,13 @@
DCHECK(!net_log_to_watch_);
DCHECK(!net_log());
net_log_to_watch_ = netlog;
- base::debug::TraceLog::GetInstance()->AddEnabledStateObserver(this);
+ base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
}
void TraceNetLogObserver::StopWatchForTraceStart() {
// Should only stop if is currently watching.
DCHECK(net_log_to_watch_);
- base::debug::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
+ base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
if (net_log())
net_log()->RemoveThreadSafeObserver(this);
net_log_to_watch_ = NULL;
diff --git a/net/base/trace_net_log_observer.h b/net/base/trace_net_log_observer.h
index 9977331..4a8355b 100644
--- a/net/base/trace_net_log_observer.h
+++ b/net/base/trace_net_log_observer.h
@@ -16,7 +16,7 @@
// events to TraceLog if it is enabled.
class NET_EXPORT TraceNetLogObserver
: public NetLog::ThreadSafeObserver,
- public base::debug::TraceLog::EnabledStateObserver {
+ public base::trace_event::TraceLog::EnabledStateObserver {
public:
TraceNetLogObserver();
~TraceNetLogObserver() override;
@@ -34,7 +34,7 @@
// TraceNetLogObserver is destroyed.
void StopWatchForTraceStart();
- // base::debug::TraceLog::EnabledStateChangedObserver implementation:
+ // base::trace_event::TraceLog::EnabledStateChangedObserver implementation:
void OnTraceLogEnabled() override;
void OnTraceLogDisabled() override;
diff --git a/net/base/trace_net_log_observer_unittest.cc b/net/base/trace_net_log_observer_unittest.cc
index 802722d..1439425 100644
--- a/net/base/trace_net_log_observer_unittest.cc
+++ b/net/base/trace_net_log_observer_unittest.cc
@@ -21,7 +21,7 @@
#include "net/base/net_log.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::debug::TraceLog;
+using base::trace_event::TraceLog;
namespace net {
@@ -90,9 +90,9 @@
static void EnableTraceLog() {
TraceLog::GetInstance()->SetEnabled(
- base::debug::CategoryFilter(kNetLogTracingCategory),
+ base::trace_event::CategoryFilter(kNetLogTracingCategory),
TraceLog::RECORDING_MODE,
- base::debug::TraceOptions());
+ base::trace_event::TraceOptions());
}
void EndTraceAndFlush() {
@@ -145,8 +145,8 @@
private:
scoped_ptr<base::ListValue> trace_events_;
- base::debug::TraceResultBuffer trace_buffer_;
- base::debug::TraceResultBuffer::SimpleOutput json_output_;
+ base::trace_event::TraceResultBuffer trace_buffer_;
+ base::trace_event::TraceResultBuffer::SimpleOutput json_output_;
CapturingNetLog net_log_;
scoped_ptr<TraceNetLogObserver> trace_net_log_observer_;
};
diff --git a/net/cert/cert_database.cc b/net/cert/cert_database.cc
index d6a9b1b..8591122 100644
--- a/net/cert/cert_database.cc
+++ b/net/cert/cert_database.cc
@@ -25,17 +25,19 @@
}
void CertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) {
- observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert));
+ observer_list_->Notify(FROM_HERE, &Observer::OnCertAdded,
+ make_scoped_refptr(cert));
}
void CertDatabase::NotifyObserversOfCertRemoved(const X509Certificate* cert) {
- observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert));
+ observer_list_->Notify(FROM_HERE, &Observer::OnCertRemoved,
+ make_scoped_refptr(cert));
}
void CertDatabase::NotifyObserversOfCACertChanged(
const X509Certificate* cert) {
- observer_list_->Notify(
- &Observer::OnCACertChanged, make_scoped_refptr(cert));
+ observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged,
+ make_scoped_refptr(cert));
}
} // namespace net
diff --git a/net/cert/cert_database_android.cc b/net/cert/cert_database_android.cc
index 6eb964d..144b9a1 100644
--- a/net/cert/cert_database_android.cc
+++ b/net/cert/cert_database_android.cc
@@ -48,7 +48,7 @@
}
void CertDatabase::OnAndroidKeyChainChanged() {
- observer_list_->Notify(&Observer::OnCACertChanged,
+ observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged,
scoped_refptr<X509Certificate>());
}
diff --git a/net/cert/nss_cert_database.cc b/net/cert/nss_cert_database.cc
index 8e9c692..e1b3198 100644
--- a/net/cert/nss_cert_database.cc
+++ b/net/cert/nss_cert_database.cc
@@ -438,18 +438,20 @@
}
void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) {
- observer_list_->Notify(&Observer::OnCertAdded, make_scoped_refptr(cert));
+ observer_list_->Notify(FROM_HERE, &Observer::OnCertAdded,
+ make_scoped_refptr(cert));
}
void NSSCertDatabase::NotifyObserversOfCertRemoved(
const X509Certificate* cert) {
- observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert));
+ observer_list_->Notify(FROM_HERE, &Observer::OnCertRemoved,
+ make_scoped_refptr(cert));
}
void NSSCertDatabase::NotifyObserversOfCACertChanged(
const X509Certificate* cert) {
- observer_list_->Notify(
- &Observer::OnCACertChanged, make_scoped_refptr(cert));
+ observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged,
+ make_scoped_refptr(cert));
}
// static
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index f689553..452ce68 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -57,6 +57,7 @@
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -1443,6 +1444,9 @@
}
void CookieMonster::ReportLoaded() {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457528 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("457528 CookieMonster::ReportLoaded"));
if (delegate_.get())
delegate_->OnLoaded();
}
@@ -1468,6 +1472,10 @@
// We need to do this repeatedly until no more tasks were added to the queue
// during the period where we release the lock.
while (true) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/456373 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile1(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("456373 CookieMonster::OnKeyLoaded1"));
{
base::AutoLock autolock(lock_);
std::map<std::string, std::deque<scoped_refptr<CookieMonsterTask> > >
@@ -1484,6 +1492,10 @@
it->second.swap(tasks_pending_for_key);
}
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/456373 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile2(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("456373 CookieMonster::OnKeyLoaded2"));
while (!tasks_pending_for_key.empty()) {
scoped_refptr<CookieMonsterTask> task = tasks_pending_for_key.front();
task->Run();
@@ -1494,6 +1506,10 @@
void CookieMonster::StoreLoadedCookies(
const std::vector<CanonicalCookie*>& cookies) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/456373 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "456373 CookieMonster::StoreLoadedCookies"));
// Initialize the store and sync in any saved persistent cookies. We don't
// care if it's expired, insert it so it can be garbage collected, removed,
// and sync'd.
@@ -1551,6 +1567,9 @@
}
void CookieMonster::InvokeQueue() {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457528 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("457528 CookieMonster::InvokeQueue"));
while (true) {
scoped_refptr<CookieMonsterTask> request_task;
{
diff --git a/net/disk_cache/blockfile/backend_impl.cc b/net/disk_cache/blockfile/backend_impl.cc
index 980249b..b9077f1 100644
--- a/net/disk_cache/blockfile/backend_impl.cc
+++ b/net/disk_cache/blockfile/backend_impl.cc
@@ -13,7 +13,6 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "base/metrics/stats_counters.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
@@ -505,7 +504,6 @@
static_cast<base::HistogramBase::Sample>(use_hours));
stats_.OnEvent(Stats::OPEN_HIT);
web_fonts_histogram::RecordCacheHit(cache_entry);
- SIMPLE_STATS_COUNTER("disk_cache.hit");
return cache_entry;
}
@@ -601,7 +599,6 @@
CACHE_UMA(AGE_MS, "CreateTime", 0, start);
stats_.OnEvent(Stats::CREATE_HIT);
- SIMPLE_STATS_COUNTER("disk_cache.miss");
Trace("create entry hit ");
FlushIndex();
cache_entry->AddRef();
diff --git a/net/disk_cache/blockfile/backend_impl_v3.cc b/net/disk_cache/blockfile/backend_impl_v3.cc
index 6d73d07..9615755 100644
--- a/net/disk_cache/blockfile/backend_impl_v3.cc
+++ b/net/disk_cache/blockfile/backend_impl_v3.cc
@@ -12,7 +12,6 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "base/metrics/stats_counters.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc
index 8cf592a..6c43eeb 100644
--- a/net/disk_cache/simple/simple_backend_impl.cc
+++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -50,7 +50,7 @@
// Maximum number of concurrent worker pool threads, which also is the limit
// on concurrent IO (as we use one thread per IO request).
-const int kDefaultMaxWorkerThreads = 50;
+const size_t kMaxWorkerThreads = 5U;
const char kThreadNamePrefix[] = "SimpleCache";
@@ -62,17 +62,8 @@
void MaybeCreateSequencedWorkerPool() {
if (!g_sequenced_worker_pool) {
- int max_worker_threads = kDefaultMaxWorkerThreads;
-
- const std::string thread_count_field_trial =
- base::FieldTrialList::FindFullName("SimpleCacheMaxThreads");
- if (!thread_count_field_trial.empty()) {
- max_worker_threads =
- std::max(1, std::atoi(thread_count_field_trial.c_str()));
- }
-
- g_sequenced_worker_pool = new SequencedWorkerPool(max_worker_threads,
- kThreadNamePrefix);
+ g_sequenced_worker_pool =
+ new SequencedWorkerPool(kMaxWorkerThreads, kThreadNamePrefix);
g_sequenced_worker_pool->AddRef(); // Leak it.
}
}
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index 98e4105..6c0a154 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -49,6 +49,7 @@
#include "net/dns/host_resolver_proc.h"
#include "net/socket/client_socket_factory.h"
#include "net/udp/datagram_client_socket.h"
+#include "url/url_canon_ip.h"
#if defined(OS_WIN)
#include "net/base/winsock_init.h"
@@ -2154,7 +2155,13 @@
AddressFamily effective_address_family = info.address_family();
if (info.address_family() == ADDRESS_FAMILY_UNSPECIFIED) {
- if (probe_ipv6_support_ && !use_local_ipv6_) {
+ unsigned char ip_number[4];
+ url::Component host_comp(0, info.hostname().size());
+ int num_components;
+ if (probe_ipv6_support_ && !use_local_ipv6_ &&
+ // Don't bother IPv6 probing when resolving IPv4 literals.
+ url::IPv4AddressToNumber(info.hostname().c_str(), host_comp, ip_number,
+ &num_components) != url::CanonHostInfo::IPV4) {
// Google DNS address.
const uint8 kIPv6Address[] =
{ 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,
diff --git a/net/dns/mojo_host_resolver_impl.cc b/net/dns/mojo_host_resolver_impl.cc
new file mode 100644
index 0000000..bf35f95
--- /dev/null
+++ b/net/dns/mojo_host_resolver_impl.cc
@@ -0,0 +1,130 @@
+// 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 "net/dns/mojo_host_resolver_impl.h"
+
+#include "base/basictypes.h"
+#include "base/stl_util.h"
+#include "net/base/address_list.h"
+#include "net/base/net_errors.h"
+#include "net/dns/host_resolver.h"
+#include "net/dns/mojo_type_converters.h"
+
+namespace net {
+
+// Handles host resolution for a single request and sends a response when done.
+// Also detects connection errors for HostResolverRequestClient and cancels the
+// outstanding resolve request. Owned by MojoHostResolverImpl.
+class MojoHostResolverImpl::Job : public mojo::ErrorHandler {
+ public:
+ Job(MojoHostResolverImpl* resolver_service,
+ net::HostResolver* resolver,
+ const net::HostResolver::RequestInfo& request_info,
+ interfaces::HostResolverRequestClientPtr client);
+ ~Job() override;
+
+ void Start();
+
+ private:
+ // Completion callback for the HostResolver::Resolve request.
+ void OnResolveDone(int result);
+
+ // Overridden from mojo::ErrorHandler:
+ void OnConnectionError() override;
+
+ MojoHostResolverImpl* resolver_service_;
+ net::HostResolver* resolver_;
+ net::HostResolver::RequestInfo request_info_;
+ interfaces::HostResolverRequestClientPtr client_;
+ net::HostResolver::RequestHandle handle_;
+ AddressList result_;
+ base::ThreadChecker thread_checker_;
+};
+
+MojoHostResolverImpl::MojoHostResolverImpl(net::HostResolver* resolver)
+ : resolver_(resolver) {
+}
+
+MojoHostResolverImpl::~MojoHostResolverImpl() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ STLDeleteElements(&pending_jobs_);
+}
+
+void MojoHostResolverImpl::Resolve(
+ interfaces::HostResolverRequestInfoPtr request_info,
+ interfaces::HostResolverRequestClientPtr client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ Job* job = new Job(this, resolver_,
+ request_info->To<net::HostResolver::RequestInfo>(),
+ client.Pass());
+ pending_jobs_.insert(job);
+ job->Start();
+}
+
+void MojoHostResolverImpl::DeleteJob(Job* job) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ size_t num_erased = pending_jobs_.erase(job);
+ DCHECK(num_erased);
+ delete job;
+}
+
+MojoHostResolverImpl::Job::Job(
+ MojoHostResolverImpl* resolver_service,
+ net::HostResolver* resolver,
+ const net::HostResolver::RequestInfo& request_info,
+ interfaces::HostResolverRequestClientPtr client)
+ : resolver_service_(resolver_service),
+ resolver_(resolver),
+ request_info_(request_info),
+ client_(client.Pass()),
+ handle_(nullptr) {
+ client_.set_error_handler(this);
+}
+
+void MojoHostResolverImpl::Job::Start() {
+ DVLOG(1) << "Resolve " << request_info_.host_port_pair().ToString();
+ BoundNetLog net_log;
+ int result =
+ resolver_->Resolve(request_info_, DEFAULT_PRIORITY, &result_,
+ base::Bind(&MojoHostResolverImpl::Job::OnResolveDone,
+ base::Unretained(this)),
+ &handle_, net_log);
+
+ if (result != ERR_IO_PENDING)
+ OnResolveDone(result);
+}
+
+MojoHostResolverImpl::Job::~Job() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (handle_)
+ resolver_->CancelRequest(handle_);
+}
+
+void MojoHostResolverImpl::Job::OnResolveDone(int result) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ handle_ = nullptr;
+ DVLOG(1) << "Resolved " << request_info_.host_port_pair().ToString()
+ << " with error " << result << " and " << result_.size()
+ << " results!";
+ for (const auto& address : result_) {
+ DVLOG(1) << address.ToString();
+ }
+ if (result == OK)
+ client_->ReportResult(result, interfaces::AddressList::From(result_));
+ else
+ client_->ReportResult(result, nullptr);
+
+ resolver_service_->DeleteJob(this);
+}
+
+void MojoHostResolverImpl::Job::OnConnectionError() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // |resolver_service_| should always outlive us.
+ DCHECK(resolver_service_);
+ DVLOG(1) << "Connection error on request for "
+ << request_info_.host_port_pair().ToString();
+ resolver_service_->DeleteJob(this);
+}
+
+} // namespace net
diff --git a/net/dns/mojo_host_resolver_impl.h b/net/dns/mojo_host_resolver_impl.h
new file mode 100644
index 0000000..aa359ef
--- /dev/null
+++ b/net/dns/mojo_host_resolver_impl.h
@@ -0,0 +1,53 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_DNS_MOJO_HOST_RESOLVER_IMPL_H_
+#define NET_DNS_MOJO_HOST_RESOLVER_IMPL_H_
+
+#include <set>
+
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "net/interfaces/host_resolver_service.mojom.h"
+
+namespace net {
+
+class HostResolver;
+
+// This is the implementation of the HostResolver Mojo interface.
+// Inbound Mojo requests are sent to the HostResolver passed into the
+// constructor. When destroyed, any outstanding resolver requests are cancelled.
+// If a request's HostResolverRequestClient is shut down, the associated
+// resolver request is cancelled.
+class MojoHostResolverImpl : public interfaces::HostResolver {
+ public:
+ // |resolver| is expected to outlive |this|.
+ explicit MojoHostResolverImpl(net::HostResolver* resolver);
+ ~MojoHostResolverImpl() override;
+
+ private:
+ class Job;
+
+ // Removes |job| from the set of pending jobs, and deletes it.
+ void DeleteJob(Job* job);
+
+ // Overridden from net::interfaces::HostResolver:
+ void Resolve(interfaces::HostResolverRequestInfoPtr request_info,
+ interfaces::HostResolverRequestClientPtr client) override;
+
+ // Resolver for resolving incoming requests. Not owned.
+ net::HostResolver* resolver_;
+
+ // All pending jobs, so they can be cancelled when this service is destroyed.
+ // Owns all jobs.
+ std::set<Job*> pending_jobs_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(MojoHostResolverImpl);
+};
+
+} // namespace net
+
+#endif // NET_DNS_MOJO_HOST_RESOLVER_IMPL_H_
diff --git a/net/dns/mojo_host_resolver_impl_unittest.cc b/net/dns/mojo_host_resolver_impl_unittest.cc
new file mode 100644
index 0000000..8587c54
--- /dev/null
+++ b/net/dns/mojo_host_resolver_impl_unittest.cc
@@ -0,0 +1,309 @@
+// 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 "net/dns/mojo_host_resolver_impl.h"
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/time/time.h"
+#include "net/base/address_list.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/dns/mojo_type_converters.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
+
+namespace net {
+
+namespace {
+
+class TestRequestClient : public interfaces::HostResolverRequestClient,
+ public mojo::ErrorHandler {
+ public:
+ explicit TestRequestClient(
+ mojo::InterfaceRequest<interfaces::HostResolverRequestClient> req)
+ : done_(false), binding_(this, req.Pass()) {
+ binding_.set_error_handler(this);
+ }
+
+ void WaitForResult();
+ void WaitForConnectionError();
+
+ int32_t error_;
+ interfaces::AddressListPtr results_;
+
+ private:
+ // Overridden from interfaces::HostResolverRequestClient.
+ void ReportResult(int32_t error, interfaces::AddressListPtr results) override;
+
+ // Overridden from mojo::ErrorHandler.
+ void OnConnectionError() override;
+
+ bool done_;
+ base::Closure run_loop_quit_closure_;
+ base::Closure connection_error_quit_closure_;
+
+ mojo::Binding<interfaces::HostResolverRequestClient> binding_;
+};
+
+void TestRequestClient::WaitForResult() {
+ if (done_)
+ return;
+
+ base::RunLoop run_loop;
+ run_loop_quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ ASSERT_TRUE(done_);
+}
+
+void TestRequestClient::WaitForConnectionError() {
+ base::RunLoop run_loop;
+ connection_error_quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+}
+
+void TestRequestClient::ReportResult(int32_t error,
+ interfaces::AddressListPtr results) {
+ if (!run_loop_quit_closure_.is_null()) {
+ run_loop_quit_closure_.Run();
+ }
+ ASSERT_FALSE(done_);
+ error_ = error;
+ results_ = results.Pass();
+ done_ = true;
+}
+
+void TestRequestClient::OnConnectionError() {
+ if (!connection_error_quit_closure_.is_null())
+ connection_error_quit_closure_.Run();
+}
+
+class CallbackMockHostResolver : public MockHostResolver {
+ public:
+ CallbackMockHostResolver() {}
+ ~CallbackMockHostResolver() override {}
+
+ // Set a callback to run whenever Resolve is called. Callback is cleared after
+ // every run.
+ void SetResolveCallback(base::Closure callback) {
+ resolve_callback_ = callback;
+ }
+
+ // Overridden from MockHostResolver.
+ int Resolve(const RequestInfo& info,
+ RequestPriority priority,
+ AddressList* addresses,
+ const CompletionCallback& callback,
+ RequestHandle* out_req,
+ const BoundNetLog& net_log) override;
+
+ private:
+ base::Closure resolve_callback_;
+};
+
+int CallbackMockHostResolver::Resolve(const RequestInfo& info,
+ RequestPriority priority,
+ AddressList* addresses,
+ const CompletionCallback& callback,
+ RequestHandle* out_req,
+ const BoundNetLog& net_log) {
+ int result = MockHostResolver::Resolve(info, priority, addresses, callback,
+ out_req, net_log);
+ if (!resolve_callback_.is_null()) {
+ resolve_callback_.Run();
+ resolve_callback_.Reset();
+ }
+ return result;
+}
+
+} // namespace
+
+class MojoHostResolverImplTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ mock_host_resolver_.rules()->AddRule("example.com", "1.2.3.4");
+ mock_host_resolver_.rules()->AddRule("chromium.org", "8.8.8.8");
+ mock_host_resolver_.rules()->AddSimulatedFailure("failure.fail");
+
+ resolver_service_.reset(new MojoHostResolverImpl(&mock_host_resolver_));
+ resolver_service_binding_.reset(
+ new mojo::Binding<interfaces::HostResolver>(resolver_service_.get()));
+ resolver_service_binding_->Bind(mojo::GetProxy(&resolver_service_ptr_));
+ }
+
+ interfaces::HostResolverRequestInfoPtr CreateRequest(const std::string& host,
+ uint16_t port,
+ bool is_my_ip_address) {
+ interfaces::HostResolverRequestInfoPtr request =
+ interfaces::HostResolverRequestInfo::New();
+ request->host = host;
+ request->port = port;
+ request->address_family = interfaces::ADDRESS_FAMILY_IPV4;
+ request->is_my_ip_address = is_my_ip_address;
+ return request.Pass();
+ }
+
+ // Wait until the mock resolver has received |num| resolve requests.
+ void WaitForRequests(size_t num) {
+ while (mock_host_resolver_.num_resolve() < num) {
+ base::RunLoop run_loop;
+ mock_host_resolver_.SetResolveCallback(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+ }
+
+ CallbackMockHostResolver mock_host_resolver_;
+ scoped_ptr<MojoHostResolverImpl> resolver_service_;
+
+ scoped_ptr<mojo::Binding<interfaces::HostResolver>> resolver_service_binding_;
+ interfaces::HostResolverPtr resolver_service_ptr_;
+};
+
+TEST_F(MojoHostResolverImplTest, Resolve) {
+ interfaces::HostResolverRequestClientPtr client_ptr;
+ TestRequestClient client(mojo::GetProxy(&client_ptr));
+
+ interfaces::HostResolverRequestInfoPtr request =
+ CreateRequest("example.com", 80, false);
+ resolver_service_ptr_->Resolve(request.Pass(), client_ptr.Pass());
+ client.WaitForResult();
+
+ EXPECT_EQ(net::OK, client.error_);
+ AddressList address_list = (*client.results_).To<AddressList>();
+ EXPECT_EQ(1U, address_list.size());
+ EXPECT_EQ("1.2.3.4:80", address_list[0].ToString());
+}
+
+TEST_F(MojoHostResolverImplTest, ResolveSynchronous) {
+ interfaces::HostResolverRequestClientPtr client_ptr;
+ TestRequestClient client(mojo::GetProxy(&client_ptr));
+
+ mock_host_resolver_.set_synchronous_mode(true);
+
+ interfaces::HostResolverRequestInfoPtr request =
+ CreateRequest("example.com", 80, false);
+ resolver_service_ptr_->Resolve(request.Pass(), client_ptr.Pass());
+ client.WaitForResult();
+
+ EXPECT_EQ(net::OK, client.error_);
+ AddressList address_list = (*client.results_).To<AddressList>();
+ EXPECT_EQ(1U, address_list.size());
+ EXPECT_EQ("1.2.3.4:80", address_list[0].ToString());
+}
+
+TEST_F(MojoHostResolverImplTest, ResolveMultiple) {
+ interfaces::HostResolverRequestClientPtr client1_ptr;
+ TestRequestClient client1(mojo::GetProxy(&client1_ptr));
+ interfaces::HostResolverRequestClientPtr client2_ptr;
+ TestRequestClient client2(mojo::GetProxy(&client2_ptr));
+
+ mock_host_resolver_.set_ondemand_mode(true);
+
+ interfaces::HostResolverRequestInfoPtr request1 =
+ CreateRequest("example.com", 80, false);
+ resolver_service_ptr_->Resolve(request1.Pass(), client1_ptr.Pass());
+ interfaces::HostResolverRequestInfoPtr request2 =
+ CreateRequest("chromium.org", 80, false);
+ resolver_service_ptr_->Resolve(request2.Pass(), client2_ptr.Pass());
+ WaitForRequests(2);
+ mock_host_resolver_.ResolveAllPending();
+
+ client1.WaitForResult();
+ client2.WaitForResult();
+
+ EXPECT_EQ(net::OK, client1.error_);
+ AddressList address_list = (*client1.results_).To<AddressList>();
+ EXPECT_EQ(1U, address_list.size());
+ EXPECT_EQ("1.2.3.4:80", address_list[0].ToString());
+ EXPECT_EQ(net::OK, client2.error_);
+ address_list = (*client2.results_).To<AddressList>();
+ EXPECT_EQ(1U, address_list.size());
+ EXPECT_EQ("8.8.8.8:80", address_list[0].ToString());
+}
+
+TEST_F(MojoHostResolverImplTest, ResolveDuplicate) {
+ interfaces::HostResolverRequestClientPtr client1_ptr;
+ TestRequestClient client1(mojo::GetProxy(&client1_ptr));
+ interfaces::HostResolverRequestClientPtr client2_ptr;
+ TestRequestClient client2(mojo::GetProxy(&client2_ptr));
+
+ mock_host_resolver_.set_ondemand_mode(true);
+
+ interfaces::HostResolverRequestInfoPtr request1 =
+ CreateRequest("example.com", 80, false);
+ resolver_service_ptr_->Resolve(request1.Pass(), client1_ptr.Pass());
+ interfaces::HostResolverRequestInfoPtr request2 =
+ CreateRequest("example.com", 80, false);
+ resolver_service_ptr_->Resolve(request2.Pass(), client2_ptr.Pass());
+ WaitForRequests(2);
+ mock_host_resolver_.ResolveAllPending();
+
+ client1.WaitForResult();
+ client2.WaitForResult();
+
+ EXPECT_EQ(net::OK, client1.error_);
+ AddressList address_list = (*client1.results_).To<AddressList>();
+ EXPECT_EQ(1U, address_list.size());
+ EXPECT_EQ("1.2.3.4:80", address_list[0].ToString());
+ EXPECT_EQ(net::OK, client2.error_);
+ address_list = (*client2.results_).To<AddressList>();
+ EXPECT_EQ(1U, address_list.size());
+ EXPECT_EQ("1.2.3.4:80", address_list[0].ToString());
+}
+
+TEST_F(MojoHostResolverImplTest, ResolveFailure) {
+ interfaces::HostResolverRequestClientPtr client_ptr;
+ TestRequestClient client(mojo::GetProxy(&client_ptr));
+
+ interfaces::HostResolverRequestInfoPtr request =
+ CreateRequest("failure.fail", 80, false);
+ resolver_service_ptr_->Resolve(request.Pass(), client_ptr.Pass());
+ client.WaitForResult();
+
+ EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, client.error_);
+ EXPECT_TRUE(client.results_.is_null());
+}
+
+TEST_F(MojoHostResolverImplTest, DestroyClient) {
+ interfaces::HostResolverRequestClientPtr client_ptr;
+ scoped_ptr<TestRequestClient> client(
+ new TestRequestClient(mojo::GetProxy(&client_ptr)));
+
+ mock_host_resolver_.set_ondemand_mode(true);
+
+ interfaces::HostResolverRequestInfoPtr request =
+ CreateRequest("example.com", 80, false);
+ resolver_service_ptr_->Resolve(request.Pass(), client_ptr.Pass());
+ WaitForRequests(1);
+
+ client.reset();
+ base::RunLoop().RunUntilIdle();
+
+ mock_host_resolver_.ResolveAllPending();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(MojoHostResolverImplTest, DestroyService) {
+ interfaces::HostResolverRequestClientPtr client_ptr;
+ TestRequestClient client(mojo::GetProxy(&client_ptr));
+
+ mock_host_resolver_.set_ondemand_mode(true);
+
+ interfaces::HostResolverRequestInfoPtr request =
+ CreateRequest("example.com", 80, false);
+ resolver_service_ptr_->Resolve(request.Pass(), client_ptr.Pass());
+ WaitForRequests(1);
+
+ resolver_service_binding_.reset();
+ resolver_service_.reset();
+
+ client.WaitForConnectionError();
+}
+
+} // namespace net
diff --git a/net/dns/mojo_type_converters.cc b/net/dns/mojo_type_converters.cc
new file mode 100644
index 0000000..b9f11e7
--- /dev/null
+++ b/net/dns/mojo_type_converters.cc
@@ -0,0 +1,51 @@
+// 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 "net/dns/mojo_type_converters.h"
+
+#include "net/base/address_list.h"
+#include "net/base/net_util.h"
+#include "third_party/mojo/src/mojo/public/cpp/bindings/type_converter.h"
+
+namespace mojo {
+
+// static
+net::HostResolver::RequestInfo
+TypeConverter<net::HostResolver::RequestInfo,
+ net::interfaces::HostResolverRequestInfo>::
+ Convert(const net::interfaces::HostResolverRequestInfo& obj) {
+ net::HostResolver::RequestInfo result(net::HostPortPair(obj.host, obj.port));
+ result.set_address_family(
+ static_cast<net::AddressFamily>(obj.address_family));
+ return result;
+}
+
+// static
+net::interfaces::AddressListPtr
+TypeConverter<net::interfaces::AddressListPtr, net::AddressList>::Convert(
+ const net::AddressList& obj) {
+ net::interfaces::AddressListPtr result(net::interfaces::AddressList::New());
+ for (const auto& endpoint : obj) {
+ net::interfaces::IPEndPointPtr ep(net::interfaces::IPEndPoint::New());
+ ep->port = endpoint.port();
+ ep->address = mojo::Array<uint8_t>::From(endpoint.address());
+ result->addresses.push_back(ep.Pass());
+ }
+ return result.Pass();
+}
+
+// static
+net::AddressList
+TypeConverter<net::AddressList, net::interfaces::AddressList>::Convert(
+ const net::interfaces::AddressList& obj) {
+ net::AddressList address_list;
+ for (size_t i = 0; i < obj.addresses.size(); i++) {
+ const net::interfaces::IPEndPointPtr& ep = obj.addresses[i];
+ address_list.push_back(
+ net::IPEndPoint(ep->address.To<net::IPAddressNumber>(), ep->port));
+ }
+ return address_list;
+}
+
+} // namespace mojo
diff --git a/net/dns/mojo_type_converters.h b/net/dns/mojo_type_converters.h
new file mode 100644
index 0000000..0c99b8c
--- /dev/null
+++ b/net/dns/mojo_type_converters.h
@@ -0,0 +1,32 @@
+// 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 NET_DNS_MOJO_TYPE_CONVERTERS_H_
+#define NET_DNS_MOJO_TYPE_CONVERTERS_H_
+
+#include "net/dns/host_resolver.h"
+#include "net/interfaces/host_resolver_service.mojom.h"
+
+namespace mojo {
+
+template <>
+struct TypeConverter<net::HostResolver::RequestInfo,
+ net::interfaces::HostResolverRequestInfo> {
+ static net::HostResolver::RequestInfo Convert(
+ const net::interfaces::HostResolverRequestInfo& obj);
+};
+
+template <>
+struct TypeConverter<net::interfaces::AddressListPtr, net::AddressList> {
+ static net::interfaces::AddressListPtr Convert(const net::AddressList& obj);
+};
+
+template <>
+struct TypeConverter<net::AddressList, net::interfaces::AddressList> {
+ static net::AddressList Convert(const net::interfaces::AddressList& obj);
+};
+
+} // namespace mojo
+
+#endif // NET_DNS_MOJO_TYPE_CONVERTERS_H_
diff --git a/net/docs/bug-triage-suggested-workflow.txt b/net/docs/bug-triage-suggested-workflow.txt
index f605c43..d3e7141 100644
--- a/net/docs/bug-triage-suggested-workflow.txt
+++ b/net/docs/bug-triage-suggested-workflow.txt
@@ -77,11 +77,16 @@
Look for new crashers:
* Go to go/chromecrash.
-* For each platform, go to the latest canary. Click on browser -> limit 1000.
- Search the page for "net::". Ignore crashes that only occur once, as
+* For each platform, go to the latest canary.
+* In the "Process Type" frame, click on "browser".
+* At the bottom of the "Magic Signature" frame, click "limit 1000".
+ Reported crashers are sorted in decreasing order of the number of reports for
+ that crash signature.
+* Search the page for "net::". Ignore crashes that only occur once, as
memory corruption can easily cause one-off failures when the sample size is
large enough.
- * Look at the stack trace to confirm it's a network bug.
+* Click on the number of reports field to see details of crash. Look at the
+ stack trace to confirm it's a network bug.
* If it is, and there's no associated bug filed, file a new bug directly from
chromecrash, looking at earlier canaries to determine if it's a recent
regression. Use the most specific label possible.
diff --git a/net/docs/bug-triage.txt b/net/docs/bug-triage.txt
index e2d7380..7139a98 100644
--- a/net/docs/bug-triage.txt
+++ b/net/docs/bug-triage.txt
@@ -23,7 +23,7 @@
and, for suspected network bugs, a network label assigned. A triager is
responsible for looking at bugs reported from noon PST / 3:00 pm EST of the
last day of the previous triager's rotation until the same time on the last
- day of his rotation.
+ day of their rotation.
* Request data about recent unassigned Cr-Internals-Network bugs from reporters.
"Recent" means issues updated in the past week or so.
* Investigate each recent (New comment within the past week or so)
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc
index 6a5ee17..3951b2e 100644
--- a/net/http/disk_cache_based_quic_server_info.cc
+++ b/net/http/disk_cache_based_quic_server_info.cc
@@ -101,6 +101,11 @@
return ERR_IO_PENDING;
}
+void DiskCacheBasedQuicServerInfo::ResetWaitForDataReadyCallback() {
+ DCHECK(CalledOnValidThread());
+ wait_for_ready_callback_.Reset();
+}
+
void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() {
DCHECK(CalledOnValidThread());
diff --git a/net/http/disk_cache_based_quic_server_info.h b/net/http/disk_cache_based_quic_server_info.h
index e95d535..3076f3a 100644
--- a/net/http/disk_cache_based_quic_server_info.h
+++ b/net/http/disk_cache_based_quic_server_info.h
@@ -34,6 +34,7 @@
// QuicServerInfo implementation.
void Start() override;
int WaitForDataReady(const CompletionCallback& callback) override;
+ void ResetWaitForDataReadyCallback() override;
void CancelWaitForDataReadyCallback() override;
bool IsDataReady() override;
bool IsReadyToPersist() override;
diff --git a/net/http/disk_cache_based_quic_server_info_unittest.cc b/net/http/disk_cache_based_quic_server_info_unittest.cc
index ef69b43..991881a 100644
--- a/net/http/disk_cache_based_quic_server_info_unittest.cc
+++ b/net/http/disk_cache_based_quic_server_info_unittest.cc
@@ -418,6 +418,28 @@
RemoveMockTransaction(&kHostInfoTransaction1);
}
+TEST(DiskCacheBasedQuicServerInfo, CancelWaitForDataReadyAfterDeleteCache) {
+ scoped_ptr<QuicServerInfo> quic_server_info;
+ {
+ MockHttpCache cache;
+ AddMockTransaction(&kHostInfoTransaction1);
+ TestCompletionCallback callback;
+
+ QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
+ quic_server_info.reset(
+ new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
+ EXPECT_FALSE(quic_server_info->IsDataReady());
+ quic_server_info->Start();
+ int rv = quic_server_info->WaitForDataReady(callback.callback());
+ quic_server_info->CancelWaitForDataReadyCallback();
+ EXPECT_EQ(OK, callback.GetResult(rv));
+ EXPECT_TRUE(quic_server_info->IsDataReady());
+ RemoveMockTransaction(&kHostInfoTransaction1);
+ }
+ // Cancel the callback after Cache is deleted.
+ quic_server_info->ResetWaitForDataReadyCallback();
+}
+
// Test Start() followed by Persist() without calling WaitForDataReady.
TEST(DiskCacheBasedQuicServerInfo, StartAndPersist) {
MockHttpCache cache;
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 0ca5683..18ee59b 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -2885,7 +2885,6 @@
void HttpCache::Transaction::FixHeadersForHead() {
if (response_.headers->response_code() == 206) {
- response_.headers->RemoveHeader("Content-Length");
response_.headers->RemoveHeader("Content-Range");
response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK");
}
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h
index 8e2a62f..f230f42 100644
--- a/net/http/http_cache_transaction.h
+++ b/net/http/http_cache_transaction.h
@@ -335,7 +335,7 @@
// Handles a response validation error by bypassing the cache.
void IgnoreRangeRequest();
- // Removes content-length and byte range related info if needed.
+ // Fixes the response headers to match expectations for a HEAD request.
void FixHeadersForHead();
// Launches an asynchronous revalidation based on this transaction.
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 3458402..66349b6 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -3169,7 +3169,7 @@
RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
EXPECT_NE(std::string::npos, headers.find("HTTP/1.1 200 OK\n"));
- EXPECT_EQ(std::string::npos, headers.find("Content-Length"));
+ EXPECT_NE(std::string::npos, headers.find("Content-Length: 80\n"));
EXPECT_EQ(std::string::npos, headers.find("Content-Range"));
EXPECT_EQ(1, cache.network_layer()->transaction_count());
EXPECT_EQ(1, cache.disk_cache()->open_count());
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 3908d74..ff87956 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/debug/stack_trace.h"
#include "base/logging.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/values.h"
@@ -35,6 +36,10 @@
net::ClientSocketPoolManager* CreateSocketPoolManager(
net::HttpNetworkSession::SocketPoolType pool_type,
const net::HttpNetworkSession::Params& params) {
+ // TODO(michaeln): Remove ScopedTracker below once crbug.com/454983 is fixed
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "454983 CreateSocketPoolManager"));
// TODO(yutak): Differentiate WebSocket pool manager and allow more
// simultaneous connections for WebSockets.
return new net::ClientSocketPoolManagerImpl(
@@ -91,6 +96,7 @@
quic_load_server_info_timeout_ms(0),
quic_load_server_info_timeout_srtt_multiplier(0.0f),
quic_enable_truncated_connection_ids(false),
+ quic_enable_connection_racing(false),
quic_clock(NULL),
quic_random(NULL),
quic_max_packet_length(kDefaultMaxPacketSize),
@@ -136,6 +142,7 @@
params.quic_load_server_info_timeout_ms,
params.quic_load_server_info_timeout_srtt_multiplier,
params.quic_enable_truncated_connection_ids,
+ params.quic_enable_connection_racing,
params.quic_connection_options),
spdy_session_pool_(params.host_resolver,
params.ssl_config_service,
@@ -156,6 +163,10 @@
DCHECK(proxy_service_);
DCHECK(ssl_config_service_.get());
CHECK(http_server_properties_);
+ // TODO(michaeln): Remove ScopedTracker below once crbug.com/454983 is fixed
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "454983 HttpNetworkSession::HttpNetworkSession"));
for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION;
i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) {
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 68b10db..3216c6c 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -119,6 +119,7 @@
int quic_load_server_info_timeout_ms;
float quic_load_server_info_timeout_srtt_multiplier;
bool quic_enable_truncated_connection_ids;
+ bool quic_enable_connection_racing;
HostPortPair origin_to_force_quic_on;
QuicClock* quic_clock; // Will be owned by QuicStreamFactory.
QuicRandom* quic_random;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 69a3aa5..e16d7c6 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -14,7 +14,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "base/metrics/stats_counters.h"
#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -163,8 +162,6 @@
int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
const CompletionCallback& callback,
const BoundNetLog& net_log) {
- SIMPLE_STATS_COUNTER("HttpNetworkTransaction.Count");
-
net_log_ = net_log;
request_ = request_info;
@@ -180,6 +177,12 @@
if (request_->privacy_mode == PRIVACY_MODE_ENABLED)
server_ssl_config_.channel_id_enabled = false;
+ if (server_ssl_config_.fastradio_padding_enabled) {
+ server_ssl_config_.fastradio_padding_eligible =
+ session_->ssl_config_service()->SupportsFastradioPadding(
+ request_info->url);
+ }
+
next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM;
int rv = DoLoop(OK);
if (rv == ERR_IO_PENDING)
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h
index a0a6897..418f09a 100644
--- a/net/http/transport_security_state_static.h
+++ b/net/http/transport_security_state_static.h
@@ -677,1299 +677,1355 @@
// value has the MSB set then it represents a literal leaf value. Otherwise
// it's a pointer to the n'th element of the array.
static const uint8 kHSTSHuffmanTree[] = {
- 0xec, 0xf2, 0x00, 0x80, 0xed, 0xae, 0xe9, 0x02, 0xb1, 0xb5, 0xf1, 0x04,
- 0xb3, 0xb2, 0x05, 0x06, 0x07, 0xfa, 0xf6, 0x08, 0xeb, 0x09, 0x0a, 0xe3,
- 0xe1, 0x0b, 0x03, 0x0c, 0x01, 0x0d, 0xe5, 0xef, 0xff, 0x0f, 0xe2, 0xe8,
- 0x11, 0xf3, 0xb9, 0xb7, 0xb6, 0x13, 0xb8, 0x14, 0x15, 0xb0, 0xb4, 0x16,
- 0x17, 0xea, 0xf8, 0x18, 0xad, 0x19, 0xf7, 0x1a, 0x1b, 0xee, 0x12, 0x1c,
- 0xe4, 0xf5, 0xf4, 0x1e, 0xf9, 0xe6, 0xf0, 0x20, 0xe7, 0x21, 0x1f, 0x22,
- 0x1d, 0x23, 0x10, 0x24, 0x0e, 0x25,
+ 0xf9, 0xe6, 0xf0, 0x00, 0xf2, 0x01, 0xae, 0xed, 0xe9, 0x03, 0x02, 0x04,
+ 0xb0, 0xb2, 0xb1, 0xb5, 0xb3, 0x07, 0x06, 0x08, 0x09, 0xfa, 0x0a, 0xf6,
+ 0xeb, 0x0b, 0x0c, 0xe3, 0xe1, 0x0d, 0x80, 0x0e, 0x05, 0x0f, 0xe2, 0xf7,
+ 0x11, 0xf3, 0xef, 0x12, 0xff, 0x13, 0xee, 0xf4, 0xe5, 0x15, 0xe8, 0xf5,
+ 0x17, 0xe7, 0xb7, 0xb6, 0xb9, 0xb8, 0x19, 0x1a, 0x1b, 0xf1, 0xb4, 0x1c,
+ 0x1d, 0xea, 0xf8, 0x1e, 0xad, 0x1f, 0x20, 0xe4, 0x21, 0xec, 0x18, 0x22,
+ 0x16, 0x23, 0x14, 0x24, 0x10, 0x25,
};
static const uint8 kPreloadedHSTSData[] = {
- 0xfe, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0x89, 0x67, 0xc1, 0xeb, 0xbf, 0x1a,
- 0x22, 0xd9, 0xab, 0x12, 0xa4, 0xc5, 0x4b, 0xe0, 0x34, 0xbf, 0x0b, 0x4f,
- 0xee, 0x50, 0x7c, 0xa4, 0xc9, 0x4b, 0x35, 0x13, 0xf3, 0xf6, 0x8e, 0xa9,
- 0xc3, 0xa1, 0x8f, 0xc6, 0xd0, 0xa7, 0xf8, 0x5b, 0x69, 0xe6, 0x52, 0x1d,
- 0x25, 0xd2, 0x68, 0xba, 0xd0, 0xf0, 0xfc, 0x41, 0x3f, 0x97, 0x41, 0xeb,
- 0xbf, 0x1a, 0x2a, 0x29, 0xff, 0xed, 0xa6, 0xd7, 0xfe, 0xab, 0x0e, 0x9a,
- 0xba, 0x3a, 0x7c, 0x1e, 0xbb, 0xf1, 0xa2, 0xbd, 0x9f, 0x23, 0xbf, 0xbb,
- 0xc0, 0xe9, 0x2e, 0x8f, 0x78, 0x0c, 0xa7, 0xfe, 0x5d, 0xbd, 0x74, 0x1e,
- 0xbb, 0xf1, 0xa2, 0x46, 0x9f, 0xfc, 0xb5, 0x5b, 0xd7, 0x41, 0xeb, 0xbf,
- 0x1a, 0x27, 0x89, 0xff, 0xcb, 0x55, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2,
- 0x7f, 0x9f, 0xfc, 0xb5, 0x5b, 0xd7, 0x41, 0xeb, 0xbf, 0x1a, 0x28, 0x69,
- 0xff, 0xcb, 0x55, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x88, 0x9f, 0xf5,
- 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x91, 0x9f, 0xff, 0xab, 0xad, 0xb7,
- 0xe5, 0xf0, 0x6f, 0xec, 0xe5, 0xbe, 0x2a, 0x4b, 0x52, 0x29, 0xb5, 0x92,
- 0x27, 0xfe, 0x5d, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x50, 0x8c, 0x17,
- 0x64, 0xdf, 0x1c, 0x17, 0x90, 0x35, 0xe7, 0xa1, 0x0b, 0x05, 0x13, 0x6d,
- 0x3b, 0xe5, 0x47, 0x61, 0x53, 0x2a, 0x9d, 0xc3, 0xe9, 0xdc, 0xb2, 0x7f,
- 0xf2, 0xd5, 0x6f, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0x9c, 0xe7, 0xff, 0x2d,
- 0x56, 0xf5, 0xd0, 0x7a, 0xef, 0xc6, 0x8a, 0x26, 0x7f, 0xe0, 0x7a, 0xf6,
- 0x99, 0x71, 0xe9, 0xf1, 0xd0, 0x08, 0xed, 0xca, 0xa7, 0x6a, 0x93, 0xf9,
- 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x1c, 0x9f, 0xe6, 0x0a, 0xf6, 0xdb, 0x17,
- 0x9d, 0x3e, 0x0f, 0x5d, 0xf8, 0xd1, 0x17, 0xcf, 0xec, 0xd7, 0x5b, 0xaf,
- 0xac, 0xe9, 0xb3, 0x89, 0xd3, 0xdc, 0x7b, 0x7f, 0x2a, 0x14, 0x6e, 0xac,
- 0x5e, 0x4b, 0xc1, 0x1e, 0xd4, 0x6e, 0xe1, 0x90, 0xb6, 0xcf, 0xfe, 0x5a,
- 0xad, 0xeb, 0xa0, 0xf5, 0xdf, 0x8d, 0x13, 0x24, 0xfe, 0x5d, 0x07, 0xae,
- 0xfc, 0x68, 0xb7, 0xa7, 0xff, 0x2d, 0x56, 0xf5, 0xd0, 0x7a, 0xef, 0xc6,
- 0x8a, 0x4e, 0x7d, 0xb5, 0xbb, 0x7a, 0xed, 0xda, 0x3a, 0x19, 0x54, 0x9b,
- 0xe3, 0x33, 0xa4, 0x3c, 0xaa, 0x3a, 0x3d, 0xfc, 0xa9, 0x3f, 0x97, 0x41,
- 0xeb, 0xbf, 0x1a, 0x21, 0xd9, 0xff, 0xcb, 0x55, 0xbd, 0x74, 0x1e, 0xbb,
- 0xf1, 0xa2, 0x58, 0x9f, 0xcb, 0xa0, 0xf5, 0xdf, 0x8d, 0x11, 0x84, 0xf8,
- 0x3d, 0x77, 0xe3, 0x44, 0x7b, 0x3d, 0x9b, 0xc5, 0xd1, 0xd3, 0xcb, 0xb7,
- 0xae, 0x8f, 0x5b, 0x86, 0x53, 0xf9, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0xc3,
- 0x9f, 0xcb, 0xa0, 0xf5, 0xdf, 0x8d, 0x17, 0x3c, 0x32, 0x7a, 0xd8, 0x1e,
- 0xbd, 0x51, 0x21, 0x26, 0xa3, 0x8e, 0x1e, 0xcf, 0xe5, 0xd0, 0x7a, 0xef,
- 0xc6, 0x88, 0x7a, 0x7c, 0x1e, 0xbb, 0xf1, 0xa2, 0x26, 0x9f, 0xfd, 0x5c,
- 0xbd, 0xed, 0x9d, 0x3e, 0x81, 0x8e, 0x9b, 0x8a, 0x3a, 0x7f, 0xf5, 0x6f,
- 0xf6, 0x19, 0x64, 0xc7, 0x8c, 0xa3, 0xa3, 0x13, 0xe2, 0xd8, 0xb4, 0xf7,
- 0x3b, 0xbf, 0xc6, 0x88, 0x5e, 0x4b, 0xa4, 0xcc, 0x36, 0x65, 0x98, 0x55,
- 0x76, 0x47, 0x38, 0x2f, 0xc7, 0x4b, 0x67, 0x47, 0xf3, 0x55, 0xd8, 0xd4,
- 0xf7, 0x36, 0x9c, 0x3a, 0x7f, 0xff, 0xed, 0xf7, 0xd2, 0x50, 0x38, 0x34,
- 0xeb, 0x75, 0xd3, 0x67, 0x2d, 0xfc, 0xe9, 0xff, 0xc8, 0xe3, 0xeb, 0x17,
- 0xea, 0x55, 0xd8, 0x9d, 0x35, 0xbb, 0x9d, 0x14, 0x8f, 0xaf, 0x10, 0xed,
- 0xda, 0xd2, 0xe7, 0x05, 0xf8, 0xe8, 0x76, 0xcf, 0x57, 0xf9, 0xdc, 0xfb,
- 0x77, 0xcb, 0x79, 0xd3, 0xf9, 0xf9, 0x6c, 0xeb, 0xaf, 0xae, 0xf5, 0xd9,
- 0xd3, 0xc9, 0x94, 0xf8, 0xe9, 0xda, 0x69, 0xa1, 0x53, 0xeb, 0x1e, 0x6e,
- 0x8a, 0x59, 0x7f, 0x3e, 0xbe, 0x39, 0x5c, 0x3a, 0x3a, 0x44, 0xdf, 0xc8,
- 0x02, 0x69, 0x3d, 0xbb, 0xbb, 0x3a, 0x7f, 0xef, 0x91, 0xcd, 0x5b, 0x64,
- 0x0e, 0xf5, 0xe7, 0x4f, 0xf9, 0x3f, 0xb0, 0xb6, 0x59, 0x14, 0x74, 0xfd,
- 0x4e, 0xbb, 0x7d, 0x64, 0xe9, 0xea, 0xea, 0xb0, 0x3a, 0x29, 0x51, 0x8e,
- 0x24, 0xc9, 0x0e, 0x3d, 0x79, 0x8b, 0x83, 0xfb, 0x4b, 0x13, 0xce, 0x17,
- 0xcf, 0xd5, 0xa3, 0x57, 0x48, 0x74, 0xe6, 0xef, 0xe3, 0xa7, 0xff, 0xff,
- 0x08, 0xe2, 0xdf, 0xc6, 0xba, 0xda, 0x39, 0xab, 0x35, 0x8b, 0xc2, 0xb4,
- 0x3a, 0x7c, 0x9c, 0xed, 0xb0, 0x3a, 0x7f, 0xff, 0x56, 0x2f, 0xca, 0xa8,
- 0x75, 0x3b, 0xa6, 0xf0, 0x4a, 0x03, 0xa7, 0xff, 0xfd, 0xa6, 0xa1, 0xaf,
- 0x6d, 0x06, 0xbb, 0xc7, 0x9a, 0xaf, 0x4a, 0xfe, 0x74, 0xfe, 0xc5, 0xf9,
- 0xff, 0xdb, 0x62, 0x74, 0xfe, 0xbd, 0x3b, 0x71, 0xb9, 0x67, 0x43, 0x23,
- 0x7d, 0x1c, 0xc4, 0xe2, 0x7b, 0xee, 0x26, 0x07, 0x4f, 0xf9, 0xaf, 0x06,
- 0x50, 0xb6, 0x3f, 0x1d, 0x0c, 0xa9, 0xd6, 0x9f, 0x10, 0xa0, 0x23, 0x43,
- 0xb2, 0xd1, 0x23, 0x9b, 0xb7, 0x9d, 0x3e, 0x6f, 0xb3, 0x87, 0x0e, 0x9d,
- 0x7c, 0xc9, 0xd3, 0x77, 0x81, 0xd3, 0x87, 0x8e, 0x3c, 0xd9, 0x80, 0xdc,
- 0xfd, 0xdf, 0xb5, 0x75, 0x8e, 0x87, 0x43, 0x1f, 0x32, 0x19, 0x4f, 0xff,
- 0xbb, 0x6e, 0x6a, 0x1e, 0xdd, 0xf5, 0x57, 0x35, 0xab, 0x87, 0x4f, 0xfd,
- 0xb6, 0xff, 0xab, 0x83, 0x7c, 0x6e, 0x1d, 0x3f, 0xb5, 0x62, 0xf4, 0xdf,
- 0x6a, 0x3a, 0x3e, 0x3f, 0xd1, 0x46, 0x9f, 0xf0, 0x39, 0xab, 0x2c, 0x98,
- 0x5f, 0x0e, 0x86, 0x3e, 0x2e, 0xc8, 0xa7, 0xff, 0xff, 0xbb, 0x1c, 0x80,
- 0xb3, 0x9a, 0xbf, 0x71, 0x1f, 0x58, 0xf2, 0x9d, 0x0d, 0x64, 0xe9, 0x31,
- 0xd3, 0xf5, 0x82, 0x65, 0xb1, 0x3a, 0x7f, 0xd7, 0xa0, 0x30, 0xf3, 0x74,
- 0xee, 0x74, 0x3c, 0xfa, 0x80, 0xae, 0x7f, 0xb6, 0x80, 0xe6, 0xee, 0x80,
- 0xe9, 0xff, 0xff, 0xfb, 0xec, 0x8d, 0x5e, 0x3a, 0xba, 0xdf, 0x7a, 0x86,
- 0xb1, 0x7d, 0x77, 0x80, 0xd5, 0xe2, 0x74, 0x79, 0x18, 0xe8, 0x6d, 0x3a,
- 0xef, 0xc6, 0x8a, 0x62, 0x28, 0xf2, 0x7c, 0x45, 0x3f, 0xea, 0x1c, 0x5f,
- 0x9e, 0x30, 0x38, 0x74, 0xea, 0x4f, 0x8e, 0x95, 0x1d, 0x3b, 0x11, 0xaf,
- 0x8d, 0x53, 0xa1, 0xb8, 0x44, 0x4e, 0xdb, 0x44, 0xe7, 0xb6, 0x27, 0x4f,
- 0xe5, 0x75, 0xb6, 0xc2, 0xb4, 0x3a, 0x31, 0x3d, 0x1b, 0x1c, 0x9f, 0xff,
- 0xc3, 0x5e, 0xe7, 0x1b, 0x99, 0x70, 0x6b, 0x4d, 0x4c, 0xec, 0x8e, 0x9f,
- 0xf7, 0x99, 0x5b, 0xac, 0xd2, 0x09, 0xd0, 0xc8, 0xa3, 0xdb, 0x44, 0xf8,
- 0x19, 0xd3, 0x01, 0xd3, 0xf5, 0x8e, 0xae, 0x98, 0x4e, 0x8a, 0x3f, 0x54,
- 0x22, 0xec, 0x9a, 0x30, 0x5f, 0x1e, 0x78, 0xbf, 0x50, 0xc2, 0xfe, 0x41,
- 0xe8, 0xcf, 0xf1, 0x22, 0x48, 0x41, 0x38, 0xf2, 0x11, 0x98, 0xaa, 0x17,
- 0xc2, 0xe5, 0xc8, 0xce, 0xa7, 0xfd, 0xfc, 0x2f, 0x4d, 0x57, 0xd5, 0xe0,
- 0x74, 0xf5, 0x0f, 0xfd, 0x79, 0xd3, 0xff, 0xff, 0xed, 0xa7, 0x37, 0x40,
- 0xce, 0xb5, 0x2b, 0xb7, 0x7d, 0x55, 0x8b, 0xeb, 0xb1, 0xfb, 0x27, 0x4b,
- 0x88, 0x8b, 0x4c, 0x93, 0x4f, 0xff, 0xaa, 0xb6, 0x9e, 0xdd, 0x6a, 0xcf,
- 0x7b, 0x6d, 0x79, 0xd3, 0xff, 0xdc, 0xdd, 0x7d, 0xa9, 0x4d, 0x5c, 0xea,
- 0x84, 0xe9, 0xfe, 0xc7, 0x52, 0x9a, 0x87, 0x9a, 0xc7, 0x4b, 0x34, 0x88,
- 0xeb, 0x51, 0x92, 0x0a, 0x61, 0xfc, 0x87, 0x44, 0xf9, 0xed, 0x8b, 0xf2,
- 0x74, 0xff, 0xff, 0xff, 0xa8, 0x7f, 0xea, 0x4d, 0xf6, 0xb7, 0x13, 0x8c,
- 0xa1, 0xbf, 0xfb, 0x45, 0xd6, 0xf1, 0xf9, 0xba, 0x2a, 0x7f, 0xff, 0xef,
- 0x26, 0x9d, 0x76, 0x1a, 0xbb, 0x6c, 0x33, 0xed, 0xf7, 0xbc, 0x6f, 0x43,
- 0xa6, 0xef, 0x0c, 0x53, 0x45, 0x42, 0x8c, 0xc2, 0x86, 0x19, 0x57, 0x6e,
- 0xe3, 0x37, 0x18, 0xdc, 0xa7, 0xff, 0x2b, 0xda, 0xb7, 0x6f, 0xa5, 0x58,
- 0xfc, 0x74, 0xff, 0xf9, 0x07, 0x9b, 0xa7, 0x7e, 0x39, 0x5a, 0xfb, 0x1f,
- 0x8e, 0x9f, 0xf9, 0x87, 0x01, 0xa7, 0x59, 0xed, 0xb1, 0x3a, 0x32, 0x8a,
- 0x1e, 0xd6, 0xe7, 0xab, 0x94, 0xec, 0x1d, 0x3b, 0x5a, 0xb6, 0x74, 0xd5,
- 0xd1, 0xd1, 0x82, 0x6d, 0x2f, 0x87, 0x66, 0x49, 0x38, 0x4a, 0xe8, 0x7a,
- 0x7c, 0x9c, 0xcd, 0x7c, 0x74, 0xfd, 0xd3, 0x0e, 0xed, 0xe7, 0x4e, 0x6e,
- 0x98, 0xe9, 0xf9, 0xf5, 0xcc, 0xdb, 0x9a, 0x8f, 0x1d, 0x45, 0x90, 0xf4,
- 0x5a, 0xb8, 0xdd, 0x3f, 0x3b, 0xee, 0xf5, 0xed, 0xf1, 0xd3, 0xf8, 0x1c,
- 0x1a, 0xdd, 0xf0, 0xe8, 0xa3, 0xe5, 0x43, 0x49, 0xf9, 0xbe, 0xae, 0x7e,
- 0xc0, 0xe8, 0x79, 0xe8, 0x09, 0x04, 0xff, 0x73, 0x74, 0xfb, 0x1a, 0xc4,
- 0xe9, 0xff, 0xfe, 0x1b, 0xfb, 0x38, 0x52, 0x0f, 0x06, 0x9d, 0x6a, 0xce,
- 0x82, 0x74, 0x0a, 0x28, 0x38, 0x6f, 0x3f, 0xe4, 0xa7, 0x35, 0x65, 0xb7,
- 0x7a, 0xf3, 0xa7, 0xf5, 0xe3, 0x9d, 0xd5, 0x81, 0xd1, 0xd1, 0xfa, 0x71,
- 0x0e, 0x7f, 0xa8, 0x30, 0x64, 0x0a, 0x13, 0xa4, 0xa3, 0xb5, 0x1b, 0x49,
- 0xc3, 0x5d, 0x1d, 0x0c, 0x6f, 0x71, 0x22, 0x9f, 0xb1, 0xcd, 0x50, 0xff,
- 0x3a, 0x79, 0x5f, 0x9b, 0xe3, 0xa2, 0x8f, 0x49, 0x0b, 0xa7, 0x77, 0x8f,
- 0xc7, 0x43, 0x27, 0xb9, 0x50, 0x96, 0x48, 0x4a, 0x03, 0x98, 0x90, 0x4f,
- 0xee, 0x26, 0x15, 0xbe, 0xf8, 0x74, 0x9c, 0x3a, 0x7e, 0xae, 0xeb, 0x7e,
- 0xc0, 0xe9, 0xab, 0x16, 0x37, 0xf9, 0x11, 0x9f, 0xb7, 0x6f, 0x50, 0x21,
- 0xd3, 0xe4, 0xf8, 0x2b, 0x13, 0xa3, 0xfa, 0x3c, 0x51, 0xcf, 0xe2, 0xce,
- 0xca, 0xe7, 0xff, 0xe0, 0x7e, 0xe9, 0xcd, 0xb0, 0xff, 0x1a, 0xe6, 0xfb,
- 0x3a, 0x7f, 0xff, 0x25, 0x62, 0xfc, 0xf3, 0x6c, 0xa6, 0x4e, 0xb5, 0x33,
- 0xb2, 0x3a, 0x7f, 0xff, 0xfd, 0xd8, 0xea, 0xd2, 0xf1, 0x78, 0x5f, 0xda,
- 0xb3, 0xdb, 0x63, 0xba, 0x41, 0xaf, 0xe7, 0x4f, 0xff, 0xbb, 0x00, 0xae,
- 0x67, 0x69, 0x5a, 0xb7, 0xf3, 0x1d, 0x14, 0x8e, 0x1d, 0xc2, 0x2e, 0x7f,
- 0xf9, 0xee, 0xfb, 0xa6, 0x17, 0x06, 0xb9, 0x9b, 0x3a, 0x7f, 0xfd, 0xd5,
- 0x2b, 0x53, 0xbf, 0x1b, 0x2e, 0x3e, 0xc3, 0x03, 0xa7, 0xff, 0xee, 0x26,
- 0x15, 0xd6, 0xa5, 0x5b, 0xc1, 0x30, 0xb5, 0x1d, 0x3f, 0xb0, 0xb5, 0x0b,
- 0x03, 0x87, 0x4f, 0xf6, 0x35, 0xff, 0xe5, 0x56, 0xa0, 0xa4, 0x47, 0xa2,
- 0xec, 0xff, 0x50, 0xe1, 0xab, 0xeb, 0xb7, 0x0e, 0x9f, 0xe0, 0xc1, 0xb0,
- 0xc3, 0xb0, 0xc0, 0xe9, 0xfe, 0xec, 0x75, 0x67, 0xbd, 0x6e, 0xc0, 0xe8,
- 0x63, 0xfc, 0xc9, 0xe4, 0xff, 0xec, 0x35, 0x67, 0x7d, 0xea, 0xe6, 0x72,
- 0xc0, 0x74, 0xff, 0xff, 0xab, 0x1c, 0xa5, 0x69, 0xab, 0x75, 0xcc, 0xd6,
- 0x1a, 0xa9, 0x3a, 0x3a, 0x29, 0x18, 0x28, 0xa1, 0x18, 0x2e, 0x5c, 0xfa,
- 0x34, 0x9c, 0x49, 0xd1, 0x40, 0x21, 0xd6, 0xa5, 0x4c, 0xc2, 0xdf, 0x90,
- 0xe2, 0x9f, 0xf5, 0x86, 0xeb, 0x8c, 0x29, 0xf1, 0xd3, 0xfd, 0x5a, 0x62,
- 0xfc, 0xea, 0xe2, 0x1d, 0x3f, 0xff, 0xe6, 0xf3, 0x2b, 0x53, 0x9b, 0x41,
- 0xeb, 0x57, 0xef, 0x0d, 0x6e, 0x8e, 0x8f, 0x23, 0xa0, 0x4e, 0xdd, 0xcf,
- 0x27, 0x93, 0x88, 0xc7, 0x4f, 0xff, 0xfe, 0x14, 0xff, 0xbb, 0x73, 0x50,
- 0xf6, 0xef, 0xaa, 0xb1, 0x7d, 0x76, 0x3f, 0x64, 0xe9, 0xf6, 0xd1, 0x87,
- 0x03, 0xa6, 0xe3, 0x29, 0x15, 0x2e, 0xa1, 0x07, 0x0f, 0x47, 0xea, 0x43,
- 0x22, 0x19, 0x7f, 0x72, 0xa7, 0x45, 0x52, 0x37, 0x1b, 0x8c, 0xbe, 0x7c,
- 0xc3, 0xc4, 0x74, 0x74, 0xf7, 0x33, 0x7f, 0x1d, 0x3f, 0xf6, 0xd3, 0x52,
- 0x07, 0x78, 0x58, 0x78, 0xe9, 0xe4, 0xdd, 0xe0, 0x74, 0xf3, 0xa6, 0xe3,
- 0x1d, 0x3f, 0x6e, 0xf0, 0xd4, 0xfe, 0x1d, 0x3e, 0xb0, 0x1c, 0x50, 0xe8,
- 0x43, 0xd5, 0xe1, 0x84, 0x74, 0x9a, 0x3d, 0x13, 0xff, 0x22, 0xf2, 0x2a,
- 0x10, 0xf1, 0xde, 0x7b, 0xf7, 0x77, 0x93, 0xa7, 0xff, 0xe4, 0x0d, 0x54,
- 0x94, 0x3f, 0xf6, 0x94, 0xaa, 0xf1, 0xd3, 0xff, 0xfc, 0x98, 0x03, 0x2b,
- 0x3d, 0xb6, 0xa6, 0x06, 0xeb, 0x6c, 0xa3, 0xa2, 0x91, 0x80, 0x0b, 0x33,
- 0xff, 0xff, 0x80, 0x13, 0x0d, 0x5b, 0xae, 0x0b, 0x39, 0xba, 0xc1, 0xb1,
- 0xe7, 0x7e, 0x3a, 0x7f, 0xff, 0xe6, 0xff, 0xb6, 0xd4, 0x35, 0xdf, 0xfd,
- 0x58, 0xbf, 0x28, 0x3f, 0x9b, 0x03, 0xa7, 0xd8, 0xe5, 0x28, 0x4e, 0x8a,
- 0x45, 0x17, 0x6f, 0x90, 0x89, 0xa0, 0x6e, 0x31, 0xd9, 0xff, 0x9f, 0x94,
- 0xff, 0xb6, 0x4c, 0x1b, 0xf9, 0xd3, 0xfc, 0x3d, 0xb8, 0x35, 0xbb, 0xe1,
- 0xd3, 0xfd, 0xd6, 0xdb, 0x4e, 0xb7, 0x6a, 0x3a, 0x7f, 0xff, 0xac, 0x37,
- 0x5c, 0x4a, 0x1c, 0x32, 0xd4, 0x3d, 0x6d, 0x8e, 0x9e, 0xe6, 0xac, 0x00,
- 0xe8, 0xc5, 0x10, 0xd6, 0xc5, 0x3f, 0xfb, 0x4b, 0x1c, 0x15, 0xda, 0x74,
- 0x82, 0x87, 0x4f, 0xce, 0x62, 0xfe, 0xdb, 0x87, 0x4f, 0xf6, 0xed, 0x43,
- 0x5b, 0xbe, 0x1d, 0x3d, 0x41, 0xf6, 0x87, 0x43, 0x22, 0x23, 0x26, 0x1c,
- 0x36, 0x9f, 0xab, 0x80, 0x14, 0xf3, 0xa7, 0xe1, 0xad, 0x8d, 0x78, 0xe9,
- 0xe1, 0xac, 0xea, 0x70, 0xf5, 0x38, 0x55, 0x1d, 0x2e, 0x3e, 0xfa, 0x36,
- 0x1c, 0x4a, 0x51, 0x1c, 0x0e, 0x37, 0x0c, 0x1c, 0x91, 0xf2, 0x1a, 0x4e,
- 0xa1, 0x07, 0x3f, 0xf0, 0x8d, 0x6a, 0x0a, 0xd8, 0xd3, 0x87, 0x43, 0x2f,
- 0x1d, 0xd4, 0xeb, 0x0d, 0xc2, 0x62, 0x7c, 0x2c, 0xab, 0xe8, 0xe9, 0xfd,
- 0x4e, 0x6e, 0xb8, 0xdd, 0x1d, 0x3f, 0xff, 0xfd, 0xba, 0xe6, 0x6d, 0xcd,
- 0x43, 0x58, 0xbe, 0xbb, 0xc0, 0x6b, 0xad, 0xa3, 0x87, 0x4d, 0xdf, 0xf3,
- 0xa0, 0x11, 0x37, 0xc8, 0x41, 0x4f, 0xd5, 0x80, 0xd6, 0x39, 0x3a, 0x7f,
- 0xf0, 0x62, 0xfc, 0xd2, 0xb1, 0x6d, 0xed, 0x8e, 0x96, 0x4e, 0x8e, 0xcf,
- 0x6b, 0xf2, 0x54, 0xfe, 0x65, 0x0d, 0x6e, 0xf8, 0x74, 0xf6, 0xaf, 0x61,
- 0xa1, 0xd3, 0xff, 0xfe, 0xe0, 0xb7, 0xd8, 0xbf, 0x3d, 0xb7, 0x06, 0xba,
- 0x4a, 0x07, 0x0e, 0x84, 0x55, 0x14, 0xe1, 0x35, 0xc3, 0x38, 0x49, 0xf3,
- 0x08, 0x7e, 0xc9, 0x5d, 0x18, 0x7e, 0x26, 0x9f, 0x3d, 0x02, 0xb1, 0x3a,
- 0x7d, 0x59, 0xc2, 0xb4, 0x3a, 0x31, 0x3c, 0xed, 0x93, 0x4f, 0xff, 0x93,
- 0x0a, 0xf7, 0x5b, 0x4a, 0xff, 0xab, 0xff, 0x6c, 0x74, 0xf3, 0xbf, 0x2b,
- 0x67, 0x4c, 0x8a, 0x3a, 0x7f, 0xff, 0xd8, 0xbe, 0xf1, 0xd4, 0x3d, 0xbb,
- 0xea, 0xac, 0x5f, 0x5d, 0x8f, 0xd9, 0x3a, 0x14, 0x88, 0xd7, 0x71, 0x58,
- 0xc1, 0x1a, 0xf5, 0x0b, 0x19, 0xff, 0xff, 0xf3, 0x63, 0x9e, 0xdb, 0x1d,
- 0x5b, 0xae, 0xb5, 0x0d, 0x77, 0xff, 0x56, 0x7e, 0xf9, 0x38, 0x74, 0xf9,
- 0x87, 0x1b, 0xc0, 0xe9, 0xff, 0xff, 0xff, 0xd4, 0xaa, 0xf3, 0x6d, 0x95,
- 0xca, 0xce, 0x58, 0x01, 0x86, 0xb0, 0xae, 0xf3, 0xdb, 0x82, 0xca, 0x3a,
- 0x7f, 0xbe, 0xae, 0x86, 0xb7, 0x7c, 0x3a, 0x7f, 0x61, 0xdb, 0x71, 0x49,
- 0xc3, 0xa7, 0xfc, 0xdf, 0xdd, 0xfb, 0xa1, 0x73, 0xf2, 0x8e, 0x8a, 0x3f,
- 0xac, 0x4d, 0x27, 0xfd, 0x55, 0xf6, 0x75, 0x06, 0x7a, 0xc9, 0xd3, 0xf8,
- 0x2b, 0xdb, 0x40, 0x70, 0xe9, 0xab, 0x9d, 0x1f, 0x95, 0x20, 0xcf, 0x60,
- 0x83, 0xc3, 0xa1, 0x97, 0x1b, 0x28, 0x8d, 0x23, 0x33, 0x02, 0x85, 0x42,
- 0x47, 0x64, 0xf7, 0x0a, 0x21, 0x85, 0x96, 0x61, 0x29, 0xd9, 0x6c, 0xee,
- 0xb5, 0x38, 0x74, 0xff, 0xf6, 0x2f, 0x16, 0xd4, 0xa1, 0x6f, 0xfc, 0x4c,
- 0x0e, 0x8a, 0x3f, 0x34, 0x20, 0x9f, 0xb0, 0x71, 0xfa, 0xe0, 0x60, 0x74,
- 0xf9, 0x49, 0xd5, 0x74, 0x74, 0x9c, 0x3a, 0x66, 0x51, 0xd2, 0xe1, 0xd0,
- 0x06, 0x96, 0xc5, 0x63, 0xa3, 0xd5, 0xd9, 0xb4, 0xf7, 0x33, 0x78, 0x9d,
- 0x33, 0x96, 0x74, 0xfe, 0xda, 0x06, 0x2f, 0x16, 0x3a, 0x35, 0xda, 0x67,
- 0xcc, 0x6b, 0x4f, 0xa8, 0x46, 0xa2, 0x2e, 0xc5, 0xa7, 0xf6, 0x53, 0x1d,
- 0x2c, 0x7e, 0x3a, 0x7f, 0xfc, 0xc0, 0xde, 0xa5, 0x37, 0x9e, 0x99, 0xed,
- 0x47, 0x43, 0x88, 0x87, 0xd6, 0x34, 0x9f, 0x82, 0x9b, 0xfb, 0x09, 0xd3,
- 0x86, 0xd4, 0x74, 0xdf, 0x31, 0xd0, 0xf3, 0xdb, 0x42, 0xb1, 0x1a, 0x87,
- 0x69, 0xdb, 0x6f, 0xeb, 0x91, 0xb9, 0xb4, 0xa5, 0xac, 0x1e, 0xde, 0x59,
- 0xd4, 0xa9, 0x2a, 0x9f, 0x77, 0xff, 0x0c, 0xcf, 0x4b, 0xe4, 0xc6, 0x3a,
- 0x54, 0x8c, 0x21, 0xc8, 0x6c, 0x84, 0xa9, 0xd5, 0x46, 0x83, 0xba, 0x40,
- 0xe5, 0xc7, 0x2e, 0x33, 0xd2, 0x99, 0x95, 0x8f, 0xc9, 0xd3, 0xa7, 0x51,
- 0x8b, 0x6b, 0x46, 0xbd, 0xfa, 0x1c, 0x6e, 0xf0, 0x82, 0x9f, 0xff, 0xbb,
- 0xf2, 0xf1, 0xe0, 0x35, 0x63, 0xae, 0x75, 0x77, 0xfc, 0xe8, 0x5a, 0xa3,
- 0x44, 0x8f, 0x42, 0x7f, 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x53, 0xb3, 0xe0,
- 0xf5, 0xdf, 0x8d, 0x15, 0x1c, 0xff, 0xad, 0xeb, 0xa0, 0xf5, 0xdf, 0x8d,
- 0x13, 0x44, 0x97, 0x47, 0xf4, 0xa3, 0x29, 0xfc, 0xba, 0x0f, 0x5d, 0xf8,
- 0xd1, 0x57, 0xcf, 0x83, 0xd7, 0x7e, 0x34, 0x56, 0xd3, 0xfc, 0xf5, 0xd0,
- 0x7a, 0xef, 0xc6, 0x89, 0x06, 0x4b, 0xa3, 0xf5, 0xb3, 0x29, 0xff, 0x97,
- 0x6f, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0x90, 0xe7, 0xfc, 0xfd, 0xb7, 0x32,
- 0xec, 0xb2, 0xed, 0x09, 0xd3, 0xea, 0xa1, 0xfb, 0x27, 0x4f, 0x83, 0xd7,
- 0x7e, 0x34, 0x58, 0x93, 0xea, 0x06, 0x1f, 0xe7, 0x4f, 0xbf, 0x6b, 0x50,
- 0x31, 0xd3, 0xb2, 0xc2, 0x74, 0xb6, 0xc7, 0x88, 0x85, 0x53, 0xff, 0x35,
- 0x66, 0x87, 0xa4, 0xf9, 0x84, 0xe9, 0xc2, 0xd8, 0x1d, 0x27, 0x89, 0xee,
- 0x76, 0x83, 0x3b, 0x59, 0x3e, 0x3a, 0x7c, 0x8e, 0xbb, 0xbc, 0x9d, 0x3f,
- 0xf3, 0xae, 0xeb, 0x1e, 0x9d, 0x6e, 0xad, 0xc3, 0xa6, 0x67, 0x9d, 0x14,
- 0x7c, 0x00, 0x97, 0x3f, 0xa8, 0x1f, 0xf5, 0x53, 0x87, 0x4f, 0xad, 0xff,
- 0xb6, 0xc7, 0x4f, 0xd9, 0xc8, 0x26, 0x9a, 0xf3, 0xa1, 0x91, 0x16, 0x86,
- 0x56, 0x51, 0x3f, 0xfc, 0xf6, 0x53, 0x3f, 0xa1, 0x6d, 0xdd, 0x01, 0xd3,
- 0xfb, 0xc3, 0x4e, 0x86, 0xb2, 0x74, 0x62, 0x7f, 0xdb, 0x4c, 0x9f, 0xdf,
- 0x35, 0x71, 0x07, 0x42, 0xa7, 0xfe, 0xdd, 0xa7, 0x1f, 0x5f, 0xc6, 0xbe,
- 0x3a, 0x7d, 0x5b, 0xc6, 0xf5, 0xe7, 0x4f, 0x7d, 0x96, 0x13, 0xa7, 0xf0,
- 0x6e, 0xd3, 0x28, 0xe8, 0xe8, 0x63, 0xd3, 0xa2, 0x18, 0x44, 0x71, 0x0a,
- 0x26, 0x5f, 0xa7, 0xeb, 0xc3, 0x8d, 0x8b, 0xce, 0x9f, 0xf0, 0xb2, 0x75,
- 0xc1, 0xbc, 0x72, 0x74, 0x3b, 0x4b, 0xb0, 0x7d, 0x24, 0xd1, 0x37, 0xf3,
- 0x2f, 0x35, 0x63, 0x08, 0x24, 0x28, 0x70, 0x7c, 0x21, 0x13, 0xb8, 0x55,
- 0xdc, 0x2a, 0xfe, 0x23, 0xcc, 0x62, 0x9c, 0x2e, 0xfc, 0x5d, 0x3f, 0xf6,
- 0xd1, 0xb9, 0xbb, 0xff, 0x43, 0xf1, 0xd3, 0xff, 0xd5, 0x8b, 0xf9, 0xde,
- 0x0b, 0xdd, 0xa9, 0x32, 0x74, 0xdb, 0x5d, 0x22, 0x58, 0x51, 0x21, 0x69,
- 0xda, 0xb4, 0x71, 0x13, 0xf9, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0xcd, 0x9a,
- 0xba, 0x3a, 0x7f, 0xd6, 0xf5, 0xd0, 0x7a, 0xef, 0xc6, 0x8a, 0x02, 0x7f,
- 0x22, 0x9b, 0x5f, 0xba, 0xc0, 0xe9, 0x2e, 0x91, 0x28, 0xa1, 0x6d, 0xa4,
- 0x4d, 0xde, 0xce, 0x9f, 0xb2, 0xca, 0x16, 0x70, 0xe9, 0x6c, 0xe9, 0xdf,
- 0x85, 0xc3, 0xa6, 0xae, 0x51, 0xae, 0xf8, 0x42, 0x3e, 0x44, 0x30, 0xad,
- 0x4d, 0xab, 0x27, 0x4f, 0xf6, 0xe8, 0x38, 0x2c, 0xac, 0x9d, 0x3d, 0xeb,
- 0xbf, 0x1a, 0x2d, 0xf9, 0xfb, 0xf7, 0x2f, 0xd6, 0x07, 0x40, 0x1e, 0xd7,
- 0xc5, 0xb3, 0xd4, 0x28, 0xe1, 0xd3, 0xee, 0x3f, 0x3f, 0xb2, 0x74, 0xfc,
- 0xeb, 0xf7, 0x05, 0xbe, 0x3a, 0x7d, 0xd3, 0x6b, 0xfb, 0x51, 0xd0, 0xc7,
- 0xbc, 0x86, 0x33, 0xd6, 0x83, 0xc3, 0xa7, 0xf7, 0x78, 0xe5, 0xbd, 0x4a,
- 0x3a, 0x7b, 0x7f, 0xfa, 0x51, 0xd3, 0x53, 0xce, 0x8a, 0x37, 0x42, 0x4b,
- 0x25, 0xbb, 0x4a, 0xbf, 0x9a, 0x13, 0xaf, 0x23, 0xe8, 0x62, 0xa1, 0x20,
- 0x84, 0x40, 0x41, 0xb8, 0x44, 0x7c, 0x40, 0x23, 0xfc, 0x6e, 0x9f, 0xf5,
- 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x94, 0x9f, 0xe7, 0xae, 0x83, 0xd7,
- 0x7e, 0x34, 0x49, 0xd2, 0x5a, 0x91, 0x17, 0x69, 0x10, 0xcf, 0x93, 0xd5,
- 0x84, 0x6d, 0xbd, 0x5b, 0x98, 0x6a, 0x2a, 0xf4, 0x2d, 0xd0, 0x9f, 0x5f,
- 0x0b, 0x27, 0x09, 0x95, 0x3f, 0x0d, 0xb2, 0x9f, 0xa1, 0xa3, 0x99, 0x66,
- 0x6e, 0xa3, 0x3c, 0x9f, 0x07, 0xae, 0xfc, 0x68, 0x87, 0xe7, 0xfd, 0x6f,
- 0x5d, 0x07, 0xae, 0xfc, 0x68, 0x94, 0xe4, 0xba, 0x3f, 0xa5, 0x19, 0x4f,
- 0xe5, 0xd0, 0x7a, 0xef, 0xc6, 0x88, 0x9e, 0x7f, 0x2e, 0x83, 0xd7, 0x7e,
- 0x34, 0x46, 0x33, 0xff, 0x96, 0xab, 0x7a, 0xe8, 0x3d, 0x77, 0xe3, 0x44,
- 0xf3, 0x0c, 0x8f, 0x5c, 0x09, 0xde, 0x7b, 0xb3, 0xd9, 0xf0, 0x7a, 0xef,
- 0xc6, 0x88, 0x82, 0x7f, 0xd6, 0xf5, 0xd0, 0x7a, 0xef, 0xc6, 0x89, 0x52,
- 0x4b, 0xa3, 0xfa, 0x51, 0x94, 0xfe, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0x8a,
- 0x27, 0xf2, 0xe8, 0x3d, 0x77, 0xe3, 0x44, 0x65, 0x3f, 0xf9, 0x6a, 0xb7,
- 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x4c, 0xb3, 0xf9, 0x74, 0x1e, 0xbb, 0xf1,
- 0xa2, 0xa4, 0x9f, 0xcb, 0xa0, 0xf5, 0xdf, 0x8d, 0x15, 0xd4, 0xfe, 0x5d,
- 0x07, 0xae, 0xfc, 0x68, 0xb1, 0x67, 0xfe, 0x55, 0xbd, 0x74, 0x1e, 0xbb,
- 0xf1, 0xa2, 0x7a, 0x9f, 0xed, 0x17, 0x6c, 0x9a, 0xc8, 0xee, 0x74, 0x2d,
- 0x11, 0x6c, 0x9d, 0x3f, 0x6b, 0xaf, 0x5c, 0x4e, 0xf2, 0x74, 0xf0, 0x2b,
- 0x98, 0x9d, 0x3b, 0xd5, 0xb2, 0xa7, 0x29, 0xb2, 0x74, 0xff, 0xfd, 0xb1,
- 0xbf, 0xe8, 0x0c, 0xf7, 0xd6, 0x7e, 0xf9, 0x8e, 0x9f, 0xff, 0x81, 0x1d,
- 0xed, 0x4b, 0x60, 0x04, 0x77, 0xf7, 0x78, 0x1d, 0x3e, 0xf2, 0x6f, 0xf2,
- 0x8e, 0x9f, 0xfd, 0x79, 0x1a, 0xf9, 0x7b, 0x4f, 0x58, 0x1d, 0x3e, 0xe6,
- 0xd9, 0x5e, 0x3a, 0x7f, 0xf0, 0xea, 0x66, 0x16, 0x56, 0xad, 0x5b, 0xd6,
- 0x3a, 0x6b, 0xc4, 0xe9, 0xfd, 0x79, 0xbd, 0xf6, 0x38, 0x1d, 0x02, 0x79,
- 0x3d, 0x8b, 0x46, 0x0a, 0x89, 0xd0, 0x6c, 0x16, 0xd4, 0xbf, 0xb2, 0x91,
- 0x47, 0xe1, 0x3b, 0xbc, 0x26, 0x67, 0x0d, 0xf0, 0xe9, 0xc2, 0x99, 0x3a,
- 0x5a, 0x3b, 0x66, 0xd1, 0x86, 0xa7, 0x81, 0xd5, 0xa8, 0xe8, 0xa3, 0xce,
- 0x42, 0xc9, 0xff, 0x26, 0xef, 0x8c, 0xe6, 0x51, 0x47, 0x4f, 0x87, 0xfa,
- 0x56, 0x4e, 0x9f, 0xfa, 0xb4, 0xbf, 0xab, 0xdb, 0xbf, 0xb2, 0x74, 0x21,
- 0xf6, 0x09, 0x3c, 0xe5, 0x36, 0xce, 0x9e, 0x1e, 0xb5, 0x7f, 0x3a, 0x7e,
- 0xac, 0xe9, 0x63, 0x81, 0xd1, 0x47, 0xdd, 0x63, 0x62, 0x4d, 0x3e, 0xef,
- 0xfe, 0x7a, 0x63, 0xa2, 0x91, 0xca, 0x90, 0x8e, 0xd9, 0x64, 0xff, 0xff,
- 0xed, 0xb2, 0x00, 0x37, 0xee, 0x20, 0xf6, 0xfa, 0xcf, 0x5d, 0xd8, 0x3c,
- 0xe9, 0xf6, 0x1d, 0x02, 0x68, 0x74, 0xfd, 0xd5, 0x87, 0xda, 0xd4, 0x74,
- 0xff, 0x85, 0x1f, 0xcd, 0xd0, 0x26, 0x4e, 0x9f, 0xf5, 0xd7, 0xcc, 0x37,
- 0xd5, 0x7f, 0x3a, 0x1e, 0x7f, 0x3f, 0x1d, 0xcf, 0xeb, 0xc7, 0x3c, 0xe5,
- 0x6b, 0xce, 0x9f, 0xfc, 0xd5, 0x8f, 0x36, 0xdc, 0x16, 0xfb, 0x27, 0x4e,
- 0xce, 0xd4, 0x74, 0x70, 0xf9, 0x7b, 0x49, 0x9f, 0xbb, 0xcf, 0x33, 0x5c,
- 0x3a, 0x76, 0x9a, 0x68, 0x54, 0xff, 0xee, 0x27, 0x33, 0xb4, 0xd6, 0xfc,
- 0x0c, 0xf2, 0x96, 0x5f, 0xc2, 0x22, 0xa7, 0xb4, 0xd8, 0x7a, 0xaf, 0x7a,
- 0x77, 0x42, 0x90, 0x85, 0x4a, 0x88, 0xc6, 0x13, 0x9c, 0x86, 0x64, 0xff,
- 0x62, 0xfc, 0xe6, 0xba, 0xbe, 0x1d, 0x2a, 0x3a, 0x18, 0xf2, 0x7f, 0x9d,
- 0x4f, 0xb4, 0xe3, 0x63, 0xa1, 0xd3, 0xbd, 0xa6, 0xce, 0x9f, 0xcd, 0x61,
- 0xbd, 0x2f, 0xa2, 0xa6, 0xd3, 0x42, 0xa3, 0xa3, 0xca, 0xd0, 0xca, 0x77,
- 0x13, 0x5e, 0x52, 0xcd, 0x24, 0xf7, 0x6f, 0xef, 0x87, 0x46, 0x4f, 0x4f,
- 0x58, 0xbe, 0x6d, 0x32, 0x74, 0xa8, 0xe9, 0x63, 0x46, 0x9b, 0x82, 0xf3,
- 0xff, 0x67, 0x3d, 0x0b, 0x75, 0xb6, 0xe6, 0x4e, 0x86, 0x3e, 0xce, 0xc9,
- 0xe7, 0xfd, 0xc4, 0x0b, 0xf9, 0xdf, 0x95, 0xb3, 0xa7, 0xf5, 0x87, 0x32,
- 0x29, 0xfc, 0xe8, 0x7a, 0x25, 0x10, 0x8a, 0xd0, 0x27, 0x52, 0x01, 0xd3,
- 0xd6, 0x0c, 0xf3, 0xa3, 0x03, 0x70, 0xa1, 0x99, 0xff, 0x36, 0x3b, 0x65,
- 0x7b, 0x68, 0xe1, 0xd1, 0x47, 0xc2, 0x04, 0x53, 0xf7, 0x18, 0x3a, 0xa1,
- 0x3a, 0x7f, 0x75, 0xb6, 0x1d, 0x2f, 0x13, 0xa7, 0xfe, 0x4e, 0xb6, 0xde,
- 0x6f, 0xac, 0x7e, 0x3a, 0x7f, 0xff, 0xc8, 0xab, 0x1c, 0x5e, 0xbd, 0x29,
- 0x1d, 0x50, 0xd7, 0x56, 0xf3, 0xc5, 0xeb, 0x0c, 0x98, 0xe5, 0x95, 0xe4,
- 0xd3, 0xb4, 0x49, 0xff, 0xea, 0xe6, 0x69, 0xcd, 0xb3, 0xaa, 0xde, 0xd8,
- 0xe9, 0xff, 0xff, 0xf2, 0x56, 0x39, 0x4a, 0xd3, 0x55, 0x62, 0xfc, 0xa7,
- 0x32, 0x98, 0xf5, 0xd7, 0x78, 0x1d, 0x3f, 0xfe, 0x41, 0xeb, 0x57, 0xee,
- 0x26, 0x6d, 0x07, 0xb7, 0x9d, 0x02, 0x99, 0x9f, 0x14, 0x1d, 0x42, 0x2e,
- 0x7f, 0x61, 0x7c, 0xfb, 0xf0, 0xbc, 0xe9, 0xaf, 0xa3, 0xa7, 0xe0, 0xbc,
- 0xee, 0xde, 0x74, 0xb1, 0x3a, 0x64, 0xd0, 0xe9, 0xbf, 0x7c, 0x74, 0x38,
- 0x6b, 0xfe, 0x16, 0x9c, 0xfb, 0xe8, 0xe9, 0xb4, 0xd0, 0xe8, 0x7a, 0x36,
- 0x28, 0x5b, 0xc5, 0x68, 0x81, 0x92, 0x3d, 0x07, 0x27, 0x73, 0xf7, 0xc5,
- 0x2c, 0xf5, 0xa7, 0xff, 0xff, 0x71, 0xba, 0xdf, 0x77, 0xfd, 0x57, 0xd5,
- 0x50, 0xff, 0xce, 0x68, 0x7e, 0x3a, 0x31, 0x45, 0x62, 0x18, 0x4f, 0xf5,
- 0x73, 0x6c, 0x1c, 0xaf, 0x1d, 0x39, 0x81, 0xc3, 0xa2, 0x95, 0x5d, 0xa1,
- 0xbd, 0xca, 0x10, 0x12, 0x3d, 0x63, 0x69, 0xd9, 0xb7, 0x0e, 0x9e, 0xae,
- 0x5b, 0xb9, 0xd1, 0x89, 0xbf, 0x11, 0xc9, 0xff, 0xa8, 0x02, 0x9c, 0xdd,
- 0x66, 0xc4, 0xe9, 0xfc, 0x2c, 0x1d, 0xfb, 0x6c, 0x74, 0xf9, 0x3f, 0xee,
- 0xde, 0x74, 0xfc, 0x8c, 0xac, 0x2b, 0x43, 0xa6, 0xd3, 0x43, 0xa3, 0xc7,
- 0xda, 0x05, 0x1a, 0x16, 0xcf, 0xf5, 0x39, 0x6e, 0x5e, 0x2f, 0xc9, 0x4b,
- 0x35, 0xf3, 0xba, 0x65, 0x1d, 0x3f, 0xab, 0xea, 0x71, 0xb1, 0xc9, 0xd0,
- 0xc7, 0xa1, 0x43, 0x93, 0xff, 0xa8, 0x7e, 0xad, 0xa6, 0x39, 0xdf, 0x79,
- 0x3a, 0x7e, 0x1b, 0xfb, 0xaa, 0x13, 0xa7, 0xe5, 0x26, 0xb5, 0x07, 0xf3,
- 0xa7, 0x69, 0xa6, 0x85, 0x4f, 0xfc, 0xc0, 0x3d, 0xdf, 0xea, 0x71, 0x94,
- 0x72, 0xcb, 0xf8, 0xd7, 0xaa, 0xa0, 0x72, 0x19, 0xa3, 0x09, 0xac, 0x90,
- 0x71, 0x2f, 0xb2, 0xcd, 0x13, 0xe7, 0xff, 0xd7, 0xd5, 0x50, 0xff, 0xfc,
- 0x2c, 0x38, 0x20, 0x1d, 0x3a, 0xc3, 0x03, 0xc8, 0x25, 0x3c, 0xfa, 0xc5,
- 0xe7, 0x90, 0x4a, 0x76, 0x53, 0xa3, 0xc8, 0x25, 0x36, 0x9a, 0x1e, 0x41,
- 0x28, 0xf2, 0x29, 0x5c, 0x28, 0xe1, 0x7e, 0x85, 0x33, 0x5f, 0x0b, 0x20,
- 0x91, 0x66, 0xfe, 0x7e, 0xad, 0xd5, 0x0f, 0xf3, 0xa7, 0x58, 0xfc, 0xa4,
- 0xe6, 0x06, 0x33, 0x9e, 0x19, 0xcf, 0x6b, 0x55, 0xec, 0xe9, 0x56, 0xbc,
- 0xfa, 0xbe, 0x47, 0x9f, 0xce, 0x3f, 0xbc, 0x38, 0x98, 0x15, 0x3f, 0x91,
- 0xfd, 0xde, 0x76, 0x87, 0x49, 0xe5, 0x4e, 0xb0, 0xc0, 0xa8, 0x2a, 0x18,
- 0xda, 0xf8, 0x41, 0x43, 0x73, 0xc2, 0xdf, 0x78, 0xa5, 0x9a, 0xd8, 0x64,
- 0x62, 0xd4, 0x25, 0x27, 0xbb, 0xb0, 0x79, 0xd2, 0x51, 0xd3, 0x53, 0xfa,
- 0x36, 0x2e, 0x10, 0xcf, 0xb4, 0xa7, 0x11, 0x47, 0x4f, 0xde, 0x67, 0x1e,
- 0xdf, 0x15, 0x24, 0x3a, 0x7f, 0xb0, 0xed, 0xfd, 0x6f, 0xbb, 0x13, 0xa7,
- 0xe4, 0x65, 0x61, 0x5a, 0x1d, 0x3e, 0xac, 0x15, 0x4a, 0x3a, 0x76, 0x50,
- 0x0e, 0x81, 0x3c, 0x1e, 0x13, 0xcf, 0xc3, 0x7f, 0x7d, 0xde, 0x4e, 0x9f,
- 0x93, 0xff, 0xe6, 0x52, 0xfa, 0x4c, 0x26, 0x83, 0xc0, 0xf3, 0x2d, 0xdc,
- 0x21, 0x8a, 0x4f, 0x3d, 0x0a, 0x06, 0x33, 0x79, 0xe1, 0xac, 0x3b, 0x3a,
- 0x1e, 0xaf, 0x4a, 0x8b, 0x37, 0x0f, 0xc1, 0x57, 0xcc, 0x7f, 0xbc, 0x34,
- 0x9f, 0xff, 0x60, 0x01, 0x5d, 0x5a, 0xb7, 0x7c, 0x16, 0x70, 0xe9, 0xff,
- 0xff, 0xdd, 0x87, 0x6e, 0x0d, 0xfd, 0x9c, 0xd7, 0xfa, 0xec, 0x2f, 0xa6,
- 0xdb, 0x1d, 0x3b, 0x4d, 0x34, 0x2a, 0x67, 0xb1, 0x4b, 0x2f, 0xe1, 0x93,
- 0x12, 0xc1, 0x50, 0x21, 0x35, 0x3f, 0x60, 0xe3, 0xf5, 0xc0, 0xc0, 0xe9,
- 0xed, 0xde, 0x3a, 0x1d, 0x3e, 0xc0, 0x11, 0x94, 0x74, 0xff, 0xf3, 0x7e,
- 0xe0, 0xb7, 0xd7, 0xcf, 0xbf, 0x0b, 0xce, 0x8d, 0x76, 0x8d, 0x14, 0x35,
- 0xb2, 0x3e, 0x13, 0x4e, 0xfd, 0xd3, 0x87, 0x4e, 0x7a, 0x09, 0xd3, 0xf7,
- 0x19, 0xc1, 0xef, 0x27, 0x46, 0x07, 0xd0, 0xf2, 0x0e, 0x0d, 0x4d, 0x79,
- 0x3a, 0x6e, 0xdd, 0x83, 0xa0, 0x4d, 0x8f, 0x62, 0xb3, 0x5a, 0xdd, 0xa6,
- 0xfd, 0x31, 0xd9, 0x9b, 0x6b, 0xac, 0x44, 0xd2, 0x90, 0xb0, 0x87, 0xdb,
- 0xc8, 0x3a, 0x8e, 0x3a, 0xa5, 0x95, 0x7f, 0x85, 0xd7, 0x88, 0xf1, 0x2a,
- 0x48, 0x6f, 0x39, 0x1a, 0x58, 0x43, 0x1d, 0x51, 0x9e, 0x6e, 0x70, 0xae,
- 0xe1, 0x22, 0x24, 0x39, 0x95, 0xc1, 0xc9, 0xe4, 0xae, 0xe3, 0x74, 0xd6,
- 0x8c, 0x1b, 0xf4, 0x2a, 0x5d, 0xd8, 0x67, 0xff, 0x2d, 0x56, 0xf5, 0xd0,
- 0x7a, 0xef, 0xc6, 0x8a, 0x2a, 0x7f, 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x5d,
- 0x13, 0xff, 0x2e, 0xde, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x25, 0xcf, 0xe5,
- 0xd0, 0x7a, 0xef, 0xc6, 0x8b, 0xca, 0x19, 0xd2, 0x48, 0x60, 0x4e, 0xf3,
- 0xda, 0x3d, 0xf2, 0xa3, 0x87, 0xaa, 0x3d, 0xdc, 0x32, 0x06, 0xbf, 0x6e,
- 0xcc, 0x79, 0xfc, 0x54, 0xec, 0xf5, 0xd2, 0x74, 0xff, 0xe5, 0xaa, 0xde,
- 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x2c, 0xcd, 0xde, 0xce, 0x9e, 0xf5, 0xdf,
- 0x8d, 0x11, 0x9c, 0xfc, 0x8c, 0xac, 0x2b, 0x43, 0xa6, 0x17, 0x9d, 0x25,
- 0x1d, 0x3e, 0x40, 0xdd, 0xac, 0x0f, 0x49, 0x45, 0xbf, 0x85, 0x67, 0xeb,
- 0x7a, 0x05, 0x81, 0xd3, 0xff, 0x65, 0x3b, 0xcd, 0x0f, 0x6f, 0xac, 0x9d,
- 0x3b, 0x2d, 0x89, 0xd0, 0x09, 0xa9, 0xa9, 0xfc, 0x52, 0xf2, 0x53, 0xc4,
- 0x49, 0xff, 0xb8, 0x81, 0x7f, 0x6a, 0xc5, 0xec, 0xa3, 0xa7, 0xc2, 0xcf,
- 0xcd, 0x9d, 0x08, 0x7d, 0x6e, 0x91, 0xa7, 0x5f, 0xe7, 0x9d, 0x3f, 0xfd,
- 0xdf, 0x33, 0x8b, 0xd8, 0x7e, 0xce, 0xae, 0xc4, 0xe9, 0xcd, 0xc6, 0x3a,
- 0x49, 0xd1, 0xf7, 0xba, 0x55, 0x9f, 0xeb, 0xc7, 0x23, 0x41, 0xd3, 0x1d,
- 0x3f, 0xf5, 0x2b, 0x89, 0xa6, 0x5b, 0x77, 0xaf, 0x3a, 0x7f, 0xdb, 0x64,
- 0xda, 0x30, 0xb9, 0xd9, 0xd3, 0xfa, 0xb2, 0xdc, 0xce, 0xd0, 0xe9, 0x2d,
- 0xda, 0x57, 0xc7, 0x51, 0xb5, 0x39, 0x0b, 0x4d, 0x91, 0xdc, 0x23, 0x3e,
- 0x2a, 0x13, 0x7c, 0xa3, 0xeb, 0x1e, 0xcf, 0xfe, 0x5a, 0xad, 0xeb, 0xa0,
- 0xf5, 0xdf, 0x8d, 0x13, 0x4c, 0xff, 0xe5, 0xaa, 0xde, 0xba, 0x0f, 0x5d,
- 0xf8, 0xd1, 0x38, 0xcf, 0xfe, 0x5a, 0xad, 0xeb, 0xa0, 0xf5, 0xdf, 0x8d,
- 0x14, 0x0c, 0xf8, 0x3d, 0x77, 0xe3, 0x45, 0xc1, 0x33, 0x21, 0xd3, 0xf8,
- 0x5e, 0xc9, 0xd5, 0x28, 0xe9, 0x2e, 0x8f, 0xdf, 0x66, 0x5d, 0x8a, 0x4f,
- 0xe4, 0x5f, 0xe6, 0xfa, 0xb4, 0x3a, 0x7f, 0x9e, 0xba, 0x0f, 0x5d, 0xf8,
- 0xd1, 0x24, 0xc9, 0x7b, 0x3f, 0x8b, 0x35, 0x9f, 0x5a, 0xfa, 0xd3, 0xe3,
- 0xa3, 0x05, 0xf4, 0x57, 0xce, 0x1b, 0xfa, 0x13, 0xae, 0x2a, 0x7c, 0xa9,
- 0x98, 0x65, 0xf2, 0x15, 0xae, 0x89, 0xe7, 0xfd, 0xfe, 0xd7, 0x41, 0xeb,
- 0xbf, 0x1a, 0x2d, 0x49, 0xff, 0x5b, 0xd7, 0x41, 0xeb, 0xbf, 0x1a, 0x25,
- 0x58, 0x3a, 0x4b, 0xfe, 0x89, 0xc5, 0x25, 0x3b, 0xa4, 0x4f, 0xe5, 0xd0,
- 0x7a, 0xef, 0xc6, 0x88, 0xa6, 0x7f, 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x46,
- 0x93, 0x77, 0xb3, 0xa7, 0xbd, 0x77, 0xe3, 0x45, 0x3f, 0x37, 0x18, 0xe8,
- 0x03, 0xc2, 0xe1, 0x6c, 0xff, 0xb8, 0xe3, 0x73, 0x76, 0xe6, 0xaa, 0x3a,
- 0x7f, 0xee, 0xf8, 0x1d, 0xb9, 0x9f, 0x5b, 0x99, 0x3a, 0x7f, 0xea, 0x73,
- 0xb1, 0xc3, 0x3e, 0xb7, 0x32, 0x74, 0x96, 0xed, 0x26, 0x95, 0x4b, 0x28,
- 0x42, 0x28, 0x3c, 0x48, 0x9f, 0xfc, 0xb5, 0x5b, 0xd7, 0x41, 0xeb, 0xbf,
- 0x1a, 0x26, 0xa9, 0xfc, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x5d, 0xcf, 0x7a,
- 0xef, 0xc6, 0x8a, 0xfa, 0x76, 0x9a, 0x68, 0x54, 0x84, 0xa5, 0x97, 0xf0,
- 0x07, 0xd4, 0xa4, 0xc9, 0xcf, 0x6c, 0x4e, 0x9c, 0xe5, 0x6c, 0xe9, 0xff,
- 0x56, 0xf4, 0xbe, 0x65, 0xab, 0x03, 0xa5, 0xc3, 0xa7, 0xf9, 0x02, 0xb0,
- 0x47, 0xd7, 0x47, 0x40, 0x1e, 0x3d, 0x88, 0x49, 0x74, 0x8f, 0xe7, 0x08,
- 0x6c, 0x70, 0x47, 0x33, 0x08, 0x59, 0xff, 0xcb, 0x55, 0xbd, 0x74, 0x1e,
- 0xbb, 0xf1, 0xa2, 0x7b, 0x9f, 0xcb, 0xa0, 0xf5, 0xdf, 0x8d, 0x17, 0x0c,
- 0xff, 0xcb, 0xb7, 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x49, 0xf0, 0xcb, 0xaf,
- 0xb8, 0x1d, 0xbc, 0xf7, 0xfc, 0x70, 0xfe, 0x53, 0x71, 0x50, 0x23, 0xa5,
- 0xda, 0x9e, 0x55, 0x1d, 0x1e, 0xcf, 0xe5, 0xd0, 0x7a, 0xef, 0xc6, 0x88,
- 0xaa, 0x7f, 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x53, 0x33, 0xff, 0x96, 0xab,
- 0x7a, 0xe8, 0x3d, 0x77, 0xe3, 0x44, 0xcf, 0x3f, 0xf9, 0x6a, 0xb7, 0xae,
- 0x83, 0xd7, 0x7e, 0x34, 0x51, 0xb1, 0x82, 0x64, 0x5d, 0x1e, 0xff, 0x3d,
- 0xe2, 0xa4, 0xff, 0xcb, 0xb7, 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x47, 0x53,
- 0x77, 0xb3, 0xa7, 0xe4, 0xa1, 0xea, 0xb0, 0x3a, 0x7b, 0xd7, 0x7e, 0x34,
- 0x53, 0x53, 0xea, 0xc7, 0x4b, 0xd9, 0xd0, 0x07, 0xaa, 0x25, 0xb3, 0xff,
- 0xb6, 0x9c, 0xcd, 0xe3, 0x4e, 0x36, 0xf2, 0x74, 0xff, 0xcf, 0xda, 0x0e,
- 0x19, 0xed, 0x81, 0xc3, 0xa6, 0x6f, 0xe7, 0x4f, 0xc8, 0xca, 0xc2, 0xb4,
- 0x3a, 0x7f, 0xfa, 0xb9, 0xba, 0x78, 0x58, 0xf3, 0x76, 0xf3, 0xa6, 0x6f,
- 0x8e, 0x9f, 0xd7, 0x8b, 0x79, 0x3c, 0xb0, 0x44, 0x78, 0x96, 0xfe, 0x4c,
- 0x8d, 0xa3, 0xfb, 0x30, 0xa6, 0x92, 0xdd, 0xa5, 0x4d, 0xbd, 0x0b, 0xd4,
- 0x20, 0x7c, 0x41, 0x8a, 0x57, 0x23, 0x43, 0x9f, 0x07, 0xae, 0xfc, 0x68,
- 0xaa, 0xa7, 0xfd, 0x6f, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0x9b, 0x64, 0xba,
- 0x3f, 0xa5, 0x19, 0x4f, 0xe5, 0xd0, 0x7a, 0xef, 0xc6, 0x8a, 0xfe, 0x7f,
- 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x58, 0xd3, 0xf9, 0x01, 0x79, 0xfe, 0xfa,
- 0x3a, 0x7c, 0x1e, 0xbb, 0xf1, 0xa2, 0xd5, 0x9f, 0xf5, 0xbd, 0x74, 0x1e,
- 0xbb, 0xf1, 0xa2, 0x82, 0x92, 0xe8, 0xfe, 0x94, 0x65, 0x3e, 0x0f, 0x5d,
- 0xf8, 0xd1, 0x71, 0x4f, 0x5b, 0xba, 0x60, 0x74, 0xf3, 0xbb, 0xba, 0x78,
- 0xe9, 0xfc, 0xca, 0xb7, 0x4c, 0x0e, 0xe7, 0x49, 0x74, 0x8b, 0x2d, 0x99,
- 0x59, 0x27, 0x09, 0xe7, 0xc1, 0xeb, 0xbf, 0x1a, 0x2e, 0x99, 0xf3, 0x0d,
- 0xf4, 0xc7, 0x49, 0x74, 0x7a, 0xe8, 0x65, 0x3f, 0xfd, 0x43, 0xc4, 0x56,
- 0xd9, 0x06, 0xc3, 0xf9, 0xd3, 0xff, 0xf2, 0x97, 0x4f, 0x60, 0xfb, 0x56,
- 0x76, 0xca, 0xb1, 0x3a, 0x7f, 0xfe, 0xd8, 0xf7, 0x7a, 0xfa, 0x7e, 0xeb,
- 0xfd, 0x74, 0xe7, 0x67, 0x4d, 0xea, 0x3a, 0x18, 0xfe, 0x3f, 0xb1, 0xcf,
- 0xf9, 0xf4, 0x01, 0x6f, 0xc2, 0xb4, 0x3a, 0x70, 0xda, 0xc0, 0xf8, 0x38,
- 0x47, 0x3f, 0xe0, 0x6c, 0x77, 0x79, 0xe3, 0x68, 0x74, 0xdd, 0xec, 0xe9,
- 0xf0, 0xd6, 0xef, 0x87, 0x4f, 0xcf, 0xba, 0x74, 0xdd, 0x1d, 0x0e, 0xd9,
- 0xe9, 0xeb, 0xa8, 0x96, 0x7e, 0xfa, 0xdc, 0x7a, 0x70, 0xe9, 0xff, 0xfe,
- 0x6e, 0xb7, 0x58, 0xf0, 0x6f, 0x7f, 0x5e, 0x73, 0x61, 0xe3, 0xa7, 0xf5,
- 0x55, 0x7f, 0xff, 0x6f, 0x3a, 0x3f, 0xa2, 0x6b, 0x8c, 0xd3, 0xff, 0xfd,
- 0xb6, 0x1e, 0xf3, 0xb4, 0xcf, 0x37, 0x5d, 0x26, 0x68, 0x4e, 0x9e, 0xf5,
- 0xdf, 0x8d, 0x12, 0x64, 0xfb, 0xda, 0xe9, 0xae, 0x6b, 0xb7, 0x6c, 0xe9,
- 0xfd, 0x58, 0xf3, 0x96, 0xfc, 0x9d, 0x0c, 0x7e, 0x40, 0x7f, 0x0f, 0x4c,
- 0x90, 0x19, 0x55, 0x09, 0xf9, 0xfb, 0xaf, 0x9d, 0xbc, 0xfd, 0xac, 0x74,
- 0xff, 0xed, 0xa7, 0x31, 0xf2, 0x06, 0x5c, 0x6b, 0x3a, 0x7d, 0x5c, 0x45,
- 0x59, 0xd3, 0xfc, 0xdb, 0xe2, 0x60, 0xa6, 0xf1, 0xd3, 0xff, 0xeb, 0xf0,
- 0x36, 0xc6, 0xb9, 0x4b, 0xd3, 0x4d, 0x0a, 0x87, 0xa2, 0xcb, 0x24, 0xbc,
- 0x38, 0x9f, 0xbd, 0xee, 0xfc, 0x2c, 0x74, 0xff, 0xee, 0xc6, 0xf8, 0xc1,
- 0x9d, 0xb0, 0xf0, 0xe9, 0xda, 0x69, 0xa1, 0x53, 0xf0, 0x5e, 0x0a, 0x4c,
- 0x94, 0xb2, 0xfe, 0x7d, 0x4a, 0x0a, 0xd7, 0x9d, 0x3e, 0x4e, 0x61, 0x5a,
- 0x1d, 0x3f, 0xcd, 0xed, 0x8f, 0x7c, 0x6c, 0x9d, 0x3f, 0xfe, 0xe6, 0xe9,
- 0xfa, 0xbd, 0xb4, 0xe6, 0x3e, 0x40, 0x3a, 0x01, 0x16, 0xea, 0x28, 0x13,
- 0x89, 0xfe, 0xab, 0xfb, 0x55, 0x75, 0x6f, 0x3a, 0x7f, 0xb5, 0x0e, 0xac,
- 0xe1, 0x77, 0xb3, 0xa7, 0xff, 0x5e, 0x1b, 0x46, 0x1a, 0x71, 0x01, 0x0e,
- 0x8a, 0x47, 0x57, 0x0b, 0xbb, 0x3a, 0xd0, 0xf2, 0x7c, 0x35, 0xbb, 0xe1,
- 0xd3, 0xfe, 0x7b, 0x0e, 0x1f, 0x80, 0x7b, 0x79, 0xd1, 0xaf, 0x3e, 0x57,
- 0x09, 0x67, 0xb9, 0x85, 0x74, 0x74, 0xff, 0x27, 0xff, 0xc1, 0xf2, 0x93,
- 0x27, 0x43, 0x87, 0xbf, 0xac, 0x47, 0x3b, 0x4d, 0x34, 0x3a, 0x7f, 0xfd,
- 0x4a, 0xe0, 0xb7, 0xd5, 0xd6, 0x69, 0x4d, 0xe2, 0x96, 0x5f, 0xc5, 0x26,
- 0x5c, 0x90, 0x86, 0xda, 0x2c, 0x90, 0xe9, 0xfb, 0x6d, 0xab, 0xc9, 0x81,
- 0xd3, 0xf0, 0x58, 0x0b, 0x3c, 0xe8, 0x76, 0x67, 0xcf, 0xd0, 0x78, 0x17,
- 0xcc, 0xf5, 0xbb, 0x4c, 0x97, 0xcd, 0x71, 0xa9, 0x8b, 0xdf, 0x0c, 0x8a,
- 0x8d, 0x27, 0xf9, 0xaf, 0x8e, 0x71, 0x87, 0xda, 0x18, 0x38, 0x5b, 0x6c,
- 0xc2, 0x77, 0x98, 0xf2, 0xb9, 0x1e, 0x8f, 0xe8, 0x4d, 0xcf, 0xfe, 0x0a,
- 0xd3, 0xad, 0xd3, 0x83, 0x40, 0xf3, 0xa7, 0x05, 0x6b, 0xce, 0x95, 0x01,
- 0xf3, 0xa9, 0x26, 0x7f, 0xea, 0xd8, 0xb6, 0x1f, 0xb7, 0xbb, 0xd7, 0x9d,
- 0x3f, 0x5f, 0x97, 0xa6, 0x9a, 0x1d, 0x25, 0xb3, 0x35, 0xe2, 0x93, 0x3d,
- 0x19, 0x98, 0x18, 0xdd, 0x26, 0xe8, 0x63, 0x6f, 0xc9, 0x33, 0xa4, 0x98,
- 0x7b, 0x69, 0x1f, 0xd4, 0xab, 0xbc, 0x61, 0xd4, 0x04, 0xea, 0x3d, 0xd9,
- 0xef, 0xd0, 0xad, 0xcc, 0x36, 0x79, 0x09, 0x8e, 0xe9, 0xb3, 0xd3, 0xf9,
- 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x35, 0x9f, 0x07, 0xae, 0xfc, 0x68, 0xa9,
- 0x66, 0xbf, 0x1a, 0x21, 0xa9, 0x2e, 0x8f, 0x52, 0xcc, 0xa7, 0xfe, 0x5d,
- 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x3e, 0x9f, 0x07, 0xae, 0xfc, 0x68,
- 0xb1, 0xe7, 0xf8, 0x6f, 0xfe, 0xd1, 0x87, 0x03, 0xa4, 0xba, 0x3e, 0xa7,
- 0x0c, 0xa7, 0x6b, 0xa2, 0xbf, 0x9d, 0x3f, 0x3b, 0x63, 0x5b, 0xbe, 0x1d,
- 0x3f, 0xc3, 0x7f, 0x66, 0xf9, 0xcb, 0x3a, 0x7b, 0xe5, 0x20, 0x1d, 0x3f,
- 0xff, 0xcc, 0x03, 0x5d, 0x56, 0xf6, 0x9e, 0xda, 0x73, 0x37, 0x89, 0xd0,
- 0x88, 0x85, 0xd9, 0x0c, 0xeb, 0xbf, 0x1a, 0x2d, 0x09, 0xff, 0x5e, 0x8e,
- 0xfe, 0xb0, 0xc2, 0xb4, 0x3a, 0x3c, 0x7d, 0x20, 0x4f, 0x3f, 0xff, 0xfc,
- 0x81, 0xbb, 0x14, 0x6e, 0x26, 0xdb, 0x3b, 0xac, 0x85, 0x7a, 0xb8, 0x74,
- 0x02, 0x25, 0xf6, 0x43, 0x3f, 0x3a, 0xfd, 0xc1, 0x6f, 0x8e, 0x9f, 0x37,
- 0x2b, 0x6c, 0x74, 0xff, 0xf5, 0x73, 0x34, 0xe6, 0xd9, 0xd5, 0x6f, 0x6c,
- 0x74, 0x60, 0x7e, 0xa2, 0x4b, 0x0c, 0x8c, 0x8a, 0x85, 0x34, 0xff, 0xbe,
- 0x6f, 0x6d, 0x1c, 0xbb, 0xc0, 0xe9, 0xfe, 0x4e, 0xc5, 0xe0, 0xd5, 0xd1,
- 0xd3, 0xff, 0xfd, 0xba, 0x7f, 0xb6, 0x9b, 0x6a, 0x07, 0xf0, 0x59, 0x59,
- 0x3a, 0x55, 0x94, 0x4d, 0x70, 0xde, 0x7e, 0x06, 0xe6, 0x15, 0xa1, 0xd3,
- 0xee, 0x6e, 0xc7, 0xf9, 0xd3, 0xfc, 0x3d, 0xe1, 0xd6, 0xe8, 0x58, 0xe9,
- 0x55, 0x1f, 0x0f, 0x8a, 0x21, 0x11, 0x68, 0x30, 0x8e, 0x9f, 0xd5, 0xb7,
- 0x13, 0x68, 0xa3, 0xa7, 0xf3, 0xe8, 0x32, 0x2d, 0x81, 0xd3, 0xab, 0x76,
- 0x74, 0xf9, 0xce, 0xbb, 0xec, 0x4e, 0x8e, 0x8f, 0x16, 0xc6, 0xa7, 0xfa,
- 0xab, 0x4a, 0xf7, 0xab, 0x43, 0xa2, 0x93, 0x02, 0xc4, 0xca, 0xdd, 0xb2,
- 0x45, 0x3d, 0x5b, 0xbe, 0x1d, 0x3f, 0x20, 0xf6, 0xfa, 0xc9, 0xd3, 0xff,
- 0xfc, 0x83, 0xdb, 0xeb, 0x3a, 0xab, 0x8d, 0x8f, 0xd7, 0xbd, 0xa1, 0xd1,
- 0xfd, 0x12, 0x9c, 0x2c, 0x92, 0xdd, 0xa5, 0xf3, 0x6d, 0x70, 0x95, 0x8c,
- 0x3a, 0x85, 0xe5, 0x46, 0x45, 0xb8, 0x75, 0x7c, 0x4c, 0x30, 0xd9, 0xcc,
- 0x37, 0x39, 0x19, 0x46, 0xb1, 0xef, 0xe8, 0x5a, 0x4f, 0xce, 0xe9, 0xd0,
- 0xb3, 0x87, 0x4f, 0x56, 0xef, 0x87, 0x49, 0xdb, 0xa3, 0xd0, 0x13, 0x09,
- 0xf0, 0x7a, 0xef, 0xc6, 0x8b, 0x5a, 0x7f, 0xd6, 0xf5, 0xd0, 0x7a, 0xef,
- 0xc6, 0x8a, 0x0e, 0x4b, 0xd7, 0x11, 0x4b, 0x45, 0x6a, 0x32, 0x9f, 0xfc,
- 0xb5, 0x5b, 0xd7, 0x41, 0xeb, 0xbf, 0x1a, 0x28, 0xb9, 0xfc, 0xba, 0x0f,
- 0x5d, 0xf8, 0xd1, 0x75, 0x43, 0xd9, 0x6d, 0xde, 0x84, 0x8a, 0x13, 0x2a,
- 0x17, 0x1b, 0x9f, 0x5e, 0xfa, 0x3d, 0x6c, 0x9d, 0x71, 0x52, 0x7c, 0x1e,
- 0xbb, 0xf1, 0xa2, 0x21, 0x9d, 0xba, 0xe8, 0xe9, 0x2e, 0x8f, 0x3b, 0x13,
- 0x29, 0xfc, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x1b, 0x4f, 0xe5, 0xd0, 0x7a,
- 0xef, 0xc6, 0x8a, 0x6e, 0x7f, 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x54, 0x13,
- 0xf9, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0xa6, 0x9f, 0x07, 0xae, 0xfc, 0x68,
- 0xac, 0x27, 0xc9, 0xa7, 0x5d, 0x81, 0xd3, 0xfc, 0xf5, 0xd0, 0x7a, 0xef,
- 0xc6, 0x88, 0xfe, 0x75, 0x36, 0x07, 0x49, 0x74, 0x8b, 0x9f, 0x19, 0x59,
- 0x48, 0xa1, 0xcf, 0xfe, 0x5a, 0xad, 0xeb, 0xa0, 0xf5, 0xdf, 0x8d, 0x13,
- 0x7c, 0xff, 0xca, 0xb7, 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x4f, 0xd3, 0xed,
- 0x76, 0xed, 0xeb, 0x56, 0x27, 0x4b, 0x67, 0x43, 0xb2, 0x3c, 0x6e, 0xcd,
- 0xa7, 0xfb, 0x5d, 0x6d, 0xdf, 0x39, 0x77, 0xa1, 0xd3, 0xed, 0x5f, 0xc2,
- 0xfc, 0x74, 0xfb, 0x5c, 0x76, 0x7f, 0x7f, 0x63, 0xa7, 0xff, 0x99, 0x99,
- 0x99, 0x99, 0x99, 0xb1, 0xc9, 0xd3, 0xe0, 0x4c, 0x2d, 0x45, 0x4d, 0xa6,
- 0x85, 0x45, 0x1b, 0xed, 0x09, 0xa5, 0xd9, 0x4b, 0x34, 0x30, 0xc8, 0xc9,
- 0xcc, 0x2a, 0x27, 0x80, 0x51, 0x8e, 0x9f, 0xff, 0xa9, 0x59, 0xe0, 0x5e,
- 0x1d, 0x6d, 0xb3, 0xce, 0xf6, 0x74, 0xfa, 0xfd, 0xb4, 0x03, 0xa7, 0xff,
- 0xff, 0x0d, 0xff, 0x40, 0x67, 0xea, 0xda, 0x2b, 0xa6, 0xd5, 0xad, 0xde,
- 0xd0, 0x0e, 0x9e, 0xb7, 0xa6, 0x27, 0x47, 0x49, 0x90, 0x82, 0xee, 0xc9,
- 0x45, 0xfa, 0x7f, 0xfc, 0xee, 0xd8, 0xbe, 0xc7, 0xed, 0x5f, 0x20, 0x27,
- 0xf3, 0xa7, 0xb0, 0x52, 0x3c, 0xe9, 0xf6, 0x47, 0xbb, 0x79, 0xd3, 0xfb,
- 0x6c, 0xa5, 0xfd, 0xf3, 0x1d, 0x20, 0x63, 0xfd, 0xa2, 0x24, 0x27, 0x9f,
- 0xf3, 0x63, 0xd7, 0xe6, 0xd7, 0xef, 0xbc, 0x9d, 0x2d, 0x79, 0xd3, 0x66,
- 0x8e, 0x84, 0x35, 0x3f, 0x0a, 0x4f, 0xfd, 0xd3, 0x72, 0xf3, 0x5b, 0xda,
- 0x28, 0xe9, 0xdc, 0x47, 0x0e, 0x86, 0x3d, 0xfc, 0xa1, 0xc3, 0x2b, 0xbe,
- 0xa2, 0x74, 0x8c, 0xfd, 0xc3, 0xd0, 0x86, 0xca, 0x8c, 0x45, 0xc3, 0x90,
- 0x80, 0x9c, 0xe7, 0xe5, 0x1d, 0x3f, 0xd5, 0xcc, 0xd7, 0x37, 0x5f, 0x1d,
- 0x16, 0x7a, 0xe2, 0x3f, 0x35, 0x89, 0xd0, 0x06, 0xd1, 0x44, 0x13, 0xb4,
- 0xd3, 0x43, 0xa7, 0xb0, 0x14, 0x62, 0x96, 0x5f, 0xcd, 0x8b, 0xce, 0x9f,
- 0xdf, 0xdb, 0x99, 0xdd, 0xf6, 0x74, 0xc9, 0xe3, 0xa5, 0x8b, 0x1f, 0x0f,
- 0xf1, 0x7e, 0x1a, 0xc3, 0x26, 0x0d, 0xb3, 0xfe, 0xe1, 0x21, 0x3f, 0xf6,
- 0x1d, 0xfd, 0x43, 0xdb, 0x8d, 0xcb, 0x3a, 0x7f, 0xe6, 0xdf, 0xee, 0xb8,
- 0x94, 0xe3, 0x28, 0xe9, 0xe6, 0xe6, 0x7c, 0x68, 0x83, 0xa7, 0xeb, 0xdb,
- 0x6b, 0xfb, 0x79, 0xd0, 0x08, 0xec, 0x52, 0x3f, 0x11, 0x9d, 0x17, 0x4c,
- 0x1d, 0x1d, 0x36, 0x9a, 0x1d, 0x0f, 0x35, 0xda, 0x0b, 0x4f, 0x65, 0x91,
- 0xd1, 0x4b, 0x34, 0x53, 0xec, 0xfe, 0xeb, 0xec, 0x9d, 0x08, 0x7b, 0xdf,
- 0x8c, 0xa7, 0x69, 0xa6, 0x85, 0x41, 0x4b, 0x2f, 0xe7, 0x93, 0x44, 0x70,
- 0xa8, 0xf1, 0xbb, 0x41, 0x98, 0x44, 0xe2, 0x77, 0x0e, 0xc1, 0x7d, 0x9c,
- 0x29, 0x93, 0xa7, 0xba, 0xb1, 0xf8, 0xe9, 0xff, 0x98, 0x7e, 0x16, 0xc5,
- 0xc6, 0x1f, 0x8e, 0x84, 0x44, 0x07, 0xc3, 0x59, 0x22, 0x9f, 0x35, 0x06,
- 0xd0, 0xe9, 0xd4, 0xad, 0x79, 0xd3, 0xfa, 0xb2, 0x35, 0xcd, 0xa1, 0xd1,
- 0xd1, 0xe7, 0x88, 0xfc, 0x38, 0x89, 0x57, 0x4e, 0x73, 0xf7, 0x29, 0xc1,
- 0x65, 0x1e, 0x20, 0x29, 0xf5, 0x8f, 0x5b, 0x63, 0x44, 0x04, 0xb3, 0x73,
- 0x3f, 0x03, 0x3e, 0xf1, 0xd0, 0xe9, 0xfe, 0x60, 0xc3, 0x55, 0x38, 0x8a,
- 0x3a, 0x79, 0x4d, 0x4a, 0x3a, 0x7c, 0xdf, 0x26, 0x39, 0x3a, 0x7f, 0x03,
- 0x99, 0x41, 0xe2, 0x1d, 0x3d, 0x8f, 0xc0, 0xc5, 0x4d, 0xa6, 0x85, 0x43,
- 0x1b, 0xad, 0x08, 0xa7, 0xeb, 0x07, 0xbc, 0x50, 0xa5, 0x9a, 0x18, 0x65,
- 0x5b, 0x95, 0x0c, 0x54, 0x5f, 0x04, 0x3d, 0x96, 0xd9, 0xd0, 0x90, 0x70,
- 0xa3, 0xb8, 0x46, 0x4f, 0xbb, 0xe7, 0x77, 0xf8, 0xd1, 0x03, 0xcf, 0xfb,
- 0x7d, 0xe0, 0xda, 0x9b, 0x8d, 0xd1, 0xd3, 0xac, 0x30, 0x3a, 0x6d, 0x34,
- 0x3a, 0x7f, 0x02, 0x53, 0xaf, 0xcf, 0x5f, 0x8d, 0x9e, 0x83, 0x71, 0xd2,
- 0x30, 0x81, 0xd6, 0x7f, 0xe1, 0xaf, 0xfb, 0xb7, 0xfe, 0xbc, 0x58, 0xe8,
- 0x63, 0xe9, 0xa2, 0x39, 0xff, 0xd4, 0xa5, 0x5b, 0xe8, 0x3d, 0x77, 0xe3,
- 0x44, 0x31, 0x1b, 0x3f, 0x31, 0x20, 0x9f, 0x07, 0xae, 0xfc, 0x68, 0x82,
- 0xa7, 0x6d, 0x94, 0x74, 0x51, 0xe6, 0xa1, 0x94, 0xf7, 0x32, 0xdf, 0x15,
- 0x3a, 0xc3, 0x02, 0xa7, 0xbb, 0x1b, 0xfe, 0x54, 0xfe, 0x4c, 0x2b, 0x99,
- 0x6f, 0x8a, 0x82, 0xa7, 0xea, 0xf3, 0x6d, 0x94, 0x54, 0xda, 0x68, 0x54,
- 0xfc, 0x2c, 0x38, 0x20, 0x15, 0x14, 0x98, 0x57, 0x88, 0x94, 0x37, 0xb2,
- 0x3f, 0x8c, 0xc4, 0x2b, 0x42, 0xbf, 0xc3, 0x13, 0x20, 0x14, 0xb3, 0xf4,
- 0x95, 0xbd, 0x3c, 0x3d, 0xc7, 0x3d, 0x3f, 0xe6, 0x7d, 0x8d, 0x64, 0x1b,
- 0x27, 0x4f, 0xf7, 0x36, 0xce, 0xba, 0x6f, 0x98, 0xe9, 0xfe, 0x6c, 0x5f,
- 0xac, 0xde, 0xa5, 0x1d, 0x0c, 0x7e, 0xdb, 0x3b, 0x9f, 0xff, 0x9c, 0xbb,
- 0x7d, 0xef, 0x55, 0x61, 0xdf, 0x3b, 0xbf, 0xc6, 0x8b, 0xee, 0x77, 0x2b,
- 0xc7, 0x4f, 0x70, 0x69, 0xe7, 0x43, 0x1b, 0xb4, 0x1b, 0x9f, 0xf0, 0xa3,
- 0xf9, 0xba, 0x04, 0xc9, 0xd3, 0xfb, 0x9f, 0x7e, 0x17, 0xee, 0x8f, 0x10,
- 0x0c, 0xeb, 0x07, 0x9e, 0x20, 0x18, 0xa3, 0xe9, 0xed, 0x0a, 0x6b, 0x79,
- 0xe2, 0x01, 0x9e, 0xb1, 0xc5, 0xe7, 0x88, 0x06, 0x7f, 0x27, 0xb7, 0x5f,
- 0x7c, 0xc7, 0x88, 0x06, 0x72, 0x0f, 0x47, 0x88, 0x06, 0x3a, 0x45, 0xc2,
- 0x88, 0xb6, 0x5c, 0xe9, 0x02, 0x70, 0x37, 0x0f, 0x10, 0x0c, 0x1e, 0x20,
- 0x19, 0x99, 0x47, 0x88, 0x06, 0x3a, 0x37, 0x28, 0x2f, 0x3c, 0x8a, 0xe9,
- 0x8f, 0x10, 0x0c, 0xee, 0x5f, 0x8f, 0x10, 0x0c, 0xff, 0x86, 0xde, 0xbd,
- 0xa7, 0xac, 0x0f, 0x10, 0x0c, 0xd7, 0xd1, 0xe2, 0x01, 0x9f, 0xc3, 0x7a,
- 0x67, 0x2d, 0xf1, 0xe2, 0x01, 0x9f, 0x27, 0xfb, 0x1f, 0x8f, 0x10, 0x0c,
- 0xc9, 0x93, 0xc4, 0x03, 0x00, 0x7a, 0xfc, 0x35, 0x9f, 0x70, 0x5b, 0x17,
- 0x9a, 0x20, 0x19, 0xbe, 0x63, 0xc4, 0x02, 0xb3, 0x69, 0x3e, 0x46, 0x55,
- 0xf4, 0x78, 0x80, 0x67, 0xbb, 0xb1, 0xf1, 0xe2, 0x01, 0x9c, 0xc1, 0xe3,
- 0xc4, 0x03, 0x3f, 0xea, 0xc7, 0x3d, 0x35, 0x0f, 0xd9, 0x3c, 0x40, 0x33,
- 0xee, 0xed, 0xef, 0x63, 0xc4, 0x03, 0x14, 0x88, 0x0d, 0xa6, 0x4c, 0x1f,
- 0x1e, 0x20, 0x18, 0x7a, 0xa8, 0xfe, 0x88, 0xea, 0x12, 0xe8, 0xab, 0xb3,
- 0x3f, 0x8c, 0xf2, 0x5d, 0xc8, 0x53, 0xf6, 0x45, 0x3e, 0xae, 0x66, 0xf1,
- 0x3c, 0x40, 0x33, 0xfb, 0xa6, 0xf3, 0x80, 0xdc, 0x3c, 0x40, 0x3d, 0x1b,
- 0x49, 0xc0, 0xda, 0x1e, 0x20, 0x18, 0xf1, 0xfc, 0x82, 0x8c, 0xf2, 0x0b,
- 0xf2, 0x78, 0x80, 0x67, 0xeb, 0x71, 0xf5, 0x8b, 0xcf, 0x10, 0x0c, 0x52,
- 0x22, 0x7e, 0x21, 0xec, 0xb6, 0x7f, 0xb6, 0xd9, 0x5e, 0x7b, 0x0f, 0x8f,
- 0x10, 0x0c, 0x90, 0xf1, 0x00, 0xcd, 0x78, 0x74, 0x7c, 0x7b, 0x47, 0x98,
- 0x3e, 0x3c, 0x40, 0x33, 0xeb, 0xe6, 0x53, 0x13, 0xc4, 0x03, 0x3f, 0x20,
- 0xf6, 0xfa, 0xc9, 0xe2, 0x01, 0x86, 0x44, 0x80, 0x91, 0xf0, 0xd2, 0x3a,
- 0x64, 0x05, 0x54, 0x36, 0x9c, 0x40, 0x06, 0x0d, 0x90, 0xd9, 0x77, 0xc5,
- 0x19, 0x95, 0xaf, 0xc8, 0xf0, 0x75, 0xa1, 0x29, 0xfa, 0x17, 0xf3, 0xae,
- 0xfc, 0x68, 0x80, 0x56, 0x8b, 0xd9, 0xef, 0xee, 0xcf, 0xa5, 0x1d, 0x3f,
- 0xf3, 0xc6, 0xbd, 0xb4, 0xfb, 0xee, 0xdc, 0x3a, 0x6f, 0x98, 0xa9, 0x7f,
- 0x2a, 0x76, 0xdb, 0x03, 0xa6, 0xd3, 0x42, 0xa1, 0x0f, 0x73, 0x5e, 0x2c,
- 0xe0, 0x96, 0x83, 0x93, 0x94, 0x99, 0x29, 0x67, 0x83, 0x3f, 0xfb, 0x99,
- 0xaf, 0xe8, 0x1f, 0xbe, 0xf9, 0xb1, 0x3a, 0x30, 0x65, 0xa6, 0xbc, 0x7f,
- 0xd4, 0x96, 0xb4, 0x39, 0xb2, 0xbf, 0xa1, 0xc9, 0xf8, 0xb2, 0x7f, 0x27,
- 0x3f, 0x3a, 0x74, 0xd9, 0x3a, 0x7e, 0x07, 0x1e, 0xc1, 0x81, 0xd3, 0xfe,
- 0x7e, 0x75, 0x0d, 0x29, 0x83, 0xf9, 0xd3, 0xff, 0x06, 0xee, 0x9e, 0xc1,
- 0xf7, 0xe5, 0x1d, 0x3f, 0x7e, 0xd0, 0x12, 0xb6, 0x54, 0xf3, 0x9b, 0xb7,
- 0x0e, 0x9f, 0x53, 0x8f, 0x6c, 0x4e, 0x9e, 0xa1, 0x67, 0x95, 0x00, 0x7d,
- 0x42, 0x46, 0xee, 0x51, 0x0c, 0x9b, 0xcd, 0x16, 0xa2, 0x06, 0xd1, 0x2e,
- 0x13, 0x13, 0xf6, 0x39, 0x00, 0x6e, 0x1d, 0x3c, 0x83, 0xcc, 0x9d, 0x3b,
- 0xb7, 0x63, 0x27, 0x4f, 0xfd, 0xf2, 0xab, 0xdb, 0x4e, 0xb7, 0xdf, 0xf3,
- 0xa7, 0xf7, 0x4d, 0x8e, 0x6b, 0x1e, 0x1d, 0x3f, 0xcd, 0xc4, 0xf2, 0x74,
- 0xdc, 0x3a, 0x6e, 0x66, 0x8f, 0xb0, 0x0d, 0x67, 0xf3, 0xeb, 0x3f, 0xb3,
- 0xca, 0x3a, 0x19, 0x33, 0x74, 0x22, 0xb8, 0x5a, 0xf6, 0x59, 0x3e, 0xb7,
- 0x5d, 0x74, 0xc7, 0x4d, 0x9c, 0x9d, 0x3b, 0x4d, 0x34, 0x3a, 0x6f, 0xac,
- 0xa5, 0x97, 0xf0, 0x07, 0xb5, 0x93, 0x59, 0xff, 0x56, 0x46, 0xff, 0xb8,
- 0x28, 0xe1, 0xd3, 0xaf, 0xea, 0x2a, 0x1e, 0x8f, 0xf5, 0x42, 0x13, 0x64,
- 0x3a, 0xc7, 0xf3, 0xfb, 0x83, 0x58, 0xfd, 0xf9, 0xe7, 0x4f, 0xf0, 0xd3,
- 0xaa, 0x5e, 0x9a, 0x68, 0x54, 0xe5, 0x5f, 0x0e, 0x8d, 0x9e, 0xbb, 0xa3,
- 0xc9, 0xf5, 0x38, 0xf6, 0x79, 0xd3, 0xf6, 0x1d, 0x35, 0x0f, 0x47, 0x43,
- 0x26, 0x96, 0x88, 0xb7, 0x08, 0xde, 0x12, 0x7e, 0x27, 0x9f, 0x9d, 0x84,
- 0x06, 0x01, 0x3a, 0x7f, 0xf5, 0x75, 0x6a, 0xac, 0x5f, 0x5f, 0x57, 0x47,
- 0x4d, 0xbb, 0x3a, 0x67, 0x32, 0x74, 0xfa, 0x9d, 0x20, 0xf5, 0x46, 0xb3,
- 0xf0, 0xac, 0x6a, 0x45, 0xba, 0xdd, 0xe7, 0xba, 0xad, 0xd9, 0xd3, 0xff,
- 0x35, 0x0b, 0xf7, 0x42, 0x2d, 0xa1, 0xd2, 0x40, 0x44, 0x30, 0x92, 0xf0,
- 0x86, 0x30, 0x6e, 0x5b, 0x5f, 0x1e, 0xb7, 0x52, 0x8c, 0x7f, 0x97, 0xfa,
- 0x16, 0x08, 0x42, 0x14, 0xbf, 0x65, 0x3c, 0x6e, 0x3b, 0x1b, 0x4c, 0xf8,
- 0xb0, 0x63, 0x57, 0xe4, 0xa8, 0xbe, 0xd3, 0xdd, 0x46, 0xd7, 0x3f, 0xd4,
- 0x02, 0xdc, 0x7d, 0x6c, 0xe9, 0xf8, 0x7e, 0xae, 0xad, 0xe7, 0x4f, 0xad,
- 0xfa, 0xba, 0x43, 0xa7, 0xdf, 0x9c, 0x7b, 0x6b, 0xca, 0x86, 0x45, 0xcd,
- 0x1a, 0xec, 0xb7, 0xf1, 0x4c, 0xff, 0xdf, 0xc7, 0xbb, 0xfd, 0x59, 0x46,
- 0x13, 0xa7, 0x6b, 0x27, 0x47, 0x40, 0x1f, 0x22, 0x91, 0x65, 0xf8, 0xd1,
- 0x02, 0xcb, 0x86, 0xa0, 0x52, 0x49, 0xc3, 0x79, 0xa0, 0xfc, 0xff, 0x93,
- 0x5b, 0x69, 0xf9, 0x7f, 0x7c, 0xc5, 0x4f, 0xf8, 0x5b, 0x15, 0x5f, 0x2b,
- 0x1e, 0x1d, 0x3f, 0xff, 0xb6, 0xc1, 0xf5, 0x3a, 0x4c, 0xe6, 0x87, 0xd6,
- 0x3f, 0x1d, 0x3f, 0xf6, 0x6f, 0x1d, 0x4a, 0x6a, 0x1e, 0x6b, 0x1d, 0x00,
- 0x8e, 0x6d, 0x9f, 0x71, 0x82, 0x19, 0x35, 0x94, 0x8c, 0xaa, 0x7f, 0xff,
- 0x83, 0x0a, 0x47, 0x2e, 0xdf, 0x96, 0x57, 0x5b, 0x61, 0xf1, 0xd3, 0xb0,
- 0x17, 0x9d, 0x0c, 0xaa, 0x19, 0x4b, 0xbb, 0x8e, 0x02, 0xca, 0x3b, 0x65,
- 0x9f, 0xcf, 0x72, 0x86, 0xf7, 0x47, 0x4f, 0xfe, 0x0f, 0x0d, 0x3a, 0x1a,
- 0x60, 0x6c, 0x9d, 0x3f, 0xad, 0xcd, 0xd2, 0xab, 0x27, 0x45, 0x1f, 0xc3,
- 0xa4, 0x69, 0xf9, 0x3f, 0xf2, 0xa9, 0x47, 0x4f, 0xab, 0xa4, 0x0c, 0x9d,
- 0x3b, 0x9c, 0xc4, 0xe9, 0xff, 0xb1, 0xf2, 0x6f, 0x53, 0xbd, 0x6d, 0x14,
- 0x74, 0xb3, 0xf1, 0xf3, 0x70, 0x76, 0x4d, 0x82, 0x2d, 0x74, 0x84, 0x64,
- 0x22, 0x66, 0x9b, 0x23, 0xe4, 0x38, 0xa7, 0xfc, 0x29, 0xfb, 0x1a, 0x75,
- 0x8b, 0x7e, 0x3a, 0x77, 0x56, 0x07, 0x4f, 0xbe, 0xb1, 0xa7, 0x73, 0xa1,
- 0x8f, 0x13, 0xb1, 0xb9, 0xca, 0xc5, 0xc3, 0xa7, 0xfe, 0x56, 0x54, 0xdd,
- 0x30, 0x76, 0xdf, 0x1d, 0x3f, 0xe6, 0xb1, 0xae, 0x71, 0x34, 0xe1, 0xd0,
- 0xc8, 0x9f, 0x41, 0xee, 0xd1, 0x61, 0x95, 0xc5, 0x3e, 0x3d, 0xda, 0x35,
- 0xcc, 0x22, 0x39, 0x0c, 0x19, 0xff, 0xcf, 0x4d, 0xd3, 0x88, 0xe7, 0x6e,
- 0xfd, 0xe4, 0xe9, 0xfc, 0x9b, 0xea, 0xc5, 0xb6, 0x74, 0xf9, 0xb0, 0x67,
- 0x76, 0x3a, 0x7e, 0xef, 0xf6, 0xeb, 0x1c, 0x9d, 0x3f, 0xff, 0xfe, 0x06,
- 0xe0, 0xdf, 0x93, 0x2e, 0x20, 0x79, 0xb3, 0xc6, 0xc5, 0xbf, 0x56, 0x4e,
- 0x9f, 0xff, 0xff, 0xf6, 0x73, 0x5c, 0xdd, 0xab, 0x20, 0x09, 0x8f, 0x2e,
- 0xff, 0xd5, 0x39, 0xdf, 0x1b, 0x4c, 0x58, 0xe8, 0x64, 0xc7, 0x6e, 0x10,
- 0x33, 0xdf, 0x5e, 0x39, 0x3a, 0x6d, 0x34, 0x3a, 0x32, 0x6e, 0xf4, 0x23,
- 0x9f, 0x26, 0xee, 0xb6, 0x52, 0xcd, 0x14, 0x62, 0xaa, 0xc5, 0xc5, 0x0d,
- 0x98, 0xbb, 0x05, 0x23, 0x1a, 0x76, 0x61, 0x09, 0x3b, 0x4d, 0x34, 0x2a,
- 0x79, 0xfc, 0xaf, 0x14, 0xb2, 0xfe, 0x7d, 0x5d, 0x27, 0xd9, 0x3d, 0xdf,
- 0xd2, 0xb0, 0x3e, 0x51, 0x30, 0x98, 0x32, 0x74, 0xe7, 0x4d, 0xe3, 0xa1,
- 0x8d, 0x92, 0x0a, 0xcf, 0xc3, 0x8e, 0x5c, 0xae, 0x1d, 0x3f, 0xfc, 0x3c,
- 0x72, 0x82, 0xad, 0x4d, 0xb4, 0xe8, 0xe9, 0xf6, 0x1a, 0xf4, 0xac, 0x4e,
- 0x9f, 0x26, 0x5b, 0x05, 0x1e, 0xcf, 0xd9, 0xf3, 0x58, 0x7d, 0xd9, 0xec,
- 0xfd, 0x9a, 0xde, 0x7b, 0x3f, 0x67, 0xbb, 0x7d, 0x64, 0xf6, 0x7e, 0xc7,
- 0x47, 0xa2, 0x24, 0x53, 0xe6, 0xac, 0xd0, 0x9e, 0xcf, 0xd8, 0x3d, 0x9f,
- 0xb3, 0x5f, 0x0f, 0x67, 0xea, 0x8b, 0x79, 0x3c, 0x4f, 0xe7, 0xb4, 0x89,
- 0xea, 0xd6, 0x4f, 0x8f, 0x67, 0xec, 0x1e, 0xcf, 0xd9, 0xbe, 0x63, 0xd9,
- 0xfb, 0x3f, 0xd5, 0xf5, 0x85, 0x3a, 0xae, 0x8f, 0x67, 0xec, 0xfd, 0x5b,
- 0x4c, 0xf7, 0x81, 0xec, 0xfd, 0x8f, 0x91, 0x48, 0x24, 0x79, 0x46, 0x9e,
- 0x0c, 0x1b, 0x87, 0xb3, 0xf6, 0x0f, 0x67, 0xed, 0x1a, 0xe9, 0xb4, 0xd0,
- 0xf6, 0x7e, 0xc3, 0xd5, 0x88, 0xf4, 0x69, 0x50, 0x85, 0xc6, 0x13, 0x60,
- 0x50, 0xa3, 0x1c, 0xc2, 0xef, 0x8b, 0xda, 0x13, 0x4f, 0x53, 0xdb, 0xf9,
- 0x6c, 0xfd, 0x2d, 0x12, 0x13, 0xfe, 0xaf, 0x75, 0x41, 0xa5, 0xed, 0xc3,
- 0xa6, 0x7e, 0x05, 0x46, 0x08, 0x98, 0xc5, 0x08, 0x4f, 0xe0, 0x17, 0x25,
- 0xae, 0x71, 0x96, 0x7f, 0xfc, 0xf0, 0x67, 0x56, 0xe3, 0x75, 0xb6, 0x55,
- 0xb8, 0x74, 0xfe, 0x77, 0xbc, 0xa6, 0x5c, 0xa3, 0xa3, 0x14, 0x46, 0x02,
- 0xbc, 0x32, 0xf3, 0x13, 0xd5, 0xe8, 0x7d, 0x0b, 0xae, 0x73, 0x8f, 0xb8,
- 0x5c, 0x4f, 0xfb, 0xfb, 0x62, 0x2d, 0xbd, 0xf7, 0xe3, 0xa7, 0xe1, 0xbf,
- 0xfb, 0xb7, 0x9d, 0x3b, 0x4d, 0x34, 0x2a, 0x77, 0xe6, 0xf8, 0xa5, 0x97,
- 0xf3, 0xfe, 0x1b, 0x7f, 0xe0, 0xa7, 0x56, 0x07, 0x4f, 0xf0, 0xdf, 0xda,
- 0x9e, 0xdf, 0x62, 0x74, 0x74, 0x99, 0xa2, 0x90, 0x7e, 0x4c, 0x12, 0xde,
- 0x1f, 0x4f, 0xf8, 0x45, 0x3b, 0x76, 0x33, 0xac, 0xdc, 0x3a, 0x76, 0x9a,
- 0x68, 0x58, 0x84, 0x13, 0xe0, 0xf5, 0xdf, 0x8b, 0x10, 0x81, 0x66, 0xb6,
- 0x76, 0x9a, 0x68, 0x58, 0x83, 0xd0, 0x58, 0x83, 0xcb, 0x35, 0xb2, 0x55,
- 0x22, 0x63, 0xce, 0x13, 0xff, 0x6d, 0x9e, 0x9c, 0xad, 0xf9, 0x94, 0x74,
- 0x31, 0xf5, 0x3a, 0x28, 0x9f, 0x71, 0xb8, 0xca, 0x3a, 0x78, 0x51, 0xbf,
- 0x9d, 0x3b, 0xf3, 0x7c, 0x74, 0x60, 0x6f, 0xd4, 0x43, 0x3e, 0xf3, 0x6d,
- 0x94, 0x54, 0xf8, 0x6c, 0x46, 0x8a, 0x9a, 0xbc, 0x54, 0xda, 0x68, 0x54,
- 0x51, 0xfb, 0x64, 0x9b, 0x84, 0x7a, 0x0a, 0xcf, 0xe1, 0xfc, 0xdf, 0x6e,
- 0x9d, 0xca, 0x59, 0xbc, 0x86, 0x4e, 0x01, 0x19, 0x6e, 0x1a, 0x93, 0xff,
- 0x37, 0xd9, 0xaa, 0xea, 0xc6, 0xff, 0x9d, 0x3f, 0xfe, 0xc5, 0xf9, 0xd1,
- 0x83, 0x6c, 0x9b, 0x61, 0x43, 0xa3, 0x68, 0x97, 0xb4, 0x49, 0xfd, 0x9f,
- 0xca, 0xce, 0x97, 0x89, 0xd0, 0xcb, 0x90, 0xd4, 0x98, 0x91, 0xba, 0x04,
- 0x74, 0x77, 0x0c, 0xac, 0x91, 0x4e, 0xd3, 0x4d, 0x0a, 0x9e, 0xfa, 0xc7,
- 0xa2, 0x96, 0x5f, 0xcf, 0xdf, 0xa8, 0x2a, 0x9c, 0x3a, 0x1e, 0x7b, 0xd9,
- 0x31, 0x9f, 0xfe, 0x1c, 0x75, 0x63, 0xf3, 0x0f, 0xaf, 0x01, 0xb3, 0xa7,
- 0xff, 0xff, 0xfb, 0x99, 0xfd, 0x9d, 0x5b, 0xb4, 0xe2, 0x6f, 0xc9, 0xa9,
- 0xe9, 0xbb, 0x1e, 0x3e, 0x82, 0x8e, 0x9f, 0xfe, 0xa6, 0x5f, 0x42, 0xdd,
- 0xfa, 0xbf, 0xa0, 0x1d, 0x3c, 0xef, 0xbf, 0x9d, 0x1d, 0x0f, 0x3f, 0x7b,
- 0x4f, 0x9f, 0xfc, 0xfa, 0x0f, 0x94, 0x99, 0xfd, 0x96, 0xa3, 0xa7, 0x93,
- 0xaa, 0x51, 0xd0, 0xca, 0x83, 0x5e, 0x45, 0x4a, 0x57, 0x18, 0x68, 0x90,
- 0xf6, 0x95, 0x3f, 0x6b, 0xf2, 0x83, 0x8b, 0xce, 0x9f, 0xf5, 0x86, 0xb2,
- 0x6e, 0xaf, 0x1f, 0x8e, 0x9f, 0xff, 0x27, 0x19, 0x55, 0x8f, 0x19, 0x5f,
- 0x82, 0xfe, 0x3a, 0x7f, 0xb2, 0xc1, 0xc6, 0x5f, 0x48, 0x74, 0x3d, 0x11,
- 0xb9, 0x56, 0x9f, 0xc9, 0xff, 0x8d, 0xb6, 0xc9, 0xd3, 0xfe, 0x1b, 0x73,
- 0x76, 0x00, 0x9d, 0x1d, 0x14, 0x9c, 0x87, 0x8c, 0x52, 0x19, 0xa0, 0x46,
- 0xa3, 0x39, 0xe7, 0xfe, 0xa7, 0x0e, 0x9f, 0x07, 0x55, 0x42, 0x74, 0xff,
- 0xda, 0xf4, 0xad, 0xb3, 0xac, 0xed, 0xb1, 0x3a, 0x2c, 0xfb, 0xb2, 0x4b,
- 0x3f, 0xd4, 0x21, 0x59, 0xa4, 0xd9, 0xd3, 0xff, 0xd5, 0xcc, 0xd3, 0x9b,
- 0x67, 0x55, 0xbd, 0xb1, 0xd3, 0xd5, 0xc4, 0xc9, 0xd3, 0xf3, 0xb2, 0x70,
- 0x5d, 0xac, 0x3b, 0x3a, 0x32, 0x7b, 0x7c, 0x20, 0x8e, 0x93, 0x22, 0xf1,
- 0x08, 0x9a, 0x72, 0x15, 0x73, 0xff, 0xc9, 0x9a, 0xeb, 0x99, 0x4f, 0xfb,
- 0xb1, 0x43, 0xa7, 0xff, 0xf0, 0xf2, 0xb6, 0x8d, 0xc4, 0xf9, 0x9e, 0xbd,
- 0x34, 0xd0, 0xa9, 0xee, 0xaa, 0xbf, 0x95, 0x3d, 0x7f, 0x5f, 0x0e, 0x9c,
- 0xf1, 0xec, 0xd1, 0x0c, 0xce, 0xd3, 0x4d, 0x0a, 0x9d, 0x43, 0xe2, 0x96,
- 0x5f, 0xcf, 0xfa, 0xb0, 0xae, 0xad, 0xe2, 0xd8, 0x1d, 0x1f, 0x1f, 0x38,
- 0x94, 0xcf, 0xe7, 0x8d, 0x73, 0x9d, 0xe0, 0x74, 0x32, 0x75, 0x78, 0x31,
- 0x74, 0x47, 0x89, 0x08, 0x42, 0xbe, 0xc8, 0xa7, 0x93, 0x88, 0xc7, 0x4f,
- 0xee, 0xe8, 0x3e, 0xf9, 0x04, 0xe9, 0xff, 0xe7, 0xa7, 0x5b, 0xfd, 0x9a,
- 0x0f, 0x5d, 0xf8, 0xd1, 0x06, 0x4f, 0xfe, 0x0b, 0x75, 0x43, 0xed, 0xa7,
- 0xdf, 0xb8, 0x74, 0x32, 0x2a, 0x7b, 0x5d, 0x8d, 0xa3, 0xff, 0x90, 0xdc,
- 0x9b, 0x7d, 0x9d, 0x3c, 0x09, 0xa6, 0xbc, 0xe8, 0x43, 0x79, 0x91, 0x79,
- 0xfd, 0xad, 0x59, 0xd6, 0xa0, 0x63, 0xa1, 0xe9, 0xec, 0x24, 0x63, 0xd9,
- 0x64, 0xe1, 0x04, 0xff, 0xf3, 0x0e, 0x1a, 0x9c, 0x41, 0xae, 0xa8, 0x7f,
- 0x9d, 0x39, 0x81, 0xc3, 0xa1, 0x97, 0xc8, 0xfa, 0x4d, 0xa8, 0xed, 0x3c,
- 0x86, 0x91, 0xfd, 0x5c, 0xa3, 0x5e, 0xd0, 0xf5, 0x94, 0xa7, 0xd6, 0xab,
- 0xac, 0x9d, 0x3f, 0xfd, 0xe6, 0xce, 0x59, 0x55, 0xc4, 0xce, 0xec, 0xe9,
- 0xfc, 0x22, 0xcf, 0x53, 0x21, 0xd3, 0xfb, 0x88, 0xe9, 0x38, 0xf6, 0x2a,
- 0x4a, 0x3a, 0x7e, 0xa1, 0xfe, 0x0c, 0xb4, 0x3c, 0x3f, 0xc6, 0x71, 0x49,
- 0x82, 0x22, 0x6e, 0x5c, 0xa7, 0x83, 0xbc, 0x5e, 0x74, 0xfe, 0x17, 0x8d,
- 0x29, 0xbc, 0x74, 0xe5, 0x75, 0x47, 0x43, 0x1f, 0x7d, 0x11, 0xd9, 0x84,
- 0xee, 0x26, 0x07, 0x4f, 0xb4, 0x4e, 0x9d, 0xd0, 0xe9, 0xff, 0x77, 0xcc,
- 0xfe, 0x0f, 0x94, 0x99, 0x3a, 0x7f, 0x65, 0xb0, 0xa1, 0x4f, 0xe7, 0x4f,
- 0xfc, 0xc3, 0x7b, 0x6f, 0x96, 0x19, 0xc9, 0x51, 0xd2, 0x2d, 0xe9, 0x09,
- 0x46, 0x73, 0xed, 0xa2, 0x63, 0x93, 0xa7, 0xff, 0xd5, 0xd6, 0xab, 0x4a,
- 0xcb, 0x61, 0x42, 0x9f, 0xce, 0x9a, 0xb4, 0x3a, 0x0a, 0x9f, 0xb3, 0xf9,
- 0x81, 0x94, 0x54, 0x15, 0x05, 0x41, 0x50, 0x54, 0x3c, 0xf7, 0xd0, 0x2b,
- 0xe2, 0xde, 0xc2, 0xb5, 0x82, 0x9d, 0xc2, 0xa6, 0xdd, 0x15, 0x3f, 0x5d,
- 0xf1, 0xc6, 0x51, 0x5a, 0x8b, 0x59, 0x3b, 0x05, 0x41, 0x50, 0x54, 0x3c,
- 0xb4, 0x40, 0xa8, 0x2a, 0x0a, 0x82, 0xa0, 0xa8, 0x2a, 0x0a, 0x8c, 0x0d,
- 0xe7, 0x41, 0x48, 0x15, 0xf0, 0x56, 0x42, 0x9d, 0x05, 0x41, 0x50, 0x54,
- 0x3c, 0xb4, 0xc8, 0x54, 0x15, 0x05, 0x41, 0x50, 0x54, 0x3c, 0xd4, 0x7c,
- 0x15, 0xc0, 0xa7, 0x70, 0xa8, 0x2a, 0x0a, 0x82, 0xa0, 0xa8, 0xc0, 0xd4,
- 0x7f, 0x0a, 0x00, 0xad, 0x85, 0x4b, 0xf9, 0x50, 0x54, 0x15, 0x05, 0x41,
- 0x51, 0xd1, 0xa8, 0xc4, 0x2b, 0xe0, 0xae, 0xc2, 0xa0, 0xa8, 0x2a, 0x0a,
- 0x9f, 0x6d, 0xbe, 0xcd, 0x15, 0x05, 0x43, 0xcf, 0x3f, 0xc1, 0x5b, 0x0a,
- 0xb0, 0xaf, 0x89, 0xe5, 0xe2, 0xa0, 0xa8, 0x2a, 0x0a, 0x82, 0xa1, 0xe6,
- 0xa3, 0x10, 0xa4, 0x0a, 0x74, 0x15, 0x05, 0x41, 0x50, 0x54, 0x15, 0x0f,
- 0x35, 0x1d, 0x05, 0x6c, 0x28, 0x42, 0xa5, 0xb2, 0xa0, 0xa8, 0x2a, 0x4f,
- 0x2a, 0x0a, 0xc4, 0xb0, 0x82, 0xa0, 0xa8, 0x2a, 0x0a, 0x8c, 0x0f, 0x99,
- 0xe1, 0x5f, 0xc6, 0xbc, 0x34, 0xe0, 0x57, 0xc1, 0x5c, 0x0a, 0x95, 0x15,
- 0x05, 0x41, 0x52, 0x79, 0x50, 0x56, 0x25, 0x84, 0x15, 0x05, 0x43, 0x1e,
- 0x93, 0xc2, 0x90, 0x68, 0x06, 0x94, 0x15, 0x05, 0x41, 0x50, 0x54, 0x15,
- 0x05, 0x43, 0x1b, 0x2c, 0x42, 0x80, 0x29, 0x41, 0x42, 0x15, 0x05, 0x41,
- 0x50, 0x54, 0x01, 0x7d, 0x90, 0xae, 0x05, 0x41, 0x50, 0x54, 0x15, 0x0a,
- 0x2f, 0x84, 0x2b, 0x81, 0x52, 0x51, 0x50, 0x54, 0x15, 0x1f, 0x16, 0x9d,
- 0x85, 0x41, 0x50, 0x54, 0x15, 0x05, 0x43, 0x1a, 0x87, 0x02, 0xb6, 0x15,
- 0xd8, 0x54, 0x32, 0xfd, 0x86, 0x0e, 0x4f, 0x3d, 0xe8, 0xa6, 0x96, 0xfc,
- 0xdb, 0x8a, 0x42, 0x33, 0xeb, 0xcf, 0x5c, 0x3a, 0x08, 0x47, 0x29, 0x27,
- 0x67, 0x16, 0xcb, 0xf1, 0xd8, 0xbb, 0x65, 0xa3, 0x8c, 0x3d, 0xbc, 0x3a,
- 0x64, 0xd1, 0x2b, 0x58, 0xb3, 0xf1, 0x23, 0xba, 0x54, 0xf9, 0xe2, 0xd5,
- 0x92, 0x96, 0x9a, 0xc4, 0xe4, 0x65, 0x15, 0x3c, 0x9e, 0xb0, 0x3a, 0x72,
- 0x75, 0x47, 0x49, 0x78, 0xa2, 0x30, 0x0e, 0x36, 0x35, 0xc1, 0xf9, 0x33,
- 0xa6, 0x52, 0x67, 0xea, 0x50, 0x4c, 0xfe, 0xda, 0x69, 0xd0, 0x36, 0x07,
- 0x46, 0x27, 0xda, 0xe1, 0xcc, 0xdf, 0x31, 0xd3, 0xf0, 0x58, 0xfe, 0x6f,
- 0x8e, 0x9a, 0xc0, 0xe9, 0x21, 0xde, 0x2d, 0x25, 0xe3, 0xa4, 0xa3, 0xa6,
- 0xd6, 0x5a, 0x22, 0x54, 0x05, 0xb6, 0x83, 0x63, 0xdf, 0x84, 0x27, 0xfb,
- 0x6c, 0xaa, 0x71, 0x87, 0x03, 0xa2, 0x91, 0x21, 0xf2, 0xc4, 0xfc, 0xa4,
- 0xd6, 0xb1, 0xf8, 0xe9, 0xff, 0xe6, 0xd5, 0x60, 0x17, 0xf3, 0x2f, 0x4d,
- 0x34, 0x3a, 0x19, 0x10, 0x3d, 0x97, 0xc6, 0x0d, 0x83, 0x3b, 0xe3, 0x29,
- 0xea, 0x13, 0xde, 0x2c, 0xc4, 0x71, 0x21, 0xc4, 0xe1, 0x82, 0x89, 0xee,
- 0x96, 0x1e, 0x31, 0xa4, 0xf2, 0x14, 0x93, 0xf9, 0x87, 0x96, 0x3d, 0xd1,
- 0xd3, 0xf3, 0xc5, 0x1f, 0xba, 0x3a, 0x7d, 0x82, 0x03, 0x3c, 0xe8, 0x03,
- 0xd1, 0x12, 0xb9, 0xff, 0x6d, 0x83, 0xe1, 0xad, 0x2f, 0xe3, 0xa7, 0x55,
- 0x38, 0x74, 0xab, 0x67, 0xb3, 0xf1, 0xf4, 0xfd, 0xd8, 0x76, 0xab, 0x13,
- 0xa7, 0x94, 0xd5, 0x81, 0xd3, 0xea, 0x74, 0x2d, 0x89, 0xd0, 0x87, 0x93,
- 0x92, 0x19, 0xe6, 0x1e, 0x78, 0xe9, 0x35, 0x26, 0xb0, 0x2f, 0x39, 0x28,
- 0xe3, 0xb6, 0xb1, 0x0c, 0xf7, 0x76, 0x0f, 0x3a, 0x79, 0xbb, 0x76, 0x32,
- 0x54, 0xf9, 0xeb, 0xd3, 0x4d, 0x0e, 0x81, 0x3d, 0x2e, 0xc9, 0xe3, 0xa4,
- 0x4a, 0xd3, 0x9c, 0x29, 0x57, 0x17, 0xd1, 0xec, 0xf7, 0x0e, 0x69, 0xf7,
- 0x7f, 0x50, 0xf8, 0xe9, 0xfd, 0xca, 0xfc, 0xce, 0x26, 0x4e, 0x80, 0x3d,
- 0xc7, 0x45, 0x13, 0xfd, 0x80, 0xd3, 0xf7, 0x5f, 0x64, 0xe9, 0xee, 0xba,
- 0x67, 0x47, 0x4f, 0xff, 0x6d, 0x95, 0xe6, 0xe5, 0x07, 0xae, 0xfc, 0x68,
- 0xbe, 0x27, 0x58, 0x60, 0x68, 0xbf, 0xe1, 0x91, 0x03, 0xe5, 0x99, 0xd7,
- 0x8b, 0xb9, 0xd3, 0xf5, 0xf3, 0x2d, 0x58, 0x1d, 0x0e, 0x8f, 0x2f, 0x41,
- 0xf9, 0xff, 0x9d, 0x73, 0xfb, 0x0b, 0xeb, 0x68, 0xa3, 0xa7, 0xea, 0xd3,
- 0xf6, 0xef, 0x87, 0x4f, 0xff, 0xb9, 0xf9, 0xec, 0xe9, 0x07, 0xe0, 0x46,
- 0x55, 0x15, 0x3d, 0xbf, 0xd8, 0xf0, 0xe8, 0xc1, 0x15, 0x54, 0x5f, 0xe5,
- 0x69, 0xb9, 0x47, 0x4f, 0x81, 0x30, 0xb5, 0x1a, 0x61, 0x39, 0xee, 0x76,
- 0xd6, 0x69, 0x84, 0xe6, 0xf9, 0x8d, 0x40, 0x9c, 0xfe, 0x1b, 0xff, 0xc6,
- 0x0f, 0x8d, 0x40, 0x9c, 0xfe, 0xcd, 0x6d, 0x33, 0xde, 0x06, 0x98, 0x4e,
- 0x6a, 0xe8, 0xd3, 0x09, 0xcd, 0xa6, 0x87, 0x98, 0x4e, 0x29, 0x34, 0xdc,
- 0x4c, 0xd0, 0xb9, 0x44, 0x79, 0x40, 0x74, 0x83, 0xa1, 0x1c, 0xb8, 0x59,
- 0x84, 0xcb, 0x3e, 0x79, 0x26, 0x29, 0xfc, 0x69, 0x1e, 0x4c, 0x5a, 0xb4,
- 0x9c, 0xc3, 0xc3, 0x92, 0x8a, 0x27, 0x0f, 0xca, 0x3a, 0x7f, 0x9b, 0xbe,
- 0x0a, 0x3a, 0xfc, 0xa3, 0xa7, 0x0d, 0x66, 0x8f, 0x60, 0x07, 0x21, 0x97,
- 0x5f, 0xfa, 0x39, 0xf4, 0x29, 0xb6, 0xdb, 0xc9, 0x6d, 0xce, 0xa1, 0x2b,
- 0x3e, 0xea, 0x81, 0x3f, 0x9d, 0x3f, 0x6d, 0xbf, 0x0e, 0x3f, 0x1d, 0x3e,
- 0x1a, 0xfd, 0x4e, 0x1d, 0x3f, 0xdb, 0xb5, 0x6d, 0x1b, 0x17, 0x9d, 0x3f,
- 0x7e, 0x17, 0xeb, 0x5e, 0x07, 0x42, 0x1f, 0x57, 0xc7, 0x10, 0x28, 0xb4,
- 0xe4, 0x24, 0xa7, 0xfd, 0x57, 0xb7, 0x10, 0x77, 0x58, 0x9d, 0x0c, 0xbe,
- 0xff, 0x53, 0xb4, 0x48, 0xdb, 0xaf, 0x28, 0xb8, 0x72, 0x09, 0x3c, 0xff,
- 0xe5, 0x73, 0x28, 0x38, 0xbf, 0x89, 0x94, 0x3a, 0x7f, 0xff, 0x0d, 0x63,
- 0x59, 0xb1, 0xda, 0x37, 0x37, 0xdd, 0xa8, 0xe9, 0xf8, 0x7b, 0x52, 0x6d,
- 0x8e, 0x9f, 0xff, 0x58, 0xf2, 0xef, 0x62, 0xdc, 0xce, 0x95, 0xb3, 0xa7,
- 0xfd, 0x85, 0x8e, 0x79, 0xb4, 0x6c, 0x9d, 0x38, 0x33, 0x93, 0xc4, 0x07,
- 0x3f, 0xf8, 0x1b, 0x6d, 0xaa, 0x83, 0xd7, 0x7e, 0x34, 0x40, 0x6b, 0x35,
- 0x11, 0x68, 0xc9, 0xfc, 0xcb, 0x1f, 0x26, 0x7f, 0xc8, 0xc6, 0xe2, 0x93,
- 0x96, 0x48, 0xda, 0xe7, 0xdc, 0x6f, 0xb5, 0xa8, 0xe9, 0xe1, 0xe7, 0xdd,
- 0x9d, 0x3f, 0xff, 0x3e, 0xb2, 0x80, 0x08, 0xaf, 0xdc, 0xdd, 0x69, 0xc3,
- 0xa2, 0x8f, 0xfa, 0xc8, 0xe7, 0xff, 0xfa, 0xdf, 0x42, 0xe3, 0xeb, 0x17,
- 0xfe, 0x6f, 0x97, 0xa6, 0x9a, 0x15, 0x0c, 0x99, 0xae, 0xe1, 0x50, 0x24,
- 0x13, 0xf9, 0xa8, 0x3d, 0x77, 0xe3, 0x44, 0x13, 0x3f, 0xcd, 0xca, 0x0f,
- 0x5d, 0xf8, 0xd1, 0x7c, 0xcf, 0x91, 0xd0, 0xd6, 0x7a, 0x3f, 0xef, 0x1e,
- 0x4f, 0xee, 0xf7, 0xad, 0xb4, 0xf6, 0xce, 0x9f, 0xf6, 0x17, 0x8e, 0xb5,
- 0x70, 0x6d, 0xd1, 0xd3, 0xb4, 0xd3, 0x42, 0xa7, 0xdb, 0xaf, 0x58, 0x14,
- 0xb2, 0xfe, 0x7f, 0xff, 0x38, 0x0c, 0xeb, 0x57, 0xfb, 0xd5, 0xf9, 0xcc,
- 0xea, 0xac, 0x78, 0x74, 0x71, 0x14, 0x7f, 0x8d, 0x23, 0x04, 0xca, 0x86,
- 0x30, 0x59, 0xff, 0xb0, 0x53, 0x63, 0x91, 0xac, 0x3f, 0x3c, 0xe9, 0xfb,
- 0x5f, 0x4f, 0xdb, 0x01, 0xd3, 0xff, 0xb1, 0x1d, 0x5e, 0xda, 0x7d, 0xf3,
- 0x03, 0xce, 0x86, 0x3f, 0xcf, 0xc5, 0xf3, 0xfe, 0xef, 0x2d, 0x43, 0xc7,
- 0x6f, 0x4f, 0x1d, 0x3b, 0x4d, 0x34, 0x2a, 0x7f, 0x7e, 0xf9, 0x86, 0xb1,
- 0xe1, 0x4b, 0x2f, 0xe7, 0xff, 0xe7, 0x63, 0x57, 0xb6, 0x9d, 0x75, 0x5a,
- 0x6a, 0xe6, 0x6b, 0x03, 0xa5, 0x7b, 0x45, 0x67, 0x68, 0x90, 0xf5, 0x7d,
- 0x5d, 0x20, 0x24, 0x6c, 0x20, 0x54, 0xa8, 0x62, 0x09, 0x1f, 0x23, 0x0f,
- 0x9f, 0x6e, 0xb8, 0xe3, 0xce, 0x9f, 0xf5, 0x71, 0x83, 0x3b, 0x61, 0xe1,
- 0xe2, 0x08, 0x9f, 0xcd, 0x41, 0xeb, 0xbf, 0x1a, 0x20, 0x85, 0x9e, 0x44,
- 0xfd, 0x7b, 0x00, 0x4d, 0x0e, 0x9f, 0xb5, 0xfd, 0x69, 0x62, 0xf3, 0xa0,
- 0x4f, 0x77, 0xb2, 0xb8, 0xda, 0x67, 0x9f, 0x38, 0x0c, 0x2a, 0xa7, 0xf9,
- 0x87, 0x9f, 0xab, 0x77, 0x89, 0xd3, 0xff, 0xd7, 0xa7, 0x2b, 0x6c, 0x9c,
- 0x1a, 0xda, 0x1d, 0x0f, 0x44, 0x28, 0x9c, 0xcf, 0xf6, 0xd8, 0x38, 0x2d,
- 0x58, 0x9d, 0x3f, 0xff, 0xc9, 0x83, 0x3f, 0x20, 0x09, 0x8b, 0x8f, 0xb0,
- 0x55, 0x62, 0x74, 0xf7, 0x37, 0x43, 0xd2, 0x27, 0x36, 0x6d, 0x3f, 0x7e,
- 0x56, 0x74, 0xbc, 0x4e, 0x86, 0x3e, 0xbe, 0x1d, 0x4f, 0x23, 0x89, 0xa1,
- 0xd3, 0xff, 0xee, 0xf0, 0x16, 0xad, 0xad, 0xb9, 0x5b, 0xec, 0x0e, 0x9f,
- 0x57, 0x33, 0xfb, 0x3d, 0x1f, 0xbf, 0xe2, 0x29, 0xfb, 0xdb, 0x4d, 0x64,
- 0xfe, 0x74, 0xfc, 0xa6, 0xd7, 0xee, 0xb0, 0x3a, 0x7f, 0xff, 0xf9, 0x39,
- 0x6a, 0xb1, 0xf9, 0xe9, 0x9e, 0xd5, 0xb4, 0x6e, 0x6f, 0xbb, 0x51, 0xd1,
- 0xd2, 0x37, 0xd0, 0xc6, 0xcc, 0x67, 0xe1, 0xfa, 0x94, 0xdb, 0x3a, 0x70,
- 0x7e, 0xc9, 0xd3, 0xfe, 0xb1, 0xf5, 0x07, 0xae, 0xfc, 0x68, 0x84, 0x61,
- 0x8f, 0x93, 0xb1, 0xd9, 0xff, 0xcd, 0x58, 0xfe, 0xe2, 0x0f, 0x6f, 0xac,
- 0x9d, 0x3f, 0xfd, 0x77, 0x87, 0xea, 0xdd, 0xa9, 0x7a, 0x69, 0xa1, 0xd1,
- 0xd2, 0x27, 0xdc, 0x4b, 0x9f, 0xee, 0x9b, 0x39, 0x6c, 0x2b, 0x43, 0xa2,
- 0x8f, 0x7e, 0xc9, 0x67, 0x69, 0xa6, 0x85, 0x4f, 0xf5, 0x7d, 0x61, 0x4e,
- 0xab, 0xa2, 0x96, 0x5f, 0xcd, 0xa6, 0x85, 0x4e, 0xd3, 0x4d, 0x0a, 0x9f,
- 0xaf, 0x0e, 0xb6, 0xd9, 0x29, 0x65, 0xfc, 0x0a, 0x2f, 0x34, 0x48, 0xd6,
- 0x37, 0x9f, 0x79, 0x3a, 0xfc, 0xa2, 0x96, 0x6c, 0xe7, 0x69, 0xa6, 0x85,
- 0x4e, 0xcb, 0x01, 0x4b, 0x2f, 0xe5, 0xf2, 0x22, 0x0b, 0x8b, 0x33, 0xf7,
- 0x42, 0xcf, 0xbf, 0x1d, 0x3f, 0xbf, 0x07, 0x48, 0xe9, 0xba, 0x3a, 0x7f,
- 0xed, 0xdb, 0xc6, 0xff, 0xb8, 0x28, 0xe1, 0xd3, 0xf6, 0xe9, 0xd5, 0x73,
- 0x27, 0x47, 0x8f, 0xcf, 0x88, 0xb0, 0x08, 0xf8, 0xd9, 0x60, 0xc2, 0xaa,
- 0x19, 0x35, 0x4a, 0x8c, 0x86, 0x76, 0x3a, 0xeb, 0xbb, 0x23, 0xa7, 0xff,
- 0x56, 0xbe, 0xc7, 0xea, 0xf3, 0x6d, 0x94, 0x74, 0xfd, 0xe4, 0xce, 0xd1,
- 0xc2, 0xa7, 0xf0, 0xd6, 0x2f, 0xca, 0x7f, 0x3a, 0x7a, 0xec, 0x3f, 0x9d,
- 0x1a, 0x8f, 0x57, 0x03, 0x49, 0xe6, 0xb5, 0x3a, 0x2a, 0x76, 0x9a, 0x68,
- 0x54, 0xff, 0xf7, 0xe6, 0xfa, 0xa8, 0x79, 0xb4, 0x61, 0xc0, 0xa5, 0x97,
- 0xf2, 0xaf, 0x22, 0x7d, 0x48, 0x30, 0xc9, 0xf2, 0xbc, 0xb3, 0x14, 0xb4,
- 0x84, 0x16, 0xe1, 0x89, 0x3f, 0xfe, 0x55, 0x79, 0x86, 0xf9, 0x9e, 0xbb,
- 0xb0, 0x79, 0xd3, 0xe6, 0xe6, 0x5d, 0x51, 0xd0, 0xc7, 0xf9, 0xc5, 0x49,
- 0xff, 0xe4, 0x75, 0x43, 0xd0, 0xde, 0x94, 0x37, 0xfc, 0xe9, 0xff, 0xfe,
- 0xeb, 0x69, 0xa5, 0x3b, 0xa2, 0xaf, 0x99, 0xed, 0xf5, 0x8f, 0x0e, 0x8a,
- 0x45, 0xe5, 0xa8, 0x43, 0x36, 0xc8, 0x98, 0x24, 0xbe, 0x3f, 0x4e, 0xa3,
- 0x5d, 0xa9, 0xc9, 0xc4, 0x8e, 0xc5, 0xc8, 0x5d, 0x84, 0x65, 0x2a, 0x84,
- 0xc6, 0xe3, 0x23, 0xb2, 0xff, 0xa1, 0x20, 0x31, 0x90, 0x66, 0x58, 0x27,
- 0x25, 0x06, 0xf7, 0x0d, 0x0d, 0x21, 0xbb, 0x39, 0xd3, 0x09, 0xd3, 0xff,
- 0xd4, 0x2b, 0xe7, 0xf4, 0xc7, 0x3b, 0xaf, 0xac, 0xe9, 0x62, 0xf3, 0xed,
- 0xe8, 0x72, 0x7e, 0xdb, 0x89, 0xb4, 0x51, 0xd3, 0xfe, 0x16, 0xe6, 0xef,
- 0xeb, 0xc7, 0x27, 0x4e, 0x73, 0xb0, 0x3a, 0x7f, 0xd6, 0x81, 0x58, 0xaf,
- 0x4d, 0x34, 0x3a, 0x2c, 0xf7, 0x72, 0x3b, 0x3f, 0xfc, 0x2c, 0xfd, 0x5f,
- 0xb8, 0x83, 0xdb, 0xeb, 0x27, 0x45, 0x26, 0x77, 0xe2, 0xdd, 0xc2, 0x6f,
- 0xe2, 0x19, 0xfc, 0xc2, 0xf1, 0xaa, 0xf8, 0xe9, 0xfc, 0xfa, 0x0c, 0x8b,
- 0x60, 0x74, 0xff, 0xf5, 0x71, 0x87, 0xd5, 0xcd, 0xa0, 0x7d, 0xe3, 0xa7,
- 0xf3, 0x2b, 0x39, 0xb1, 0xc0, 0xe9, 0xf5, 0xe6, 0x87, 0x87, 0x4e, 0xe5,
- 0xeb, 0xce, 0x9f, 0xdc, 0xda, 0x2f, 0xeb, 0x43, 0xa3, 0xa4, 0x7a, 0xed,
- 0x34, 0x4c, 0xb8, 0x4b, 0xd8, 0xfc, 0xfe, 0xef, 0xe6, 0xda, 0x5b, 0xce,
- 0x9f, 0xef, 0x57, 0x19, 0xd2, 0x0f, 0xc7, 0x4f, 0xff, 0xdd, 0xb7, 0x33,
- 0x43, 0xa8, 0x19, 0x3a, 0x1b, 0x79, 0xd0, 0x88, 0x93, 0x13, 0x99, 0xff,
- 0xf8, 0x6b, 0x3d, 0xea, 0xad, 0xd8, 0xd3, 0x8f, 0x6c, 0x4e, 0x9f, 0xf5,
- 0x67, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x03, 0x4f, 0x73, 0x76, 0xfd, 0x48,
- 0xa5, 0x15, 0xc8, 0x64, 0xc0, 0x6a, 0x18, 0xd3, 0xfe, 0xb0, 0xa1, 0xfb,
- 0x3c, 0xce, 0x27, 0x4f, 0xff, 0xff, 0xd5, 0xcd, 0xd8, 0xff, 0xd5, 0x90,
- 0xbb, 0xe3, 0xaa, 0xeb, 0x55, 0x2a, 0xc7, 0x17, 0x9e, 0x20, 0xb9, 0xff,
- 0x5d, 0xff, 0xf5, 0xf5, 0xab, 0xfe, 0x87, 0x88, 0x2e, 0x7f, 0xed, 0xa6,
- 0xd1, 0x87, 0x9a, 0xbf, 0xe8, 0x78, 0x82, 0xe7, 0xf3, 0x20, 0xf3, 0x57,
- 0xfd, 0x0f, 0x10, 0x5c, 0xfc, 0xaa, 0xeb, 0x57, 0xfd, 0x0f, 0x10, 0x5c,
- 0xff, 0xff, 0x58, 0x8a, 0x2b, 0x56, 0x7d, 0xb4, 0x04, 0xff, 0x85, 0x68,
- 0x78, 0x82, 0xe6, 0xc7, 0x57, 0x49, 0xcf, 0x79, 0x48, 0x15, 0x2d, 0x0c,
- 0x50, 0x21, 0x95, 0x67, 0xec, 0xf8, 0x65, 0x1c, 0xcf, 0xe4, 0x6f, 0xf9,
- 0xe6, 0x71, 0x3a, 0x7a, 0xc3, 0xeb, 0x3a, 0x7f, 0xed, 0xa6, 0xd1, 0x87,
- 0x9a, 0xbf, 0xe8, 0x78, 0x82, 0xe7, 0xf9, 0xcc, 0xf9, 0x30, 0xd5, 0xff,
- 0x43, 0xc4, 0x17, 0x3e, 0xe6, 0x59, 0x5a, 0xbc, 0x8a, 0x1f, 0xca, 0x93,
- 0xff, 0xb5, 0x7b, 0x69, 0xe6, 0xe6, 0x75, 0x7f, 0xd0, 0xf1, 0x05, 0xcf,
- 0xff, 0xfc, 0x22, 0x8a, 0xd5, 0xdd, 0x6a, 0xcf, 0xb6, 0x80, 0x9f, 0xf0,
- 0xad, 0x0f, 0x10, 0x5c, 0x52, 0x64, 0xd8, 0xa2, 0x5a, 0xf4, 0xff, 0x6d,
- 0x01, 0x3f, 0xe1, 0x5a, 0x1e, 0x20, 0xb9, 0xff, 0xeb, 0xbc, 0x5f, 0x9d,
- 0xa7, 0x5d, 0x30, 0x31, 0x53, 0xfe, 0xa7, 0xbf, 0xbc, 0x80, 0xe1, 0xac,
- 0x78, 0x82, 0xe3, 0xc8, 0xe5, 0x04, 0x7c, 0xa7, 0xcf, 0xfb, 0xc8, 0x1c,
- 0xbf, 0xb3, 0xab, 0x43, 0xc4, 0x17, 0x3f, 0x6d, 0x37, 0xb4, 0xf8, 0xd0,
- 0x05, 0xcf, 0xab, 0xed, 0x5f, 0xf4, 0x3c, 0x41, 0x73, 0x57, 0x3c, 0x7e,
- 0x9b, 0x3a, 0x8c, 0x51, 0xdf, 0x98, 0x61, 0x4f, 0xca, 0xae, 0xb5, 0x7f,
- 0xd0, 0xf1, 0x05, 0xcf, 0xfb, 0xdb, 0x40, 0x4f, 0xf8, 0x56, 0x87, 0x88,
- 0x2e, 0x6a, 0xd5, 0x68, 0x8d, 0xca, 0x04, 0xfe, 0xed, 0x15, 0x63, 0x8b,
- 0xcf, 0x10, 0x5c, 0xff, 0xa9, 0x1d, 0x50, 0xd7, 0x56, 0xf3, 0xc4, 0x16,
- 0xa3, 0xc0, 0x8e, 0x97, 0x81, 0x80, 0xdf, 0xe3, 0x51, 0x8f, 0x9f, 0x31,
- 0x8a, 0xf2, 0x31, 0xee, 0xe1, 0x6d, 0xa3, 0x7c, 0xfb, 0xec, 0xfd, 0xf3,
- 0x1a, 0x20, 0xb5, 0xa2, 0x36, 0x7f, 0xd4, 0xfd, 0xdb, 0xdd, 0xdd, 0xfb,
- 0xc0, 0xe9, 0xca, 0x67, 0x9d, 0x3e, 0xae, 0xb7, 0xde, 0x87, 0x48, 0x2c,
- 0xf1, 0x44, 0x6e, 0x72, 0x6b, 0x51, 0xd3, 0xac, 0x3e, 0x3a, 0x58, 0xb1,
- 0xb8, 0xe0, 0xec, 0xfd, 0x58, 0x5e, 0xdb, 0x5e, 0x74, 0x22, 0x2d, 0x2d,
- 0x74, 0x49, 0xe7, 0x58, 0x60, 0x74, 0xdf, 0x31, 0xd3, 0xc8, 0xca, 0xa3,
- 0xa0, 0xe9, 0xfa, 0xff, 0xf1, 0x83, 0xe3, 0xa3, 0xa3, 0x70, 0x21, 0x53,
- 0xff, 0xf9, 0x93, 0xa1, 0x6e, 0xfd, 0xca, 0xf7, 0x4d, 0xef, 0xca, 0x3a,
- 0x6f, 0x98, 0xe9, 0x9b, 0xf9, 0xd3, 0xfd, 0x5c, 0xcb, 0x2b, 0xf5, 0x38,
- 0x74, 0xfe, 0xcd, 0x6d, 0x33, 0xde, 0x07, 0x4d, 0xa6, 0x85, 0x4f, 0xf0,
- 0xd3, 0xab, 0x7e, 0x53, 0xa3, 0xa3, 0xc9, 0xfc, 0x20, 0xd8, 0x0b, 0x29,
- 0x5f, 0x64, 0x3f, 0x31, 0xbb, 0x02, 0xc2, 0x2f, 0x93, 0xad, 0x0d, 0x3f,
- 0x0c, 0x4e, 0xd3, 0x4d, 0x0a, 0x92, 0x8a, 0x59, 0x7f, 0x3e, 0xb7, 0x2e,
- 0xc0, 0xa5, 0xa3, 0x77, 0xf4, 0x2f, 0xa7, 0xf6, 0x3c, 0x6a, 0xdd, 0x60,
- 0x74, 0x33, 0x67, 0x43, 0x51, 0xb2, 0xff, 0x43, 0xc4, 0xc1, 0x23, 0x26,
- 0x04, 0xbd, 0xc7, 0x8f, 0x74, 0x98, 0x91, 0x49, 0xcc, 0x67, 0xfd, 0xcb,
- 0x02, 0x74, 0x97, 0x3d, 0x5e, 0x6e, 0x1d, 0x3d, 0x4a, 0xae, 0x1d, 0x3f,
- 0xf6, 0xfb, 0xc3, 0xb5, 0xed, 0x3d, 0x60, 0x74, 0xf5, 0xe1, 0xf9, 0xe7,
- 0x43, 0x22, 0xab, 0x12, 0x0e, 0x10, 0x3b, 0xa3, 0x4f, 0xc3, 0xdf, 0x4a,
- 0xb7, 0x9d, 0x3f, 0xfd, 0x8b, 0xc5, 0xb5, 0x28, 0x5b, 0xff, 0x13, 0x03,
- 0xa7, 0xf6, 0x78, 0xea, 0x86, 0xba, 0x3a, 0x19, 0x16, 0xa8, 0x5d, 0x6a,
- 0x73, 0xaf, 0x57, 0xe3, 0xa7, 0xff, 0x85, 0xfa, 0xab, 0xa4, 0xce, 0x3c,
- 0xee, 0xf2, 0x74, 0xfb, 0x56, 0xd8, 0x1e, 0x74, 0x6a, 0x44, 0xd5, 0x0f,
- 0xe8, 0xa7, 0x3f, 0x60, 0xe3, 0xf5, 0xc0, 0xc0, 0xe9, 0x9f, 0x81, 0xd3,
- 0xed, 0xd2, 0x3f, 0x27, 0x4f, 0xff, 0x6d, 0xbf, 0x2f, 0x83, 0x7f, 0x67,
- 0x2d, 0xf1, 0x53, 0xfb, 0xea, 0x0f, 0x5d, 0xf8, 0xf1, 0x02, 0x4e, 0xe2,
- 0x60, 0x74, 0x3d, 0x1a, 0x5d, 0x13, 0x02, 0x92, 0x8f, 0xa6, 0x77, 0x79,
- 0xd3, 0xdc, 0xc2, 0xc4, 0xe9, 0xec, 0x73, 0x7c, 0x3a, 0x30, 0x3d, 0xca,
- 0x19, 0xd9, 0x0c, 0xfe, 0x1b, 0xd3, 0x39, 0x6f, 0x8e, 0x9d, 0xa6, 0x9a,
- 0x1e, 0xaf, 0xa9, 0xd6, 0x3d, 0x16, 0xaf, 0xa2, 0xcd, 0x64, 0x74, 0x89,
- 0x8f, 0x97, 0xe7, 0xff, 0xd4, 0x29, 0xfd, 0x79, 0xe6, 0xfb, 0xb7, 0xbd,
- 0x8e, 0x8c, 0x0f, 0xef, 0xf9, 0x2c, 0xfa, 0xc4, 0x51, 0x47, 0x46, 0xbb,
- 0x56, 0x84, 0xf3, 0x5a, 0x87, 0x4a, 0x42, 0x66, 0xe3, 0x42, 0x12, 0x59,
- 0xf2, 0x71, 0xb9, 0x92, 0xa7, 0xbc, 0xdc, 0xc9, 0x53, 0x69, 0xa1, 0x50,
- 0xf3, 0xdf, 0xa2, 0x6d, 0x08, 0x66, 0xad, 0x0a, 0x59, 0xaf, 0x9f, 0xff,
- 0x57, 0x1b, 0xd5, 0x43, 0xcd, 0xa3, 0x0e, 0x07, 0x47, 0xc7, 0xef, 0xa1,
- 0x34, 0xff, 0xfe, 0x67, 0x48, 0x3f, 0x6a, 0xe6, 0x6b, 0xdb, 0xb1, 0xe6,
- 0x4e, 0x9f, 0xb1, 0x7e, 0xfb, 0x60, 0x3a, 0x7f, 0xd5, 0x4e, 0x05, 0x76,
- 0xa6, 0xc9, 0xd0, 0xe1, 0xf5, 0x81, 0x74, 0xe7, 0xd8, 0x1d, 0x3e, 0x7d,
- 0x72, 0xba, 0x2a, 0x48, 0xe1, 0xe0, 0xf0, 0x6a, 0x7b, 0x9f, 0xeb, 0x67,
- 0x4d, 0xf3, 0x1d, 0x37, 0xcc, 0x74, 0xfb, 0xb7, 0xd0, 0xad, 0x0d, 0x67,
- 0xc2, 0xd0, 0xc8, 0x8d, 0x14, 0xf9, 0xff, 0xb9, 0xba, 0x57, 0xe6, 0xfa,
- 0xb1, 0xe1, 0xd3, 0xfb, 0x1f, 0x20, 0x7e, 0x6e, 0x8e, 0x9e, 0xf9, 0x56,
- 0xfc, 0x9f, 0xe7, 0x11, 0xe7, 0x6b, 0x56, 0x27, 0x4f, 0x7c, 0x08, 0x07,
- 0x43, 0x1f, 0xcd, 0x9d, 0x68, 0x3f, 0x3d, 0x9e, 0xf1, 0xe1, 0xd3, 0xb4,
- 0xd3, 0x42, 0xa7, 0xd5, 0xfc, 0x7b, 0xc9, 0x4b, 0x2f, 0xe7, 0xd4, 0xbd,
- 0x34, 0xd0, 0xe8, 0x63, 0xe2, 0xe1, 0xc4, 0xff, 0xd4, 0x35, 0x9f, 0x6d,
- 0x3c, 0xc2, 0x74, 0xf6, 0x96, 0x2f, 0x3a, 0x7f, 0xb8, 0xd8, 0xfd, 0x7b,
- 0xda, 0x1d, 0x2d, 0x9d, 0x14, 0x79, 0x3e, 0x39, 0x9d, 0xa6, 0x9a, 0x15,
- 0x3f, 0x25, 0xff, 0xda, 0x70, 0xa5, 0x97, 0xf3, 0xea, 0xfa, 0xa9, 0xc3,
- 0xa5, 0x9d, 0x48, 0xa3, 0x04, 0x01, 0x3c, 0x9b, 0xb7, 0xf4, 0x9a, 0x1d,
- 0x46, 0x1b, 0x24, 0xda, 0x77, 0x43, 0x1c, 0x1c, 0xf5, 0x82, 0x6c, 0xe8,
- 0x65, 0xe1, 0xb7, 0x92, 0x54, 0x33, 0xbf, 0xb1, 0x84, 0x2d, 0x77, 0x18,
- 0xb5, 0x97, 0x66, 0x14, 0xbc, 0x8f, 0x6f, 0x58, 0xba, 0x7e, 0x65, 0x00,
- 0x5f, 0x0e, 0x9f, 0xfe, 0x45, 0x62, 0xfc, 0xea, 0xa1, 0x1a, 0x4f, 0x8e,
- 0x8d, 0x9f, 0xd7, 0x0a, 0xa4, 0xb7, 0x6a, 0x14, 0x9d, 0x2e, 0xcc, 0xa7,
- 0x5d, 0x48, 0x3a, 0xe8, 0x54, 0xd3, 0x97, 0x98, 0x4a, 0x10, 0x7c, 0xaa,
- 0xbe, 0xa5, 0xc8, 0x55, 0x73, 0xe5, 0xfe, 0x3c, 0x2f, 0x4b, 0x27, 0xc6,
- 0x5e, 0xda, 0x4b, 0x0b, 0x72, 0x7d, 0x40, 0x27, 0x87, 0x95, 0x2b, 0xc3,
- 0x74, 0x90, 0xfb, 0xac, 0x3b, 0xfe, 0x97, 0x48, 0x34, 0x81, 0xac, 0xd6,
- 0xd5, 0x5c, 0xad, 0x53, 0x3b, 0x8d, 0xf1, 0xd4, 0x3d, 0x74, 0x86, 0x3e,
- 0xb4, 0xb7, 0x4f, 0xd3, 0xf1, 0x6e, 0xf1, 0x92, 0x42, 0xe1, 0x4f, 0xb8,
- 0xfc, 0x52, 0xbe, 0xcf, 0xe5, 0xd0, 0x7a, 0xef, 0xc6, 0x8b, 0x8e, 0x7f,
- 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x5d, 0x73, 0xff, 0x2e, 0xde, 0xba, 0x0f,
- 0x5d, 0xf8, 0xd1, 0x28, 0xc3, 0x42, 0xad, 0x15, 0xe5, 0x1d, 0x1e, 0xff,
- 0x3d, 0xf1, 0xea, 0x43, 0xdb, 0x5e, 0x81, 0x78, 0xa8, 0x30, 0xc9, 0xc7,
- 0x0f, 0x5d, 0xcf, 0x67, 0xff, 0x2d, 0x56, 0xf5, 0xd0, 0x7a, 0xef, 0xc6,
- 0x89, 0x6a, 0x7c, 0x1e, 0xbb, 0xf1, 0xa2, 0x37, 0x9f, 0xf5, 0xbd, 0x74,
- 0x1e, 0xbb, 0xf1, 0xa2, 0x5f, 0x92, 0xe8, 0xfe, 0x94, 0x65, 0x3f, 0x97,
- 0x41, 0xeb, 0xbf, 0x1a, 0x2a, 0xb9, 0xfe, 0xff, 0x43, 0x58, 0xf2, 0xd4,
- 0x74, 0xdd, 0x21, 0xd3, 0xf5, 0x07, 0xae, 0xfc, 0x68, 0x90, 0x23, 0x51,
- 0xe6, 0xac, 0x5a, 0x7d, 0x9b, 0x1b, 0xc4, 0xe8, 0x79, 0xe5, 0x62, 0x49,
- 0x3f, 0xfa, 0x9c, 0xdd, 0xab, 0x9b, 0x6e, 0x76, 0xa3, 0xa3, 0xfa, 0x67,
- 0xd7, 0x0d, 0x0f, 0xc4, 0x73, 0xff, 0x0d, 0x60, 0xbd, 0x66, 0x11, 0xae,
- 0x1d, 0x0b, 0x3f, 0xd0, 0x39, 0x9f, 0xcb, 0xa0, 0xf5, 0xdf, 0x8d, 0x16,
- 0x44, 0xfe, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0xb5, 0xe7, 0xf2, 0xe8, 0x3d,
- 0x77, 0xe3, 0x45, 0xc9, 0x3e, 0x0f, 0x5d, 0xf8, 0xd1, 0x76, 0x4f, 0xfa,
- 0xde, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x47, 0x49, 0x74, 0x7f, 0x4a, 0x32,
- 0x93, 0xce, 0x9f, 0x07, 0xae, 0xfc, 0x68, 0xa5, 0x67, 0xff, 0xff, 0xb6,
- 0xd8, 0x36, 0xd1, 0xd5, 0xf5, 0xb4, 0x5f, 0xb6, 0x8e, 0x6d, 0xb0, 0xa3,
- 0xa6, 0x7a, 0xe9, 0x16, 0x4e, 0x19, 0x4c, 0xb5, 0x62, 0x8f, 0x1b, 0x86,
- 0x14, 0x60, 0xbb, 0x16, 0xf8, 0x67, 0x62, 0x4e, 0x91, 0xfc, 0x28, 0x87,
- 0xe3, 0xdc, 0x9e, 0xf2, 0x16, 0xee, 0xa3, 0x18, 0x9f, 0xe7, 0xae, 0x83,
- 0xd7, 0x7e, 0x34, 0x47, 0x13, 0xfc, 0x8b, 0xa0, 0xf5, 0xdf, 0x8d, 0x15,
- 0xac, 0x97, 0x68, 0x85, 0xe2, 0x1c, 0xff, 0xe5, 0xaa, 0xde, 0xba, 0x0f,
- 0x5d, 0xf8, 0xd1, 0x2d, 0xcd, 0x58, 0x9d, 0x3f, 0xba, 0xa5, 0x29, 0x93,
- 0x27, 0x46, 0x27, 0x90, 0x82, 0xd3, 0xb7, 0xd3, 0xce, 0x9c, 0xf5, 0x78,
- 0xe9, 0xff, 0xfb, 0x77, 0x8f, 0xdd, 0x6e, 0xdf, 0x59, 0x1e, 0xef, 0xf1,
- 0xd0, 0x68, 0x86, 0xe7, 0xfd, 0x6f, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0x98,
- 0x26, 0xf5, 0x1d, 0x37, 0x7f, 0x15, 0x08, 0x6b, 0x40, 0x56, 0x7f, 0x0d,
- 0x73, 0x8c, 0x19, 0x3a, 0x4b, 0x64, 0xe5, 0x70, 0x22, 0xe8, 0x76, 0x87,
- 0x3c, 0xbe, 0xa1, 0x7e, 0x3a, 0xfe, 0x1f, 0x9c, 0xae, 0xc0, 0xa9, 0xff,
- 0x5b, 0xd7, 0x41, 0xeb, 0xbf, 0x1a, 0x26, 0x39, 0x2d, 0x0f, 0x91, 0x43,
- 0x93, 0xf3, 0x67, 0x57, 0x2b, 0x67, 0x4e, 0x61, 0xc0, 0xe9, 0xff, 0xff,
- 0xe7, 0xe7, 0x75, 0xde, 0x99, 0xdd, 0x7a, 0xb3, 0xaa, 0xb1, 0x7e, 0x50,
- 0x50, 0xe9, 0xef, 0x5d, 0xf8, 0xd1, 0x58, 0xcf, 0xfb, 0x5a, 0xb8, 0x35,
- 0xdb, 0x0f, 0x0e, 0x8f, 0xe9, 0x9a, 0xf8, 0xbb, 0x11, 0xb0, 0x84, 0x07,
- 0x0b, 0x67, 0xff, 0x30, 0xf3, 0xff, 0x6c, 0x35, 0xe6, 0x03, 0xa7, 0xfb,
- 0xad, 0xd6, 0x71, 0x7b, 0x6c, 0xe9, 0xfe, 0x6c, 0x5e, 0xe3, 0xec, 0x30,
- 0x3a, 0x28, 0xfd, 0x10, 0xea, 0x7f, 0xd5, 0xd0, 0x27, 0x78, 0x7d, 0x97,
- 0x9d, 0x3f, 0xff, 0xf0, 0xf7, 0x85, 0x7b, 0x50, 0xf6, 0xef, 0xaa, 0xb1,
- 0x7d, 0x76, 0x3f, 0x64, 0xe9, 0xfd, 0xae, 0xf0, 0x71, 0xfa, 0xe0, 0x60,
- 0x74, 0xff, 0xea, 0x73, 0x76, 0xae, 0x6d, 0xb9, 0xda, 0x8e, 0x9d, 0xb4,
- 0x5d, 0x2a, 0x78, 0xf2, 0x96, 0xe1, 0x78, 0x24, 0x1c, 0x41, 0xd6, 0x7d,
- 0xfc, 0x83, 0x37, 0xef, 0x8e, 0x9b, 0xb7, 0x0e, 0x9f, 0x58, 0xe1, 0xde,
- 0x4e, 0x8f, 0x8f, 0x64, 0x46, 0x72, 0x31, 0x3b, 0x3f, 0xb2, 0x74, 0xf6,
- 0x38, 0x37, 0xf3, 0xa3, 0xa3, 0xc3, 0xec, 0x7a, 0x7c, 0xaa, 0x16, 0x79,
- 0xd3, 0xcc, 0x16, 0x27, 0x4f, 0x67, 0x2d, 0xf1, 0xd0, 0xc7, 0xcb, 0xb2,
- 0x5d, 0x07, 0xa7, 0xcc, 0xff, 0xbb, 0x79, 0xd3, 0x98, 0x5e, 0x74, 0x38,
- 0x78, 0x7c, 0x29, 0x9d, 0xbf, 0xca, 0x3a, 0x7e, 0x65, 0x50, 0xa7, 0xf3,
- 0xa5, 0x93, 0xa1, 0x0d, 0xe5, 0x96, 0x4d, 0xf3, 0x15, 0x36, 0x9a, 0x15,
- 0x08, 0x6b, 0xb4, 0x16, 0x9f, 0xd6, 0xf1, 0xae, 0x6d, 0x0a, 0x59, 0xa1,
- 0x9e, 0xea, 0xf1, 0xc9, 0xd3, 0x98, 0x5c, 0x3a, 0x61, 0x63, 0xa1, 0xc3,
- 0x5e, 0x03, 0x73, 0xff, 0x7f, 0x41, 0xf6, 0x59, 0x57, 0x8f, 0x0e, 0x9d,
- 0xf5, 0x3b, 0x9d, 0x1f, 0xcf, 0x90, 0x11, 0x65, 0xfc, 0xe9, 0x83, 0xf9,
- 0xd0, 0x86, 0xa7, 0xf0, 0x94, 0xff, 0xf2, 0x71, 0x9e, 0x9c, 0xdd, 0x63,
- 0xce, 0xd8, 0xe8, 0x64, 0xe5, 0x29, 0x49, 0x21, 0x0b, 0xb4, 0xcb, 0x22,
- 0x83, 0xa4, 0xa3, 0xa5, 0xbe, 0x17, 0x4e, 0x82, 0xa7, 0xef, 0x9b, 0x74,
- 0xea, 0xce, 0x9f, 0x93, 0x95, 0xbb, 0xfe, 0x74, 0xed, 0x34, 0xd0, 0xa9,
- 0xff, 0xab, 0xdd, 0x36, 0x1f, 0xab, 0x77, 0x89, 0x4b, 0x2f, 0xe7, 0x90,
- 0x1d, 0xfa, 0x3a, 0x40, 0x74, 0xf9, 0x49, 0xcf, 0xac, 0xe8, 0xc0, 0xf6,
- 0xb5, 0xe4, 0x9d, 0x87, 0xcf, 0xef, 0x26, 0x46, 0x9d, 0x59, 0xd3, 0x57,
- 0x0e, 0x8c, 0x4f, 0x1f, 0x66, 0x53, 0xdc, 0x1a, 0x79, 0xd3, 0xff, 0x93,
- 0x3b, 0xae, 0x86, 0x9d, 0x0d, 0x64, 0xe8, 0x03, 0xe9, 0xe1, 0x04, 0x96,
- 0xcb, 0xe1, 0xb8, 0x39, 0x75, 0x08, 0x9a, 0x72, 0x42, 0x30, 0x5a, 0x53,
- 0x76, 0xe3, 0xd4, 0xb6, 0x6f, 0x8a, 0x1d, 0x82, 0xe1, 0x4c, 0xcc, 0x2c,
- 0x38, 0xf9, 0xfa, 0x11, 0x93, 0xe0, 0xf5, 0xdf, 0x8d, 0x15, 0xbc, 0xff,
- 0xad, 0xeb, 0xa0, 0xf5, 0xdf, 0x8d, 0x13, 0x84, 0x97, 0x47, 0xf4, 0xa3,
- 0x29, 0xbb, 0xd9, 0xd3, 0xe0, 0xf5, 0xdf, 0x8d, 0x16, 0x8c, 0xfc, 0xd6,
- 0x3d, 0xf5, 0x47, 0x4c, 0x9f, 0xce, 0x9f, 0xff, 0x60, 0xdc, 0x6e, 0x81,
- 0xb7, 0x79, 0x1a, 0xf8, 0xe9, 0xff, 0x36, 0x37, 0xaf, 0xd8, 0xde, 0xbf,
- 0x03, 0xa1, 0x91, 0x35, 0xb5, 0x49, 0x53, 0x88, 0xd3, 0xcc, 0x2c, 0x64,
- 0xb7, 0x69, 0x37, 0x6a, 0x17, 0x51, 0x96, 0xe1, 0xff, 0x3d, 0xeb, 0xbf,
- 0x1a, 0x2d, 0xa9, 0xfb, 0x6c, 0xa6, 0x4e, 0x8e, 0x95, 0x01, 0xec, 0xf0,
- 0xb6, 0x7f, 0x97, 0xff, 0xfd, 0x87, 0x5d, 0x89, 0xd0, 0xb3, 0xe3, 0xf8,
- 0x9a, 0x7f, 0x2e, 0x83, 0xd7, 0x7e, 0x34, 0x5c, 0xb3, 0xf9, 0x74, 0x1e,
- 0xbb, 0xf1, 0xa2, 0xed, 0x86, 0x6c, 0xe6, 0xf0, 0x28, 0x7c, 0xa3, 0x1e,
- 0xa1, 0xbd, 0xfe, 0x5e, 0xa2, 0x4f, 0xf2, 0xeb, 0xe3, 0x68, 0xdc, 0x73,
- 0xa3, 0x18, 0x4e, 0x48, 0xf8, 0x7b, 0x3f, 0x97, 0x41, 0xeb, 0xbf, 0x1a,
- 0x2a, 0x79, 0x93, 0x87, 0x4f, 0x7a, 0xef, 0xc6, 0x8a, 0xe6, 0x7f, 0x2e,
- 0x83, 0xd7, 0x7e, 0x34, 0x59, 0xd0, 0x07, 0xd5, 0xb2, 0xd9, 0xff, 0xea,
- 0xe3, 0x67, 0x57, 0x79, 0xe3, 0x38, 0xe2, 0x1d, 0x3f, 0xed, 0xa0, 0x75,
- 0xba, 0x41, 0xfe, 0x74, 0xf8, 0x3d, 0x77, 0xe3, 0x44, 0x85, 0x3f, 0xc9,
- 0x8e, 0x78, 0x2c, 0xac, 0x9d, 0x33, 0xd7, 0x47, 0xd5, 0xf1, 0x94, 0xf3,
- 0xb5, 0xb6, 0x51, 0xd3, 0xfa, 0xb7, 0x9c, 0xd0, 0x60, 0x74, 0x97, 0xd2,
- 0xa2, 0x1a, 0x7f, 0x42, 0x17, 0x14, 0xee, 0x15, 0x19, 0x2e, 0xe1, 0x34,
- 0xff, 0xe5, 0xaa, 0xde, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x3e, 0x47, 0x95,
- 0x91, 0x6b, 0xe5, 0x2f, 0x6d, 0xc2, 0x7c, 0x1e, 0xbb, 0xf1, 0xa2, 0xb2,
- 0x9f, 0xf5, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x6e, 0x99, 0x17, 0x47,
- 0xf4, 0xa3, 0x29, 0xff, 0xcb, 0x55, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2,
- 0x56, 0x9f, 0xf2, 0x67, 0xb5, 0x0a, 0x3a, 0xee, 0xce, 0x9f, 0xc2, 0xc1,
- 0x4e, 0xad, 0x47, 0x43, 0xcf, 0xc5, 0x10, 0x27, 0xc1, 0xeb, 0xbf, 0x1a,
- 0x25, 0xc9, 0xfe, 0x4b, 0x7f, 0x05, 0x95, 0x93, 0xa7, 0x9d, 0x20, 0xb1,
- 0xd3, 0xe5, 0xaa, 0xde, 0xb6, 0x45, 0x55, 0x10, 0xec, 0xca, 0xcd, 0xa7,
- 0xfe, 0x5d, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x3b, 0x9f, 0xee, 0x6e,
- 0x9e, 0xbb, 0x1c, 0x9d, 0x3f, 0x6b, 0x82, 0xde, 0xa1, 0x3a, 0x6e, 0xf6,
- 0x74, 0xfc, 0xed, 0x8d, 0x6e, 0xf8, 0x74, 0xfe, 0xad, 0x32, 0xc3, 0xcc,
- 0x9d, 0x3e, 0x0f, 0x5d, 0xf8, 0xd1, 0x50, 0xcf, 0x6f, 0x95, 0x81, 0xd3,
- 0xea, 0xc2, 0xc5, 0xd1, 0xd3, 0xff, 0xff, 0xf9, 0x9f, 0xab, 0x9b, 0x46,
- 0xce, 0xaa, 0xef, 0xcc, 0xeb, 0x55, 0x00, 0x53, 0xae, 0xef, 0x67, 0x45,
- 0x23, 0x80, 0x48, 0xb2, 0x51, 0x3f, 0xff, 0xdd, 0xde, 0xbd, 0x30, 0xdd,
- 0xa7, 0x1b, 0x69, 0xcc, 0xd7, 0x47, 0x49, 0x6e, 0xda, 0xa5, 0x27, 0x68,
- 0xbf, 0x5c, 0x17, 0xc0, 0xc2, 0x8c, 0xb9, 0x18, 0x96, 0xb1, 0x74, 0xf8,
- 0x3d, 0x77, 0xe3, 0x45, 0x51, 0x3f, 0xeb, 0x7a, 0xe8, 0x3d, 0x77, 0xe3,
- 0x44, 0xd7, 0x25, 0xd1, 0xfd, 0x28, 0xca, 0x7f, 0x2e, 0x83, 0xd7, 0x7e,
- 0x34, 0x55, 0x93, 0xfe, 0x5e, 0xdb, 0x1e, 0x36, 0xef, 0x5e, 0x74, 0xff,
- 0xcb, 0xb7, 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x48, 0x93, 0xe0, 0xf5, 0xdf,
- 0x8d, 0x16, 0x94, 0xff, 0xad, 0xeb, 0xa0, 0xf5, 0xdf, 0x8d, 0x13, 0xec,
- 0x97, 0x47, 0xf4, 0xa3, 0x29, 0xff, 0xcb, 0x55, 0xbd, 0x74, 0x1e, 0xbb,
- 0xf1, 0xa2, 0x84, 0x9f, 0x6d, 0x30, 0x60, 0x3a, 0x7c, 0x1e, 0xbb, 0xf1,
- 0xa2, 0x8f, 0x9f, 0xf0, 0xb3, 0x8c, 0x2c, 0xe6, 0xd8, 0xe9, 0xff, 0xfa,
- 0xba, 0xdb, 0x7e, 0x5f, 0x06, 0xfe, 0xce, 0x5b, 0xe2, 0xa7, 0xcb, 0x55,
- 0xbd, 0x6c, 0x8f, 0x2a, 0x26, 0xe1, 0x96, 0xb1, 0xe4, 0x33, 0x23, 0x47,
- 0x08, 0xdb, 0xde, 0xaf, 0x49, 0xdf, 0xe5, 0x44, 0xfa, 0x1f, 0xd8, 0x93,
- 0xa1, 0xeb, 0x88, 0x5b, 0x86, 0x47, 0xc4, 0xfc, 0x8d, 0x1a, 0x7f, 0x2e,
- 0x83, 0xd7, 0x7e, 0x34, 0x44, 0x53, 0xf5, 0x07, 0xae, 0xfc, 0x68, 0x8a,
- 0xe7, 0xfb, 0x5e, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x5c, 0x42, 0xcf, 0xfa,
- 0xcd, 0xe7, 0xab, 0x77, 0xc3, 0xa7, 0xf5, 0x20, 0x7d, 0xf7, 0x79, 0x3a,
- 0x4e, 0xd8, 0x9e, 0xa6, 0x48, 0x27, 0xff, 0xee, 0x65, 0x37, 0x68, 0xf4,
- 0x1e, 0x77, 0xb0, 0xa3, 0xa7, 0xc1, 0xeb, 0xbf, 0x1a, 0x29, 0xe9, 0xfa,
- 0xb3, 0xa8, 0x6d, 0xe7, 0x46, 0xb8, 0x8e, 0x36, 0x2c, 0xa5, 0x81, 0x32,
- 0x9f, 0xfd, 0x6f, 0x5f, 0x43, 0x7a, 0x67, 0x2d, 0xf1, 0xd0, 0xb4, 0x45,
- 0x74, 0x7f, 0x39, 0x7d, 0x51, 0xd3, 0xff, 0xed, 0xb0, 0x53, 0xd2, 0xf9,
- 0x5d, 0x27, 0x7e, 0x3a, 0x7c, 0xcf, 0xfb, 0xb7, 0x9d, 0x3d, 0xeb, 0xbf,
- 0x1a, 0x2b, 0x38, 0x70, 0xf5, 0x80, 0xa6, 0x7e, 0xc1, 0x4c, 0x2f, 0xc9,
- 0xd3, 0x9b, 0x04, 0x3a, 0x7d, 0xcf, 0xbf, 0x0b, 0xce, 0x9d, 0xdd, 0xe4,
- 0xe9, 0xf5, 0x39, 0x87, 0x7f, 0x1d, 0x25, 0xf4, 0x9c, 0x25, 0x42, 0xa4,
- 0x08, 0xb6, 0x5b, 0x63, 0x62, 0x55, 0xf8, 0x72, 0x7f, 0xe5, 0xdb, 0xd7,
- 0x41, 0xeb, 0xbf, 0x1a, 0x24, 0x59, 0xfa, 0x83, 0xd7, 0x7e, 0x34, 0x59,
- 0x33, 0xff, 0xb9, 0x9f, 0xd9, 0x5d, 0x60, 0x82, 0xfc, 0x9d, 0x0b, 0x44,
- 0x1d, 0x1b, 0xcf, 0xe5, 0xd0, 0x7a, 0xef, 0xc6, 0x8b, 0x62, 0x75, 0x66,
- 0x8e, 0x9e, 0xf5, 0xdf, 0x8d, 0x16, 0xdc, 0xf6, 0x70, 0xb0, 0x3a, 0x00,
- 0xf3, 0xb8, 0x5b, 0x25, 0xbd, 0x11, 0x34, 0xd1, 0x3b, 0x0d, 0xa1, 0xd3,
- 0xfe, 0xd7, 0x35, 0xc7, 0x67, 0xcd, 0xd0, 0xb7, 0xc7, 0x4f, 0xcc, 0x2f,
- 0xeb, 0xb5, 0x1d, 0x3e, 0x0f, 0x5d, 0xf8, 0xd1, 0x78, 0x4f, 0x73, 0x5a,
- 0xb6, 0x74, 0xff, 0xcd, 0xf9, 0x58, 0xbf, 0x94, 0x3c, 0xc9, 0xd3, 0xea,
- 0x1f, 0x9d, 0xd8, 0xe9, 0xf3, 0x7e, 0xee, 0xf2, 0x74, 0xee, 0x37, 0xc7,
- 0x49, 0x7a, 0xe2, 0x74, 0x5a, 0xea, 0x1c, 0xc1, 0x3a, 0x8b, 0xb1, 0x32,
- 0xd9, 0x27, 0xc8, 0xc2, 0x53, 0xc2, 0x99, 0xc9, 0x58, 0x9d, 0x3e, 0x0f,
- 0x5d, 0xf8, 0xd1, 0x7a, 0x4f, 0xf8, 0x6f, 0x8f, 0x6f, 0xfc, 0x4c, 0x0e,
- 0x9f, 0x52, 0xb7, 0x7d, 0x1d, 0x25, 0xf4, 0x8b, 0x3a, 0x1b, 0xfc, 0x64,
- 0xee, 0x7f, 0x0c, 0xc9, 0xe1, 0xc2, 0x17, 0x75, 0x1f, 0x17, 0x89, 0x12,
- 0x3a, 0x00, 0x6f, 0x54, 0x34, 0x7e, 0x22, 0x18, 0x63, 0x77, 0x1e, 0x56,
- 0x91, 0xa3, 0x4d, 0xde, 0xce, 0x9e, 0xad, 0xdf, 0x0e, 0x9f, 0xd4, 0x81,
- 0xf7, 0xdd, 0xe4, 0xe9, 0x3b, 0x62, 0x7a, 0x99, 0x20, 0x9f, 0x27, 0x1b,
- 0x1c, 0x0e, 0x9f, 0x07, 0xae, 0xfc, 0x68, 0x88, 0xe7, 0xff, 0xb7, 0xde,
- 0x73, 0x4a, 0x1a, 0x75, 0xa9, 0x9d, 0x91, 0xd3, 0xfe, 0x7b, 0x60, 0x15,
- 0xce, 0x27, 0x0e, 0x9f, 0xea, 0x0a, 0xcd, 0x58, 0xe0, 0x74, 0xff, 0xff,
- 0x36, 0xed, 0x38, 0xdb, 0x1a, 0xe6, 0xd3, 0x74, 0x9a, 0x1d, 0x36, 0x0a,
- 0x2a, 0x6d, 0x34, 0x2a, 0x7f, 0xcb, 0xf6, 0xd1, 0xcd, 0xb6, 0x0b, 0xf8,
- 0xd7, 0xe8, 0x2f, 0x3c, 0xe9, 0xb8, 0xc7, 0x43, 0xcf, 0xed, 0x16, 0x67,
- 0xed, 0x78, 0xd6, 0xef, 0x87, 0x4f, 0xcd, 0xfe, 0x85, 0x3f, 0x9d, 0x3f,
- 0x57, 0x1d, 0xf9, 0x5b, 0x3a, 0x29, 0x11, 0x82, 0x5f, 0x92, 0xe9, 0xff,
- 0xfb, 0xcb, 0x0b, 0x14, 0xe2, 0xc1, 0xb8, 0x37, 0xf1, 0xd0, 0xed, 0x2b,
- 0xfa, 0xd7, 0x1a, 0xd8, 0xb2, 0x8a, 0x3c, 0x65, 0x8a, 0xca, 0x1e, 0x81,
- 0xad, 0xc6, 0x19, 0xc8, 0x56, 0xba, 0x2e, 0x9f, 0x07, 0xae, 0xfc, 0x68,
- 0x8b, 0xa7, 0xdc, 0xfb, 0xf0, 0xbc, 0xa9, 0x2e, 0x8f, 0x72, 0xcc, 0xa1,
- 0x69, 0x97, 0xbe, 0x30, 0x99, 0xff, 0x95, 0x6f, 0x5d, 0x07, 0xae, 0xfc,
- 0x68, 0x99, 0xa7, 0xed, 0x74, 0x76, 0x6e, 0xde, 0x5b, 0x87, 0x4e, 0xc5,
- 0xb2, 0x74, 0xef, 0x22, 0x8e, 0x9b, 0x5b, 0x5d, 0x9d, 0x3f, 0x72, 0xb0,
- 0xaf, 0x9c, 0x3a, 0x35, 0xd9, 0xe7, 0x38, 0x3f, 0x3e, 0xf5, 0xed, 0x1c,
- 0x3a, 0x7f, 0xfd, 0xf6, 0x2f, 0xdf, 0x6c, 0x0b, 0xda, 0x7a, 0xc0, 0xe9,
- 0xff, 0x9d, 0xd3, 0x89, 0xe4, 0xeb, 0x95, 0xe3, 0xa7, 0xff, 0xfb, 0xbb,
- 0x1f, 0x0d, 0x75, 0xbe, 0xf5, 0x6d, 0x9e, 0x0d, 0x81, 0xd0, 0xc9, 0x82,
- 0xd2, 0xb6, 0xd1, 0xa7, 0xff, 0xdd, 0x20, 0xe1, 0x59, 0x4b, 0xda, 0xf4,
- 0xd3, 0x42, 0xa7, 0xec, 0x5f, 0x9f, 0xbb, 0x70, 0xe9, 0xef, 0x5d, 0xf8,
- 0xd1, 0x67, 0xcf, 0xf9, 0x36, 0xcf, 0x4e, 0x37, 0x32, 0x74, 0xff, 0xf2,
- 0x06, 0xef, 0x55, 0x3a, 0x1a, 0xcd, 0x09, 0xd3, 0xb4, 0xd3, 0x42, 0xa7,
- 0xfd, 0x6f, 0xc8, 0xd7, 0xba, 0xa0, 0x29, 0x65, 0xfc, 0xff, 0x36, 0xd3,
- 0xa1, 0xbb, 0x70, 0xe9, 0xfe, 0x41, 0xeb, 0xf7, 0x5d, 0xf3, 0x27, 0x47,
- 0x95, 0x0f, 0xb8, 0xb0, 0x06, 0x4a, 0x2d, 0xd9, 0xe7, 0xcd, 0xbc, 0x4b,
- 0x74, 0x6f, 0x3f, 0xc1, 0x7a, 0x6d, 0x18, 0x18, 0xe9, 0xff, 0xff, 0xfa,
- 0xab, 0xec, 0xd5, 0x0f, 0xff, 0xc0, 0x2d, 0x5b, 0x5e, 0x46, 0xb0, 0x55,
- 0x28, 0xe9, 0xd9, 0x6c, 0x0e, 0x9d, 0xad, 0x5b, 0x3a, 0x1e, 0x8c, 0x2c,
- 0xc2, 0x23, 0x83, 0x93, 0xb7, 0xde, 0x87, 0x4e, 0xfb, 0xbf, 0x1d, 0x3b,
- 0x95, 0xf8, 0xe8, 0xe8, 0xf6, 0x71, 0x1e, 0x41, 0xe9, 0xf8, 0x11, 0xd5,
- 0x0e, 0x4e, 0x9f, 0x6c, 0x5a, 0x80, 0xc9, 0xff, 0x20, 0x3e, 0x83, 0x0e,
- 0xef, 0xa3, 0x44, 0x1a, 0xb3, 0x49, 0x3e, 0xbf, 0x22, 0x98, 0xe9, 0xf9,
- 0xfb, 0x1b, 0xc7, 0x87, 0x4a, 0xbc, 0x7a, 0x42, 0x4b, 0x3f, 0xf5, 0x0e,
- 0x3c, 0xa0, 0x4c, 0x2d, 0x47, 0x4c, 0x82, 0x74, 0xfd, 0x7a, 0x72, 0xb7,
- 0xc6, 0x3d, 0x6f, 0xe8, 0x50, 0xc9, 0xdf, 0xbd, 0x42, 0xa1, 0x5a, 0x2f,
- 0x93, 0xf0, 0x57, 0x59, 0xdb, 0x1d, 0x3f, 0xff, 0xbb, 0x1b, 0xff, 0xab,
- 0xf0, 0xdf, 0x32, 0x98, 0xed, 0x34, 0x3a, 0x7f, 0xca, 0xae, 0x67, 0xf6,
- 0x6d, 0xf4, 0x74, 0xfd, 0x9c, 0xb0, 0x71, 0x8e, 0x59, 0xbf, 0x9e, 0xdd,
- 0x23, 0xa3, 0xa7, 0xec, 0xa0, 0x57, 0x60, 0x74, 0x22, 0x22, 0x36, 0x77,
- 0xc2, 0x29, 0x94, 0xed, 0x9a, 0x2f, 0xc9, 0xff, 0x9f, 0xce, 0xde, 0xf5,
- 0x73, 0x8c, 0xa3, 0xa7, 0xfe, 0x4a, 0x1a, 0xac, 0xea, 0x7e, 0x54, 0x74,
- 0x62, 0x88, 0x9c, 0xa3, 0x4c, 0x8e, 0x1d, 0x3b, 0x89, 0x81, 0xd3, 0x85,
- 0xbc, 0x74, 0x6a, 0x3c, 0xc5, 0x0b, 0x08, 0xe4, 0x32, 0x70, 0x1d, 0x17,
- 0xd4, 0x2c, 0x6d, 0xc2, 0x7f, 0xff, 0xe7, 0x76, 0xda, 0x29, 0x6e, 0x3e,
- 0xc3, 0xf6, 0xd3, 0x1c, 0xf9, 0x30, 0x3a, 0x7e, 0xb0, 0x6d, 0xfe, 0xe8,
- 0xe9, 0xed, 0x2e, 0xb2, 0x74, 0xff, 0x3d, 0x56, 0xfe, 0x65, 0xbf, 0x9d,
- 0x0c, 0x7b, 0x76, 0x43, 0x3d, 0x59, 0x41, 0x3a, 0x2d, 0x19, 0x03, 0x08,
- 0x9e, 0xc8, 0x27, 0xbf, 0x77, 0x79, 0x3a, 0x7b, 0xef, 0xab, 0x13, 0xa7,
- 0xe7, 0x7e, 0x55, 0x8f, 0x8e, 0x9f, 0xec, 0xfc, 0x98, 0xe2, 0xfa, 0xe1,
- 0xd3, 0xf3, 0x63, 0x95, 0x26, 0xbc, 0xe8, 0x04, 0x5f, 0x6c, 0x93, 0x85,
- 0xce, 0x8e, 0xe1, 0x93, 0x20, 0xa8, 0x71, 0x4c, 0xe7, 0x67, 0x49, 0x47,
- 0x46, 0x26, 0xa1, 0xd8, 0x18, 0x9f, 0xd7, 0x78, 0xbc, 0x5b, 0xa3, 0xa7,
- 0xff, 0x0a, 0x36, 0x46, 0xdf, 0xab, 0x34, 0x07, 0x4f, 0xff, 0xfb, 0x69,
- 0x8f, 0x2b, 0x1e, 0x00, 0x37, 0x3e, 0xfc, 0x2f, 0xdd, 0x1d, 0x3d, 0xd7,
- 0x56, 0x27, 0x4f, 0xfa, 0xf7, 0xe4, 0xbd, 0x59, 0xbd, 0x9d, 0x0c, 0x9b,
- 0x77, 0x44, 0xf4, 0x65, 0xe4, 0x74, 0x6e, 0xd9, 0x14, 0xff, 0xd4, 0x38,
- 0xf2, 0x81, 0x30, 0xb5, 0x1d, 0x3e, 0xae, 0x3d, 0x5b, 0x3a, 0x7d, 0x8e,
- 0x45, 0x94, 0x74, 0x32, 0x24, 0x32, 0x85, 0xd9, 0x3c, 0xf9, 0xc4, 0xda,
- 0x28, 0xe9, 0x6c, 0xe9, 0xb2, 0xf3, 0xa3, 0xe3, 0x4d, 0xd8, 0x84, 0xfd,
- 0x83, 0x8f, 0xd7, 0x03, 0x03, 0xa7, 0xf7, 0xfd, 0xd7, 0x36, 0x9c, 0x3a,
- 0x64, 0x03, 0xa3, 0x5d, 0x9f, 0xea, 0x1a, 0xec, 0xd2, 0x7f, 0xee, 0x9b,
- 0xa0, 0x6e, 0x27, 0x93, 0xa3, 0xa7, 0xed, 0xf7, 0x83, 0x9b, 0x43, 0xa3,
- 0xa3, 0xf4, 0xda, 0x24, 0x97, 0xae, 0xdb, 0x2c, 0xb7, 0x68, 0xfd, 0xd9,
- 0x8e, 0x33, 0x4e, 0x05, 0x3d, 0x46, 0x59, 0x52, 0x93, 0xbf, 0xbb, 0x63,
- 0x0f, 0x74, 0x84, 0x73, 0x91, 0xf7, 0x82, 0x02, 0x8b, 0x37, 0x2a, 0xba,
- 0xd0, 0x7e, 0x8d, 0x00, 0x63, 0x54, 0xcc, 0x77, 0xbc, 0x87, 0x37, 0x66,
- 0x1a, 0x26, 0xeb, 0x42, 0x83, 0xf4, 0x2a, 0x21, 0x6d, 0xa5, 0xb6, 0xeb,
- 0x31, 0x99, 0xff, 0xcb, 0x55, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x6c,
- 0x9f, 0xcb, 0xa0, 0xf5, 0xdf, 0x8d, 0x15, 0x6c, 0xfe, 0x7b, 0xfb, 0xe0,
- 0xb3, 0xce, 0x9e, 0xad, 0xdf, 0x0e, 0x93, 0xb7, 0x47, 0xa6, 0x26, 0x73,
- 0xe0, 0xf5, 0xdf, 0x8d, 0x15, 0xa4, 0xff, 0xf7, 0x98, 0x2b, 0xeb, 0x55,
- 0xbd, 0x93, 0xc7, 0x4f, 0xff, 0x3f, 0x34, 0x2c, 0xab, 0xae, 0x71, 0x94,
- 0x74, 0xdc, 0xe3, 0x22, 0x62, 0xd3, 0x27, 0xf3, 0x3a, 0xfd, 0xc1, 0x6f,
- 0x8e, 0x9f, 0xb0, 0xad, 0xa5, 0x28, 0xe9, 0xf3, 0x95, 0xd2, 0xb5, 0xe7,
- 0x4f, 0xc2, 0xda, 0x62, 0xfc, 0x9d, 0x2a, 0x70, 0xf6, 0xdd, 0xcb, 0x67,
- 0xf3, 0xeb, 0x96, 0x3f, 0x76, 0x74, 0x97, 0xae, 0x2a, 0x3d, 0xa2, 0xb4,
- 0x86, 0x56, 0xcb, 0x6c, 0xd8, 0x61, 0x0f, 0xc2, 0xb9, 0xfc, 0xba, 0x0f,
- 0x5d, 0xf8, 0xd1, 0x60, 0x4f, 0x83, 0xd7, 0x7e, 0x34, 0x4e, 0xb3, 0xff,
- 0xfb, 0x6d, 0x87, 0x54, 0xa5, 0xe7, 0x35, 0xb4, 0xcf, 0x78, 0x1d, 0x3e,
- 0x5a, 0xad, 0xeb, 0xa4, 0x4b, 0x38, 0x65, 0x3f, 0x9f, 0x95, 0xff, 0xfe,
- 0xca, 0x3a, 0x7c, 0x1e, 0xbb, 0xf1, 0xa2, 0xd9, 0x9f, 0xf7, 0xcd, 0x95,
- 0xed, 0x3d, 0x60, 0x74, 0x97, 0x47, 0xdf, 0x66, 0x53, 0xde, 0xbb, 0xf1,
- 0xa2, 0xe6, 0x92, 0x8e, 0x80, 0x37, 0xba, 0x16, 0xcc, 0xe2, 0x8e, 0x92,
- 0xe8, 0xdc, 0x68, 0x43, 0x3f, 0x97, 0x41, 0xeb, 0xbf, 0x1a, 0x2e, 0xf9,
- 0xe5, 0xff, 0xeb, 0xe3, 0xa1, 0x9b, 0xb8, 0x8a, 0xad, 0x38, 0x3c, 0x65,
- 0x8a, 0xa2, 0x4a, 0xcd, 0x07, 0x75, 0x43, 0x4e, 0xd0, 0x3e, 0x85, 0x36,
- 0x61, 0x37, 0xc2, 0x7f, 0xc7, 0xb3, 0xec, 0xe5, 0x56, 0xf3, 0xa7, 0xfe,
- 0xc7, 0xdd, 0xde, 0x3c, 0xaa, 0x1f, 0xe7, 0x4e, 0x1b, 0x5b, 0x1f, 0x77,
- 0x09, 0xe7, 0xf0, 0xe1, 0x4e, 0xfc, 0x6f, 0xe7, 0x4f, 0x83, 0xd7, 0x7e,
- 0x34, 0x4a, 0xf3, 0xfe, 0x1b, 0xd3, 0xad, 0xb6, 0x15, 0xa1, 0xd3, 0xff,
- 0xf3, 0xe9, 0x3e, 0xa5, 0x27, 0x32, 0xca, 0xbc, 0x78, 0x74, 0xf7, 0x76,
- 0x0f, 0x3a, 0x7f, 0xff, 0x27, 0x2d, 0x56, 0x3f, 0x6f, 0x4b, 0x1c, 0x3c,
- 0x98, 0x1d, 0x1d, 0x22, 0x0a, 0xc8, 0x63, 0xa4, 0xcf, 0xe9, 0x03, 0x70,
- 0xdc, 0x9f, 0xf7, 0x2d, 0xf9, 0xdb, 0x07, 0xee, 0x8e, 0x9f, 0xfb, 0x88,
- 0xe9, 0x38, 0xe3, 0xd8, 0x78, 0x74, 0xeb, 0x7a, 0xd9, 0x53, 0x1d, 0x1b,
- 0xe6, 0x37, 0x1e, 0x1b, 0x7e, 0x40, 0x9f, 0xfd, 0x5b, 0x58, 0xd7, 0x48,
- 0x3c, 0xad, 0x9d, 0x3b, 0x8d, 0xd1, 0x53, 0xff, 0xb7, 0x69, 0xc6, 0x7a,
- 0x06, 0x1d, 0xfc, 0x54, 0xfe, 0xbf, 0x2f, 0xa0, 0x76, 0x16, 0xc7, 0xcd,
- 0x91, 0xc9, 0x2f, 0xca, 0xfc, 0xd5, 0x2a, 0x53, 0x8c, 0x6e, 0xa1, 0x5b,
- 0x3f, 0xf9, 0x6a, 0xb7, 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x4c, 0x33, 0xff,
- 0x85, 0x9d, 0x0b, 0x62, 0xbd, 0x76, 0xec, 0xf2, 0xf3, 0xa7, 0xff, 0x05,
- 0xfc, 0xbf, 0xfc, 0x7e, 0x8d, 0x97, 0x9d, 0x35, 0x2f, 0xa4, 0x52, 0x7e,
- 0x57, 0x9f, 0xf9, 0xdb, 0xac, 0x5f, 0xdd, 0xf0, 0x59, 0xe7, 0x4f, 0xe6,
- 0xbc, 0x39, 0xfe, 0xc0, 0xe9, 0xf5, 0x83, 0xed, 0x47, 0x40, 0x9e, 0xc7,
- 0x66, 0x73, 0xf2, 0x9a, 0x87, 0x9a, 0xc7, 0x4b, 0x27, 0x4f, 0x9a, 0x87,
- 0x9a, 0xc7, 0x4f, 0xdb, 0x4e, 0x66, 0xf1, 0xd4, 0x7c, 0xce, 0x17, 0x28,
- 0x42, 0x7f, 0xff, 0xc3, 0x5a, 0x3b, 0xf2, 0xb7, 0xa8, 0x6b, 0x04, 0xa1,
- 0xc5, 0xf9, 0x3a, 0x7f, 0xf9, 0xb8, 0x37, 0xf6, 0xe9, 0x3a, 0xef, 0x99,
- 0x3a, 0x7e, 0x75, 0xfb, 0x82, 0xdf, 0x1d, 0x3f, 0xf9, 0xb9, 0xf3, 0x3e,
- 0xb1, 0xe6, 0x1d, 0xe8, 0x74, 0x31, 0xff, 0xa1, 0x8c, 0xfd, 0x94, 0xfe,
- 0xab, 0xe1, 0xd3, 0xff, 0xfe, 0x0a, 0x74, 0xc3, 0xcd, 0x5f, 0x85, 0xb7,
- 0x69, 0xc6, 0xe6, 0x4e, 0x95, 0x62, 0x89, 0xb0, 0x2e, 0x9f, 0xff, 0x6c,
- 0x6b, 0x9b, 0x4a, 0xc7, 0x94, 0xe9, 0xb2, 0x74, 0xe6, 0xfb, 0xf1, 0xd1,
- 0x47, 0xe6, 0x2a, 0xb3, 0xd7, 0xfb, 0xaa, 0x3a, 0x4b, 0xd7, 0x17, 0x15,
- 0xba, 0x85, 0x0f, 0xa1, 0x10, 0xe2, 0xa8, 0x38, 0x6e, 0x19, 0xe3, 0x0b,
- 0xbe, 0x42, 0x6f, 0xb2, 0x09, 0xff, 0xe0, 0x4c, 0x5f, 0x94, 0xe6, 0xd8,
- 0x38, 0xc7, 0x4f, 0x83, 0xd7, 0x7e, 0x34, 0x55, 0xd3, 0xfc, 0xf5, 0xd0,
- 0x7a, 0xef, 0xc6, 0x88, 0xf2, 0x4b, 0xe9, 0x18, 0x54, 0x9b, 0x66, 0x53,
- 0xf9, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0xc1, 0x9f, 0xcb, 0xa0, 0xf5, 0xdf,
- 0x8d, 0x16, 0x54, 0xfe, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0xb4, 0xe7, 0xf5,
- 0x67, 0x50, 0x07, 0x7b, 0x3a, 0x7b, 0xd7, 0x7e, 0x34, 0x5b, 0x93, 0xff,
- 0x35, 0x05, 0x0e, 0xad, 0xd6, 0x3a, 0x1d, 0x00, 0x7e, 0x39, 0x2d, 0x9f,
- 0xe6, 0x1e, 0xd4, 0xd9, 0xe2, 0x1d, 0x3f, 0xae, 0xf0, 0xe9, 0xa8, 0x0e,
- 0x9f, 0xf5, 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x87, 0x9f, 0xf9, 0x57,
- 0xd3, 0x75, 0xb4, 0x14, 0x51, 0xd3, 0xff, 0x76, 0xfd, 0xd8, 0x63, 0xc6,
- 0x4c, 0x0e, 0x9f, 0xf7, 0x61, 0xf0, 0x58, 0xf2, 0xbe, 0x3a, 0x7f, 0xa8,
- 0x46, 0xf9, 0xf9, 0xbc, 0x74, 0xfa, 0xf1, 0xcf, 0x10, 0xe8, 0xd9, 0xef,
- 0x64, 0xde, 0x7e, 0x1d, 0x72, 0x81, 0xb2, 0x74, 0xff, 0xfd, 0x5d, 0x6d,
- 0xbf, 0x2f, 0x83, 0x7f, 0x67, 0x2d, 0xf1, 0x52, 0x5b, 0xd5, 0xa4, 0xd4,
- 0x29, 0x50, 0x85, 0xc3, 0x75, 0x18, 0xda, 0x47, 0xc8, 0x79, 0x45, 0xe4,
- 0x27, 0x3b, 0x22, 0xd6, 0x2f, 0x9f, 0xcb, 0xa0, 0xf5, 0xdf, 0x8d, 0x17,
- 0x9c, 0x33, 0x31, 0x65, 0xea, 0x7d, 0x43, 0xe2, 0xa7, 0x21, 0xf1, 0x8d,
- 0xa0, 0x0d, 0x54, 0x7b, 0xb3, 0xd1, 0x97, 0x0c, 0xea, 0x15, 0xb3, 0xf9,
- 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x96, 0x9f, 0x07, 0xae, 0xfc, 0x68, 0xb0,
- 0xa7, 0xff, 0xcd, 0x43, 0xd3, 0x6d, 0xb1, 0xe5, 0x0d, 0xa8, 0xe9, 0x2e,
- 0x91, 0x08, 0xa3, 0x29, 0xfc, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x65, 0xcf,
- 0x2f, 0xfe, 0xba, 0x3b, 0x23, 0xa7, 0x2f, 0xf2, 0x8e, 0x96, 0x7c, 0x79,
- 0xfd, 0x98, 0xcf, 0xac, 0x2b, 0xfe, 0x07, 0x4f, 0xec, 0x31, 0xcb, 0x75,
- 0xc4, 0x3a, 0x7c, 0xd4, 0xe9, 0xb2, 0x74, 0xc2, 0xd6, 0x7b, 0x9a, 0x1a,
- 0xcf, 0x5b, 0xdf, 0xd1, 0xd3, 0xf5, 0x83, 0x72, 0xf6, 0x74, 0xcd, 0x93,
- 0xa3, 0xa3, 0xe1, 0xd9, 0x13, 0xa2, 0xa9, 0xf9, 0x2f, 0x3f, 0x67, 0xb3,
- 0xa4, 0xf3, 0xa4, 0xf3, 0xa4, 0xf3, 0xa1, 0x8d, 0x87, 0xf1, 0x04, 0x10,
- 0x9d, 0xcc, 0xf6, 0x74, 0xc8, 0xc7, 0x4f, 0xc2, 0xca, 0x16, 0xa3, 0xa3,
- 0xa3, 0x7a, 0xe0, 0xa4, 0xcc, 0xa3, 0xa7, 0xff, 0xe7, 0xb0, 0xf6, 0xf7,
- 0xb7, 0x37, 0x4a, 0xfc, 0xdf, 0x1d, 0x37, 0x96, 0xca, 0xb9, 0xf0, 0x29,
- 0xea, 0x10, 0x95, 0x08, 0xdf, 0x19, 0x5a, 0xf0, 0x97, 0x65, 0x6b, 0x58,
- 0x8f, 0xf0, 0xac, 0xff, 0xe5, 0xaa, 0xde, 0xba, 0x0f, 0x5d, 0xf8, 0xd1,
- 0x46, 0x4f, 0xe5, 0xb3, 0xa6, 0x06, 0xf8, 0xe8, 0x7a, 0xec, 0x48, 0x43,
- 0x05, 0x45, 0x17, 0x2d, 0xcf, 0x30, 0xa6, 0xe2, 0xa4, 0xff, 0xcb, 0xb7,
- 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x47, 0x33, 0xff, 0x96, 0xab, 0x7a, 0xe8,
- 0x3d, 0x77, 0xe3, 0x44, 0xe5, 0x3f, 0x97, 0x41, 0xeb, 0xbf, 0x1a, 0x2c,
- 0xc9, 0xfe, 0xf8, 0x1b, 0x9b, 0xbc, 0x5e, 0x74, 0xfe, 0xac, 0x80, 0x56,
- 0x39, 0x3a, 0x4b, 0x63, 0xea, 0x79, 0xcc, 0xfe, 0x5d, 0x07, 0xae, 0xfc,
- 0x68, 0xb7, 0x67, 0xff, 0x2d, 0x56, 0xf5, 0xd0, 0x7a, 0xef, 0xc6, 0x8a,
- 0x42, 0x7f, 0xe5, 0xdb, 0xd7, 0x41, 0xeb, 0xbf, 0x1a, 0x25, 0x28, 0xc1,
- 0x52, 0x7b, 0x89, 0xca, 0x54, 0xfa, 0x14, 0xe2, 0x4f, 0xc3, 0xd7, 0x75,
- 0x49, 0xff, 0x5b, 0xd7, 0x41, 0xeb, 0xbf, 0x1a, 0x27, 0x69, 0xff, 0xf2,
- 0x75, 0xda, 0x99, 0xde, 0xfa, 0x16, 0x1a, 0xf1, 0xd2, 0x5a, 0x91, 0x3f,
- 0x69, 0x13, 0xff, 0x5a, 0xb7, 0x5e, 0xbd, 0xb7, 0xe7, 0x9d, 0x3f, 0xf0,
- 0xd6, 0xef, 0x0a, 0xc8, 0xde, 0x27, 0x4d, 0xac, 0xbe, 0x91, 0x0d, 0x94,
- 0x48, 0x52, 0x38, 0x75, 0xa1, 0x5d, 0x3e, 0x0f, 0x5d, 0xf8, 0xd1, 0x16,
- 0x4f, 0xfa, 0xde, 0xba, 0x0f, 0x5d, 0xf8, 0xd1, 0x2e, 0xcf, 0xff, 0xd5,
- 0xd6, 0xdb, 0xf2, 0xf8, 0x37, 0xf6, 0x72, 0xdf, 0x15, 0x25, 0xd2, 0x36,
- 0x14, 0x65, 0xac, 0x91, 0x3f, 0xf9, 0x6a, 0xb7, 0xae, 0x83, 0xd7, 0x7e,
- 0x34, 0x4c, 0x53, 0xe0, 0xf5, 0xdf, 0x8d, 0x15, 0x4c, 0xa8, 0xe8, 0xa3,
- 0xc1, 0xfe, 0x65, 0x3f, 0xff, 0xf8, 0x2f, 0x78, 0xbe, 0xb8, 0xbd, 0xde,
- 0x41, 0x34, 0xe6, 0xd0, 0x1e, 0x74, 0x2d, 0x13, 0x36, 0x47, 0x3f, 0xf9,
- 0x6a, 0xb7, 0xae, 0x83, 0xd7, 0x7e, 0x34, 0x4e, 0x93, 0xf9, 0x2c, 0x19,
- 0xf6, 0xe8, 0xe9, 0xf3, 0x8c, 0xe3, 0x64, 0xe9, 0xfb, 0x4a, 0x47, 0x54,
- 0x27, 0x42, 0x1e, 0xae, 0x4a, 0x27, 0x26, 0xd8, 0xe5, 0x9a, 0x19, 0xff,
- 0xbb, 0xcf, 0x1b, 0x15, 0xf6, 0xe2, 0x28, 0xe8, 0x51, 0xf9, 0x6c, 0xaa,
- 0x7f, 0xd6, 0xf5, 0xd0, 0x7a, 0xef, 0xc6, 0x89, 0xde, 0x7d, 0xce, 0xed,
- 0x48, 0x54, 0x97, 0xd2, 0x75, 0x55, 0x18, 0xca, 0x88, 0xad, 0x22, 0x7f,
- 0xf2, 0xd5, 0x6f, 0x5d, 0x07, 0xae, 0xfc, 0x68, 0xa1, 0x67, 0xff, 0x2d,
- 0x56, 0xf5, 0xd0, 0x7a, 0xef, 0xc6, 0x8a, 0x4a, 0x7f, 0xff, 0x56, 0x57,
- 0xfa, 0x9c, 0xdd, 0xab, 0x9b, 0x6e, 0x76, 0xa3, 0xa3, 0x05, 0xcd, 0xb7,
- 0x9c, 0x7a, 0x32, 0xe0, 0x22, 0x54, 0x7f, 0xdf, 0x24, 0xf6, 0xa9, 0xac,
- 0xa9, 0x3f, 0x97, 0x41, 0xeb, 0xbf, 0x1a, 0x22, 0x49, 0xff, 0xcb, 0x55,
- 0xbd, 0x74, 0x1e, 0xbb, 0xf1, 0xa2, 0x5e, 0x9e, 0x0e, 0xf9, 0x93, 0xa7,
- 0xc1, 0xf2, 0x93, 0x27, 0x4e, 0xf9, 0xb8, 0x74, 0xff, 0xd6, 0xe6, 0x59,
- 0xd5, 0xed, 0xb1, 0x70, 0xe8, 0xe9, 0x15, 0x88, 0x44, 0xe1, 0x38, 0x0e,
- 0x4f, 0xf2, 0x58, 0xf7, 0xc7, 0x1b, 0xf9, 0xd3, 0xe0, 0xf5, 0xdf, 0x8d,
- 0x14, 0xbc, 0xf8, 0x79, 0x85, 0x68, 0x74, 0xff, 0x7d, 0x90, 0x6c, 0x5e,
- 0x8a, 0x3a, 0x7f, 0xaf, 0x0d, 0x58, 0x76, 0xe3, 0x6b, 0xce, 0x9a, 0x9e,
- 0xc7, 0xf7, 0xd9, 0xcc, 0xcf, 0xa3, 0xa7, 0x37, 0xd9, 0x3a, 0x3a, 0x36,
- 0x3a, 0x0a, 0xcf, 0xfc, 0x8a, 0xbe, 0xbf, 0x38, 0xf6, 0x1c, 0x4e, 0x9e,
- 0xca, 0x69, 0xc3, 0xa3, 0x67, 0xd3, 0xc4, 0x79, 0xfe, 0xbd, 0xdb, 0x88,
- 0x0d, 0x81, 0xd3, 0xe7, 0x74, 0x53, 0x64, 0xe9, 0xf5, 0xba, 0xa0, 0xc9,
- 0xd2, 0x6e, 0x8f, 0x41, 0x45, 0x33, 0xe4, 0xff, 0x9f, 0xbc, 0x74, 0x96,
- 0xca, 0xcc, 0x7a, 0x3d, 0xa3, 0xac, 0x4c, 0x9c, 0x85, 0x1e, 0xd7, 0xae,
- 0x11, 0x99, 0x22, 0xe4, 0x21, 0xf5, 0x8a, 0x27, 0xf2, 0xe8, 0x3d, 0x77,
- 0xe3, 0x45, 0x39, 0x3f, 0xe4, 0x0b, 0xce, 0xea, 0x87, 0xc7, 0x4f, 0xfa,
- 0xb6, 0xc1, 0x4b, 0xd3, 0x4d, 0x0a, 0x99, 0x34, 0x3a, 0x6c, 0x17, 0xd2,
- 0x23, 0xf5, 0x8e, 0x9d, 0xcf, 0xe7, 0xc1, 0xeb, 0xbf, 0x1a, 0x2b, 0xc9,
- 0xff, 0xfa, 0xba, 0xdb, 0x7e, 0x5f, 0x06, 0xfe, 0xce, 0x5b, 0xe2, 0xa4,
- 0xba, 0x44, 0x86, 0xb1, 0x94, 0xff, 0xcb, 0xb7, 0xae, 0x83, 0xd7, 0x7e,
- 0x34, 0x48, 0xf3, 0x93, 0xe6, 0x3a, 0x77, 0xa9, 0x45, 0x2c, 0xbb, 0x9f,
- 0x07, 0xae, 0xfc, 0x68, 0x92, 0x27, 0x97, 0x6f, 0x5b, 0x1e, 0xe5, 0x15,
- 0x4f, 0xfc, 0xbb, 0x7a, 0xe8, 0x3d, 0x77, 0xe3, 0x44, 0x95, 0x3e, 0x0f,
- 0x5d, 0xf8, 0xd1, 0x78, 0xcf, 0xb3, 0x9e, 0x57, 0x8e, 0x9f, 0xe7, 0xae,
- 0x83, 0xd7, 0x7e, 0x34, 0x49, 0xb2, 0x5d, 0x22, 0x70, 0x0c, 0xac, 0x9e,
- 0x19, 0x91, 0xef, 0x81, 0xeb, 0xe7, 0x0c, 0x7a, 0x85, 0x2a, 0x43, 0x31,
- 0xc8, 0x6a, 0x28, 0xaf, 0x70, 0xc5, 0xe1, 0xbf, 0x70, 0xea, 0x86, 0x8f,
- 0x5d, 0x83, 0x08, 0xec, 0xdf, 0x2b, 0x0f, 0xa9, 0x46, 0xf5, 0x79, 0x48,
- 0xdf, 0xe5, 0x32, 0x7a, 0xd2, 0xa3, 0xe3, 0x48, 0x14, 0x49, 0xea, 0x9d,
- 0x7c, 0x78, 0x0e, 0x56, 0x9a, 0x21, 0x4c, 0x25, 0x56, 0x2b, 0x08, 0x37,
- 0x3c, 0x89, 0x75, 0xa5, 0xdf, 0xd2, 0xfc, 0x5d, 0x88, 0x5b, 0x8d, 0x23,
- 0xf7, 0x34, 0xaa, 0xae, 0x5a, 0x17, 0x3e, 0xeb, 0x18, 0x37, 0x53, 0xc6,
- 0xfa, 0x4a, 0xb8, 0xd6, 0x8f, 0xc3, 0xf4, 0xee, 0xf3, 0xbd, 0x25, 0xf2,
- 0x00,
+ 0xfe, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x44, 0xb3, 0xef, 0xf6, 0xab, 0xaa,
+ 0x88, 0xb6, 0x6c, 0xe1, 0x29, 0x32, 0x52, 0x17, 0xcd, 0x28, 0x85, 0xa7,
+ 0xf6, 0xf3, 0xe2, 0x39, 0x5d, 0x23, 0x1a, 0x79, 0xf9, 0xfa, 0x27, 0x78,
+ 0xe2, 0xd0, 0xc7, 0xe3, 0x48, 0x53, 0xfc, 0x0d, 0xa2, 0xeb, 0x1c, 0x96,
+ 0x91, 0xb1, 0x34, 0x5f, 0x28, 0x78, 0x0c, 0x41, 0x3f, 0x8d, 0x9f, 0xed,
+ 0x57, 0x55, 0x15, 0x14, 0xff, 0xf6, 0x8b, 0x46, 0x1f, 0x32, 0xcf, 0x5b,
+ 0x3d, 0x5a, 0x7d, 0xfe, 0xd5, 0x75, 0x51, 0x5e, 0xcf, 0x89, 0xd7, 0xbc,
+ 0xd8, 0xb4, 0x8d, 0x87, 0xbf, 0xf3, 0x39, 0xff, 0x8d, 0x4f, 0x36, 0x7f,
+ 0xb5, 0x5d, 0x54, 0x48, 0xd3, 0xff, 0x8c, 0x7a, 0x79, 0xb3, 0xfd, 0xaa,
+ 0xea, 0xa2, 0x78, 0x9f, 0xfc, 0x63, 0xd3, 0xcd, 0x9f, 0xed, 0x57, 0x55,
+ 0x13, 0xfc, 0xff, 0xe3, 0x1e, 0x9e, 0x6c, 0xff, 0x6a, 0xba, 0xa8, 0xa1,
+ 0xa7, 0xff, 0x18, 0xf4, 0xf3, 0x67, 0xfb, 0x55, 0xd5, 0x45, 0x11, 0x3f,
+ 0xea, 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x91, 0x9f, 0xff, 0xb3, 0xdd,
+ 0x30, 0xc6, 0xd8, 0x50, 0xaf, 0x76, 0x12, 0x52, 0x31, 0xd1, 0x49, 0xe4,
+ 0x93, 0x3f, 0xf1, 0xa9, 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0x42, 0x2c,
+ 0x5d, 0x99, 0x7c, 0x70, 0x7d, 0x3f, 0xf3, 0x9f, 0x7e, 0x16, 0x07, 0x27,
+ 0xd2, 0x78, 0x95, 0x7c, 0xda, 0xad, 0xd5, 0x79, 0x87, 0xcb, 0xa9, 0x64,
+ 0xff, 0xe3, 0x1e, 0x9e, 0x6c, 0xff, 0x6a, 0xba, 0xa8, 0x9c, 0xe7, 0xff,
+ 0x18, 0xf4, 0xf3, 0x67, 0xfb, 0x55, 0xd5, 0x45, 0x13, 0x3f, 0xf7, 0xde,
+ 0x6d, 0x15, 0xdc, 0x79, 0x09, 0x68, 0xfa, 0x3b, 0xee, 0xab, 0xca, 0xac,
+ 0xfe, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x43, 0x93, 0xfc, 0xdf, 0xce, 0xe9,
+ 0xb8, 0x7a, 0xd3, 0xef, 0xf6, 0xab, 0xaa, 0x88, 0xbe, 0x7f, 0x5f, 0x3d,
+ 0xd6, 0x0a, 0x96, 0x9a, 0xfc, 0x2d, 0x3d, 0xb7, 0xb0, 0xe9, 0x41, 0xcd,
+ 0xcd, 0x0b, 0xc8, 0xd6, 0x23, 0xdb, 0x0e, 0x1c, 0x33, 0x06, 0xb9, 0xff,
+ 0xc6, 0x3d, 0x3c, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x32, 0x4f, 0xe3, 0x67,
+ 0xfb, 0x55, 0xd5, 0x45, 0xbd, 0x3f, 0xf8, 0xc7, 0xa7, 0x9b, 0x3f, 0xda,
+ 0xae, 0xaa, 0x29, 0x39, 0x9d, 0x07, 0x49, 0x69, 0xfb, 0x81, 0x0d, 0xfa,
+ 0x12, 0xd3, 0x68, 0xce, 0x89, 0xe7, 0xd1, 0x04, 0x32, 0xae, 0x07, 0xc6,
+ 0x69, 0x88, 0x77, 0x55, 0x76, 0x7c, 0x34, 0x29, 0x27, 0xf1, 0xb3, 0xfd,
+ 0xaa, 0xea, 0xa2, 0x1d, 0x9f, 0xfc, 0x63, 0xd3, 0xcd, 0x9f, 0xed, 0x57,
+ 0x55, 0x12, 0xc4, 0xfe, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x46, 0x13, 0xef,
+ 0xf6, 0xab, 0xaa, 0x88, 0xf6, 0x7a, 0xf5, 0xc3, 0xb5, 0xa7, 0x8d, 0x4f,
+ 0x36, 0x1e, 0xbe, 0xcc, 0xe7, 0xf1, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0xc3,
+ 0x9f, 0xc6, 0xcf, 0xf6, 0xab, 0xaa, 0x8b, 0x9e, 0x19, 0x3d, 0xcb, 0x0f,
+ 0x9e, 0xaa, 0x50, 0x95, 0x39, 0xc6, 0xcf, 0xa7, 0xf1, 0xb3, 0xfd, 0xaa,
+ 0xea, 0xa2, 0x1e, 0x9f, 0x7f, 0xb5, 0x5d, 0x54, 0x44, 0xd3, 0xff, 0xb3,
+ 0x75, 0xad, 0x33, 0xb7, 0xe7, 0xd9, 0x69, 0xb6, 0x75, 0xa7, 0xff, 0x66,
+ 0x86, 0xb2, 0xec, 0x5c, 0x6d, 0x8e, 0xb4, 0x70, 0x7c, 0x3a, 0x16, 0x9e,
+ 0xdf, 0x34, 0x32, 0xa2, 0x17, 0x91, 0xb1, 0x33, 0x0d, 0x19, 0xde, 0x15,
+ 0x5c, 0x91, 0xce, 0xfd, 0x75, 0x69, 0x69, 0x68, 0x1c, 0xd5, 0xf2, 0x37,
+ 0x3d, 0xbd, 0x16, 0xd6, 0x9f, 0xff, 0xfb, 0x5c, 0xfa, 0x59, 0xf7, 0x03,
+ 0x1d, 0xeb, 0x3d, 0x6b, 0xdd, 0x87, 0x5a, 0x7f, 0xf1, 0x38, 0xfc, 0xe1,
+ 0xfe, 0x0f, 0x54, 0x0b, 0x4d, 0x4e, 0xab, 0x46, 0x23, 0xeb, 0xa4, 0x3a,
+ 0x76, 0xa4, 0xb9, 0xdf, 0xae, 0xad, 0x0e, 0x89, 0xeb, 0x0e, 0x77, 0x3e,
+ 0xd5, 0x6e, 0x9e, 0xb4, 0xfe, 0x7d, 0xda, 0xfe, 0x68, 0x74, 0x1d, 0x05,
+ 0xa7, 0x8a, 0xe4, 0x25, 0xa7, 0x5b, 0x6d, 0xa9, 0x4f, 0xa8, 0x37, 0xac,
+ 0x48, 0xc5, 0xfc, 0xfa, 0xb6, 0xe6, 0x6d, 0x68, 0xf5, 0x13, 0x42, 0x3f,
+ 0x03, 0x49, 0xed, 0x55, 0x52, 0xd3, 0xff, 0x08, 0x9c, 0xf1, 0xa6, 0x2f,
+ 0xf3, 0xe7, 0x5a, 0x7f, 0xc4, 0x3b, 0x03, 0x5d, 0x88, 0xeb, 0x4f, 0xd8,
+ 0xef, 0x97, 0xe5, 0xd6, 0x9e, 0xcf, 0x72, 0xc5, 0xa3, 0x15, 0x15, 0xf0,
+ 0x4c, 0x50, 0xdf, 0xf3, 0x98, 0x38, 0x3f, 0xa4, 0xb0, 0x3b, 0xd9, 0x7c,
+ 0xfd, 0x96, 0xb6, 0x7a, 0x4b, 0x4e, 0x6e, 0x44, 0xb4, 0xff, 0xff, 0xe0,
+ 0x0e, 0x18, 0x70, 0xcf, 0x74, 0x4e, 0x78, 0xbe, 0x70, 0xff, 0xe5, 0xab,
+ 0x4f, 0x8b, 0x7c, 0xb5, 0x8b, 0x4f, 0xff, 0xec, 0xe1, 0xf7, 0x3e, 0x07,
+ 0x87, 0x52, 0xd5, 0x85, 0x9f, 0x5a, 0x7f, 0xff, 0xd6, 0xf8, 0x0c, 0xee,
+ 0x88, 0x33, 0x9e, 0x37, 0xe2, 0xad, 0xc1, 0xd6, 0x9f, 0xdc, 0x3e, 0xe3,
+ 0xf2, 0xdc, 0x2d, 0x3f, 0xaa, 0xde, 0x5c, 0x6d, 0xd2, 0xd0, 0xc8, 0xdd,
+ 0x27, 0x20, 0x37, 0x9e, 0x16, 0xca, 0xc5, 0xa7, 0xfc, 0xd5, 0x63, 0x1c,
+ 0x1b, 0x81, 0x2d, 0x0c, 0xa9, 0xcb, 0x1f, 0x08, 0xa3, 0xf1, 0xa1, 0x51,
+ 0x68, 0x11, 0x4d, 0xcb, 0xd6, 0x9f, 0x30, 0xaf, 0x66, 0xd6, 0x9d, 0x5b,
+ 0xba, 0xd3, 0x73, 0x62, 0xd3, 0x83, 0x6e, 0x3c, 0xd9, 0xfc, 0x6e, 0x7e,
+ 0xe7, 0xbe, 0x3d, 0xe2, 0xd5, 0xa1, 0x8f, 0x9c, 0x8c, 0xe7, 0xff, 0xdc,
+ 0xb6, 0xfc, 0x07, 0x2e, 0xbe, 0x33, 0x7e, 0x59, 0xb5, 0xa7, 0xfe, 0xd3,
+ 0x0f, 0xe3, 0x61, 0x5b, 0x6d, 0xad, 0x3f, 0xbc, 0x70, 0xf2, 0xd7, 0x27,
+ 0x5a, 0x04, 0x7f, 0x80, 0x8b, 0x3f, 0xef, 0xb9, 0xe2, 0xec, 0x56, 0x56,
+ 0xd6, 0x86, 0x3e, 0x2e, 0x48, 0x67, 0xff, 0xff, 0xb9, 0x0b, 0xfc, 0x19,
+ 0xcf, 0x03, 0x6c, 0x9f, 0x9c, 0x6f, 0x1d, 0x86, 0x5d, 0x69, 0x32, 0xd3,
+ 0xf5, 0x7c, 0xae, 0xdc, 0x2d, 0x3f, 0xea, 0xb7, 0xec, 0x1b, 0xd6, 0x3a,
+ 0xad, 0x0f, 0x3e, 0xcf, 0x96, 0x4f, 0xf6, 0x8b, 0xee, 0x6a, 0xb3, 0xeb,
+ 0x4f, 0xff, 0xff, 0xc2, 0xb8, 0x65, 0x71, 0xe3, 0xdd, 0x73, 0xe0, 0x33,
+ 0x87, 0xe7, 0x36, 0x06, 0x57, 0x0b, 0x47, 0x51, 0x90, 0x47, 0x13, 0xaa,
+ 0xba, 0xa8, 0xa6, 0x23, 0x0f, 0x27, 0xa4, 0x53, 0xfe, 0xc0, 0xe1, 0xf7,
+ 0xdb, 0x7d, 0xc5, 0xa7, 0x61, 0x09, 0x69, 0x62, 0xd3, 0xb8, 0x0c, 0x11,
+ 0xa9, 0x76, 0x35, 0x04, 0x89, 0xca, 0x68, 0x9c, 0xf6, 0xe1, 0x69, 0xfc,
+ 0x7f, 0x74, 0xd6, 0x65, 0xab, 0x47, 0x07, 0xa3, 0x43, 0x93, 0xff, 0xf8,
+ 0x33, 0xbb, 0xdb, 0x6e, 0xee, 0x06, 0x5b, 0xe1, 0x9d, 0x32, 0xd3, 0xfe,
+ 0xeb, 0x1f, 0x59, 0x7c, 0x20, 0x5a, 0x19, 0x14, 0x7a, 0x68, 0x9f, 0x7d,
+ 0x9d, 0xb7, 0xd6, 0x9f, 0xa8, 0x3c, 0x7a, 0xc0, 0xb4, 0x61, 0xfb, 0x91,
+ 0x17, 0x25, 0x11, 0x62, 0xf9, 0x13, 0xc5, 0xfd, 0x86, 0x10, 0xe4, 0x1d,
+ 0x8c, 0xfb, 0x82, 0x22, 0x84, 0x13, 0x8f, 0x7f, 0x8c, 0xcc, 0xf0, 0xbd,
+ 0x07, 0x2d, 0xc6, 0x79, 0x3f, 0xe1, 0xff, 0x56, 0xf8, 0xaf, 0x6a, 0xc5,
+ 0xa7, 0xb0, 0x07, 0xf3, 0xad, 0x3f, 0xff, 0xfe, 0xd1, 0x6f, 0x59, 0xf6,
+ 0x77, 0xe0, 0xfc, 0xba, 0xf8, 0xce, 0x1f, 0x9c, 0x80, 0xae, 0xb4, 0xb6,
+ 0x48, 0xb3, 0xb9, 0x2c, 0xff, 0xfb, 0x33, 0x45, 0xdd, 0x67, 0x8b, 0xf3,
+ 0xa6, 0xf3, 0xad, 0x3f, 0xfd, 0xbd, 0x60, 0xbc, 0x1d, 0xb3, 0x7e, 0xe0,
+ 0x2d, 0x3f, 0xdc, 0x78, 0x3b, 0x60, 0x6f, 0xc9, 0x69, 0x5f, 0x11, 0x1b,
+ 0x4a, 0x12, 0x20, 0x4c, 0x3b, 0x70, 0xe7, 0x9f, 0x3d, 0xb8, 0x7d, 0xd6,
+ 0x9f, 0xff, 0xff, 0xf6, 0x00, 0xfe, 0x0b, 0x5c, 0x99, 0xc2, 0xdb, 0x1c,
+ 0x28, 0x7d, 0x11, 0xb3, 0x5c, 0x09, 0xbd, 0x4a, 0x7f, 0xff, 0xee, 0x95,
+ 0xbe, 0xf3, 0xff, 0x1c, 0xb5, 0x97, 0xee, 0xb9, 0xd7, 0x15, 0x6a, 0xd3,
+ 0x73, 0x67, 0x09, 0xa1, 0x91, 0x45, 0xe1, 0x3d, 0x0c, 0xab, 0xab, 0x51,
+ 0x9b, 0x04, 0x6e, 0x13, 0xff, 0x8f, 0xdf, 0x1a, 0xa7, 0xe1, 0xe8, 0x04,
+ 0xb4, 0xff, 0xf8, 0x83, 0x7a, 0xc7, 0x5d, 0xb9, 0x9e, 0x7a, 0x01, 0x2d,
+ 0x3f, 0xf3, 0x05, 0x81, 0x8e, 0xef, 0xcb, 0x70, 0xb4, 0x5d, 0x14, 0x1c,
+ 0xad, 0x4f, 0x66, 0xf3, 0xcd, 0xad, 0x3b, 0xcb, 0x34, 0xb4, 0xd9, 0xea,
+ 0xd1, 0x62, 0x6d, 0x0f, 0x87, 0x55, 0xc9, 0x36, 0x4c, 0xec, 0x7a, 0x7c,
+ 0x5b, 0xbe, 0x09, 0x69, 0xfb, 0xd6, 0x0d, 0x53, 0xd6, 0x9c, 0xde, 0xb2,
+ 0xd3, 0xf3, 0xf3, 0x77, 0xa7, 0x3c, 0x1e, 0x39, 0xcb, 0x21, 0xe8, 0xb4,
+ 0x71, 0xb6, 0x7e, 0x75, 0xd5, 0x79, 0xd8, 0x4b, 0x4f, 0xef, 0xb8, 0x19,
+ 0xaa, 0xda, 0xd1, 0x87, 0xca, 0x46, 0x73, 0xf3, 0x0b, 0x36, 0x35, 0x8b,
+ 0x43, 0xcf, 0x38, 0x08, 0x27, 0xfb, 0x7a, 0xc7, 0xd0, 0x67, 0x0b, 0x4f,
+ 0xff, 0xf0, 0x50, 0xaf, 0x66, 0x10, 0x6c, 0x31, 0xdf, 0x8b, 0xda, 0x0b,
+ 0x40, 0x22, 0x7f, 0x66, 0xf3, 0xfe, 0x2c, 0x73, 0xc5, 0xdb, 0x55, 0xe7,
+ 0x5a, 0x7f, 0x57, 0x17, 0xd6, 0x57, 0xd6, 0x8f, 0x4f, 0xd7, 0x68, 0x73,
+ 0xfd, 0x9f, 0xb1, 0x8b, 0xf8, 0x0b, 0x48, 0xeb, 0x78, 0x36, 0xd3, 0x83,
+ 0x3d, 0x5a, 0x18, 0xde, 0xf0, 0x45, 0x3f, 0x71, 0x7c, 0xc0, 0x1d, 0x69,
+ 0xe3, 0x8c, 0xc2, 0x5a, 0x30, 0xf3, 0xc8, 0xb6, 0x77, 0x3c, 0x09, 0x68,
+ 0x64, 0xf6, 0xf2, 0x12, 0xe5, 0x09, 0x6f, 0xb8, 0x01, 0x04, 0xfe, 0xd9,
+ 0x59, 0x9a, 0xe7, 0x6b, 0x49, 0xc5, 0xa7, 0xec, 0xe7, 0x35, 0xdb, 0x16,
+ 0x9b, 0x38, 0x63, 0x7f, 0x71, 0x19, 0xfb, 0x54, 0xf3, 0xfc, 0x96, 0x9e,
+ 0x17, 0xf3, 0x85, 0xa7, 0xc5, 0x7b, 0xb1, 0xd6, 0x82, 0x3c, 0x87, 0x64,
+ 0x50, 0x3a, 0x66, 0xc4, 0xe6, 0x22, 0xce, 0x5d, 0x27, 0xff, 0xef, 0xbf,
+ 0x58, 0xe6, 0x98, 0x07, 0x0c, 0xde, 0xb9, 0x5a, 0x7f, 0xff, 0x16, 0x70,
+ 0xfb, 0xef, 0x4c, 0x76, 0x2f, 0x7c, 0x33, 0xa6, 0x5a, 0x7f, 0xff, 0xfd,
+ 0xc8, 0x78, 0xb6, 0xb8, 0x7f, 0xe8, 0x5e, 0x2f, 0xcb, 0x71, 0xac, 0x20,
+ 0xc1, 0xd6, 0x9f, 0xff, 0x73, 0xff, 0xe6, 0xef, 0xa2, 0xcf, 0x1a, 0x13,
+ 0x2d, 0x18, 0x8e, 0x1d, 0x42, 0x2a, 0x7f, 0xf9, 0xee, 0xba, 0xc6, 0x07,
+ 0x03, 0x37, 0x7a, 0x5a, 0x7f, 0xfd, 0xee, 0x1f, 0xc3, 0xae, 0xda, 0xee,
+ 0x3e, 0xbf, 0x62, 0xd3, 0xff, 0xf6, 0xca, 0xcc, 0xf7, 0xc1, 0xe9, 0xff,
+ 0x2b, 0x28, 0xeb, 0x4f, 0xeb, 0x28, 0xe0, 0xdf, 0x71, 0x69, 0xfe, 0xe3,
+ 0x07, 0x11, 0xf3, 0xc7, 0xf1, 0x12, 0x24, 0xbd, 0x3f, 0xd8, 0x16, 0x78,
+ 0x15, 0x53, 0x8b, 0x4f, 0xf7, 0xec, 0x6b, 0x2c, 0xe7, 0xf6, 0x2d, 0x3f,
+ 0xdc, 0x87, 0x8b, 0xf3, 0xe5, 0xcf, 0xd6, 0x86, 0x3f, 0xfb, 0x9f, 0x4f,
+ 0xfe, 0xb3, 0xc5, 0xf5, 0xcf, 0x8d, 0xde, 0xed, 0xf5, 0xa7, 0xff, 0xfd,
+ 0x9c, 0x5c, 0xb2, 0xdf, 0x1a, 0xcd, 0xdf, 0x2c, 0xf1, 0x85, 0xea, 0xd1,
+ 0x88, 0xc2, 0x25, 0x18, 0xb1, 0x72, 0xfb, 0xb1, 0xa4, 0xf0, 0x4e, 0x4a,
+ 0x1f, 0x87, 0x71, 0xd4, 0xef, 0x0b, 0x9d, 0xc3, 0x8e, 0x7f, 0x6c, 0x33,
+ 0x7a, 0xcb, 0x16, 0x9f, 0xf5, 0x7f, 0x59, 0xb6, 0x02, 0x12, 0xd3, 0xfd,
+ 0x96, 0xf0, 0xfb, 0xf8, 0xd9, 0x2d, 0x3f, 0xff, 0xe6, 0xeb, 0x1f, 0xc3,
+ 0x9a, 0x20, 0xf7, 0xc0, 0xdd, 0x0c, 0xd6, 0x2d, 0x0c, 0x98, 0xcf, 0x4c,
+ 0x80, 0xed, 0xd4, 0xf2, 0x78, 0xb6, 0x4c, 0xb4, 0xff, 0xff, 0xe0, 0x21,
+ 0xf5, 0x4e, 0x78, 0x0e, 0x5d, 0x7c, 0x67, 0x0f, 0xce, 0x40, 0x57, 0x5a,
+ 0x7d, 0xa2, 0x60, 0xb1, 0x69, 0xb6, 0xc7, 0x45, 0x3b, 0xb8, 0x40, 0xc3,
+ 0xd1, 0xf6, 0x50, 0xc6, 0x86, 0x64, 0x0f, 0x64, 0xe8, 0xd1, 0x47, 0x47,
+ 0x51, 0x9d, 0x4f, 0x98, 0x36, 0x4e, 0xd6, 0x9e, 0xdd, 0xe8, 0x4b, 0x4f,
+ 0xfd, 0xa2, 0xf0, 0x5f, 0xe6, 0xca, 0xff, 0x56, 0x9e, 0x2d, 0x55, 0x8b,
+ 0x4f, 0x3b, 0x6d, 0xb2, 0xd3, 0xf6, 0xaa, 0xcf, 0x0f, 0xda, 0xd3, 0xea,
+ 0xf8, 0x70, 0x4b, 0x41, 0x1e, 0xb6, 0xcc, 0x23, 0xd4, 0xd2, 0x70, 0x9c,
+ 0x72, 0x1e, 0xa3, 0x91, 0x0e, 0xde, 0x27, 0x86, 0xe6, 0xae, 0xb4, 0xff,
+ 0xfc, 0x5f, 0xf1, 0x85, 0x80, 0x3e, 0x8b, 0x0f, 0x9d, 0x5a, 0x7f, 0xff,
+ 0x8a, 0xcf, 0xb1, 0xef, 0xcb, 0x78, 0x6f, 0xb7, 0xba, 0x63, 0xad, 0x18,
+ 0x8c, 0x2f, 0xac, 0xcf, 0xff, 0xfe, 0xff, 0xca, 0xcf, 0x1a, 0xcd, 0x83,
+ 0x39, 0xac, 0xb1, 0xb8, 0xdf, 0x3d, 0x5a, 0x7f, 0xff, 0xe6, 0x1f, 0x4d,
+ 0xe0, 0x33, 0x91, 0xfc, 0x70, 0xfb, 0x90, 0x0c, 0xd6, 0x2d, 0x3e, 0xe2,
+ 0xe5, 0x80, 0xb4, 0x62, 0x27, 0xf9, 0x79, 0x82, 0x4c, 0xff, 0x51, 0x8e,
+ 0x4f, 0xfc, 0xfb, 0x90, 0xfa, 0x62, 0xb1, 0x87, 0x5a, 0x7f, 0x83, 0x97,
+ 0x03, 0x35, 0x5b, 0x5a, 0x7f, 0xbd, 0xd3, 0x5b, 0xee, 0xa8, 0xeb, 0x4f,
+ 0xff, 0xf5, 0x7f, 0x59, 0xb2, 0xc0, 0xb2, 0xed, 0x81, 0xee, 0x99, 0x69,
+ 0xed, 0xf8, 0xb3, 0xeb, 0x47, 0x08, 0x88, 0xa6, 0x39, 0xff, 0xd6, 0xd0,
+ 0x58, 0x7e, 0x4b, 0xd2, 0x02, 0x5a, 0x7e, 0x73, 0x87, 0xf2, 0xdb, 0x5a,
+ 0x7f, 0xb5, 0x47, 0x0c, 0xd5, 0x6d, 0x69, 0xec, 0xf8, 0xad, 0x5a, 0x19,
+ 0x11, 0x17, 0x30, 0xd9, 0xb4, 0xfd, 0x9b, 0xff, 0xf1, 0xeb, 0x4f, 0xc1,
+ 0x9a, 0x0c, 0xea, 0xd3, 0xc1, 0x97, 0xf0, 0xe1, 0xeb, 0x6c, 0xb2, 0x3d,
+ 0x5c, 0x7f, 0xec, 0x6c, 0x3c, 0x14, 0x92, 0x2f, 0xce, 0x35, 0x0c, 0x3b,
+ 0x91, 0xee, 0x1a, 0x4e, 0xe1, 0x0b, 0x3f, 0xf0, 0x06, 0x78, 0xfe, 0x68,
+ 0x31, 0xc5, 0xa1, 0x97, 0x90, 0x32, 0x75, 0x92, 0xa1, 0x33, 0x3e, 0x06,
+ 0x3d, 0x7a, 0xb4, 0xfe, 0xc7, 0x35, 0x9b, 0x6f, 0x56, 0x9f, 0xff, 0xfe,
+ 0xd6, 0x6e, 0xf4, 0xe7, 0x80, 0xce, 0x1f, 0x9c, 0xd8, 0x19, 0xee, 0x89,
+ 0xc5, 0xa6, 0xe4, 0x75, 0xa3, 0xe8, 0x9a, 0xdc, 0x20, 0xa7, 0xec, 0xb0,
+ 0x33, 0x8b, 0xad, 0x3f, 0xfb, 0xfc, 0x3e, 0xf8, 0x7e, 0x1b, 0x5a, 0x65,
+ 0xa5, 0x75, 0xa3, 0x93, 0xdb, 0x19, 0x2e, 0x7f, 0x31, 0xc3, 0x35, 0x5b,
+ 0x5a, 0x7b, 0xc7, 0x6c, 0xb5, 0x69, 0xff, 0xff, 0x6c, 0x18, 0x5c, 0x3e,
+ 0xfc, 0xb6, 0xc3, 0x3d, 0x2c, 0xfb, 0x8b, 0x41, 0x2a, 0x8a, 0x70, 0x9a,
+ 0xa1, 0x9a, 0x05, 0x17, 0x84, 0x47, 0x24, 0x8e, 0xcc, 0x06, 0x26, 0x9f,
+ 0x3c, 0xbf, 0x9c, 0x2d, 0x3e, 0xcb, 0xd9, 0x96, 0xad, 0x1c, 0x1e, 0x7e,
+ 0x89, 0xe7, 0xff, 0xc5, 0x66, 0x77, 0xdd, 0x16, 0x0f, 0xe0, 0x7e, 0x59,
+ 0x69, 0xe7, 0x5d, 0xe6, 0x96, 0x98, 0x8e, 0xb4, 0xff, 0xff, 0xb8, 0x7d,
+ 0x71, 0xe0, 0x39, 0x75, 0xf1, 0x9c, 0x3f, 0x39, 0x01, 0x5d, 0x68, 0x3a,
+ 0x23, 0x1d, 0x45, 0x62, 0xc4, 0x6b, 0x64, 0x2c, 0x27, 0xff, 0xff, 0xcd,
+ 0xc5, 0xf9, 0x6e, 0x3c, 0x6b, 0x3d, 0xf0, 0x19, 0xc8, 0xfe, 0x2e, 0x21,
+ 0x16, 0xd6, 0x9f, 0x30, 0x71, 0x56, 0x2d, 0x3f, 0xff, 0xff, 0xfb, 0x0f,
+ 0x9d, 0x6d, 0x31, 0xf7, 0x97, 0xbb, 0x7f, 0xec, 0x19, 0x66, 0x73, 0x7e,
+ 0x5c, 0x06, 0x3a, 0xd3, 0xfc, 0x2c, 0xf4, 0x33, 0x55, 0xb5, 0xa7, 0xf5,
+ 0x9c, 0xb6, 0xce, 0x5b, 0x5a, 0x7f, 0xcc, 0x3b, 0xaf, 0x38, 0x0e, 0x0c,
+ 0x75, 0xa3, 0x0f, 0xe3, 0x83, 0x49, 0xff, 0x66, 0x0a, 0xfe, 0x3f, 0x7f,
+ 0x6e, 0xb4, 0xfe, 0xfe, 0x77, 0x45, 0xf7, 0x16, 0x9b, 0x37, 0xe9, 0xfa,
+ 0x62, 0x0c, 0xf5, 0x84, 0x1b, 0x5a, 0x19, 0x71, 0x9f, 0x08, 0xca, 0x33,
+ 0x0f, 0x94, 0x1e, 0x11, 0xda, 0x27, 0xa8, 0x52, 0x04, 0x2b, 0xef, 0x09,
+ 0x6e, 0x4b, 0x67, 0x7b, 0xe1, 0xc5, 0xa7, 0xff, 0xb8, 0x78, 0x37, 0x83,
+ 0x83, 0x0f, 0xb2, 0xb1, 0x68, 0xc3, 0xf2, 0x22, 0x09, 0xfa, 0xc7, 0x1f,
+ 0xe6, 0x7e, 0xc5, 0xa7, 0xc7, 0x2f, 0x73, 0xd5, 0xa4, 0xe2, 0xd3, 0x31,
+ 0xd6, 0x96, 0xd6, 0x8f, 0x9a, 0x5a, 0x15, 0x8f, 0x4f, 0x5b, 0x46, 0xd3,
+ 0xdb, 0xbd, 0x70, 0xb4, 0xce, 0x52, 0xd3, 0xfb, 0x45, 0xfe, 0x1e, 0x0c,
+ 0xb4, 0x3a, 0x09, 0xa0, 0xb1, 0xb6, 0x3f, 0x11, 0x19, 0xc8, 0xb9, 0x16,
+ 0x9f, 0xd7, 0x2e, 0x2d, 0xa0, 0x12, 0xd3, 0xff, 0xe6, 0xfb, 0x77, 0x0e,
+ 0xdd, 0x79, 0x5f, 0x93, 0xad, 0x0e, 0x22, 0x1f, 0xc8, 0xce, 0x7e, 0xfe,
+ 0x30, 0xec, 0x0b, 0x4e, 0x0a, 0x3a, 0xd3, 0x09, 0x96, 0x87, 0x9e, 0xd1,
+ 0x15, 0x80, 0xd4, 0x3a, 0x4e, 0xdd, 0x67, 0xcc, 0x8d, 0xcd, 0xa5, 0x29,
+ 0xd8, 0xf6, 0xf2, 0xcf, 0x65, 0x47, 0x64, 0xfb, 0xe0, 0xf0, 0xcc, 0xec,
+ 0xbe, 0x0e, 0x23, 0xa4, 0x28, 0xc1, 0xdc, 0x86, 0xbf, 0xe5, 0x4d, 0x9e,
+ 0x38, 0x7d, 0x52, 0x17, 0x6a, 0x39, 0xa0, 0x9e, 0x98, 0xbc, 0xac, 0x7d,
+ 0xce, 0x9a, 0xbb, 0x8c, 0x5b, 0xca, 0x36, 0x11, 0xa1, 0xc4, 0xeb, 0x08,
+ 0x19, 0xff, 0xfb, 0x9e, 0x9b, 0x8d, 0xfd, 0xb3, 0x8f, 0x33, 0xda, 0xa1,
+ 0xd6, 0x83, 0x2a, 0x33, 0x28, 0xf3, 0xe7, 0xf1, 0xb3, 0xfd, 0xaa, 0xea,
+ 0xa2, 0x9d, 0x9f, 0x7f, 0xb5, 0x5d, 0x54, 0x54, 0x73, 0xfe, 0xa7, 0x9b,
+ 0x3f, 0xda, 0xae, 0xaa, 0x26, 0x88, 0xc3, 0xfc, 0x39, 0x9c, 0xfe, 0x1a,
+ 0x9d, 0x9b, 0x65, 0x62, 0xd0, 0x63, 0xd7, 0x62, 0x19, 0xfc, 0x6c, 0xff,
+ 0x6a, 0xba, 0xa8, 0xab, 0xe7, 0xdf, 0xed, 0x57, 0x55, 0x15, 0xb4, 0xff,
+ 0x3c, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x20, 0xc8, 0xd8, 0x7e, 0xf4, 0x67,
+ 0x3f, 0xf1, 0xa9, 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0x0e, 0x7f, 0xcf,
+ 0xd3, 0x6e, 0xee, 0x9a, 0xee, 0x90, 0x2d, 0x2e, 0x16, 0x98, 0x81, 0x68,
+ 0xf4, 0xd2, 0xb8, 0x23, 0x3e, 0xcc, 0x01, 0x5d, 0x69, 0xf7, 0xfb, 0x55,
+ 0xd5, 0x45, 0x89, 0x3e, 0xcf, 0xb0, 0x0e, 0xb4, 0xf8, 0x6f, 0x2c, 0xfb,
+ 0x2d, 0x3a, 0xec, 0x0b, 0x4b, 0x4c, 0x78, 0x84, 0x55, 0x3f, 0xf3, 0x65,
+ 0xf0, 0x3d, 0x21, 0x30, 0x2d, 0x38, 0x1a, 0xc5, 0xa4, 0xf0, 0x3d, 0xbe,
+ 0x50, 0x27, 0x79, 0x10, 0x96, 0x9f, 0x13, 0xbe, 0x6a, 0xeb, 0x4f, 0xfc,
+ 0xef, 0x9c, 0xe3, 0xd7, 0x7a, 0xca, 0x71, 0x69, 0x99, 0xeb, 0x46, 0x1f,
+ 0x07, 0xd2, 0xe7, 0xf6, 0x7d, 0xe2, 0xcc, 0x71, 0x69, 0xf5, 0x3c, 0x6d,
+ 0x32, 0xd3, 0xf5, 0xef, 0xf2, 0xb7, 0xce, 0xb4, 0x32, 0x22, 0xc8, 0xca,
+ 0x89, 0xe7, 0xff, 0x9e, 0xc7, 0x67, 0xfa, 0x0d, 0xaa, 0xcf, 0xad, 0x3f,
+ 0xba, 0x18, 0xec, 0x32, 0xeb, 0x47, 0x07, 0xff, 0xa4, 0xd9, 0xfc, 0x26,
+ 0xcd, 0x90, 0x5a, 0x94, 0xff, 0xda, 0xa2, 0xdb, 0xf0, 0x70, 0xc1, 0x2d,
+ 0x3e, 0xcd, 0x71, 0x5e, 0x75, 0xa7, 0x85, 0x76, 0x05, 0xa7, 0xf7, 0xf5,
+ 0x45, 0x72, 0x76, 0xb4, 0x31, 0xe9, 0xe1, 0x04, 0x12, 0x38, 0x01, 0x0a,
+ 0xef, 0xd3, 0xf5, 0x59, 0xb6, 0xe1, 0xeb, 0x4f, 0xf8, 0x18, 0xbd, 0xd8,
+ 0x57, 0x17, 0x5a, 0x1d, 0x25, 0xdc, 0x86, 0x6e, 0xf4, 0x8f, 0x09, 0x47,
+ 0x33, 0xeb, 0x57, 0x10, 0x81, 0x22, 0x87, 0x07, 0xbf, 0x08, 0x9d, 0x42,
+ 0xb2, 0xa1, 0x58, 0x22, 0x3b, 0xc6, 0x23, 0xb2, 0xe1, 0x8b, 0xa7, 0xfe,
+ 0xd1, 0x36, 0xf5, 0x43, 0xe0, 0x09, 0x69, 0xff, 0xec, 0xe1, 0xfb, 0xe6,
+ 0xc3, 0x6a, 0x8e, 0x57, 0x5a, 0x6d, 0x1b, 0x11, 0x28, 0x08, 0x50, 0x64,
+ 0xef, 0x5a, 0x39, 0x09, 0xfc, 0x6c, 0xff, 0x6a, 0xba, 0xa8, 0xb3, 0x66,
+ 0xcf, 0x56, 0x9f, 0xf5, 0x3c, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x40, 0x4f,
+ 0xe2, 0x3b, 0x79, 0xf5, 0x96, 0x2d, 0x23, 0x62, 0x25, 0x4e, 0x2d, 0xa4,
+ 0x99, 0xb9, 0xd2, 0xd3, 0xf5, 0xd8, 0xe0, 0xce, 0x2d, 0x2d, 0x2d, 0x38,
+ 0x60, 0x71, 0x69, 0xb3, 0x78, 0x6b, 0x44, 0x21, 0x02, 0x44, 0x20, 0x2c,
+ 0xcd, 0xe2, 0xeb, 0x4f, 0xf6, 0xb3, 0xfb, 0x06, 0x3d, 0xd6, 0x9e, 0xed,
+ 0x57, 0x55, 0x16, 0xfc, 0xfc, 0x36, 0xeb, 0xb5, 0xf5, 0xa3, 0xe7, 0xb4,
+ 0x22, 0xd9, 0xec, 0x02, 0x71, 0x69, 0xf6, 0xdf, 0x71, 0xae, 0xb4, 0xfc,
+ 0xec, 0x6d, 0x83, 0x09, 0x69, 0xf7, 0xad, 0xe7, 0xe4, 0xeb, 0x43, 0x1e,
+ 0xe1, 0x17, 0xcf, 0x51, 0x06, 0xd6, 0x9f, 0xdc, 0xf1, 0x76, 0xee, 0x1d,
+ 0x69, 0xed, 0x0f, 0xe9, 0xd6, 0x9b, 0x1e, 0xb4, 0x61, 0xb9, 0x02, 0x49,
+ 0x19, 0xd2, 0x55, 0xf0, 0xd0, 0x9b, 0x79, 0x17, 0xa3, 0x19, 0x09, 0x12,
+ 0x22, 0xf9, 0x06, 0xa1, 0x0a, 0x22, 0x00, 0x1f, 0xdb, 0x6c, 0xff, 0xa9,
+ 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x8a, 0x52, 0x7f, 0x9e, 0x6c, 0xff, 0x6a,
+ 0xba, 0xa8, 0x93, 0xa4, 0x63, 0xa2, 0x36, 0x92, 0x61, 0x9f, 0x2c, 0x22,
+ 0xc8, 0xdb, 0xbd, 0xb7, 0x40, 0x18, 0x55, 0xd8, 0xc4, 0x48, 0x87, 0xcf,
+ 0x0b, 0x57, 0x09, 0x8f, 0x3f, 0xa9, 0xa2, 0x91, 0x43, 0x4e, 0xf2, 0xcb,
+ 0x5d, 0xc6, 0x7d, 0x3e, 0xff, 0x6a, 0xba, 0xa8, 0x87, 0xe7, 0xfd, 0x4f,
+ 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x4a, 0x72, 0x36, 0x1f, 0xe1, 0xcc, 0xe7,
+ 0xf1, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x27, 0x9f, 0xc6, 0xcf, 0xf6, 0xab,
+ 0xaa, 0x88, 0xc6, 0x7f, 0xf1, 0x8f, 0x4f, 0x36, 0x7f, 0xb5, 0x5d, 0x54,
+ 0x4f, 0x30, 0xc8, 0xf8, 0xb0, 0x9d, 0xe7, 0xda, 0x3e, 0x9f, 0x7f, 0xb5,
+ 0x5d, 0x54, 0x44, 0x13, 0xfe, 0xa7, 0x9b, 0x3f, 0xda, 0xae, 0xaa, 0x25,
+ 0x49, 0x1b, 0x0f, 0xf0, 0xe6, 0x73, 0xf8, 0xd9, 0xfe, 0xd5, 0x75, 0x51,
+ 0x14, 0x4f, 0xe3, 0x67, 0xfb, 0x55, 0xd5, 0x44, 0x65, 0x3f, 0xf8, 0xc7,
+ 0xa7, 0x9b, 0x3f, 0xda, 0xae, 0xaa, 0x26, 0x59, 0xfc, 0x6c, 0xff, 0x6a,
+ 0xba, 0xa8, 0xa9, 0x27, 0xf1, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0xba, 0x9f,
+ 0xc6, 0xcf, 0xf6, 0xab, 0xaa, 0x8b, 0x16, 0x7f, 0xe3, 0xd3, 0xcd, 0x9f,
+ 0xed, 0x57, 0x55, 0x13, 0xd4, 0xff, 0x5a, 0x6a, 0x62, 0xf2, 0x27, 0x55,
+ 0xa0, 0xc8, 0x8c, 0x64, 0xf9, 0xfb, 0xcd, 0x19, 0xb2, 0xe6, 0xeb, 0x4f,
+ 0x7c, 0xfb, 0xe1, 0x69, 0xdd, 0xcd, 0x25, 0x38, 0xed, 0x75, 0xa7, 0xff,
+ 0xed, 0x05, 0x0e, 0x5f, 0x67, 0xbf, 0x2e, 0x21, 0x32, 0xd3, 0xff, 0xf7,
+ 0xc9, 0xd6, 0x8e, 0x66, 0xff, 0xc9, 0xd7, 0xbc, 0xd8, 0xb4, 0xf1, 0x68,
+ 0x63, 0xad, 0x3f, 0xf8, 0x87, 0xf1, 0x81, 0x5c, 0x5c, 0x71, 0xe9, 0x68,
+ 0xe9, 0xf7, 0x81, 0x14, 0xff, 0xea, 0xb8, 0x60, 0x8d, 0xa2, 0xed, 0x7d,
+ 0x69, 0xfb, 0xdc, 0x1f, 0x79, 0xd5, 0xa7, 0xb4, 0xc7, 0xea, 0xd1, 0x47,
+ 0x9f, 0xb2, 0xe9, 0xff, 0xc1, 0xe1, 0x98, 0x18, 0xfe, 0x3c, 0x6b, 0xc9,
+ 0x69, 0xab, 0x85, 0xa7, 0xf5, 0x5e, 0xb5, 0xc8, 0x58, 0xb4, 0x01, 0xe4,
+ 0xf2, 0x2d, 0x16, 0x2a, 0xd8, 0x21, 0xbf, 0xac, 0x9e, 0x1a, 0x3a, 0x21,
+ 0x08, 0x4b, 0x6c, 0x85, 0xd6, 0x13, 0x33, 0x82, 0xb6, 0xb4, 0xe0, 0x2b,
+ 0xad, 0x2b, 0x5d, 0x13, 0x68, 0xc3, 0x53, 0xdf, 0x77, 0x47, 0x5a, 0x30,
+ 0xf3, 0xc8, 0xb2, 0x7f, 0xc5, 0xaa, 0xdb, 0x39, 0x72, 0x3a, 0xd3, 0xe0,
+ 0x1c, 0xb2, 0xeb, 0x4f, 0xfd, 0x96, 0xd0, 0xb3, 0xba, 0xa1, 0x5d, 0x69,
+ 0xff, 0x5e, 0xb8, 0x60, 0xaf, 0x70, 0x75, 0xa0, 0x91, 0x4e, 0x04, 0xdb,
+ 0x43, 0x9c, 0x76, 0xd2, 0xd3, 0xc1, 0xef, 0x81, 0xd6, 0x9f, 0xb2, 0xf6,
+ 0xd0, 0x58, 0xb4, 0x61, 0xf6, 0xd0, 0xd8, 0x12, 0xcf, 0xb9, 0x1e, 0xfe,
+ 0xb2, 0xd1, 0x88, 0xf1, 0x28, 0x4d, 0xe8, 0xb2, 0x7f, 0xff, 0xf6, 0x98,
+ 0xbf, 0xf6, 0x1b, 0x64, 0x1c, 0xbf, 0x2f, 0xef, 0x35, 0xf7, 0xad, 0x3e,
+ 0xb3, 0xdf, 0x95, 0xab, 0x4f, 0xde, 0xd7, 0xc5, 0xe5, 0x8b, 0x4f, 0xf8,
+ 0x09, 0xfb, 0xd6, 0x7c, 0xae, 0xb4, 0xff, 0xab, 0x04, 0xc1, 0x5e, 0xe0,
+ 0xeb, 0x43, 0xcf, 0xe0, 0x47, 0x93, 0xfa, 0xb8, 0xbe, 0xf7, 0x9e, 0x75,
+ 0xa7, 0xff, 0x36, 0x71, 0xbd, 0x36, 0xc1, 0x85, 0x75, 0xa7, 0x5f, 0x47,
+ 0x5a, 0x36, 0x7c, 0x9c, 0xa4, 0x4f, 0xdc, 0xdf, 0x77, 0xcd, 0xad, 0x3a,
+ 0xdb, 0x6d, 0x4a, 0x7f, 0xf6, 0xcb, 0x77, 0xd1, 0x79, 0x0d, 0xf6, 0x7a,
+ 0x46, 0x2f, 0xe0, 0x91, 0x53, 0xca, 0x6c, 0x3d, 0x57, 0xbe, 0x3c, 0x91,
+ 0x57, 0xe1, 0x50, 0x72, 0x20, 0x84, 0xde, 0xe1, 0x99, 0x3f, 0xdc, 0x3e,
+ 0xf7, 0xcf, 0x6b, 0x6b, 0x4b, 0x16, 0x86, 0x3c, 0x91, 0xce, 0xa7, 0xff,
+ 0xf8, 0x82, 0xb6, 0x5a, 0xa3, 0xf8, 0xcb, 0xb6, 0x7f, 0x01, 0x69, 0xed,
+ 0xb7, 0x16, 0xad, 0x1a, 0x44, 0x2d, 0xac, 0x53, 0xbb, 0x6e, 0x96, 0x9f,
+ 0xcd, 0x5f, 0xd5, 0xb5, 0xea, 0x53, 0x5b, 0x6a, 0x51, 0xe9, 0xe5, 0xda,
+ 0x67, 0x3b, 0x65, 0xe7, 0x48, 0xc6, 0x92, 0x7b, 0x97, 0xf3, 0xb5, 0xa2,
+ 0xe7, 0xa7, 0xe4, 0x5f, 0x35, 0xb7, 0x5a, 0x58, 0xb4, 0xb8, 0xc3, 0x4d,
+ 0xb1, 0x79, 0xff, 0xaf, 0x7f, 0x41, 0xbd, 0xd3, 0x6e, 0xeb, 0x43, 0x1f,
+ 0x67, 0x24, 0xf3, 0xfe, 0xd9, 0x7e, 0x84, 0xeb, 0xbc, 0xd2, 0xd3, 0xfc,
+ 0x56, 0x86, 0x6c, 0xb9, 0x12, 0xd3, 0xfa, 0xbf, 0xbb, 0x81, 0x0e, 0xb4,
+ 0x3d, 0x19, 0x84, 0x45, 0xe7, 0x40, 0xa3, 0x89, 0xd8, 0x5f, 0x5a, 0x7a,
+ 0xbe, 0xcf, 0x5a, 0x2c, 0x37, 0x47, 0x1a, 0x9f, 0xf3, 0x71, 0xa6, 0x3f,
+ 0x74, 0x4e, 0x2d, 0x18, 0x7c, 0x3f, 0x22, 0x9f, 0xb6, 0xdf, 0xf7, 0x01,
+ 0x69, 0xfd, 0xee, 0x98, 0x2d, 0xae, 0x16, 0x9f, 0xf8, 0xbd, 0xd3, 0x75,
+ 0x85, 0x40, 0x25, 0xa7, 0xff, 0xfc, 0x47, 0xa0, 0xe1, 0xe6, 0xb7, 0x09,
+ 0xde, 0x06, 0x7b, 0x4f, 0x5c, 0x5e, 0xb0, 0xc9, 0x8d, 0xd1, 0x65, 0xcd,
+ 0x39, 0x42, 0x9f, 0xfe, 0xcd, 0xdf, 0x1c, 0xd3, 0x3b, 0xcd, 0x69, 0x96,
+ 0x9f, 0xff, 0xff, 0x16, 0x71, 0x72, 0xcb, 0x7c, 0x67, 0x0f, 0xb9, 0x6e,
+ 0xe5, 0xc7, 0xbe, 0xf3, 0x62, 0xd3, 0xff, 0xe2, 0x0f, 0x7c, 0x0d, 0xb2,
+ 0xbd, 0x10, 0x72, 0xf5, 0xa0, 0x13, 0x32, 0xda, 0x83, 0xb8, 0x45, 0xcf,
+ 0xeb, 0x2b, 0x62, 0x18, 0x1e, 0xb4, 0xd5, 0xea, 0xd3, 0xf7, 0xea, 0xfa,
+ 0xa7, 0xad, 0x2e, 0x16, 0x98, 0xad, 0x5a, 0x61, 0x84, 0xb4, 0x38, 0x6b,
+ 0x44, 0x2d, 0x39, 0xf5, 0xea, 0xd3, 0x5b, 0x6a, 0xd0, 0xf4, 0x6b, 0x60,
+ 0xb7, 0x4b, 0x08, 0xfa, 0xe4, 0x56, 0x8e, 0x4e, 0xd8, 0xc2, 0x48, 0xc7,
+ 0xad, 0x3f, 0xff, 0xfb, 0x6d, 0xee, 0xb9, 0xa1, 0xcf, 0x5e, 0xe6, 0x00,
+ 0xf7, 0xbe, 0x00, 0x96, 0x8e, 0x11, 0x4e, 0x45, 0xd3, 0xfd, 0x9b, 0xd3,
+ 0x7f, 0x79, 0xd5, 0xa7, 0x37, 0xdc, 0x5a, 0x31, 0x55, 0xa1, 0x1b, 0xd4,
+ 0xa0, 0x70, 0x23, 0xf2, 0x37, 0x9d, 0x7a, 0x71, 0x69, 0xec, 0xdd, 0x3a,
+ 0xad, 0x1c, 0x1b, 0xf0, 0x1c, 0x9f, 0xfb, 0x3f, 0xfc, 0x73, 0x59, 0x7a,
+ 0x05, 0xa7, 0xf0, 0x37, 0xf9, 0xee, 0x99, 0x69, 0xf1, 0x0f, 0xaa, 0x7a,
+ 0xd3, 0xf1, 0x31, 0xec, 0xcb, 0x56, 0x9a, 0xdb, 0x56, 0x8e, 0x9f, 0x67,
+ 0xc9, 0xed, 0x2d, 0x9f, 0xec, 0x72, 0x9c, 0xae, 0x1f, 0x74, 0x8c, 0x6c,
+ 0x27, 0x7a, 0xc7, 0x5a, 0x7f, 0x60, 0xb1, 0xc6, 0xe2, 0xeb, 0x43, 0x1e,
+ 0x7e, 0x0e, 0x4f, 0xfe, 0xc0, 0x16, 0x68, 0xb8, 0xbe, 0xb9, 0xba, 0xd3,
+ 0xf0, 0x50, 0xbd, 0xc0, 0x5a, 0x7e, 0x39, 0x79, 0x67, 0xc7, 0x5a, 0x75,
+ 0xb6, 0xda, 0x94, 0xff, 0xcd, 0xf0, 0xe6, 0x86, 0xc7, 0x18, 0xeb, 0x18,
+ 0xbf, 0x8f, 0x3a, 0xa9, 0xe7, 0x21, 0x9c, 0x10, 0x99, 0xb9, 0x06, 0xd2,
+ 0xb9, 0x2b, 0xb5, 0x3e, 0x7f, 0xfd, 0x5e, 0xe6, 0x00, 0xe3, 0x03, 0x05,
+ 0x85, 0xf5, 0xa7, 0x57, 0xec, 0x5c, 0x82, 0x53, 0xcf, 0xce, 0x1e, 0xb9,
+ 0x04, 0xa7, 0x5c, 0xbd, 0x5c, 0x82, 0x53, 0x5b, 0x6a, 0xe4, 0x12, 0x8e,
+ 0xa2, 0x99, 0xc2, 0x9d, 0x97, 0xda, 0x53, 0x35, 0x6d, 0x32, 0x09, 0x0c,
+ 0x6f, 0xe7, 0xec, 0xd6, 0x60, 0x0e, 0xb4, 0xea, 0x01, 0x1d, 0x39, 0x70,
+ 0x8c, 0xe7, 0x66, 0x73, 0xde, 0x59, 0x5a, 0x5a, 0x59, 0xe7, 0x3e, 0x91,
+ 0x23, 0x4f, 0xe7, 0x1f, 0xcd, 0x9b, 0x2b, 0x12, 0x9f, 0xc4, 0xfe, 0x6a,
+ 0xfa, 0x25, 0xa4, 0xf4, 0xa7, 0x57, 0xec, 0x4a, 0x12, 0x86, 0x36, 0xdd,
+ 0x10, 0x38, 0xe4, 0xf0, 0x30, 0xba, 0x91, 0x8d, 0x6c, 0x32, 0x31, 0x72,
+ 0x12, 0xb3, 0xdc, 0xd7, 0xde, 0xb4, 0x8e, 0xb4, 0xd8, 0xff, 0x4d, 0x93,
+ 0x84, 0x53, 0xeb, 0x71, 0xc2, 0x3a, 0xd3, 0xf7, 0x59, 0xc7, 0xb0, 0x92,
+ 0x91, 0x2d, 0x3f, 0xd6, 0x72, 0xff, 0x75, 0xcd, 0x02, 0xd3, 0xf1, 0x31,
+ 0xec, 0xcb, 0x56, 0x9f, 0x65, 0x87, 0xc3, 0xad, 0x3a, 0xe5, 0xf5, 0xa0,
+ 0x0f, 0x0b, 0x64, 0xf3, 0xf0, 0x50, 0x85, 0xcd, 0xd6, 0x9f, 0x88, 0x71,
+ 0x98, 0xe6, 0xf5, 0x30, 0x8c, 0x0f, 0xf9, 0xe5, 0xdb, 0xf6, 0x43, 0x18,
+ 0x9e, 0x61, 0x14, 0x04, 0x66, 0xb3, 0xc1, 0x96, 0x72, 0xb4, 0x3d, 0x5e,
+ 0x7e, 0x15, 0xea, 0x1f, 0x80, 0xb1, 0x78, 0xfe, 0xb6, 0x69, 0x3f, 0xfe,
+ 0xb3, 0xff, 0xcf, 0x68, 0xfa, 0xad, 0x83, 0x38, 0xb4, 0xff, 0xff, 0xee,
+ 0x7f, 0xcb, 0x81, 0x42, 0xbd, 0xf0, 0x7c, 0xe7, 0xf5, 0xeb, 0x69, 0x96,
+ 0x9d, 0x6d, 0xb6, 0xa5, 0x33, 0xd9, 0x23, 0x17, 0xf0, 0xc9, 0x8a, 0x58,
+ 0xad, 0xf8, 0x4d, 0x4f, 0xd6, 0x38, 0xff, 0x33, 0xf6, 0x2d, 0x3d, 0xaa,
+ 0xe2, 0xd5, 0xa7, 0xd6, 0x7c, 0x98, 0xeb, 0x4f, 0xff, 0x30, 0xdb, 0x06,
+ 0x15, 0x6c, 0x43, 0x03, 0xd6, 0x87, 0x41, 0x19, 0xe4, 0x6d, 0x44, 0x7b,
+ 0x27, 0x9c, 0x37, 0xae, 0x2d, 0x39, 0xe4, 0x0b, 0x4f, 0xdb, 0x67, 0x03,
+ 0x9b, 0xad, 0x16, 0x1f, 0x3b, 0xc7, 0xf6, 0x35, 0x35, 0x5d, 0x69, 0xb9,
+ 0xf3, 0x6b, 0x40, 0x1b, 0x2e, 0x45, 0x66, 0xa3, 0x3a, 0x4e, 0x84, 0x39,
+ 0xd3, 0x9a, 0xf9, 0xa8, 0x8d, 0xa5, 0x79, 0xd9, 0x18, 0x3b, 0xc8, 0x3d,
+ 0x8f, 0x57, 0x25, 0x95, 0x0f, 0x0b, 0xbe, 0xc2, 0x9f, 0x82, 0x42, 0x86,
+ 0xfb, 0x91, 0xc1, 0xfe, 0x1b, 0x47, 0x8c, 0xf3, 0x53, 0x84, 0x75, 0x09,
+ 0x10, 0x21, 0xbc, 0xae, 0x0d, 0xcf, 0x22, 0xf3, 0x1b, 0xb7, 0x94, 0x60,
+ 0xa3, 0x42, 0x9d, 0xd5, 0x8a, 0x7f, 0xf1, 0x8f, 0x4f, 0x36, 0x7f, 0xb5,
+ 0x5d, 0x54, 0x51, 0x53, 0xf8, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x74, 0x4f,
+ 0xfc, 0x6a, 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x4b, 0x9f, 0xc6, 0xcf,
+ 0xf6, 0xab, 0xaa, 0x8b, 0xca, 0x19, 0xd3, 0x31, 0x58, 0x4e, 0xf3, 0xec,
+ 0x3e, 0xea, 0xab, 0x87, 0xc7, 0x3e, 0xd4, 0x32, 0x82, 0xd0, 0x98, 0x5e,
+ 0x3d, 0x4d, 0xaa, 0xf2, 0x7c, 0xed, 0x3e, 0x7f, 0xf1, 0x8f, 0x4f, 0x36,
+ 0x7f, 0xb5, 0x5d, 0x54, 0x4b, 0x33, 0x73, 0xa5, 0xa7, 0xbb, 0x55, 0xd5,
+ 0x44, 0x67, 0x3f, 0x13, 0x1e, 0xcc, 0xb5, 0x69, 0x81, 0xeb, 0x48, 0xeb,
+ 0x4f, 0x8b, 0xfa, 0xa3, 0x7c, 0xf4, 0x8e, 0x5a, 0x30, 0xac, 0xfd, 0x4f,
+ 0x2f, 0xd7, 0xd6, 0x9f, 0xfa, 0xe5, 0xcd, 0xf0, 0x39, 0x7e, 0x5d, 0x69,
+ 0xd7, 0x6e, 0x16, 0x8f, 0xa6, 0xac, 0x77, 0xf0, 0x4c, 0xb9, 0x5e, 0xd1,
+ 0x27, 0xf9, 0xf7, 0xc6, 0xf0, 0xd7, 0x3a, 0xd3, 0xff, 0x6c, 0xbf, 0x42,
+ 0xf1, 0xc3, 0xd8, 0xeb, 0x4f, 0x81, 0x9f, 0x7a, 0x5a, 0x08, 0xfa, 0xdd,
+ 0xa3, 0x4e, 0xa1, 0x9e, 0xb4, 0xff, 0xf7, 0x3b, 0xbf, 0x0f, 0x60, 0x15,
+ 0xfc, 0x72, 0x0b, 0x4e, 0x6d, 0xb2, 0xd2, 0x2f, 0x4f, 0xb9, 0xda, 0xa4,
+ 0xda, 0x71, 0x69, 0xfd, 0xc5, 0xc3, 0x3f, 0xeb, 0x2d, 0x04, 0x79, 0x54,
+ 0x2f, 0x3d, 0xbd, 0x73, 0xe4, 0xb4, 0xff, 0x6c, 0xad, 0xbb, 0x6a, 0xbc,
+ 0xeb, 0x4b, 0x08, 0xf8, 0x8e, 0x4d, 0x3f, 0xed, 0x31, 0x68, 0x98, 0x1c,
+ 0xe5, 0x69, 0xfd, 0x97, 0x6d, 0xdf, 0x44, 0xb4, 0x8c, 0xe9, 0x2e, 0x49,
+ 0x64, 0x6d, 0xbc, 0x25, 0x39, 0x0a, 0x4d, 0x11, 0xd4, 0x22, 0x84, 0xe8,
+ 0x10, 0x82, 0xb9, 0x37, 0x91, 0xec, 0xff, 0xe3, 0x1e, 0x9e, 0x6c, 0xff,
+ 0x6a, 0xba, 0xa8, 0x9a, 0x67, 0xff, 0x18, 0xf4, 0xf3, 0x67, 0xfb, 0x55,
+ 0xd5, 0x44, 0xe3, 0x3f, 0xf8, 0xc7, 0xa7, 0x9b, 0x3f, 0xda, 0xae, 0xaa,
+ 0x28, 0x19, 0xf7, 0xfb, 0x55, 0xd5, 0x45, 0xc1, 0x33, 0x12, 0xd3, 0xf8,
+ 0x1e, 0xc5, 0xee, 0x1d, 0x69, 0x1b, 0x0f, 0xe3, 0x46, 0x7c, 0x8a, 0x4f,
+ 0xe2, 0x30, 0xcc, 0x2c, 0xb5, 0x69, 0xfe, 0x79, 0xb3, 0xfd, 0xaa, 0xea,
+ 0xa2, 0x49, 0x91, 0xb4, 0x7e, 0xf4, 0x67, 0x3e, 0xa3, 0x7b, 0x68, 0x96,
+ 0x8b, 0x19, 0x01, 0x4f, 0x9c, 0xe7, 0xec, 0x2c, 0x1c, 0x55, 0x12, 0xad,
+ 0xe1, 0x9b, 0xb8, 0x56, 0x3b, 0x27, 0x9f, 0xf0, 0xf4, 0x6c, 0xff, 0x6a,
+ 0xba, 0xa8, 0xb5, 0x27, 0xfd, 0x4f, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x4a,
+ 0xb0, 0xb4, 0x8c, 0x3a, 0x27, 0x4e, 0x94, 0xea, 0x93, 0x3f, 0x8d, 0x9f,
+ 0xed, 0x57, 0x55, 0x11, 0x4c, 0xfe, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x46,
+ 0x93, 0x73, 0xa5, 0xa7, 0xbb, 0x55, 0xd5, 0x45, 0x3f, 0x36, 0xd9, 0x68,
+ 0xf9, 0xe1, 0x6c, 0xb6, 0x7f, 0xdb, 0x71, 0xb7, 0xaa, 0x73, 0xc6, 0x2d,
+ 0x3f, 0xf7, 0x3b, 0xff, 0x2e, 0x5f, 0xb4, 0xe5, 0xd6, 0x9f, 0xfb, 0x1c,
+ 0xe4, 0x2c, 0xbf, 0x69, 0xcb, 0xad, 0x23, 0x3a, 0x49, 0xa6, 0x62, 0xc9,
+ 0x11, 0x02, 0x0e, 0xd2, 0x67, 0xff, 0x18, 0xf4, 0xf3, 0x67, 0xfb, 0x55,
+ 0xd5, 0x44, 0xd5, 0x3f, 0x8d, 0x9f, 0xed, 0x57, 0x55, 0x15, 0xdc, 0xf7,
+ 0x6a, 0xba, 0xa8, 0xaf, 0xa7, 0x5b, 0x6d, 0xa9, 0x48, 0x12, 0x31, 0x7f,
+ 0x1f, 0x3e, 0xa3, 0xa6, 0x4e, 0x7b, 0x70, 0xb4, 0xe7, 0x33, 0x4b, 0x4f,
+ 0xfb, 0x35, 0x6d, 0x6e, 0xed, 0x96, 0x2d, 0x2d, 0xad, 0x3f, 0xc5, 0xfc,
+ 0xb0, 0x9f, 0x9e, 0xad, 0x1f, 0x3c, 0x8a, 0x10, 0x91, 0xb1, 0x30, 0x17,
+ 0x08, 0xa8, 0x70, 0x07, 0x2f, 0x08, 0x69, 0xff, 0xc6, 0x3d, 0x3c, 0xd9,
+ 0xfe, 0xd5, 0x75, 0x51, 0x3d, 0xcf, 0xe3, 0x67, 0xfb, 0x55, 0xd5, 0x45,
+ 0xc3, 0x3f, 0xf1, 0xa9, 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0x3e, 0x19,
+ 0x76, 0x26, 0xc3, 0xa7, 0x9f, 0x0f, 0x1c, 0x57, 0x54, 0xdc, 0x55, 0xfc,
+ 0x75, 0x3a, 0x54, 0xba, 0xab, 0xb3, 0xe9, 0xfc, 0x6c, 0xff, 0x6a, 0xba,
+ 0xa8, 0x8a, 0xa7, 0xdf, 0xed, 0x57, 0x55, 0x14, 0xcc, 0xfc, 0x5a, 0xca,
+ 0xe0, 0x4b, 0x48, 0xd8, 0x7b, 0xfe, 0x46, 0x73, 0xff, 0x8c, 0x7a, 0x79,
+ 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x67, 0x9f, 0xfc, 0x63, 0xd3, 0xcd, 0x9f,
+ 0xed, 0x57, 0x55, 0x14, 0x6c, 0x58, 0x9b, 0x8f, 0xb0, 0x9d, 0x1c, 0xab,
+ 0x6a, 0xb3, 0xff, 0x1a, 0x9e, 0x6c, 0xff, 0x6a, 0xba, 0xa8, 0x8e, 0xa6,
+ 0xe7, 0x4b, 0x4f, 0xc5, 0x81, 0xee, 0x58, 0xb4, 0xf7, 0x6a, 0xba, 0xa8,
+ 0xa6, 0xa7, 0xd9, 0xc5, 0xb5, 0xa5, 0xa3, 0xe7, 0xaa, 0x05, 0xb3, 0xff,
+ 0xb4, 0x5b, 0xbd, 0x71, 0x8e, 0x36, 0xae, 0xb4, 0xff, 0xcf, 0xd1, 0x05,
+ 0x97, 0xe5, 0xbe, 0xe2, 0xd3, 0x30, 0xeb, 0x4f, 0xc4, 0xc7, 0xb3, 0x2d,
+ 0x5a, 0x7f, 0xfb, 0x37, 0xac, 0x7f, 0xe8, 0x37, 0xaa, 0x7a, 0xd3, 0x30,
+ 0x96, 0x9f, 0xd5, 0xc3, 0x74, 0xba, 0x6f, 0xa2, 0x3c, 0x0b, 0x46, 0x4d,
+ 0x8d, 0x23, 0xf6, 0xf0, 0xa5, 0x91, 0x9d, 0x25, 0x4d, 0xde, 0x8b, 0xe4,
+ 0x20, 0x7a, 0x43, 0xc2, 0x56, 0xe3, 0x43, 0x9f, 0x7f, 0xb5, 0x5d, 0x54,
+ 0x55, 0x53, 0xfe, 0xa7, 0x9b, 0x3f, 0xda, 0xae, 0xaa, 0x26, 0xd9, 0x1b,
+ 0x0f, 0xf0, 0xe6, 0x73, 0xf8, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x5f, 0xcf,
+ 0xe3, 0x67, 0xfb, 0x55, 0xd5, 0x45, 0x8d, 0x3f, 0xd9, 0xbd, 0xe7, 0xfd,
+ 0xc0, 0x5a, 0x70, 0xef, 0xc5, 0xa7, 0x17, 0xcc, 0x07, 0xa7, 0x73, 0x79,
+ 0xf7, 0xfb, 0x55, 0xd5, 0x45, 0xab, 0x3f, 0xea, 0x79, 0xb3, 0xfd, 0xaa,
+ 0xea, 0xa2, 0x82, 0x91, 0xb0, 0xff, 0x0e, 0x67, 0x3e, 0xff, 0x6a, 0xba,
+ 0xa8, 0xb8, 0xa7, 0xa9, 0xd4, 0xac, 0x5a, 0x79, 0xd5, 0xd4, 0xba, 0xb4,
+ 0xfe, 0x63, 0xd3, 0xb6, 0xfb, 0xaa, 0xd2, 0x36, 0x22, 0xd3, 0x46, 0x74,
+ 0x49, 0xb2, 0x79, 0xf7, 0xfb, 0x55, 0xd5, 0x45, 0xd3, 0x3e, 0x60, 0xaf,
+ 0x59, 0x69, 0x1b, 0x0f, 0x60, 0x8c, 0xe7, 0xff, 0xb0, 0x36, 0x47, 0xd3,
+ 0x10, 0x57, 0xc7, 0x5a, 0x7f, 0xfe, 0x39, 0xb1, 0xed, 0xf1, 0x78, 0xbe,
+ 0x98, 0xf4, 0x0b, 0x4f, 0x65, 0xae, 0x81, 0xd6, 0x9f, 0xff, 0xb4, 0x1c,
+ 0xd7, 0x9f, 0x1f, 0xac, 0x1f, 0x3d, 0x73, 0x95, 0xa6, 0xee, 0x2d, 0x0c,
+ 0x7e, 0xe3, 0xb1, 0x4f, 0xf9, 0xf9, 0xff, 0xd3, 0xec, 0xcb, 0x56, 0x9c,
+ 0x14, 0x6f, 0x9f, 0x0e, 0xc8, 0xa7, 0xfd, 0xf6, 0xe3, 0x55, 0x7d, 0xb5,
+ 0xab, 0x4d, 0xce, 0x96, 0x9f, 0x06, 0x6a, 0xb6, 0xb4, 0xfc, 0xfa, 0xc7,
+ 0x6d, 0xea, 0xd0, 0xe8, 0x9e, 0x9f, 0x9a, 0x49, 0x67, 0xe1, 0x53, 0x8f,
+ 0x2d, 0xad, 0x3f, 0xff, 0xcd, 0xee, 0xb3, 0x8d, 0x85, 0x68, 0x55, 0x7b,
+ 0xd7, 0xfa, 0xb4, 0xfe, 0xcc, 0xc1, 0xc7, 0xa7, 0xad, 0x03, 0xa2, 0x63,
+ 0x6c, 0xd3, 0xff, 0xfd, 0xa6, 0x0e, 0x6f, 0xa2, 0xbe, 0xf5, 0x9e, 0x95,
+ 0xf0, 0x16, 0x9e, 0xed, 0x57, 0x55, 0x12, 0x64, 0xfb, 0xbe, 0x6b, 0xf3,
+ 0x1d, 0x07, 0x45, 0x69, 0xfd, 0x9c, 0x6f, 0x74, 0xfb, 0xad, 0x0c, 0x7e,
+ 0x5f, 0x3f, 0x87, 0xa6, 0x4b, 0xf6, 0x53, 0xc2, 0x7e, 0x7e, 0xf4, 0x4e,
+ 0x8d, 0xc5, 0xe4, 0xb4, 0xff, 0xed, 0x16, 0xf8, 0xe9, 0x7e, 0xee, 0x35,
+ 0x2d, 0x3e, 0xcd, 0x91, 0xe9, 0x69, 0xfe, 0x6d, 0x6c, 0xac, 0x3b, 0x75,
+ 0x69, 0xff, 0xf5, 0x77, 0xed, 0xa0, 0xcd, 0xe1, 0xad, 0xb6, 0xd4, 0xa1,
+ 0xe8, 0xb3, 0xb9, 0x2e, 0xce, 0x27, 0xee, 0xf7, 0x9e, 0x83, 0x2d, 0x3f,
+ 0xfb, 0x90, 0xad, 0xb7, 0xef, 0xa6, 0x0d, 0xad, 0x3a, 0xdb, 0x6d, 0x4a,
+ 0x7e, 0xfd, 0x58, 0x72, 0xba, 0x46, 0x2f, 0xe7, 0xd8, 0x7f, 0xe7, 0x9d,
+ 0x69, 0xf1, 0x6e, 0xcc, 0xb5, 0x69, 0xfe, 0x6e, 0xe8, 0x39, 0xdb, 0x5d,
+ 0x69, 0xff, 0xf6, 0xf5, 0x8f, 0xf1, 0xdd, 0x16, 0xf8, 0xe9, 0x7d, 0x68,
+ 0xfa, 0x2e, 0x0e, 0x50, 0x07, 0x13, 0xfd, 0x94, 0x2f, 0x19, 0xed, 0x3d,
+ 0x69, 0xfe, 0xf0, 0x1e, 0x2f, 0x65, 0x56, 0x96, 0x9f, 0xfd, 0x56, 0x68,
+ 0x98, 0x31, 0xc2, 0xf9, 0x2d, 0x18, 0x8e, 0xbd, 0x97, 0xf2, 0x73, 0x69,
+ 0xe4, 0xf8, 0x33, 0x55, 0xb5, 0xa7, 0xfc, 0xf6, 0x0b, 0x06, 0xf8, 0x72,
+ 0xf5, 0xa3, 0xce, 0x7c, 0xae, 0x12, 0xcf, 0x6e, 0xcc, 0xf5, 0x69, 0xfe,
+ 0x21, 0xc6, 0xf8, 0x8e, 0x57, 0x5a, 0x1c, 0x3d, 0xdf, 0x22, 0x39, 0xd6,
+ 0xdb, 0x6a, 0xd3, 0xff, 0xec, 0x3e, 0xc1, 0x85, 0x9e, 0xdf, 0x0e, 0xdd,
+ 0x48, 0xc5, 0xfc, 0x62, 0x65, 0x65, 0x08, 0x4d, 0x22, 0xc8, 0x96, 0x9f,
+ 0xb4, 0xde, 0x3a, 0x56, 0x2d, 0x3f, 0x7e, 0xbe, 0x0c, 0xf5, 0xa1, 0xd3,
+ 0x9f, 0x4f, 0xa1, 0xff, 0x2f, 0x99, 0xe6, 0x74, 0x99, 0x2f, 0xfe, 0x63,
+ 0x53, 0x17, 0xbe, 0x18, 0xb9, 0x1a, 0x48, 0xe6, 0xdd, 0x37, 0xe2, 0x1f,
+ 0xa4, 0x60, 0xe1, 0x6d, 0x33, 0x81, 0xe5, 0xe3, 0xcd, 0xdc, 0x79, 0xc3,
+ 0x42, 0x76, 0x7f, 0xf7, 0xf2, 0xdf, 0x75, 0x8e, 0x06, 0x7d, 0xeb, 0x4e,
+ 0xfe, 0x79, 0xd6, 0x96, 0x7c, 0xfa, 0x8e, 0x97, 0x3f, 0xf6, 0x68, 0x1a,
+ 0xc1, 0xb5, 0xaa, 0xf3, 0xad, 0x3f, 0x57, 0x4d, 0x6d, 0xb6, 0xad, 0x23,
+ 0x33, 0x36, 0x97, 0x13, 0x07, 0x5b, 0xec, 0x3f, 0xfe, 0x65, 0x54, 0x9b,
+ 0xe0, 0x8d, 0xc2, 0xe4, 0xee, 0xd2, 0x21, 0xed, 0xa9, 0x3f, 0xb2, 0xaf,
+ 0x78, 0x87, 0x67, 0xc9, 0xce, 0x7d, 0xa8, 0x48, 0x8a, 0x15, 0xd7, 0x86,
+ 0xde, 0xe1, 0x33, 0xcd, 0x37, 0x2e, 0x7f, 0x1b, 0x3f, 0xda, 0xae, 0xaa,
+ 0x23, 0x59, 0xf7, 0xfb, 0x55, 0xd5, 0x45, 0x4b, 0x35, 0x75, 0x51, 0x0d,
+ 0x48, 0xd8, 0x7a, 0xb4, 0x67, 0x3f, 0xf1, 0xa9, 0xe6, 0xcf, 0xf6, 0xab,
+ 0xaa, 0x88, 0xfa, 0x7d, 0xfe, 0xd5, 0x75, 0x51, 0x63, 0xcf, 0xf0, 0x50,
+ 0xfa, 0x26, 0x0b, 0x16, 0x91, 0xb0, 0xfa, 0x9c, 0x33, 0x9d, 0xe6, 0xb3,
+ 0x8e, 0xb4, 0xfc, 0xe8, 0x86, 0x6a, 0xb6, 0xb4, 0xff, 0x05, 0x0a, 0xf5,
+ 0xbd, 0xd2, 0xd3, 0xc2, 0x39, 0x7d, 0x69, 0xff, 0xfe, 0x6f, 0x86, 0x7b,
+ 0x9a, 0xd1, 0x77, 0x45, 0xbb, 0xd7, 0x0b, 0x41, 0x22, 0x1b, 0x44, 0x33,
+ 0xaa, 0xba, 0xa8, 0xb4, 0x27, 0xfd, 0x56, 0xba, 0xf6, 0xbf, 0x66, 0x5a,
+ 0xb4, 0x74, 0xfa, 0xbe, 0x4f, 0x3f, 0xff, 0xfc, 0x5f, 0xd5, 0x01, 0x36,
+ 0xcb, 0x4d, 0x7d, 0x65, 0xff, 0x9d, 0xcd, 0xad, 0x1f, 0x44, 0xd6, 0x88,
+ 0xa7, 0xd4, 0xf0, 0xa1, 0x96, 0x9f, 0x9d, 0x8d, 0xb0, 0x61, 0x2d, 0x3e,
+ 0x6d, 0xe6, 0x99, 0x69, 0xff, 0xec, 0xdd, 0xf1, 0xcd, 0x33, 0xbc, 0xd6,
+ 0x99, 0x68, 0xb0, 0xfd, 0x40, 0x96, 0x19, 0x18, 0xd9, 0x0a, 0x49, 0xff,
+ 0x09, 0xbb, 0xa2, 0x72, 0xaa, 0xc5, 0xa7, 0xf8, 0xb9, 0x07, 0xfd, 0xb3,
+ 0xd5, 0xa7, 0xff, 0xfb, 0x58, 0xfe, 0xe8, 0xb4, 0xd9, 0xf7, 0xec, 0x18,
+ 0xf7, 0x5a, 0x59, 0x74, 0x4e, 0x6c, 0xe2, 0x7e, 0xfb, 0x6e, 0xcc, 0xb5,
+ 0x69, 0xf6, 0xf5, 0x40, 0x3a, 0xd3, 0xfc, 0x1c, 0xd9, 0xee, 0xb0, 0x19,
+ 0x69, 0x66, 0x1f, 0x07, 0x49, 0xe0, 0x91, 0x68, 0x10, 0x8e, 0x9f, 0xd9,
+ 0xa7, 0x0b, 0x44, 0x75, 0xa7, 0xf3, 0xf3, 0xf7, 0x06, 0xb1, 0x69, 0xd9,
+ 0xaa, 0x5a, 0x7c, 0xe7, 0xbc, 0xf2, 0x0b, 0x47, 0xa7, 0x8b, 0x43, 0x53,
+ 0xfd, 0x99, 0x6e, 0x77, 0xb9, 0x6a, 0xd1, 0x89, 0x81, 0xf0, 0x65, 0x4e,
+ 0xf7, 0x22, 0x9e, 0xcd, 0x56, 0xd6, 0x9f, 0x88, 0x39, 0x7e, 0x5d, 0x69,
+ 0xff, 0xfe, 0x20, 0xe5, 0xf9, 0x7f, 0x19, 0xb6, 0xe0, 0x55, 0xad, 0x12,
+ 0xd0, 0x3a, 0x24, 0xf6, 0x59, 0x23, 0x3a, 0x4b, 0xeb, 0xfe, 0x61, 0x2b,
+ 0x18, 0x7b, 0x0b, 0xcc, 0x8c, 0x98, 0xe4, 0x7a, 0x87, 0x60, 0x89, 0x82,
+ 0x1b, 0x57, 0x86, 0xe6, 0xe3, 0x29, 0xf2, 0x3d, 0x1a, 0x16, 0x73, 0xf3,
+ 0xa9, 0x7a, 0x0c, 0xe2, 0xd3, 0xd9, 0xaa, 0xda, 0xd2, 0x74, 0x70, 0xf4,
+ 0x00, 0xc2, 0x7d, 0xfe, 0xd5, 0x75, 0x51, 0x6b, 0x4f, 0xfa, 0x9e, 0x6c,
+ 0xff, 0x6a, 0xba, 0xa8, 0xa0, 0xe4, 0x6f, 0x31, 0x14, 0xf8, 0x56, 0x73,
+ 0x39, 0xff, 0xc6, 0x3d, 0x3c, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x45, 0xcf,
+ 0xe3, 0x67, 0xfb, 0x55, 0xd5, 0x45, 0xd5, 0x0f, 0x65, 0xd4, 0xf6, 0x12,
+ 0x64, 0x4c, 0x78, 0x5c, 0xea, 0x7e, 0x1c, 0x51, 0xf1, 0xdc, 0xeb, 0x6a,
+ 0xb3, 0xef, 0xf6, 0xab, 0xaa, 0x88, 0x86, 0x76, 0xb3, 0xd5, 0xa7, 0xb1,
+ 0xd9, 0x7d, 0x69, 0x1b, 0x0f, 0xc7, 0x83, 0x3f, 0x38, 0xe4, 0xfe, 0x36,
+ 0x7f, 0xb5, 0x5d, 0x54, 0x46, 0xd3, 0xf8, 0xd9, 0xfe, 0xd5, 0x75, 0x51,
+ 0x4d, 0xcf, 0xe3, 0x67, 0xfb, 0x55, 0xd5, 0x45, 0x41, 0x3f, 0x8d, 0x9f,
+ 0xed, 0x57, 0x55, 0x15, 0x34, 0xfb, 0xfd, 0xaa, 0xea, 0xa2, 0xb0, 0x9f,
+ 0x15, 0xbe, 0xf3, 0xf5, 0xa7, 0xf9, 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x88,
+ 0xfe, 0x76, 0x35, 0x8b, 0x48, 0xd8, 0x8b, 0xce, 0x99, 0xd1, 0x50, 0x22,
+ 0x4f, 0xfe, 0x31, 0xe9, 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0xbe, 0x7f,
+ 0xe3, 0xd3, 0xcd, 0x9f, 0xed, 0x57, 0x55, 0x13, 0xf4, 0xf9, 0xd0, 0x74,
+ 0x7c, 0xb3, 0x85, 0xa5, 0xa5, 0xa1, 0xd3, 0x1e, 0x2f, 0x26, 0xb3, 0xfd,
+ 0xe6, 0xad, 0x56, 0xf7, 0x55, 0x6a, 0xd3, 0xef, 0x03, 0xfe, 0xba, 0xb4,
+ 0xfb, 0xcc, 0x74, 0xe2, 0x1d, 0x96, 0x9f, 0xfe, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0xe2, 0xeb, 0x4f, 0xbe, 0x56, 0x51, 0xd2, 0x9a, 0xdb, 0x52, 0x8c,
+ 0x37, 0xf6, 0x93, 0xcb, 0x94, 0x8c, 0x68, 0x61, 0x91, 0x95, 0x78, 0x54,
+ 0xcf, 0x7c, 0x09, 0x96, 0x9f, 0xff, 0xb0, 0xf7, 0xdf, 0xea, 0xcf, 0x74,
+ 0xd7, 0xdf, 0x3a, 0x5a, 0x7d, 0x5d, 0xd1, 0x7d, 0x69, 0xff, 0xff, 0xc1,
+ 0x43, 0x97, 0xd9, 0xfe, 0x34, 0x47, 0xf5, 0xbc, 0x79, 0x73, 0xa2, 0xfa,
+ 0xd3, 0xd4, 0xf2, 0xe1, 0x68, 0xf5, 0x32, 0x4f, 0xaf, 0x68, 0x98, 0x1f,
+ 0xe7, 0xff, 0xce, 0xad, 0xc3, 0xe8, 0x05, 0xe0, 0x45, 0xf2, 0x1d, 0x69,
+ 0xeb, 0x0e, 0x4f, 0x5a, 0x7d, 0x70, 0xe6, 0x9e, 0xb4, 0xfe, 0xd3, 0x1c,
+ 0xc2, 0x13, 0x2d, 0x2f, 0xb1, 0xfd, 0xe1, 0x11, 0x13, 0xcf, 0xf9, 0xb8,
+ 0xf4, 0x66, 0xf3, 0xeb, 0x9b, 0xad, 0x3b, 0x31, 0xc5, 0xa5, 0xe7, 0x5a,
+ 0x6b, 0xe2, 0xd0, 0x46, 0xa4, 0x42, 0x93, 0xff, 0x7a, 0xdb, 0xab, 0xe6,
+ 0xb4, 0x47, 0x5a, 0x76, 0xc9, 0xc5, 0xa1, 0x8f, 0x7e, 0xe8, 0x70, 0xca,
+ 0xf6, 0x70, 0x9c, 0xa3, 0x43, 0x70, 0xfb, 0xf0, 0xd5, 0x39, 0x90, 0x91,
+ 0x81, 0x13, 0x6f, 0xf3, 0x9c, 0x18, 0xeb, 0x4f, 0xf6, 0x6e, 0xf9, 0xbd,
+ 0x60, 0x96, 0x8a, 0x3d, 0x50, 0x1e, 0x9a, 0x81, 0x68, 0xf9, 0xb4, 0x39,
+ 0x04, 0xeb, 0x6d, 0xb5, 0x69, 0xeb, 0x00, 0x99, 0x23, 0x17, 0xf3, 0x70,
+ 0xf5, 0xa7, 0xf0, 0xed, 0xbb, 0xea, 0xb9, 0x5a, 0x7c, 0x56, 0x67, 0x1b,
+ 0x5a, 0x62, 0xea, 0xd2, 0xe1, 0x91, 0x10, 0x38, 0xb9, 0xcd, 0x36, 0x51,
+ 0x0c, 0x99, 0xde, 0x90, 0x39, 0x85, 0xbc, 0xff, 0xd6, 0x72, 0x2c, 0x0e,
+ 0x5c, 0x6d, 0xd2, 0xd3, 0xff, 0x36, 0x86, 0xf7, 0x65, 0x8e, 0x31, 0xd6,
+ 0x9e, 0x6d, 0xf2, 0x75, 0xa6, 0xbf, 0x55, 0x10, 0x74, 0x98, 0xe7, 0x8b,
+ 0xb2, 0x29, 0xfa, 0xb4, 0xde, 0x7e, 0x5e, 0xb4, 0x7d, 0x32, 0x83, 0xa3,
+ 0x6e, 0x11, 0x4e, 0xc9, 0xe6, 0xff, 0xab, 0x4d, 0x6d, 0xab, 0x43, 0xcd,
+ 0x7d, 0xa2, 0xf3, 0xd7, 0x62, 0x76, 0x91, 0x8d, 0x14, 0xfa, 0xe3, 0x7a,
+ 0x2b, 0xad, 0x04, 0x7b, 0x83, 0x19, 0x4e, 0xb6, 0xdb, 0x52, 0x84, 0x8c,
+ 0x5f, 0xcf, 0x15, 0xa4, 0xe2, 0x51, 0xd3, 0x76, 0x43, 0x30, 0x49, 0xc7,
+ 0x6a, 0x1e, 0x40, 0xf9, 0x38, 0x0a, 0xeb, 0x4f, 0x7b, 0x40, 0x25, 0xa7,
+ 0xfe, 0x60, 0x10, 0x37, 0x0e, 0x30, 0x09, 0x68, 0x23, 0xfd, 0x10, 0xd5,
+ 0xc8, 0x67, 0xcd, 0x9f, 0xd1, 0x2d, 0x3b, 0x0f, 0xe7, 0x5a, 0x7f, 0x65,
+ 0xc3, 0x37, 0xa2, 0x5a, 0x3d, 0x3c, 0xf0, 0x1f, 0x87, 0x11, 0x2c, 0xed,
+ 0xd2, 0x7e, 0xde, 0x38, 0x0c, 0x75, 0xc4, 0x05, 0x3e, 0xa0, 0xf7, 0x4c,
+ 0xa8, 0x80, 0x8c, 0x6e, 0x67, 0xef, 0xb3, 0xeb, 0x8b, 0x56, 0x9f, 0xe6,
+ 0xfd, 0x9e, 0x31, 0xc2, 0x3a, 0xd3, 0xc7, 0x6c, 0x3a, 0xd3, 0xe6, 0x11,
+ 0x71, 0x75, 0xa7, 0xf7, 0xdc, 0xb9, 0x06, 0xc9, 0x69, 0xee, 0x05, 0xf6,
+ 0x4a, 0x6b, 0x6d, 0x4a, 0x18, 0xdd, 0x5a, 0x45, 0x3f, 0x57, 0xde, 0xf0,
+ 0x24, 0x8c, 0x68, 0x61, 0x95, 0x6f, 0x64, 0x31, 0x09, 0x7f, 0xe8, 0x7a,
+ 0x2e, 0xa3, 0xb0, 0x20, 0xd9, 0x3f, 0x30, 0x8d, 0x9f, 0x73, 0xbe, 0x68,
+ 0x65, 0x44, 0x0f, 0x33, 0x72, 0xb4, 0xfb, 0x90, 0x10, 0xcf, 0x5a, 0x7f,
+ 0xfc, 0xec, 0x32, 0xfe, 0x06, 0xd3, 0x08, 0xf4, 0xff, 0x18, 0x6f, 0xee,
+ 0x2d, 0x3f, 0xed, 0x73, 0x63, 0x78, 0x6d, 0xb7, 0xab, 0x4e, 0xaf, 0xd8,
+ 0xb4, 0xd6, 0xda, 0xb4, 0xfe, 0xf9, 0x63, 0xb1, 0x9e, 0x6e, 0x9b, 0x4b,
+ 0x47, 0x23, 0xd4, 0x61, 0xfd, 0xda, 0x7f, 0xe0, 0xc1, 0xf5, 0x4f, 0x1a,
+ 0xb8, 0x65, 0xa1, 0x8f, 0xa3, 0x09, 0x27, 0xff, 0x61, 0xcf, 0x4f, 0xcf,
+ 0xf6, 0xab, 0xaa, 0x88, 0x62, 0x09, 0x50, 0x86, 0xa3, 0x9c, 0x02, 0x09,
+ 0xf7, 0xfb, 0x55, 0xd5, 0x44, 0x15, 0x3b, 0x4c, 0x75, 0xa3, 0x0f, 0x38,
+ 0x8c, 0xe7, 0xb7, 0x76, 0x12, 0x53, 0xab, 0xf6, 0x25, 0x3d, 0xc8, 0x50,
+ 0xe9, 0x4f, 0xe2, 0xb3, 0x37, 0x76, 0x12, 0x50, 0x94, 0xfd, 0x9d, 0x6d,
+ 0x31, 0xd2, 0x9a, 0xdb, 0x52, 0x9f, 0x81, 0x82, 0xc2, 0xfa, 0x51, 0x89,
+ 0x84, 0xf4, 0x84, 0xe3, 0x9a, 0x22, 0x11, 0x90, 0x05, 0x5a, 0x56, 0x30,
+ 0xc4, 0xc5, 0xf4, 0x8c, 0x7e, 0x52, 0xa7, 0xa7, 0x83, 0xa8, 0xe6, 0xe7,
+ 0xfc, 0xcf, 0xa0, 0xcb, 0xfd, 0xae, 0xb4, 0xff, 0x6f, 0x4c, 0xef, 0xd6,
+ 0x13, 0x2d, 0x3f, 0xcd, 0xc3, 0xfc, 0x9b, 0xb8, 0x75, 0xa1, 0x8f, 0xd7,
+ 0x47, 0x53, 0xff, 0xf3, 0x95, 0x4f, 0xad, 0x78, 0xcb, 0x39, 0xdf, 0x34,
+ 0x32, 0xa2, 0xfb, 0x9d, 0xbc, 0xea, 0xd3, 0xdb, 0x0c, 0x7a, 0xd0, 0xc6,
+ 0xec, 0x86, 0xe7, 0xfc, 0x04, 0xfd, 0xeb, 0x3e, 0x57, 0x5a, 0x7f, 0x6c,
+ 0x43, 0x03, 0xf5, 0x8b, 0x88, 0x06, 0x75, 0x7d, 0xeb, 0x88, 0x06, 0x30,
+ 0xfa, 0x39, 0x40, 0x9a, 0x9e, 0xb8, 0x80, 0x67, 0xa8, 0x38, 0x7a, 0xe2,
+ 0x01, 0x9f, 0xc5, 0xdd, 0x60, 0x84, 0xcb, 0x88, 0x06, 0x71, 0x07, 0xab,
+ 0x88, 0x06, 0x3d, 0x45, 0xb1, 0xc8, 0xb4, 0x5c, 0xec, 0xfa, 0x77, 0xdb,
+ 0x6b, 0x88, 0x06, 0x17, 0x10, 0x0c, 0xcc, 0x75, 0xc4, 0x03, 0x1e, 0x9b,
+ 0x92, 0x17, 0x9e, 0x23, 0xfa, 0xcb, 0x88, 0x06, 0x76, 0xeb, 0xab, 0x88,
+ 0x06, 0x7f, 0xc1, 0x4f, 0x36, 0x8b, 0xb5, 0xf5, 0xc4, 0x03, 0x35, 0x7a,
+ 0xb8, 0x80, 0x67, 0xf0, 0x55, 0xb7, 0xbb, 0x09, 0x71, 0x00, 0xcf, 0x88,
+ 0x7a, 0x01, 0x2e, 0x20, 0x19, 0x8a, 0xeb, 0x88, 0x06, 0x3e, 0x7a, 0xbb,
+ 0x33, 0x9f, 0x6c, 0x1b, 0x87, 0xaa, 0x20, 0x19, 0x84, 0xcb, 0x88, 0x04,
+ 0xc6, 0xd2, 0x7c, 0x4c, 0x7a, 0xf5, 0x71, 0x00, 0xcf, 0x73, 0x41, 0xd5,
+ 0xc4, 0x03, 0x39, 0xbf, 0xd5, 0xc4, 0x03, 0x3f, 0xec, 0xe2, 0xfe, 0xb6,
+ 0x00, 0xae, 0xb8, 0x80, 0x67, 0xdc, 0xd3, 0xde, 0xcb, 0x88, 0x06, 0x30,
+ 0xff, 0xf4, 0x97, 0x37, 0xc4, 0xb8, 0x80, 0x61, 0xea, 0xa2, 0xfd, 0x23,
+ 0xc8, 0x4a, 0x12, 0xb6, 0x8c, 0x84, 0x67, 0x72, 0xed, 0xc2, 0x9f, 0x92,
+ 0x19, 0xf6, 0x6e, 0xf5, 0xc2, 0xe2, 0x01, 0x9f, 0xde, 0xb7, 0x5c, 0xfb,
+ 0x6d, 0x71, 0x00, 0xfa, 0x6d, 0x27, 0x7d, 0xad, 0x5c, 0x40, 0x31, 0xd3,
+ 0xfb, 0xfa, 0x94, 0xf1, 0x03, 0xee, 0xb8, 0x80, 0x67, 0xea, 0x71, 0xf9,
+ 0xc3, 0xd7, 0x10, 0x0c, 0x62, 0x22, 0x84, 0x45, 0xc9, 0x6c, 0xff, 0x69,
+ 0xae, 0x6b, 0xf3, 0xf1, 0x2e, 0x20, 0x19, 0x12, 0xe2, 0x01, 0x9a, 0xac,
+ 0xf4, 0xf8, 0xf4, 0x8f, 0x37, 0xc4, 0xb8, 0x80, 0x67, 0xd5, 0xbb, 0x97,
+ 0x0b, 0x88, 0x06, 0x7e, 0x20, 0xe5, 0xf9, 0x75, 0xc4, 0x03, 0x0c, 0x89,
+ 0x00, 0x23, 0xd9, 0xa4, 0x7a, 0xc8, 0x07, 0xc8, 0x6c, 0x38, 0x81, 0xf6,
+ 0x1d, 0x10, 0xd1, 0x70, 0x8a, 0x2f, 0x2b, 0x53, 0x71, 0xe1, 0xf9, 0x42,
+ 0x4c, 0x68, 0x5f, 0xce, 0xaa, 0xea, 0xa2, 0x01, 0x32, 0x2f, 0x27, 0x87,
+ 0x74, 0xfe, 0x9d, 0x69, 0xff, 0x9e, 0x19, 0xdd, 0x10, 0x85, 0xcb, 0x8b,
+ 0x4c, 0x26, 0x4a, 0x43, 0xa5, 0x3b, 0x4d, 0x62, 0xd3, 0x5b, 0x6a, 0x50,
+ 0x47, 0xb5, 0xe7, 0x15, 0x70, 0x46, 0xd1, 0xc9, 0xc7, 0x2b, 0xa4, 0x63,
+ 0xc1, 0x9f, 0xfd, 0xbb, 0xe0, 0xe5, 0xf1, 0x84, 0x26, 0xe1, 0x68, 0xb1,
+ 0x96, 0x82, 0xf1, 0xfe, 0xd2, 0x59, 0xc8, 0xe6, 0x8a, 0x85, 0x0e, 0x01,
+ 0x8b, 0x27, 0xf1, 0x6c, 0x67, 0x6e, 0xda, 0xeb, 0x4f, 0xdf, 0x71, 0xed,
+ 0xfb, 0x16, 0x9f, 0xf3, 0xef, 0xe0, 0x30, 0xed, 0xf1, 0xd6, 0x9f, 0xfb,
+ 0xfa, 0xac, 0x7b, 0x7c, 0x43, 0x1d, 0x69, 0xf8, 0x6b, 0x7e, 0x59, 0xa4,
+ 0xa7, 0x9c, 0xd5, 0x38, 0xb4, 0xfb, 0x1c, 0x7b, 0x70, 0xb4, 0xf6, 0x03,
+ 0x3d, 0x28, 0xf9, 0xf5, 0x01, 0x1b, 0xa9, 0x44, 0x32, 0x6f, 0x98, 0x5e,
+ 0x48, 0x1a, 0x44, 0xa8, 0x4c, 0x4f, 0xdc, 0x5f, 0xff, 0x6d, 0xad, 0x3c,
+ 0x41, 0xbb, 0xad, 0x3b, 0x9f, 0x37, 0x75, 0xa7, 0xfe, 0x11, 0xf3, 0xba,
+ 0x2f, 0x75, 0xc8, 0xeb, 0x4f, 0xfd, 0x71, 0xc7, 0xaf, 0x0c, 0x70, 0x21,
+ 0xd6, 0x9f, 0xec, 0xde, 0xc8, 0x7d, 0xe7, 0x56, 0x9f, 0xde, 0xb7, 0x17,
+ 0xce, 0x36, 0xb4, 0xff, 0x36, 0xcb, 0xa5, 0xeb, 0x6d, 0x69, 0x5f, 0xd4,
+ 0x52, 0x61, 0xc7, 0xcd, 0x63, 0x84, 0xc8, 0x77, 0x0e, 0xb9, 0xfc, 0xfc,
+ 0xb8, 0xd7, 0xde, 0x2d, 0x0c, 0x9f, 0x41, 0x11, 0xd4, 0x6d, 0x1c, 0x95,
+ 0x4f, 0xfc, 0xdc, 0x3c, 0x39, 0x17, 0x8e, 0x9c, 0x4b, 0x4f, 0xa9, 0xdf,
+ 0xbe, 0xb2, 0xd3, 0x5e, 0xeb, 0x4e, 0xb6, 0xdb, 0x56, 0x98, 0x54, 0x91,
+ 0x8b, 0xf8, 0xf9, 0xec, 0xdc, 0xd6, 0x7f, 0xd9, 0x70, 0xa1, 0xdc, 0x02,
+ 0x71, 0x69, 0xd4, 0x2c, 0x4a, 0x1e, 0x8f, 0xd3, 0xc2, 0x0f, 0x44, 0x5e,
+ 0x47, 0xd3, 0xfb, 0x61, 0x9c, 0x08, 0x67, 0xad, 0x35, 0x1d, 0x69, 0xfe,
+ 0x0c, 0x77, 0x86, 0xb6, 0xdb, 0x52, 0x9c, 0x7a, 0xda, 0xd0, 0xe1, 0xf6,
+ 0x68, 0x55, 0xd9, 0xe4, 0xfb, 0x1c, 0x7b, 0x3d, 0x69, 0xfa, 0xcf, 0x5b,
+ 0x03, 0xd5, 0xa1, 0x93, 0x6c, 0x24, 0x5a, 0x85, 0x06, 0xcc, 0x86, 0x27,
+ 0x9f, 0xbc, 0xd9, 0x7d, 0xbe, 0x0b, 0x4f, 0xfe, 0xcf, 0x68, 0xf9, 0xc3,
+ 0xf0, 0x59, 0xea, 0xd3, 0x6a, 0x96, 0x99, 0xcb, 0xad, 0x3e, 0xc7, 0x64,
+ 0x1e, 0xe1, 0xac, 0x18, 0x56, 0x3c, 0x22, 0xd4, 0xce, 0xd3, 0xde, 0xe6,
+ 0xa9, 0x69, 0xff, 0x9b, 0x01, 0xfa, 0xc0, 0x06, 0xb5, 0x69, 0x17, 0xd1,
+ 0x0c, 0x04, 0xbb, 0x21, 0x8b, 0x1b, 0xb4, 0x07, 0xca, 0x86, 0xf6, 0x52,
+ 0x28, 0xe5, 0xfd, 0x85, 0x81, 0x10, 0xfe, 0x97, 0xd2, 0x77, 0x6d, 0x47,
+ 0x67, 0x49, 0x82, 0x2e, 0x09, 0x41, 0x17, 0x42, 0xdc, 0xab, 0x1e, 0x53,
+ 0x9d, 0xc6, 0xd9, 0x3f, 0xd9, 0xf0, 0x6d, 0xbf, 0x34, 0xb4, 0xfc, 0x02,
+ 0xcf, 0x69, 0xeb, 0x4f, 0xa9, 0xfe, 0x3d, 0x25, 0xa7, 0xc3, 0x38, 0xf6,
+ 0xf3, 0xa5, 0x0c, 0x8b, 0x8c, 0x36, 0xd1, 0x60, 0xc5, 0x33, 0xff, 0x0e,
+ 0x1c, 0xd0, 0xd9, 0x72, 0x60, 0x5a, 0x77, 0x91, 0x7a, 0xb4, 0x7c, 0xf8,
+ 0x8e, 0x87, 0x21, 0x95, 0x10, 0x2c, 0xb6, 0xaa, 0x05, 0x24, 0x5b, 0x37,
+ 0x76, 0x8f, 0x4f, 0xf8, 0xbc, 0xb4, 0x43, 0x18, 0x42, 0x64, 0xa7, 0xfb,
+ 0x5c, 0xd5, 0xf3, 0x00, 0x75, 0xa7, 0xfc, 0x0d, 0xc1, 0xeb, 0x79, 0xc6,
+ 0xd6, 0x9f, 0xff, 0xda, 0x6f, 0x8b, 0x1d, 0x95, 0xef, 0x81, 0xda, 0x01,
+ 0x2d, 0x3e, 0x6c, 0x0d, 0xf9, 0x2d, 0x23, 0xad, 0x3d, 0x7a, 0xe3, 0xc1,
+ 0xcd, 0xc0, 0x14, 0x47, 0xa9, 0xa3, 0xfc, 0xe3, 0x47, 0xdb, 0x84, 0xbc,
+ 0x32, 0x79, 0x85, 0x1c, 0x44, 0xff, 0xff, 0x7e, 0xcc, 0x27, 0x2a, 0x9f,
+ 0x76, 0x3f, 0xba, 0x60, 0xea, 0xd3, 0xac, 0x07, 0xad, 0x0c, 0xab, 0xe8,
+ 0xeb, 0xba, 0x8f, 0xce, 0x8a, 0x39, 0x66, 0x9f, 0xcf, 0x73, 0x02, 0xb5,
+ 0x8b, 0x4f, 0xfe, 0xff, 0x43, 0x1d, 0x86, 0x37, 0xda, 0xeb, 0x4f, 0xea,
+ 0x73, 0x58, 0x7c, 0xba, 0xd1, 0x87, 0xf4, 0xed, 0x22, 0x7e, 0x21, 0xf7,
+ 0x98, 0x75, 0xa7, 0xd9, 0xe9, 0x7e, 0xeb, 0x4e, 0xde, 0xf8, 0x5a, 0x7f,
+ 0xee, 0x3a, 0x5a, 0xf0, 0xeb, 0x9a, 0x23, 0xad, 0x2b, 0x88, 0xf9, 0xb6,
+ 0x3b, 0x26, 0xb1, 0x16, 0xb6, 0xc2, 0x36, 0x09, 0x33, 0x3d, 0x11, 0xee,
+ 0x1c, 0x33, 0xfe, 0x02, 0x1b, 0x8c, 0x77, 0xc3, 0x0c, 0xb4, 0xef, 0x6b,
+ 0xeb, 0x4f, 0x85, 0x41, 0x8e, 0xab, 0x43, 0x1e, 0x27, 0x23, 0x93, 0x8f,
+ 0xc3, 0x8b, 0x4f, 0xfc, 0x7b, 0x9d, 0xbd, 0x6f, 0xf2, 0xc2, 0x5a, 0x7f,
+ 0xcd, 0x41, 0x9b, 0xd9, 0x5b, 0xb5, 0xa1, 0x91, 0x3e, 0x43, 0xdc, 0xa2,
+ 0xc3, 0x2b, 0x89, 0x7c, 0x7b, 0xd8, 0x6b, 0x78, 0x43, 0x6e, 0x18, 0x33,
+ 0xff, 0x9e, 0x5a, 0xc7, 0x09, 0xce, 0x5d, 0x79, 0xba, 0xd3, 0xf8, 0xb5,
+ 0xed, 0x03, 0x69, 0x69, 0xf3, 0x58, 0xce, 0xac, 0xb4, 0xfd, 0xc8, 0xda,
+ 0xce, 0x2e, 0xb4, 0xff, 0xff, 0xfb, 0xed, 0xb0, 0xae, 0x95, 0xdc, 0x2f,
+ 0xf5, 0xaf, 0xb6, 0xe1, 0x86, 0xcb, 0xad, 0x3f, 0xff, 0xff, 0xeb, 0xdf,
+ 0x37, 0xaa, 0x3d, 0xff, 0xf2, 0xe3, 0x75, 0x43, 0xe6, 0x39, 0xce, 0xda,
+ 0xde, 0x19, 0x68, 0x64, 0xc7, 0xea, 0x10, 0x53, 0xc2, 0xae, 0x2e, 0xb4,
+ 0xd6, 0xda, 0xb4, 0x5c, 0xdd, 0x5a, 0x45, 0x3e, 0x2d, 0x56, 0x69, 0x23,
+ 0x1a, 0x28, 0xe1, 0x55, 0x8b, 0x8a, 0x1a, 0x31, 0xf3, 0x65, 0x21, 0x1a,
+ 0x7d, 0xe1, 0x07, 0x3a, 0xdb, 0x6d, 0x4a, 0x79, 0xfb, 0xce, 0xa4, 0x62,
+ 0xfe, 0x7d, 0x9e, 0x90, 0xae, 0xbb, 0xbf, 0xa5, 0x5f, 0x3e, 0x40, 0x30,
+ 0x9b, 0xf7, 0x5a, 0x73, 0xb6, 0xea, 0xd0, 0xc6, 0xcc, 0x85, 0xa7, 0xe0,
+ 0xe2, 0xee, 0x66, 0xd6, 0x9f, 0xfe, 0x0d, 0xb9, 0x9f, 0xca, 0x3b, 0x68,
+ 0xbd, 0x5a, 0x7d, 0x67, 0x9c, 0xb3, 0x85, 0xa7, 0xc5, 0x76, 0xb0, 0xeb,
+ 0xb3, 0xf6, 0x7c, 0xd5, 0xf1, 0x72, 0xbb, 0x3f, 0x66, 0xa7, 0xae, 0xcf,
+ 0xd9, 0xee, 0x5f, 0x97, 0x5d, 0x9f, 0xb1, 0xe9, 0xe8, 0x81, 0x14, 0xf9,
+ 0xb2, 0xf8, 0x0b, 0xb3, 0xf6, 0x17, 0x67, 0xec, 0xd5, 0xb5, 0xd9, 0xfa,
+ 0x72, 0xde, 0x4f, 0x03, 0xf9, 0xe5, 0x22, 0x7b, 0x3c, 0x88, 0x4b, 0xb3,
+ 0xf6, 0x17, 0x67, 0xec, 0xc2, 0x65, 0xd9, 0xfb, 0x3f, 0xd8, 0x2a, 0xfe,
+ 0x3b, 0xcf, 0x57, 0x67, 0xec, 0xfd, 0x9a, 0x2b, 0xf3, 0x62, 0xec, 0xfd,
+ 0x81, 0x22, 0x8c, 0x08, 0xae, 0x8d, 0x3d, 0xfb, 0x1b, 0x6b, 0xb3, 0xf6,
+ 0x17, 0x67, 0xee, 0x1a, 0xf9, 0xad, 0xb5, 0x76, 0x7e, 0xc3, 0xd5, 0x87,
+ 0xfa, 0x69, 0x90, 0x85, 0xe2, 0x13, 0x7f, 0x28, 0x39, 0x85, 0xe1, 0x75,
+ 0xb5, 0xeb, 0x49, 0xa7, 0xb1, 0xec, 0x3a, 0x6c, 0xfd, 0x19, 0x12, 0x33,
+ 0xfe, 0xce, 0xfb, 0x9f, 0xb6, 0xb4, 0xe2, 0xd3, 0x3e, 0xc4, 0xa2, 0xc4,
+ 0x4c, 0x70, 0x82, 0x08, 0x11, 0xf5, 0xc9, 0x5a, 0x9c, 0x64, 0x9f, 0xff,
+ 0x3f, 0xec, 0xee, 0x9c, 0x6f, 0x74, 0xc7, 0xa7, 0x16, 0x9f, 0xce, 0xb5,
+ 0x72, 0xbb, 0x98, 0xb4, 0x70, 0x88, 0xdf, 0xac, 0x43, 0x2f, 0x33, 0xbd,
+ 0x67, 0x07, 0xc8, 0xba, 0xa7, 0x38, 0xf9, 0x85, 0xd4, 0xff, 0x87, 0x6e,
+ 0x01, 0xb5, 0xae, 0x7a, 0xb4, 0xfc, 0x14, 0x3e, 0xa9, 0xeb, 0x4e, 0xb6,
+ 0xdb, 0x52, 0x9c, 0x33, 0x09, 0x23, 0x17, 0xf3, 0xfe, 0x0a, 0x78, 0xdf,
+ 0xc7, 0x75, 0xf5, 0xa7, 0xf8, 0x28, 0x5e, 0x1e, 0xc2, 0xe1, 0x68, 0xf5,
+ 0x32, 0xf3, 0xa0, 0x09, 0x2c, 0x0a, 0xf6, 0x7f, 0x3f, 0xe0, 0x02, 0xe7,
+ 0xcd, 0xdf, 0xc9, 0xb6, 0xb4, 0xeb, 0x6d, 0xb5, 0x31, 0x08, 0x27, 0xdf,
+ 0xed, 0x57, 0x53, 0x10, 0x80, 0xc6, 0xb6, 0x75, 0xb6, 0xda, 0x98, 0x83,
+ 0xd0, 0x98, 0x83, 0xc6, 0x35, 0xb2, 0x3e, 0x22, 0x67, 0xae, 0x33, 0xff,
+ 0x69, 0x9e, 0x5b, 0xcd, 0x75, 0x8e, 0xb4, 0x31, 0xf5, 0x3b, 0x28, 0x9f,
+ 0x6d, 0xb6, 0xc7, 0x5a, 0x78, 0x09, 0x87, 0x5a, 0x70, 0xcc, 0x25, 0xa2,
+ 0xc3, 0x78, 0x72, 0x09, 0xf7, 0x5b, 0x4c, 0x74, 0xa7, 0xc1, 0x40, 0x18,
+ 0x94, 0xd9, 0xd4, 0xa6, 0xb6, 0xd4, 0xa3, 0x0f, 0xda, 0xe4, 0xdb, 0x23,
+ 0xb4, 0x56, 0x7f, 0x00, 0xcc, 0x2d, 0x63, 0xaa, 0x46, 0x37, 0x90, 0xc9,
+ 0xbd, 0x93, 0x15, 0x43, 0x52, 0x7f, 0xe6, 0x15, 0xf3, 0x3d, 0xa0, 0xa1,
+ 0xd6, 0x9f, 0xff, 0x70, 0xfb, 0xda, 0xdf, 0xd3, 0x16, 0x98, 0x09, 0x68,
+ 0xd2, 0x25, 0xa9, 0x0a, 0x7f, 0x5c, 0x63, 0xde, 0xda, 0xe1, 0x68, 0x65,
+ 0xc8, 0x0c, 0x4b, 0x28, 0xdd, 0xbf, 0x1c, 0xf5, 0x43, 0x26, 0xe4, 0x53,
+ 0xad, 0xb6, 0xd4, 0xa7, 0x85, 0x41, 0xea, 0x46, 0x2f, 0xe7, 0xe1, 0xb3,
+ 0xf9, 0x8e, 0x2d, 0x0f, 0x3d, 0xdb, 0x98, 0x4f, 0xff, 0x07, 0x1e, 0x38,
+ 0x13, 0x07, 0x6a, 0xc0, 0xa5, 0xa7, 0xff, 0xff, 0xfb, 0x77, 0x1a, 0xfe,
+ 0x35, 0x45, 0xb2, 0xd7, 0x4b, 0xc3, 0xcb, 0x54, 0x1b, 0x7e, 0x7f, 0x16,
+ 0x9f, 0xfe, 0xc6, 0x37, 0xa0, 0xdc, 0xf7, 0x07, 0x2f, 0xad, 0x3c, 0xeb,
+ 0xa1, 0x3b, 0x5a, 0x1e, 0x7e, 0xd4, 0x9f, 0x3f, 0xf6, 0x7c, 0x47, 0x2b,
+ 0x8d, 0x76, 0xc5, 0xa7, 0x57, 0x9e, 0xeb, 0x43, 0xcf, 0x8a, 0x90, 0xe7,
+ 0x8b, 0xdc, 0x3a, 0xd0, 0xca, 0x91, 0x1e, 0x45, 0x8a, 0x35, 0x18, 0x60,
+ 0x42, 0x0f, 0x92, 0x19, 0xfb, 0xcf, 0x72, 0x0e, 0x1e, 0xb4, 0xff, 0xab,
+ 0xfe, 0x45, 0xac, 0xae, 0x04, 0xb4, 0xff, 0xf8, 0xb6, 0xc7, 0xce, 0x36,
+ 0xc7, 0x1b, 0xf4, 0x25, 0xa7, 0xfa, 0xed, 0xfd, 0xb1, 0xbd, 0x25, 0xa1,
+ 0xe8, 0x8d, 0xba, 0xac, 0xfe, 0x21, 0xf6, 0xda, 0x6b, 0xad, 0x3f, 0xe0,
+ 0xa7, 0x35, 0x5f, 0xf9, 0x7a, 0xb4, 0x62, 0x72, 0x3d, 0x31, 0x28, 0x66,
+ 0xfc, 0x8c, 0xe6, 0x53, 0xcf, 0x1b, 0x1c, 0x5a, 0x7d, 0xff, 0x73, 0x01,
+ 0x69, 0xff, 0xbc, 0xe5, 0x9a, 0x67, 0x77, 0xd3, 0x70, 0xb4, 0x51, 0xf7,
+ 0xdc, 0x9a, 0x7f, 0xb0, 0x3f, 0x97, 0xc2, 0xd2, 0xd3, 0xff, 0xb7, 0x7c,
+ 0x73, 0x4c, 0xef, 0x35, 0xa6, 0x5a, 0x7e, 0xd7, 0xa4, 0xed, 0xbd, 0x5a,
+ 0x30, 0xfe, 0xe9, 0x2e, 0x7b, 0x36, 0x57, 0x5a, 0x7e, 0x74, 0xce, 0x03,
+ 0xa5, 0x67, 0x2b, 0x45, 0xcf, 0x6f, 0x64, 0x11, 0xea, 0x6d, 0xdd, 0x21,
+ 0x08, 0x58, 0x6d, 0xee, 0x7f, 0xf8, 0xaf, 0x9e, 0xee, 0xe4, 0x3e, 0xa8,
+ 0x09, 0x69, 0xff, 0xfc, 0x1b, 0xcd, 0x13, 0x6c, 0x84, 0xcf, 0x35, 0xb6,
+ 0xda, 0x94, 0xf7, 0xb9, 0x83, 0xa5, 0x3d, 0x42, 0xad, 0xad, 0x39, 0xe1,
+ 0xca, 0xa2, 0x19, 0x9d, 0x6d, 0xb6, 0xa5, 0x3b, 0x03, 0xa9, 0x18, 0xbf,
+ 0x9f, 0xf6, 0x59, 0x9e, 0xd3, 0xc1, 0xac, 0x5a, 0x04, 0x7c, 0xe0, 0x53,
+ 0x3f, 0x9e, 0x19, 0xbd, 0xf3, 0x62, 0xd3, 0xab, 0xce, 0xcb, 0x43, 0x27,
+ 0x8b, 0x63, 0x0f, 0xa4, 0x5c, 0x10, 0x7e, 0x15, 0xf4, 0x43, 0xc9, 0xa4,
+ 0xf1, 0x6c, 0x99, 0x69, 0xfd, 0xce, 0x7c, 0x42, 0x20, 0x5a, 0x7f, 0xf9,
+ 0xe5, 0xee, 0x86, 0xbe, 0x7f, 0xb5, 0x5d, 0x54, 0x41, 0x93, 0xff, 0xbf,
+ 0x4e, 0xf0, 0x3b, 0xa2, 0x10, 0xdb, 0x5a, 0x19, 0x15, 0x1c, 0xae, 0xc6,
+ 0x91, 0xfb, 0xb8, 0x6d, 0x4d, 0xae, 0x56, 0x9e, 0xf9, 0x5b, 0xe7, 0x5a,
+ 0x08, 0xde, 0xdc, 0x5e, 0x7f, 0x79, 0x65, 0xfc, 0xb3, 0xec, 0xb4, 0x3d,
+ 0x3d, 0x82, 0x8c, 0x72, 0xec, 0xbb, 0x20, 0x9f, 0xfe, 0x60, 0xb3, 0xc3,
+ 0x84, 0x19, 0xee, 0x00, 0xeb, 0x4e, 0x6f, 0xb8, 0xb4, 0x32, 0xfc, 0xc7,
+ 0xa9, 0xd9, 0x28, 0x03, 0xa8, 0x65, 0x28, 0x4e, 0xa5, 0x22, 0x72, 0x87,
+ 0xe4, 0xa3, 0x3e, 0xa3, 0xd6, 0x5d, 0x69, 0xff, 0xee, 0xb5, 0xee, 0xc7,
+ 0xcd, 0x95, 0xf5, 0x4b, 0x4f, 0xe0, 0x06, 0x79, 0xd8, 0x96, 0x9f, 0xdb,
+ 0x27, 0x65, 0xb7, 0xb2, 0x52, 0x3a, 0xd3, 0xf6, 0x00, 0xff, 0x63, 0x11,
+ 0xe1, 0x8c, 0x67, 0x18, 0x98, 0x19, 0x26, 0xdd, 0xca, 0x7b, 0xfc, 0xf0,
+ 0xf5, 0xa7, 0xf0, 0x3c, 0x30, 0xed, 0xd5, 0xa7, 0x1f, 0xdc, 0x5a, 0x18,
+ 0xfc, 0x30, 0x92, 0x8c, 0x27, 0x6c, 0xac, 0x5a, 0x7d, 0x69, 0x7a, 0xea,
+ 0x4b, 0x4f, 0xfb, 0x9d, 0xdc, 0x6f, 0x88, 0xe5, 0x75, 0xa7, 0xf5, 0xda,
+ 0xcc, 0x02, 0x1d, 0x69, 0xff, 0x98, 0x2b, 0x4c, 0x23, 0x7e, 0xf7, 0x4a,
+ 0x3d, 0x45, 0xae, 0x20, 0x9c, 0xca, 0x7f, 0x70, 0xfe, 0x2e, 0x5b, 0x65,
+ 0xa7, 0x17, 0x17, 0x5a, 0x5a, 0xc3, 0xd0, 0x23, 0x49, 0xff, 0xf6, 0x7b,
+ 0xe2, 0x8b, 0x2e, 0xd6, 0x60, 0x10, 0xeb, 0x4d, 0x96, 0xad, 0x09, 0x4f,
+ 0xd7, 0x19, 0xbe, 0xc7, 0x4a, 0x12, 0x84, 0xa1, 0x28, 0x4a, 0x1e, 0x7b,
+ 0xe4, 0x14, 0x22, 0xde, 0x42, 0xbc, 0x82, 0x9d, 0x42, 0xa6, 0xd6, 0x25,
+ 0x3f, 0x55, 0x6d, 0xc6, 0x3a, 0x5e, 0x0b, 0x59, 0x79, 0xb4, 0xa1, 0x28,
+ 0x4a, 0x1e, 0x5a, 0x10, 0x54, 0x25, 0x09, 0x42, 0x50, 0x94, 0x25, 0x09,
+ 0x45, 0x86, 0xf3, 0xd0, 0xa2, 0x0a, 0x10, 0x55, 0xc2, 0x9d, 0x85, 0x42,
+ 0x50, 0x94, 0x3c, 0xb4, 0xb8, 0x54, 0x25, 0x09, 0x42, 0x50, 0x94, 0x3c,
+ 0xd4, 0x08, 0x2b, 0x61, 0x4e, 0xa1, 0x50, 0x94, 0x25, 0x09, 0x42, 0x51,
+ 0x61, 0xa8, 0x1c, 0x2b, 0xe1, 0x5a, 0x0a, 0x90, 0xe9, 0x42, 0x50, 0x94,
+ 0x25, 0x09, 0x47, 0xa6, 0xa3, 0x80, 0xa1, 0x05, 0x72, 0x15, 0x09, 0x42,
+ 0x50, 0x94, 0xfb, 0x4c, 0x2b, 0xe2, 0x50, 0x94, 0x3c, 0xf3, 0xba, 0x15,
+ 0xa0, 0xaa, 0x0a, 0x11, 0x34, 0xba, 0x94, 0x25, 0x09, 0x42, 0x50, 0x94,
+ 0x3c, 0xd4, 0x70, 0x14, 0x41, 0x4e, 0xc2, 0xa1, 0x28, 0x4a, 0x12, 0x84,
+ 0xa1, 0xe6, 0xa3, 0xd0, 0xad, 0x05, 0x00, 0x54, 0xb4, 0x94, 0x25, 0x09,
+ 0x49, 0xe9, 0x42, 0x5c, 0x16, 0x10, 0x94, 0x25, 0x09, 0x42, 0x51, 0x61,
+ 0xf3, 0x3c, 0x28, 0x71, 0xae, 0x8d, 0x38, 0x14, 0x20, 0xad, 0x85, 0x4b,
+ 0x12, 0x84, 0xa1, 0x29, 0x3d, 0x28, 0x4b, 0x82, 0xc2, 0x12, 0x84, 0xa1,
+ 0x8f, 0x49, 0xe1, 0x44, 0x35, 0xf1, 0xa3, 0x85, 0x42, 0x50, 0x94, 0x25,
+ 0x09, 0x42, 0x50, 0xc6, 0xcb, 0x80, 0xaf, 0x85, 0x1c, 0x28, 0x02, 0xa1,
+ 0x28, 0x4a, 0x12, 0x8f, 0x97, 0xd7, 0x0a, 0xd8, 0x54, 0x25, 0x09, 0x42,
+ 0x50, 0x72, 0xf8, 0x02, 0xb6, 0x15, 0x23, 0xa5, 0x09, 0x42, 0x50, 0x22,
+ 0xd3, 0x90, 0xa8, 0x4a, 0x12, 0x84, 0xa1, 0x28, 0x63, 0x50, 0xe0, 0x56,
+ 0x82, 0xb9, 0x0a, 0x86, 0x5f, 0xaa, 0xb1, 0xc5, 0xe7, 0xbe, 0x95, 0x62,
+ 0xdf, 0x5b, 0x38, 0x48, 0x26, 0x6f, 0x39, 0xeb, 0x87, 0x3f, 0x84, 0x61,
+ 0xd2, 0x34, 0x71, 0x4c, 0xa2, 0x3b, 0x07, 0x6b, 0xb3, 0x6d, 0x87, 0x97,
+ 0x97, 0x6c, 0xb6, 0xa5, 0xf9, 0x16, 0x0c, 0x48, 0xea, 0x93, 0x3e, 0x78,
+ 0x36, 0x5d, 0x23, 0x26, 0xaf, 0x38, 0x98, 0xe9, 0x4f, 0x17, 0x6b, 0xeb,
+ 0x4e, 0x2f, 0x71, 0x69, 0x1b, 0x84, 0x46, 0xfc, 0xe3, 0x43, 0x5b, 0x20,
+ 0x93, 0x3b, 0x65, 0x23, 0x8d, 0x4a, 0x03, 0x9f, 0xda, 0x2b, 0x7d, 0xfb,
+ 0x58, 0xb4, 0x70, 0x7d, 0xae, 0x1c, 0x4c, 0x26, 0x5a, 0x7e, 0xfd, 0x00,
+ 0xcc, 0x25, 0xa6, 0xaf, 0xad, 0x22, 0x5b, 0xa5, 0xac, 0xba, 0xb4, 0x8e,
+ 0xb4, 0xde, 0x46, 0x24, 0x4a, 0x7c, 0x57, 0x48, 0x34, 0x3c, 0x30, 0x84,
+ 0xff, 0x69, 0x8f, 0x8e, 0x30, 0x58, 0xb4, 0x62, 0x24, 0x04, 0xb1, 0x3f,
+ 0x1c, 0xbc, 0xa8, 0x04, 0xb4, 0xfe, 0xe0, 0x58, 0x19, 0xc5, 0xab, 0x4f,
+ 0xff, 0x37, 0x8a, 0xff, 0xe8, 0x4c, 0x6b, 0x6d, 0xb5, 0x68, 0x64, 0x5a,
+ 0xd1, 0x77, 0x26, 0x91, 0x63, 0x61, 0xd8, 0xf8, 0xca, 0x3d, 0x84, 0xff,
+ 0x4b, 0x38, 0x1c, 0x28, 0x70, 0x39, 0x08, 0x03, 0x93, 0x55, 0x2c, 0x24,
+ 0x23, 0x48, 0xdc, 0x35, 0xe7, 0xc7, 0x20, 0xeb, 0x2d, 0x3f, 0x98, 0x37,
+ 0x41, 0xce, 0x2d, 0x3f, 0x3c, 0x09, 0xfa, 0xc5, 0xa7, 0xd6, 0x17, 0xd9,
+ 0xeb, 0x47, 0xcf, 0x48, 0x0a, 0xe7, 0xfd, 0xa6, 0xf8, 0x83, 0x2d, 0xa1,
+ 0x2d, 0x3b, 0x31, 0xc5, 0xa5, 0x9a, 0x3d, 0x81, 0x1e, 0xcf, 0xdc, 0xff,
+ 0x93, 0xd0, 0x2d, 0x3c, 0x76, 0xcb, 0x16, 0x9f, 0x63, 0xb0, 0x6e, 0x16,
+ 0x82, 0x3c, 0x9b, 0x90, 0xcf, 0x30, 0x6f, 0xab, 0x49, 0xb1, 0x35, 0x80,
+ 0x79, 0xb9, 0x3e, 0xdd, 0xfc, 0x88, 0x67, 0xb9, 0xaf, 0xbd, 0x69, 0xe6,
+ 0xe7, 0xcd, 0xdd, 0x29, 0xf3, 0xcd, 0x6d, 0xb6, 0xad, 0x00, 0x7a, 0x7c,
+ 0x94, 0x4f, 0x56, 0xcf, 0xb5, 0xa3, 0xd4, 0x5c, 0x63, 0xa8, 0x88, 0xa1,
+ 0x95, 0x9c, 0x1c, 0x94, 0x51, 0xed, 0x73, 0x18, 0x4c, 0xfb, 0x91, 0x60,
+ 0x75, 0x69, 0xfd, 0xbc, 0x19, 0x9c, 0x2b, 0xad, 0x1f, 0x3d, 0xa7, 0x64,
+ 0xf3, 0xfd, 0x60, 0x63, 0xf5, 0x82, 0xba, 0xd3, 0xde, 0xfa, 0xce, 0xd6,
+ 0x9f, 0xfe, 0xd3, 0x1f, 0xad, 0xbc, 0xff, 0x6a, 0xba, 0xa8, 0xbe, 0x27,
+ 0x57, 0xec, 0x54, 0x5f, 0xf0, 0xc8, 0x83, 0xea, 0xd4, 0xff, 0x9d, 0x4b,
+ 0x03, 0xd1, 0xcb, 0x3e, 0xb4, 0xea, 0xe1, 0xd5, 0x69, 0xfa, 0xb7, 0x76,
+ 0xcb, 0x16, 0x87, 0x67, 0x97, 0x68, 0xfc, 0xe2, 0xd1, 0x2d, 0x3f, 0xf3,
+ 0xbd, 0x8e, 0xc0, 0xfc, 0xd1, 0x1d, 0x69, 0xfb, 0x2d, 0x1b, 0x55, 0xb5,
+ 0xa7, 0xff, 0xdb, 0x19, 0xec, 0xec, 0x80, 0x5f, 0x26, 0x3e, 0x25, 0x3d,
+ 0xa1, 0xb8, 0xda, 0xd1, 0x62, 0x29, 0xf0, 0xbb, 0xaa, 0xb3, 0x6f, 0x16,
+ 0x9f, 0x7c, 0xac, 0xa3, 0xaa, 0x61, 0x39, 0xed, 0xf2, 0xd4, 0xa9, 0x84,
+ 0xe6, 0x13, 0x2a, 0x81, 0x39, 0xfc, 0x14, 0x3e, 0xdb, 0xe2, 0x55, 0x02,
+ 0x73, 0xfa, 0xf9, 0xa2, 0xbf, 0x36, 0x2a, 0x61, 0x39, 0xb3, 0xd5, 0x4c,
+ 0x27, 0x35, 0xb6, 0xae, 0x61, 0x38, 0xc4, 0xd3, 0x38, 0x34, 0x22, 0xe3,
+ 0x91, 0x5c, 0xfd, 0xda, 0x0d, 0xa4, 0x72, 0xda, 0x66, 0x13, 0x18, 0xf9,
+ 0xe4, 0x5c, 0x27, 0xef, 0x6c, 0x79, 0x10, 0x4a, 0xd7, 0xa8, 0x6a, 0xf0,
+ 0xec, 0xdc, 0xa2, 0x79, 0xc0, 0x23, 0xad, 0x3f, 0xcd, 0xce, 0xc0, 0x9d,
+ 0x8c, 0x75, 0xa7, 0x06, 0x5f, 0x0f, 0x5b, 0xe3, 0x70, 0xcb, 0xbc, 0x1e,
+ 0x9c, 0x76, 0x15, 0x1f, 0x22, 0xd4, 0x22, 0xf7, 0x2e, 0x0d, 0xdc, 0x27,
+ 0xe7, 0xde, 0xe7, 0xc8, 0x75, 0xa7, 0xed, 0x30, 0xc1, 0xc0, 0x96, 0x9f,
+ 0x9b, 0x78, 0xe1, 0x1d, 0x69, 0xf0, 0x60, 0xd8, 0xe2, 0xd3, 0xfd, 0xaa,
+ 0x3e, 0x89, 0xb8, 0x7a, 0xd3, 0xf0, 0xc0, 0xff, 0x2a, 0xb1, 0x68, 0x23,
+ 0xe9, 0x11, 0xc4, 0x58, 0x8d, 0xd0, 0x2c, 0xdc, 0x24, 0x27, 0xfd, 0x95,
+ 0xa7, 0x08, 0x35, 0x9c, 0x2d, 0x0c, 0xc8, 0x28, 0xc9, 0xe0, 0x42, 0x7f,
+ 0xf3, 0x94, 0x54, 0x61, 0x60, 0x6b, 0x3f, 0xf8, 0xfb, 0xb9, 0x07, 0x0f,
+ 0xd9, 0x5c, 0x96, 0x9f, 0xff, 0xc1, 0x9c, 0x65, 0xe8, 0x34, 0x4d, 0xbd,
+ 0x73, 0x47, 0x5a, 0x7e, 0x0e, 0x4e, 0x5a, 0x65, 0xa7, 0xff, 0xd4, 0x1b,
+ 0xaa, 0xd0, 0x36, 0xef, 0x6e, 0x69, 0x69, 0xff, 0x59, 0x41, 0x7d, 0xe8,
+ 0x9a, 0xeb, 0x4e, 0xfd, 0xee, 0xb8, 0x80, 0xe7, 0xff, 0x7d, 0xb4, 0xde,
+ 0x33, 0xfd, 0xaa, 0xea, 0xa2, 0x03, 0x31, 0xa9, 0x8a, 0x46, 0x60, 0xcc,
+ 0xd0, 0x24, 0xd0, 0x77, 0x18, 0xf4, 0x62, 0x72, 0xe5, 0x1b, 0x6c, 0xfb,
+ 0x6c, 0x2f, 0x2c, 0x5a, 0x78, 0x36, 0x2e, 0x56, 0x9f, 0xff, 0x9f, 0x97,
+ 0x2f, 0xfc, 0x8e, 0x36, 0xf5, 0x96, 0xed, 0x68, 0xc3, 0xfe, 0xa2, 0x29,
+ 0xff, 0xfe, 0xa7, 0xe0, 0x38, 0xfc, 0xe1, 0xe3, 0x30, 0x8d, 0x6d, 0xb6,
+ 0xa5, 0x0c, 0x99, 0x96, 0xa1, 0x4e, 0x04, 0x13, 0xf9, 0xb3, 0xfd, 0xaa,
+ 0xea, 0xa2, 0x09, 0x9f, 0xe6, 0xde, 0x7f, 0xb5, 0x5d, 0x54, 0x5f, 0x33,
+ 0xe2, 0x76, 0x19, 0x7f, 0x51, 0x01, 0xd3, 0xd9, 0xfd, 0xce, 0xbc, 0xb4,
+ 0x5d, 0xd2, 0xd3, 0xfe, 0xb2, 0xb8, 0xf2, 0xcd, 0x85, 0x3b, 0x5a, 0x7f,
+ 0xd9, 0xeb, 0x3d, 0xb5, 0x82, 0xa5, 0xa7, 0x5b, 0x6d, 0xa9, 0x4f, 0xb5,
+ 0x9d, 0xaf, 0xa4, 0x62, 0xfe, 0x7f, 0xff, 0x39, 0xf6, 0x77, 0xe0, 0x7a,
+ 0xf0, 0x33, 0x97, 0xf1, 0x9c, 0x6d, 0x68, 0xda, 0x28, 0xc6, 0x35, 0x8b,
+ 0x13, 0x65, 0x3a, 0x18, 0x43, 0xfa, 0x7f, 0xeb, 0x0e, 0xdc, 0x5c, 0x32,
+ 0xc1, 0x9e, 0xb4, 0xfd, 0xe7, 0xc7, 0xe9, 0xbe, 0xb4, 0xff, 0xee, 0x03,
+ 0xc7, 0x74, 0x42, 0x13, 0x7d, 0xeb, 0x43, 0x1f, 0xe0, 0xc6, 0x13, 0xfe,
+ 0xe6, 0xed, 0x81, 0xb7, 0x46, 0xde, 0xad, 0x3a, 0xdb, 0x6d, 0x4a, 0x7f,
+ 0x0c, 0x26, 0x0c, 0xe3, 0x69, 0x18, 0xbf, 0x9f, 0xff, 0xbc, 0xdf, 0x8e,
+ 0xe8, 0xbd, 0xf7, 0x2d, 0xf1, 0xbb, 0xe5, 0x8b, 0x4a, 0xb4, 0x8a, 0xbe,
+ 0x50, 0xa1, 0xeb, 0x85, 0xfe, 0xa0, 0x94, 0x73, 0x9f, 0x36, 0x3c, 0x30,
+ 0xc0, 0x8b, 0x71, 0x87, 0x4f, 0xfb, 0x45, 0x6f, 0xba, 0xcd, 0xf9, 0x62,
+ 0xd3, 0xed, 0x66, 0xdc, 0x7a, 0xd3, 0xfe, 0xcd, 0xb7, 0xef, 0xa6, 0x0d,
+ 0xae, 0x20, 0x89, 0xfc, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x04, 0x18, 0xf2,
+ 0x67, 0xea, 0xd7, 0xfe, 0x56, 0xad, 0x3f, 0x79, 0xfd, 0xb6, 0x81, 0xeb,
+ 0x40, 0x1e, 0xff, 0x25, 0xb1, 0xa4, 0xd0, 0x04, 0xe2, 0x10, 0xad, 0x9f,
+ 0xe6, 0x0d, 0x8d, 0x9a, 0xae, 0x16, 0x9f, 0xfe, 0xab, 0x77, 0x9a, 0x62,
+ 0xd8, 0x66, 0x89, 0x68, 0x7a, 0x21, 0x00, 0xe2, 0x7f, 0xb4, 0xdf, 0xd8,
+ 0x36, 0x70, 0xb4, 0xff, 0xff, 0x15, 0x8c, 0xfb, 0xff, 0xe5, 0xc3, 0x8f,
+ 0xaf, 0x9f, 0x38, 0x5a, 0x7b, 0x7a, 0xc0, 0xf5, 0x14, 0x1a, 0x37, 0x9f,
+ 0x86, 0x3d, 0xed, 0xae, 0x16, 0x86, 0x3e, 0xad, 0x9d, 0x4f, 0x13, 0x85,
+ 0x6a, 0xd3, 0xff, 0xee, 0x6c, 0x06, 0xcd, 0x19, 0xb7, 0x9a, 0xe7, 0xeb,
+ 0x4f, 0xb3, 0x77, 0x1a, 0xfe, 0x9f, 0xc0, 0xc4, 0x53, 0xf7, 0x74, 0x5e,
+ 0x44, 0x3a, 0xd3, 0xf1, 0xdb, 0xcf, 0xac, 0xb1, 0x69, 0xff, 0xff, 0xe2,
+ 0xdd, 0x1e, 0x80, 0x4f, 0x2b, 0xf2, 0x7d, 0x13, 0x6f, 0x5c, 0xd1, 0xd6,
+ 0x8f, 0x51, 0xba, 0x46, 0x14, 0x63, 0x3f, 0x00, 0xb0, 0xed, 0xa5, 0xa7,
+ 0x7c, 0x6b, 0xad, 0x3f, 0xea, 0x0e, 0xe7, 0xfb, 0x55, 0xd5, 0x44, 0x23,
+ 0x0c, 0x7c, 0xbc, 0x8e, 0xcf, 0xfe, 0x6c, 0xe0, 0x6d, 0x90, 0x72, 0xfc,
+ 0xba, 0xd3, 0xff, 0xd5, 0x56, 0x0d, 0x9a, 0xa3, 0x9a, 0xdb, 0x6d, 0x5a,
+ 0x3d, 0x44, 0xeb, 0x89, 0x53, 0xfd, 0xeb, 0x5e, 0xed, 0x66, 0x5a, 0xb4,
+ 0x61, 0xef, 0xd1, 0x2c, 0xeb, 0x6d, 0xb5, 0x29, 0xfe, 0xc1, 0x57, 0xf1,
+ 0xde, 0x7a, 0x91, 0x8b, 0xf9, 0xad, 0xb5, 0x29, 0xd6, 0xdb, 0x6a, 0x53,
+ 0xf5, 0x59, 0xee, 0x9a, 0xe9, 0x18, 0xbf, 0x80, 0x45, 0xe5, 0xa9, 0x1e,
+ 0x46, 0xf3, 0xee, 0x97, 0xa3, 0x1d, 0x23, 0x1b, 0x39, 0xd6, 0xdb, 0x6a,
+ 0x53, 0xae, 0xdf, 0x48, 0xc5, 0xfc, 0x84, 0x48, 0x82, 0xda, 0xc4, 0xfd,
+ 0xe8, 0x33, 0xeb, 0xab, 0x4f, 0xe1, 0xbf, 0xe9, 0x3b, 0x6f, 0x56, 0x9f,
+ 0xfb, 0x54, 0xf0, 0xa1, 0xdc, 0x02, 0x71, 0x69, 0xfb, 0x58, 0xef, 0x37,
+ 0x75, 0xa3, 0xa7, 0xe5, 0xb4, 0x48, 0xfa, 0x3d, 0xf4, 0x58, 0x10, 0xa9,
+ 0x86, 0x4d, 0x4f, 0x23, 0x1f, 0x9d, 0xc7, 0x9a, 0x1d, 0x32, 0xd3, 0xff,
+ 0xb3, 0xcf, 0x40, 0x2c, 0xeb, 0x69, 0x8e, 0xb4, 0xfd, 0xd2, 0xbe, 0x89,
+ 0xc4, 0xa7, 0xf0, 0x67, 0x0f, 0xb9, 0x0e, 0xb4, 0xf5, 0x57, 0xc7, 0x5a,
+ 0x3c, 0x1e, 0xa5, 0x86, 0x73, 0xcd, 0x47, 0x76, 0x94, 0xeb, 0x6d, 0xb5,
+ 0x29, 0xff, 0xe1, 0x98, 0x59, 0x81, 0xbd, 0x13, 0x05, 0x89, 0x18, 0xbf,
+ 0x96, 0x75, 0x13, 0xa7, 0x41, 0x86, 0x4f, 0x81, 0xe5, 0x7c, 0x25, 0x14,
+ 0x20, 0x75, 0x0c, 0x29, 0xff, 0xf1, 0xf3, 0xac, 0x15, 0xbb, 0xfb, 0xcd,
+ 0x7d, 0xeb, 0x4f, 0x9b, 0x77, 0x77, 0x8b, 0x43, 0x1f, 0xee, 0xd5, 0x67,
+ 0xff, 0x89, 0xde, 0x07, 0xa1, 0x56, 0xe0, 0x50, 0xeb, 0x4f, 0xff, 0xf7,
+ 0xba, 0x2b, 0x71, 0xd4, 0x8f, 0x5b, 0xbf, 0x2f, 0xce, 0x36, 0xb4, 0x62,
+ 0x2e, 0xe9, 0x3e, 0x19, 0xb6, 0xc7, 0xb1, 0x25, 0xf1, 0xfa, 0xfb, 0x1a,
+ 0xd6, 0x4e, 0x71, 0xf5, 0xdc, 0xa3, 0x82, 0x72, 0x17, 0x3f, 0x8c, 0xb0,
+ 0xf0, 0x99, 0xd4, 0x63, 0xf4, 0x5e, 0x28, 0x48, 0x04, 0x63, 0xd7, 0x96,
+ 0x07, 0xb9, 0x41, 0x1c, 0xc3, 0x46, 0xd8, 0x6e, 0x4e, 0x76, 0xc0, 0xb4,
+ 0xff, 0xf6, 0x01, 0xb6, 0x39, 0x71, 0x7d, 0x60, 0xa9, 0x69, 0x70, 0xf3,
+ 0xeb, 0xf4, 0x72, 0x7e, 0xd3, 0x85, 0xa2, 0x3a, 0xd3, 0xfe, 0x06, 0xde,
+ 0xa8, 0x55, 0xc5, 0xd6, 0x9c, 0xe7, 0x3f, 0x5a, 0x7f, 0xd4, 0x5f, 0xce,
+ 0x0d, 0x6d, 0xb6, 0xad, 0x14, 0x7b, 0xf7, 0x1e, 0x9f, 0xfe, 0x06, 0x7f,
+ 0x81, 0xb6, 0x41, 0xcb, 0xf2, 0xeb, 0x46, 0x26, 0x77, 0xd2, 0xdd, 0x42,
+ 0x70, 0x44, 0x33, 0xf9, 0x81, 0xe1, 0x98, 0x25, 0xa7, 0xf3, 0xf3, 0xf7,
+ 0x06, 0xb1, 0x69, 0xff, 0xec, 0xdb, 0x07, 0x73, 0x7a, 0x2f, 0x8b, 0xab,
+ 0x4f, 0xe6, 0x3d, 0xef, 0x41, 0x62, 0xd3, 0xea, 0xbe, 0x06, 0xd6, 0x9d,
+ 0xba, 0xf3, 0xad, 0x3f, 0xb7, 0xa2, 0x30, 0xa8, 0x96, 0x8f, 0x51, 0xe9,
+ 0xa4, 0xd0, 0x32, 0xd9, 0x2f, 0x23, 0xf3, 0xfb, 0x91, 0x36, 0x8a, 0x9e,
+ 0xb4, 0xff, 0x77, 0x36, 0xce, 0xc8, 0x04, 0xb4, 0xff, 0xfd, 0xcb, 0x6e,
+ 0xf8, 0x1e, 0x3e, 0xc5, 0xe8, 0x53, 0xd6, 0x82, 0x44, 0x98, 0x1c, 0x4f,
+ 0xff, 0xc1, 0x97, 0xe7, 0xc6, 0x6a, 0x83, 0x1c, 0x7b, 0x70, 0xb4, 0xff,
+ 0xb2, 0xfc, 0xe7, 0xfb, 0x55, 0xd5, 0x44, 0x0d, 0x3d, 0xbd, 0x53, 0xfc,
+ 0x22, 0x98, 0x17, 0x21, 0x93, 0x02, 0xc8, 0x63, 0xcf, 0xfa, 0xbf, 0x80,
+ 0x2b, 0xee, 0xfc, 0x2d, 0x3f, 0xff, 0xff, 0x66, 0xf5, 0x40, 0x3f, 0x8b,
+ 0xfe, 0xab, 0x6e, 0xf3, 0xdf, 0x18, 0x7a, 0x0e, 0x1e, 0xb8, 0x82, 0xe7,
+ 0xfd, 0x54, 0x3f, 0x6b, 0xdf, 0x03, 0xda, 0xb8, 0x82, 0xe7, 0xfe, 0xd1,
+ 0x68, 0x98, 0x37, 0xe0, 0x7b, 0x57, 0x10, 0x5c, 0xfe, 0x62, 0x0d, 0xf8,
+ 0x1e, 0xd5, 0xc4, 0x17, 0x3f, 0x1f, 0x3d, 0xf0, 0x3d, 0xab, 0x88, 0x2e,
+ 0x7f, 0xff, 0xa8, 0x00, 0x8f, 0xe2, 0xfd, 0xd1, 0x7c, 0x87, 0xb3, 0x2d,
+ 0x5c, 0x41, 0x73, 0x71, 0xe3, 0xd4, 0xe6, 0x7a, 0xa1, 0xf5, 0x3a, 0x42,
+ 0x03, 0xf8, 0x65, 0x59, 0x7a, 0x3e, 0x09, 0x46, 0x93, 0xf8, 0x98, 0x7b,
+ 0xee, 0xfc, 0x2d, 0x3d, 0x5f, 0x15, 0x2d, 0x3f, 0xf6, 0x8b, 0x44, 0xc1,
+ 0xbf, 0x03, 0xda, 0xb8, 0x82, 0xe7, 0xf9, 0xcb, 0xf4, 0xac, 0xf0, 0x3d,
+ 0xab, 0x88, 0x2e, 0x7d, 0xbb, 0xb1, 0xfc, 0x75, 0x13, 0xe3, 0x29, 0xcf,
+ 0xfe, 0xf1, 0xdd, 0x17, 0x5b, 0x77, 0xf0, 0x3d, 0xab, 0x88, 0x2e, 0x7f,
+ 0xff, 0xe0, 0x02, 0x3f, 0x8e, 0x73, 0xc5, 0xfb, 0xa2, 0xf9, 0x0f, 0x66,
+ 0x5a, 0xb8, 0x82, 0xe3, 0x13, 0x24, 0xe1, 0x0e, 0x97, 0x67, 0xfb, 0x45,
+ 0xf2, 0x1e, 0xcc, 0xb5, 0x71, 0x05, 0xcf, 0xff, 0x55, 0x70, 0xfb, 0xe8,
+ 0xbd, 0xf5, 0xbe, 0xc9, 0x4f, 0xfb, 0x1e, 0xfe, 0x6f, 0xf0, 0xb3, 0xc9,
+ 0x71, 0x05, 0xc7, 0x51, 0xcf, 0xf4, 0x7b, 0xa8, 0x4f, 0xfb, 0xa5, 0xfd,
+ 0xd0, 0xaf, 0xe2, 0xd5, 0xc4, 0x17, 0x3f, 0x68, 0xb5, 0xa2, 0x12, 0xa0,
+ 0x0b, 0x9f, 0x60, 0xbc, 0x0f, 0x6a, 0xe2, 0x0b, 0x9b, 0x37, 0xd3, 0xf1,
+ 0xd1, 0xcc, 0x70, 0x8e, 0xcb, 0xc2, 0xfe, 0x7e, 0x3e, 0x7b, 0xe0, 0x7b,
+ 0x57, 0x10, 0x5c, 0xff, 0xbb, 0xa2, 0xf9, 0x0f, 0x66, 0x5a, 0xb8, 0x82,
+ 0xe6, 0xcf, 0x14, 0x88, 0xcb, 0x9f, 0xcf, 0xee, 0x48, 0xf4, 0x1c, 0x3d,
+ 0x71, 0x05, 0xcf, 0xfb, 0x09, 0xde, 0x06, 0x7b, 0x4f, 0x5c, 0x41, 0x67,
+ 0x3c, 0x08, 0xf5, 0x78, 0x03, 0xe6, 0xe2, 0x34, 0x08, 0xf8, 0xef, 0x18,
+ 0xbe, 0xe3, 0x1c, 0xe6, 0x16, 0xb6, 0xb7, 0xcf, 0x85, 0x71, 0x09, 0x95,
+ 0x10, 0x59, 0x91, 0x1b, 0x3f, 0xec, 0x7e, 0xa9, 0xee, 0xae, 0xbc, 0xd8,
+ 0xb4, 0xe3, 0xb3, 0xd6, 0x9f, 0x67, 0xba, 0xe6, 0xd5, 0xa5, 0xfa, 0x3c,
+ 0x50, 0x1b, 0x9c, 0x5e, 0x58, 0xb4, 0xea, 0xf8, 0x96, 0x97, 0x0c, 0x6e,
+ 0x36, 0x3b, 0x3f, 0x65, 0x95, 0xa6, 0xf3, 0xad, 0x04, 0x8b, 0x5a, 0x5e,
+ 0x02, 0x79, 0xd5, 0xfb, 0x16, 0x98, 0x4c, 0xb4, 0xf1, 0x31, 0xf1, 0x68,
+ 0x5a, 0x7e, 0xa1, 0xf6, 0xdf, 0x12, 0xd1, 0xe9, 0xb7, 0x00, 0xa9, 0xff,
+ 0xfc, 0xc5, 0xe8, 0x37, 0x3d, 0xde, 0x77, 0xd6, 0xe8, 0xc7, 0x5a, 0x61,
+ 0x32, 0xd3, 0x30, 0xeb, 0x4f, 0xf6, 0x6e, 0xec, 0x71, 0xb1, 0xc5, 0xa7,
+ 0xf5, 0xf3, 0x45, 0x7e, 0x6c, 0x5a, 0x6b, 0x6d, 0x4a, 0x7f, 0x83, 0x1d,
+ 0xd3, 0xee, 0x5e, 0xad, 0x1d, 0x4f, 0xcc, 0x87, 0x3e, 0x2a, 0x75, 0x6d,
+ 0x10, 0x89, 0x8b, 0xcd, 0x8a, 0x80, 0xb5, 0xce, 0x6d, 0x34, 0x18, 0x62,
+ 0x75, 0xb6, 0xda, 0x94, 0x8e, 0x91, 0x8b, 0xf9, 0xf5, 0x39, 0x55, 0xf4,
+ 0x8c, 0x8d, 0xd1, 0xa1, 0x7d, 0x3f, 0xb8, 0xdb, 0x66, 0xb2, 0xc5, 0xa1,
+ 0x9b, 0x38, 0xec, 0x8d, 0x94, 0x74, 0x2e, 0x0b, 0xca, 0x32, 0x6f, 0xa5,
+ 0xea, 0x3c, 0x7a, 0xa4, 0xbf, 0x82, 0x35, 0xe3, 0x40, 0xe6, 0x57, 0xeb,
+ 0xb4, 0xb9, 0xec, 0xeb, 0x6d, 0x69, 0xec, 0x3e, 0x6d, 0x69, 0xff, 0xb5,
+ 0xcd, 0x9c, 0x9b, 0x45, 0xda, 0xfa, 0xd3, 0xd5, 0x60, 0xcf, 0x5a, 0x19,
+ 0x15, 0x5c, 0x10, 0x6c, 0x81, 0xd5, 0x1e, 0x7e, 0x0e, 0x7d, 0x3d, 0x3d,
+ 0x69, 0xff, 0xee, 0x1e, 0x0d, 0xe0, 0xe0, 0xc3, 0xec, 0xac, 0x5a, 0x7f,
+ 0x5f, 0x6e, 0xf0, 0x33, 0xd5, 0xa1, 0x91, 0x68, 0x45, 0xd4, 0xa5, 0x3a,
+ 0xbc, 0x0c, 0xb4, 0xff, 0xf0, 0x3f, 0xc6, 0x7a, 0x57, 0xe3, 0x7c, 0xd5,
+ 0xd6, 0x9f, 0x78, 0xd3, 0x7d, 0xeb, 0x47, 0x84, 0x4d, 0x60, 0xf5, 0xaa,
+ 0x73, 0xf5, 0x8e, 0x3f, 0xcc, 0xfd, 0x8b, 0x4c, 0xfb, 0x16, 0x9f, 0x6b,
+ 0x09, 0xf7, 0x5a, 0x7f, 0xfb, 0x4c, 0x31, 0xb6, 0x14, 0x2b, 0xdd, 0x84,
+ 0x94, 0xfe, 0x16, 0x7f, 0xb5, 0x5d, 0x5c, 0x40, 0x93, 0xb6, 0x56, 0x2d,
+ 0x0f, 0x46, 0x7f, 0xa4, 0xdf, 0x4f, 0x39, 0xf4, 0xce, 0xaf, 0x5a, 0x7b,
+ 0x76, 0x50, 0x2d, 0x3d, 0xc5, 0xeb, 0x6b, 0x45, 0x87, 0xb9, 0x83, 0x3a,
+ 0x21, 0x9f, 0xc1, 0x56, 0xde, 0xec, 0x25, 0xa7, 0x5b, 0x6d, 0xab, 0xab,
+ 0xea, 0x75, 0x07, 0xa9, 0xab, 0xe8, 0x63, 0x59, 0x1e, 0xa2, 0x5c, 0x4b,
+ 0xd3, 0xff, 0xec, 0x02, 0x1c, 0xd7, 0xde, 0xb9, 0xa7, 0xbd, 0x96, 0x8b,
+ 0x0f, 0xe4, 0x72, 0x49, 0xec, 0xf6, 0x9e, 0xb4, 0xfa, 0x80, 0x08, 0xeb,
+ 0x43, 0xa0, 0xad, 0x79, 0xe6, 0xd9, 0x0e, 0x62, 0x84, 0xd5, 0x46, 0x7e,
+ 0x22, 0x40, 0x21, 0x9f, 0x16, 0xdb, 0x77, 0x4a, 0x7b, 0xad, 0xbb, 0xa5,
+ 0x35, 0xb6, 0xa5, 0x0f, 0x3d, 0xfc, 0x26, 0xb4, 0x86, 0x6c, 0xb5, 0x23,
+ 0x1a, 0xf9, 0xff, 0xf6, 0x6d, 0xbb, 0x98, 0x1b, 0xd1, 0x30, 0x58, 0xb4,
+ 0x08, 0xfd, 0xed, 0x26, 0x9f, 0xff, 0xcc, 0xec, 0x80, 0x5e, 0x37, 0x7c,
+ 0xee, 0xa8, 0x37, 0x75, 0xa7, 0xcf, 0xd7, 0x2d, 0xf5, 0xa7, 0xfe, 0xa3,
+ 0xfd, 0x9d, 0x93, 0xb0, 0xe6, 0xeb, 0x47, 0x07, 0xdf, 0xa2, 0x89, 0xff,
+ 0x66, 0x39, 0xfc, 0xe4, 0xed, 0x75, 0xa1, 0xc3, 0xe1, 0xf9, 0x1c, 0xe7,
+ 0xd7, 0xd6, 0x9f, 0x3f, 0x37, 0x9e, 0xa5, 0x22, 0x70, 0xf0, 0xb6, 0x37,
+ 0x3d, 0xb1, 0xf3, 0x4b, 0x4c, 0x26, 0x5a, 0x61, 0x32, 0xd3, 0xee, 0x5f,
+ 0x80, 0x62, 0x35, 0x42, 0x15, 0x86, 0x44, 0x48, 0x26, 0x4f, 0xff, 0x60,
+ 0x57, 0x17, 0x1c, 0x7a, 0xf1, 0xd3, 0x89, 0x69, 0xff, 0xb7, 0xac, 0x38,
+ 0xcc, 0x2c, 0xe3, 0x6b, 0x4f, 0xee, 0x3a, 0x5f, 0x19, 0xbd, 0x5a, 0x78,
+ 0x47, 0xa7, 0xf8, 0x46, 0x6d, 0xd4, 0xf6, 0x8b, 0x3b, 0xcb, 0x38, 0x5a,
+ 0x78, 0x5f, 0x2f, 0xad, 0x0c, 0x88, 0x9a, 0x49, 0xb4, 0x7e, 0x7a, 0xfc,
+ 0xf1, 0xb5, 0xa7, 0x5b, 0x6d, 0xa9, 0x4f, 0xb0, 0x70, 0xe6, 0xe9, 0x18,
+ 0xbf, 0x9f, 0x61, 0xad, 0xb6, 0xd5, 0xa1, 0x8f, 0x87, 0x66, 0xf3, 0xff,
+ 0x60, 0x65, 0xfb, 0xa2, 0xeb, 0x02, 0xd3, 0xd6, 0xd0, 0x3d, 0x69, 0xfe,
+ 0xdb, 0x70, 0x2a, 0xd6, 0x89, 0x69, 0x69, 0x68, 0xc3, 0xc8, 0xe9, 0xc4,
+ 0xeb, 0x6d, 0xb5, 0x29, 0xf8, 0xa8, 0x7d, 0x16, 0xd2, 0x31, 0x7f, 0x3e,
+ 0xc1, 0x66, 0x38, 0xb4, 0xaf, 0xe1, 0x14, 0x3f, 0x40, 0x03, 0xb9, 0xb9,
+ 0x7f, 0xa9, 0xa0, 0xe4, 0x61, 0x52, 0x2d, 0x27, 0x70, 0x11, 0xc0, 0xcf,
+ 0x57, 0xcb, 0x4b, 0x43, 0x2f, 0x6e, 0x3c, 0x8f, 0x23, 0x32, 0x1d, 0x97,
+ 0xf0, 0xb1, 0xd4, 0x6e, 0xf4, 0x5f, 0x78, 0x52, 0x6e, 0x3d, 0x9f, 0x22,
+ 0xe9, 0xf9, 0x8f, 0xff, 0xd6, 0xd6, 0x9f, 0xfe, 0x23, 0xf0, 0xfb, 0xf8,
+ 0xc0, 0x0c, 0x21, 0x2d, 0x1a, 0x3f, 0xbd, 0x96, 0x48, 0xce, 0x94, 0x2a,
+ 0xdd, 0xdd, 0x39, 0x4f, 0x9a, 0x50, 0x3c, 0xd6, 0x54, 0xd3, 0x9a, 0xd6,
+ 0x4a, 0x4c, 0x7c, 0xae, 0xcf, 0x65, 0xc7, 0xe5, 0x77, 0x8c, 0x3c, 0x79,
+ 0xfd, 0x97, 0x31, 0xc4, 0xbd, 0xa2, 0x96, 0x16, 0xe4, 0xfa, 0xaf, 0xe7,
+ 0x84, 0xcf, 0x2c, 0x9f, 0x54, 0x98, 0xaa, 0xac, 0x5d, 0x85, 0x2f, 0xfc,
+ 0x29, 0x19, 0xb7, 0xad, 0xcb, 0xf7, 0x5a, 0xa2, 0x73, 0x1b, 0xe3, 0xb8,
+ 0x7a, 0x5b, 0x0c, 0x7f, 0x29, 0x72, 0x03, 0x52, 0x16, 0x1d, 0x63, 0x26,
+ 0x83, 0x42, 0xb9, 0xa9, 0xf8, 0xac, 0x0b, 0x9f, 0xc6, 0xcf, 0xf6, 0xab,
+ 0xaa, 0x8b, 0x8e, 0x7f, 0x1b, 0x3f, 0xda, 0xae, 0xaa, 0x2e, 0xb9, 0xff,
+ 0x8d, 0x4f, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x4a, 0x30, 0xd0, 0xb1, 0xef,
+ 0x79, 0xcf, 0xa7, 0xc3, 0x9f, 0x74, 0xf8, 0xa1, 0xf5, 0xe7, 0x40, 0xac,
+ 0x57, 0x5f, 0xdc, 0xe3, 0x67, 0xce, 0xa7, 0xd3, 0xff, 0x8c, 0x7a, 0x79,
+ 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x5a, 0x9f, 0x7f, 0xb5, 0x5d, 0x54, 0x46,
+ 0xf3, 0xfe, 0xa7, 0x9b, 0x3f, 0xda, 0xae, 0xaa, 0x25, 0xf9, 0x1b, 0x0f,
+ 0xf0, 0xe6, 0x73, 0xf8, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x55, 0xce, 0x07,
+ 0x5b, 0x56, 0x9f, 0xe1, 0xf0, 0x33, 0x8d, 0xd1, 0xd6, 0x9b, 0xd2, 0x5a,
+ 0x7e, 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0x02, 0x3c, 0x1e, 0x71, 0x85, 0xa7,
+ 0xd7, 0xa0, 0xae, 0x16, 0x87, 0x9e, 0x57, 0x04, 0x93, 0xfd, 0x9f, 0xb0,
+ 0xec, 0x0f, 0xba, 0xd3, 0xff, 0xb1, 0xcd, 0x51, 0xf7, 0xa6, 0xdf, 0x27,
+ 0x5a, 0x3d, 0x4e, 0x54, 0x71, 0xfa, 0x86, 0x80, 0x11, 0x8c, 0x71, 0x3f,
+ 0xf0, 0x65, 0x86, 0xf2, 0x60, 0x0c, 0xda, 0xd0, 0x64, 0x4a, 0xfd, 0x46,
+ 0x7f, 0x1b, 0x3f, 0xda, 0xae, 0xaa, 0x2c, 0x89, 0xfc, 0x6c, 0xff, 0x6a,
+ 0xba, 0xa8, 0xb5, 0xe7, 0xf1, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0xe4, 0x9f,
+ 0x7f, 0xb5, 0x5d, 0x54, 0x5d, 0x93, 0xfe, 0xa7, 0x9b, 0x3f, 0xda, 0xae,
+ 0xaa, 0x28, 0xe9, 0x1b, 0x0f, 0xf0, 0xe6, 0x72, 0x7a, 0xd3, 0xef, 0xf6,
+ 0xab, 0xaa, 0x8a, 0x56, 0x7f, 0xff, 0xfb, 0x4d, 0x63, 0x68, 0x9d, 0xd7,
+ 0xba, 0x23, 0x77, 0x44, 0xe6, 0x9a, 0xcc, 0x5a, 0x67, 0x9b, 0x11, 0x66,
+ 0xe1, 0x9c, 0xc6, 0x3f, 0x08, 0xf2, 0xa8, 0x61, 0xc5, 0x8b, 0xc0, 0xcf,
+ 0x86, 0x8f, 0x04, 0xe5, 0x29, 0xa0, 0xe4, 0x62, 0x3e, 0xb9, 0xf6, 0xe1,
+ 0x74, 0xee, 0x31, 0x99, 0xfe, 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x38,
+ 0x9f, 0xe2, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x56, 0xb2, 0x35, 0x22, 0x1f,
+ 0x68, 0x93, 0xff, 0x8c, 0x7a, 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x5b,
+ 0x9b, 0x38, 0x5a, 0x7f, 0x7b, 0x87, 0x3b, 0x15, 0xd6, 0x8e, 0x0f, 0x20,
+ 0x85, 0xa7, 0x6b, 0xd7, 0xad, 0x39, 0xe7, 0xea, 0xd3, 0xff, 0xf6, 0xab,
+ 0x81, 0x7b, 0xaa, 0x7e, 0x5c, 0x39, 0xa1, 0x96, 0x85, 0x44, 0x37, 0x3f,
+ 0xea, 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x60, 0x9b, 0xb8, 0xb4, 0xdc,
+ 0x89, 0x28, 0x23, 0x59, 0xf1, 0x59, 0xfc, 0x19, 0xbd, 0xb7, 0xee, 0xb4,
+ 0x8c, 0xc9, 0xca, 0xd8, 0x45, 0xe8, 0xee, 0x0e, 0x75, 0x74, 0xe2, 0xfb,
+ 0x75, 0x18, 0x82, 0x71, 0xf9, 0xfa, 0x53, 0xfe, 0xa7, 0x9b, 0x3f, 0xda,
+ 0xae, 0xaa, 0x26, 0x39, 0x18, 0x8f, 0x98, 0xe3, 0xb3, 0xf3, 0x5f, 0xc6,
+ 0xf3, 0x4b, 0x4e, 0x60, 0xb1, 0x69, 0xff, 0xff, 0xe7, 0xdf, 0x59, 0xcd,
+ 0xb7, 0xd6, 0x77, 0x2f, 0xe3, 0x38, 0x7d, 0xc8, 0x09, 0x69, 0xee, 0xd5,
+ 0x75, 0x51, 0x58, 0xcf, 0xfb, 0xcb, 0x36, 0x19, 0xcb, 0x06, 0xd6, 0x81,
+ 0xd3, 0x35, 0xe9, 0x77, 0x03, 0x7f, 0x84, 0x06, 0xcb, 0x67, 0xff, 0x30,
+ 0x6c, 0x7e, 0x58, 0x33, 0xad, 0xf5, 0xa7, 0xfb, 0xdd, 0x65, 0xf8, 0x7b,
+ 0x69, 0x69, 0xfe, 0x6e, 0x1e, 0xe3, 0xeb, 0xf6, 0x2d, 0x18, 0x7e, 0xa4,
+ 0x75, 0x3f, 0xec, 0xf7, 0xe5, 0xcd, 0x82, 0xbb, 0xd6, 0x9f, 0xff, 0xf8,
+ 0x39, 0xb3, 0x3b, 0xe0, 0x39, 0x75, 0xf1, 0x9c, 0x3f, 0x39, 0x01, 0x5d,
+ 0x69, 0xfc, 0xe8, 0x58, 0xe3, 0xfc, 0xcf, 0xd8, 0xb4, 0xff, 0xec, 0x73,
+ 0x54, 0x7d, 0xe9, 0xb7, 0xc9, 0xd6, 0x9d, 0xa2, 0x36, 0x2a, 0x78, 0xea,
+ 0x96, 0xa1, 0x7a, 0x04, 0x1b, 0x41, 0xf2, 0x7c, 0x19, 0x06, 0x61, 0x84,
+ 0xb4, 0xdc, 0xb8, 0xb4, 0xfa, 0x82, 0xce, 0x6e, 0xb4, 0x08, 0xf5, 0xc0,
+ 0x5e, 0xe3, 0x13, 0xae, 0x35, 0xd6, 0x9e, 0xe2, 0xc6, 0x1d, 0x68, 0xf4,
+ 0xf0, 0x79, 0x1d, 0x9f, 0x1f, 0x01, 0x9e, 0xb4, 0xf3, 0x7e, 0x81, 0x69,
+ 0xeb, 0xdd, 0x84, 0xb4, 0x31, 0xf2, 0xe8, 0x96, 0xd1, 0xf9, 0xf3, 0x3c,
+ 0x5c, 0xbd, 0x69, 0xcc, 0x0f, 0x5a, 0x1c, 0x3c, 0x2d, 0x94, 0x4e, 0xd0,
+ 0xc7, 0x5a, 0x7e, 0x63, 0xe0, 0x10, 0xeb, 0x4a, 0xeb, 0x41, 0x1b, 0xba,
+ 0x2b, 0x98, 0x4c, 0x94, 0xd6, 0xda, 0x94, 0x11, 0xad, 0xb4, 0x56, 0x7f,
+ 0x53, 0xc3, 0x37, 0xa2, 0x48, 0xc6, 0x86, 0x7b, 0xda, 0xe2, 0xeb, 0x4e,
+ 0x60, 0x71, 0x69, 0x81, 0x96, 0x87, 0x0d, 0x7f, 0xc6, 0xe7, 0xfe, 0x1c,
+ 0x83, 0xb7, 0x63, 0xd7, 0x1b, 0x5a, 0x70, 0xb1, 0xd5, 0x68, 0x1c, 0xf8,
+ 0xbe, 0x89, 0x21, 0xd6, 0x9b, 0xe3, 0xad, 0x04, 0x6a, 0x06, 0x11, 0x9f,
+ 0xfd, 0xb6, 0x79, 0x6f, 0x59, 0xc6, 0xf9, 0x65, 0xa5, 0x8b, 0x41, 0x1e,
+ 0xcf, 0x92, 0x54, 0x32, 0x77, 0xf8, 0xa4, 0x50, 0x84, 0xd2, 0x5d, 0x3d,
+ 0x42, 0xd2, 0x3a, 0xd2, 0xd6, 0xcb, 0xa7, 0x61, 0x53, 0xf0, 0x9b, 0x58,
+ 0xee, 0x96, 0x9f, 0x8b, 0x79, 0xaa, 0x1d, 0x69, 0xd6, 0xdb, 0x6a, 0x53,
+ 0xff, 0x67, 0x7d, 0x6b, 0x06, 0xcd, 0x57, 0x09, 0x18, 0xbf, 0x9e, 0x2f,
+ 0xba, 0xfa, 0xb4, 0xbe, 0xb4, 0xf8, 0xe5, 0xb1, 0x52, 0xd1, 0x61, 0xed,
+ 0xf9, 0xc9, 0x79, 0x10, 0x9f, 0xdd, 0x2b, 0x86, 0x3b, 0xa5, 0xa6, 0xcd,
+ 0xad, 0x1c, 0x1e, 0x3e, 0x8c, 0xa7, 0xb6, 0x18, 0xf5, 0xa7, 0xff, 0x15,
+ 0xf5, 0x9e, 0x86, 0x3b, 0x0c, 0xba, 0xd1, 0xf3, 0xe9, 0xd9, 0x04, 0x8c,
+ 0xcb, 0xe6, 0x16, 0x37, 0xfb, 0x08, 0x9c, 0x71, 0x22, 0x3f, 0xac, 0x1d,
+ 0xb7, 0x51, 0xff, 0xd3, 0x30, 0x8a, 0x3c, 0xd9, 0x68, 0x25, 0xde, 0x16,
+ 0x1b, 0x7c, 0x1a, 0x11, 0x93, 0xef, 0xf6, 0xab, 0xaa, 0x8a, 0xde, 0x7f,
+ 0xd4, 0xf3, 0x67, 0xfb, 0x55, 0xd5, 0x44, 0xe1, 0x23, 0x61, 0xfe, 0x1c,
+ 0xce, 0x6e, 0x74, 0xb4, 0xfb, 0xfd, 0xaa, 0xea, 0xa2, 0xd1, 0x9f, 0x9a,
+ 0x83, 0x9f, 0x71, 0x69, 0x88, 0x75, 0xa7, 0xff, 0xd6, 0x36, 0xdb, 0xdf,
+ 0xb6, 0xaa, 0xe1, 0x82, 0x5a, 0x7f, 0xcd, 0xc5, 0x79, 0xf4, 0x15, 0xe7,
+ 0xb1, 0x68, 0x64, 0x4d, 0x69, 0x52, 0x58, 0xe2, 0x34, 0xaf, 0x0b, 0x09,
+ 0x19, 0xd2, 0x4d, 0xdb, 0x05, 0xce, 0x67, 0xa8, 0x7f, 0x4f, 0x76, 0xab,
+ 0xaa, 0x8b, 0x6a, 0x7e, 0xd3, 0x1d, 0x8b, 0xd5, 0xa3, 0xe7, 0xb3, 0xb2,
+ 0xd9, 0xfe, 0x6f, 0xf8, 0xbb, 0x6a, 0x89, 0x68, 0xc3, 0xda, 0xb4, 0x8a,
+ 0x7e, 0x1e, 0xbf, 0xef, 0x20, 0xb4, 0xfa, 0xb8, 0x78, 0xd7, 0x5a, 0x46,
+ 0x1c, 0xf6, 0x1d, 0x97, 0xc1, 0x91, 0x4a, 0x27, 0xa9, 0xfc, 0x6c, 0xff,
+ 0x6a, 0xba, 0xa8, 0xb9, 0x67, 0xf1, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0xed,
+ 0x86, 0x6d, 0x17, 0x6c, 0x28, 0x7c, 0xa3, 0x2f, 0x61, 0xbe, 0x3c, 0xbd,
+ 0x42, 0xa4, 0x02, 0xf9, 0xe3, 0x6a, 0xd4, 0x73, 0xa1, 0x1d, 0x2d, 0xc8,
+ 0xf6, 0x7d, 0x3f, 0x8d, 0x9f, 0xed, 0x57, 0x55, 0x15, 0x3c, 0xc5, 0xb5,
+ 0xa7, 0xbb, 0x55, 0xd5, 0x45, 0x73, 0x3f, 0x8d, 0x9f, 0xed, 0x57, 0x55,
+ 0x16, 0x74, 0x7c, 0xfa, 0xf4, 0x5b, 0x3f, 0xfd, 0x9b, 0x6b, 0xf8, 0xe6,
+ 0xfb, 0x67, 0x1c, 0x25, 0xa7, 0xfd, 0xa2, 0xff, 0xba, 0xc2, 0x01, 0xd6,
+ 0x9e, 0xa0, 0x6f, 0x56, 0x9f, 0x7f, 0xb5, 0x5d, 0x54, 0x48, 0x53, 0xfc,
+ 0x5c, 0x5f, 0x60, 0xc7, 0xba, 0xd3, 0x3c, 0xd8, 0x7d, 0x62, 0x33, 0x9e,
+ 0x74, 0xb4, 0xc7, 0x5a, 0x7f, 0x66, 0xaf, 0x7c, 0xfd, 0x8b, 0x48, 0xde,
+ 0xaa, 0x44, 0xc8, 0x40, 0x11, 0x13, 0x8a, 0x67, 0x3e, 0xa8, 0x45, 0xdc,
+ 0xb7, 0x64, 0xd3, 0xff, 0x8c, 0x7a, 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2,
+ 0x7c, 0x8e, 0xab, 0x59, 0xf3, 0xca, 0x82, 0xd4, 0x20, 0xa7, 0xdf, 0xed,
+ 0x57, 0x55, 0x15, 0x94, 0xff, 0xa9, 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x89,
+ 0xba, 0x62, 0x36, 0x1f, 0xe1, 0xcc, 0xe7, 0xff, 0x18, 0xf4, 0xf3, 0x67,
+ 0xfb, 0x55, 0xd5, 0x44, 0xad, 0x3f, 0xe2, 0xbf, 0x27, 0x02, 0x77, 0xcd,
+ 0x2d, 0x3f, 0x81, 0xbf, 0x8e, 0xe8, 0xeb, 0x43, 0xcf, 0xc8, 0x90, 0x27,
+ 0xdf, 0xed, 0x57, 0x55, 0x12, 0xe4, 0xff, 0x15, 0x3f, 0x60, 0xc7, 0xba,
+ 0xd3, 0xce, 0xc8, 0x19, 0x69, 0xf1, 0x8f, 0x4f, 0x33, 0x22, 0xaf, 0x08,
+ 0x74, 0x67, 0x46, 0xd3, 0xff, 0x1a, 0x9e, 0x6c, 0xff, 0x6a, 0xba, 0xa8,
+ 0x8e, 0xe7, 0xfb, 0x7a, 0xc7, 0x9a, 0x82, 0xeb, 0x4f, 0xde, 0x60, 0x37,
+ 0x70, 0x16, 0x9b, 0x9d, 0x2d, 0x3f, 0x3a, 0x21, 0x9a, 0xad, 0xad, 0x3f,
+ 0xb2, 0xdb, 0xb0, 0x6e, 0xeb, 0x4f, 0xbf, 0xda, 0xae, 0xaa, 0x2a, 0x19,
+ 0x9f, 0x8b, 0x4f, 0x6b, 0x79, 0x62, 0xd3, 0xec, 0xb2, 0x81, 0xda, 0xd3,
+ 0xff, 0xff, 0xf9, 0x9f, 0xe3, 0x7a, 0x26, 0xbf, 0x8c, 0xe7, 0xac, 0xef,
+ 0xc6, 0x7f, 0xf8, 0xef, 0x9a, 0xd2, 0xd1, 0x88, 0xe2, 0x02, 0x2b, 0x94,
+ 0x4f, 0xff, 0xf7, 0x35, 0xe7, 0x2b, 0x35, 0x45, 0xb6, 0xd1, 0x6e, 0xf9,
+ 0xea, 0xd2, 0x33, 0xa2, 0xa9, 0xa9, 0xd2, 0x2f, 0xf3, 0x05, 0xec, 0x30,
+ 0xc3, 0x2e, 0x99, 0xee, 0x1e, 0xfe, 0x45, 0xd3, 0xef, 0xf6, 0xab, 0xaa,
+ 0x8a, 0xa2, 0x7f, 0xd4, 0xf3, 0x67, 0xfb, 0x55, 0xd5, 0x44, 0xd7, 0x23,
+ 0x61, 0xfe, 0x1c, 0xce, 0x7f, 0x1b, 0x3f, 0xda, 0xae, 0xaa, 0x2a, 0xc9,
+ 0xff, 0x1b, 0x4d, 0xc6, 0xdb, 0x55, 0xe7, 0x5a, 0x7f, 0xe3, 0x53, 0xcd,
+ 0x9f, 0xed, 0x57, 0x55, 0x12, 0x24, 0xfb, 0xfd, 0xaa, 0xea, 0xa2, 0xd2,
+ 0x9f, 0xf5, 0x3c, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x3e, 0xc8, 0xd8, 0x7f,
+ 0x87, 0x33, 0x9f, 0xfc, 0x63, 0xd3, 0xcd, 0x9f, 0xed, 0x57, 0x55, 0x14,
+ 0x24, 0xfb, 0x45, 0x63, 0x7d, 0x69, 0xf7, 0xfb, 0x55, 0xd5, 0x45, 0x1f,
+ 0x3f, 0xe0, 0x67, 0x18, 0x19, 0xcd, 0x32, 0xd3, 0xff, 0xf6, 0x7b, 0xa6,
+ 0x18, 0xdb, 0x0a, 0x15, 0xee, 0xc2, 0x4a, 0x7c, 0x63, 0xd3, 0xcc, 0xc8,
+ 0xf1, 0xc2, 0x7d, 0x99, 0xf9, 0x1e, 0x43, 0x32, 0x3f, 0xec, 0x8d, 0xc9,
+ 0xea, 0xf8, 0x9e, 0x3c, 0xaa, 0x1e, 0xc6, 0x19, 0xc1, 0x39, 0x1f, 0x38,
+ 0x85, 0xa8, 0x65, 0x88, 0x9f, 0x71, 0xa3, 0x4f, 0xe3, 0x67, 0xfb, 0x55,
+ 0xd5, 0x44, 0x45, 0x3f, 0x67, 0xfb, 0x55, 0xd5, 0x44, 0x57, 0x3f, 0xde,
+ 0x73, 0x67, 0xfb, 0x55, 0xd5, 0x45, 0x71, 0x06, 0x44, 0x05, 0x1c, 0x4f,
+ 0x66, 0xab, 0x6b, 0x4f, 0xec, 0x2f, 0x88, 0x5c, 0xdd, 0x69, 0x3a, 0x20,
+ 0x7a, 0x77, 0x20, 0x9f, 0xff, 0xb7, 0x72, 0xd5, 0x13, 0xc8, 0x37, 0xce,
+ 0xbf, 0x8b, 0x4f, 0xbf, 0xda, 0xae, 0xaa, 0x29, 0xe9, 0xef, 0x01, 0x4f,
+ 0x5a, 0x7d, 0x59, 0xa2, 0x3a, 0xd2, 0xcb, 0x9e, 0x3b, 0xb2, 0x28, 0xf3,
+ 0x13, 0x28, 0x62, 0xcc, 0x59, 0x07, 0xa9, 0xff, 0xd4, 0xf3, 0x7a, 0x15,
+ 0x6d, 0xee, 0xc2, 0x5a, 0x0c, 0x88, 0xaf, 0x50, 0x27, 0x1b, 0xdc, 0x5a,
+ 0x7f, 0xfd, 0xa6, 0xfe, 0x3c, 0xab, 0x79, 0xe9, 0x73, 0xd5, 0xa7, 0xcc,
+ 0xf1, 0x72, 0xf5, 0xa7, 0xbb, 0x55, 0xd5, 0x45, 0x67, 0x0e, 0x1e, 0xaf,
+ 0xca, 0x27, 0xeb, 0x0e, 0xc0, 0xfb, 0xad, 0x39, 0xac, 0x25, 0xa7, 0xdb,
+ 0x10, 0xc0, 0xf5, 0xa7, 0x73, 0x57, 0x5a, 0x7d, 0x8e, 0x59, 0xc8, 0x96,
+ 0x91, 0xbd, 0x4e, 0x0b, 0x21, 0x53, 0xf2, 0x3d, 0x16, 0xd0, 0xd8, 0x14,
+ 0x0c, 0x39, 0x3f, 0xf1, 0xa9, 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0x16,
+ 0x7e, 0xcf, 0xf6, 0xab, 0xaa, 0x8b, 0x26, 0x7f, 0xf6, 0xee, 0x35, 0xcd,
+ 0x96, 0x10, 0x3e, 0xeb, 0x41, 0x91, 0x07, 0x87, 0x13, 0xf8, 0xd9, 0xfe,
+ 0xd5, 0x75, 0x51, 0x6c, 0x4e, 0xcb, 0xe2, 0xd3, 0xdd, 0xaa, 0xea, 0xa2,
+ 0xdb, 0x9e, 0xbd, 0x95, 0xf5, 0xa3, 0xe7, 0x9f, 0xb2, 0xd9, 0x19, 0xe8,
+ 0x8b, 0xc6, 0x99, 0xd6, 0x68, 0x96, 0x9f, 0xf7, 0x99, 0xe6, 0x3a, 0x7d,
+ 0xeb, 0x01, 0x84, 0xb4, 0xfc, 0xc0, 0xff, 0x79, 0x3a, 0xd3, 0xef, 0xf6,
+ 0xab, 0xaa, 0x8b, 0xc2, 0x7b, 0x7e, 0x59, 0xa5, 0xa7, 0xfe, 0x61, 0x8f,
+ 0xc3, 0xf7, 0x81, 0xbb, 0xad, 0x3e, 0xc0, 0x13, 0xab, 0x2d, 0x3e, 0x61,
+ 0xb9, 0xab, 0xad, 0x3b, 0x6c, 0x25, 0xa4, 0x6f, 0x31, 0x39, 0xef, 0x34,
+ 0x8e, 0x58, 0x9b, 0x85, 0xdc, 0x19, 0xe8, 0x90, 0x48, 0xa0, 0x51, 0xb2,
+ 0x89, 0xc5, 0x9c, 0x2d, 0x3e, 0xff, 0x6a, 0xba, 0xa8, 0xbd, 0x27, 0xfc,
+ 0x15, 0xb7, 0xb0, 0xfb, 0x2b, 0x16, 0x9f, 0x61, 0xf5, 0x5e, 0xad, 0x23,
+ 0x7a, 0x8b, 0x3c, 0x1b, 0x18, 0xcd, 0xd4, 0xfa, 0x19, 0x94, 0x4b, 0x64,
+ 0x2f, 0xb2, 0x51, 0x3f, 0x49, 0x0a, 0x39, 0xef, 0xb7, 0x9e, 0x1a, 0x42,
+ 0x22, 0x08, 0x64, 0xf3, 0x1e, 0x35, 0xb1, 0xa2, 0xcd, 0xce, 0x96, 0x9e,
+ 0xcd, 0x56, 0xd6, 0x9f, 0xd8, 0x5f, 0x10, 0xb9, 0xba, 0xd2, 0x74, 0x40,
+ 0xf4, 0xee, 0x41, 0x3e, 0x2d, 0xb7, 0x16, 0x2d, 0x3e, 0xff, 0x6a, 0xba,
+ 0xa8, 0x88, 0xe7, 0xff, 0xb5, 0xcd, 0xef, 0x87, 0x0c, 0x77, 0xe1, 0x9d,
+ 0x32, 0xd3, 0xfe, 0x7b, 0x59, 0xfc, 0xde, 0xcb, 0x6b, 0x4f, 0xf6, 0x7f,
+ 0x2f, 0x94, 0x16, 0x2d, 0x3f, 0xff, 0xcd, 0xaa, 0x2d, 0xb6, 0x83, 0x37,
+ 0xa2, 0xd6, 0x15, 0xab, 0x4d, 0x61, 0xd2, 0x9a, 0xdb, 0x52, 0x9f, 0xf1,
+ 0xbb, 0xa2, 0x73, 0x4d, 0x61, 0x84, 0x6b, 0xed, 0x17, 0x9e, 0x76, 0xdb,
+ 0x65, 0xa1, 0xe7, 0xf4, 0x4b, 0x13, 0xf7, 0x9c, 0x33, 0x55, 0xb5, 0xa7,
+ 0xe6, 0x1f, 0x00, 0x87, 0x5a, 0x7e, 0xcd, 0xba, 0xef, 0x34, 0xb4, 0x62,
+ 0x22, 0x80, 0xbe, 0xe5, 0x93, 0xff, 0xf7, 0x4d, 0xfa, 0x02, 0xd9, 0xbe,
+ 0xdb, 0x0a, 0x12, 0xd0, 0xe9, 0x2b, 0xfa, 0xf3, 0x1a, 0x98, 0xb3, 0x0a,
+ 0x3a, 0x67, 0xc2, 0xc9, 0x1f, 0x7c, 0xda, 0xa3, 0x0b, 0xdc, 0x2a, 0xdd,
+ 0x97, 0x4f, 0xbf, 0xda, 0xae, 0xaa, 0x22, 0xe9, 0xf6, 0xc4, 0x30, 0x3d,
+ 0x29, 0x1b, 0x0f, 0x6e, 0x8c, 0xe0, 0xc9, 0x97, 0xbe, 0x30, 0x99, 0xff,
+ 0x8f, 0x4f, 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x4c, 0xd3, 0x5d, 0xeb, 0x4f,
+ 0x9d, 0x3b, 0xa3, 0x76, 0xda, 0xd0, 0xe9, 0xcf, 0x23, 0xcd, 0x62, 0xd3,
+ 0xb8, 0x6b, 0xad, 0x3b, 0xa4, 0x75, 0xa6, 0xf2, 0x74, 0x16, 0x9f, 0xfd,
+ 0xa6, 0x3d, 0x6f, 0x38, 0x11, 0xc6, 0xd2, 0xd3, 0xf6, 0xf2, 0xcc, 0x13,
+ 0x8b, 0x4f, 0xf7, 0xbe, 0x30, 0x2b, 0xe2, 0xf2, 0x5a, 0x1d, 0x04, 0x6a,
+ 0x10, 0xf3, 0x89, 0x7a, 0x2e, 0x9f, 0x76, 0xb4, 0x4e, 0x2d, 0x3f, 0xfe,
+ 0x17, 0x0f, 0xd7, 0x2d, 0xf3, 0x68, 0xbb, 0x5f, 0x5a, 0x7f, 0xe7, 0x52,
+ 0xd9, 0x74, 0xbd, 0xde, 0x75, 0x69, 0xff, 0xfe, 0xe6, 0x83, 0xa1, 0x9e,
+ 0xeb, 0x9f, 0x1a, 0x67, 0xfd, 0xac, 0x5a, 0x19, 0x30, 0x7c, 0x57, 0xd2,
+ 0x34, 0xff, 0xfb, 0xd2, 0x0b, 0x32, 0xe5, 0x5a, 0x35, 0xb6, 0xda, 0x94,
+ 0xfd, 0xc3, 0xee, 0x2e, 0x5c, 0x5a, 0x7b, 0xb5, 0x5d, 0x54, 0x59, 0xf3,
+ 0xfe, 0x2d, 0x33, 0xcb, 0x6d, 0xbb, 0xad, 0x3f, 0xfc, 0x5f, 0xd5, 0x78,
+ 0xc7, 0x61, 0x97, 0xc0, 0x5a, 0x75, 0xb6, 0xda, 0x94, 0xff, 0xa9, 0xf7,
+ 0x0c, 0xef, 0xb9, 0xf4, 0x8c, 0x5f, 0xcf, 0xfc, 0xdc, 0x3c, 0x39, 0x17,
+ 0x8e, 0x9c, 0x4b, 0x4f, 0xf3, 0x68, 0xbd, 0x0a, 0xa7, 0x16, 0x9f, 0xe2,
+ 0x0f, 0x46, 0xf7, 0x9d, 0xdd, 0x68, 0xea, 0xa6, 0x77, 0x16, 0x3e, 0x62,
+ 0x72, 0xdd, 0x1e, 0x09, 0xba, 0xe9, 0x9b, 0x48, 0x76, 0x6f, 0x3f, 0xdf,
+ 0xab, 0x74, 0x4d, 0xf6, 0x5a, 0x7f, 0xff, 0xfd, 0x82, 0xbe, 0x60, 0x0e,
+ 0x37, 0xc1, 0xb3, 0x46, 0xb8, 0x65, 0x87, 0xc3, 0xad, 0x3e, 0x77, 0x5a,
+ 0x61, 0x96, 0x8c, 0x45, 0x51, 0x42, 0x06, 0x75, 0xda, 0xc5, 0xa7, 0x79,
+ 0x66, 0x96, 0x87, 0x9f, 0x05, 0xc9, 0xb6, 0x39, 0x3b, 0x5c, 0xda, 0xb4,
+ 0xe1, 0x73, 0xd5, 0xa7, 0x6f, 0x06, 0x5a, 0x3d, 0x3d, 0x7e, 0x07, 0x88,
+ 0x76, 0x7e, 0xf9, 0x3b, 0xc0, 0xba, 0xd3, 0xed, 0x03, 0x67, 0xd4, 0x9f,
+ 0xf1, 0x7d, 0xf9, 0xfb, 0x39, 0xaf, 0x55, 0x10, 0x69, 0x8d, 0x2c, 0xfa,
+ 0xba, 0x47, 0x65, 0xa7, 0xe7, 0xe8, 0x2b, 0x8d, 0xad, 0x2c, 0xe9, 0xe9,
+ 0x01, 0x2c, 0xff, 0xd8, 0x1c, 0x6f, 0x3e, 0x56, 0x51, 0xd6, 0x98, 0x81,
+ 0x69, 0xfa, 0xad, 0xde, 0x6b, 0x6c, 0x7a, 0xe3, 0xa1, 0xc3, 0x27, 0x86,
+ 0xf5, 0x2c, 0x85, 0x78, 0x3e, 0xcf, 0xdf, 0xcf, 0x6f, 0xa6, 0x5a, 0x7f,
+ 0xff, 0x72, 0x14, 0x3f, 0x81, 0x82, 0xb7, 0x72, 0xe3, 0x45, 0x6a, 0xd3,
+ 0xfe, 0x3e, 0x6e, 0xe3, 0x5e, 0x9f, 0x8b, 0x4f, 0xd7, 0xbb, 0x7f, 0x6c,
+ 0xb1, 0x8d, 0xf4, 0xf6, 0xb0, 0x9d, 0xad, 0x3f, 0x5c, 0xbf, 0x9c, 0xfd,
+ 0x68, 0x24, 0x45, 0xe8, 0xf3, 0x64, 0x53, 0x1d, 0xd1, 0x54, 0x5f, 0x93,
+ 0xff, 0x3f, 0x7c, 0xbd, 0xe7, 0xde, 0xd8, 0xeb, 0x4f, 0xfc, 0x58, 0x19,
+ 0x97, 0xf0, 0xfb, 0x9d, 0x68, 0xe1, 0x11, 0x37, 0x46, 0x9c, 0x3b, 0x7d,
+ 0x69, 0xfb, 0xd6, 0x17, 0xf3, 0x85, 0xa0, 0xc7, 0x94, 0x71, 0xc9, 0x89,
+ 0xc5, 0xa7, 0x6c, 0xac, 0x5a, 0x70, 0x37, 0x56, 0x8f, 0x07, 0x98, 0x71,
+ 0x60, 0x1c, 0x86, 0x4f, 0xb3, 0xd2, 0xfc, 0x85, 0x89, 0x37, 0x53, 0x74,
+ 0xf5, 0x6d, 0xb8, 0x5a, 0x7f, 0xff, 0xcd, 0xa2, 0x39, 0x9c, 0x7d, 0x7c,
+ 0x6d, 0x17, 0x17, 0xe9, 0x58, 0xb4, 0x38, 0x89, 0x07, 0x52, 0x19, 0xfa,
+ 0xbe, 0xda, 0x1b, 0xd5, 0xa7, 0xad, 0xac, 0xba, 0xd3, 0xfc, 0xf3, 0xd3,
+ 0xf7, 0x76, 0x1d, 0x68, 0x63, 0xda, 0xa2, 0x19, 0xec, 0xb9, 0x02, 0xd1,
+ 0x48, 0xc7, 0x08, 0x44, 0x72, 0x41, 0x3c, 0x37, 0x35, 0x75, 0xa7, 0x84,
+ 0x2c, 0xe1, 0x69, 0xf9, 0xd7, 0x79, 0x41, 0xd5, 0xa7, 0xfa, 0xe2, 0x2e,
+ 0x38, 0x7e, 0x6d, 0x69, 0xf9, 0xb8, 0xb9, 0xcb, 0xce, 0xb4, 0x7d, 0x17,
+ 0x7a, 0x22, 0xd9, 0x73, 0xb3, 0xa8, 0x64, 0xc7, 0x72, 0x1b, 0xd3, 0x39,
+ 0xca, 0xd2, 0x3a, 0xd1, 0xc1, 0xa8, 0xf3, 0x63, 0x13, 0xfa, 0xab, 0x87,
+ 0x83, 0x7a, 0xb4, 0xff, 0xe0, 0x26, 0xb8, 0x53, 0xfc, 0x5f, 0x3e, 0xb4,
+ 0xff, 0xff, 0xb4, 0x5c, 0x6f, 0x38, 0xdf, 0xfe, 0xdb, 0x10, 0xc0, 0xfd,
+ 0x62, 0xd3, 0xde, 0xfb, 0x40, 0xb4, 0xff, 0xab, 0x5d, 0x2a, 0xf1, 0x7a,
+ 0xd2, 0xd3, 0xfd, 0xa2, 0xa1, 0x67, 0xb4, 0xf5, 0xa1, 0x93, 0xa7, 0xf4,
+ 0xa3, 0x0c, 0xba, 0x90, 0x4d, 0xda, 0x22, 0xd9, 0xf4, 0xff, 0xd8, 0x1c,
+ 0x6f, 0x3e, 0x56, 0x51, 0xd6, 0x9f, 0x66, 0xde, 0x7d, 0x2d, 0x37, 0x8c,
+ 0x5a, 0x7a, 0xe0, 0xc7, 0x5a, 0x18, 0xdb, 0xf0, 0x2f, 0x0c, 0x8c, 0x2b,
+ 0xa1, 0xf2, 0xbd, 0x2d, 0x2d, 0x35, 0xde, 0xb4, 0x08, 0xd3, 0x72, 0x21,
+ 0x3f, 0x58, 0xe3, 0xfc, 0xcf, 0xd8, 0xb4, 0xfe, 0x1f, 0x59, 0xbd, 0x16,
+ 0xd6, 0x98, 0xbe, 0xb4, 0x3a, 0x07, 0xfc, 0x46, 0xda, 0x33, 0x9f, 0xfb,
+ 0xd6, 0xf7, 0xed, 0xb2, 0xe9, 0x7a, 0xb4, 0xfd, 0xae, 0x6c, 0x73, 0x44,
+ 0xb4, 0xf0, 0x06, 0x6d, 0x68, 0xf5, 0x12, 0x9a, 0x45, 0xd9, 0x84, 0x8c,
+ 0xe8, 0x36, 0xa5, 0x4e, 0x91, 0x83, 0xa7, 0x1c, 0x68, 0x77, 0xd8, 0x85,
+ 0xec, 0x65, 0xd9, 0x2a, 0x58, 0x78, 0x41, 0xf1, 0x1a, 0x09, 0x42, 0x19,
+ 0xc8, 0xfc, 0xfe, 0x80, 0x72, 0xdd, 0x4b, 0x1a, 0xa8, 0x6e, 0x8a, 0x1d,
+ 0xc1, 0x1a, 0x8d, 0xe3, 0xf6, 0xdc, 0x64, 0xb6, 0xab, 0x79, 0x42, 0x80,
+ 0x68, 0x63, 0xc1, 0x9b, 0x75, 0xdd, 0x56, 0xb8, 0x33, 0xff, 0x8c, 0x7a,
+ 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x6c, 0x9f, 0xc6, 0xcf, 0xf6, 0xab,
+ 0xaa, 0x8a, 0xb6, 0x7f, 0x3d, 0xfc, 0xec, 0x19, 0xeb, 0x4f, 0x66, 0xab,
+ 0x6b, 0x49, 0xd1, 0xc3, 0xd3, 0x03, 0x39, 0xf7, 0xfb, 0x55, 0xd5, 0x45,
+ 0x69, 0x3f, 0xfd, 0xd6, 0xfe, 0x0a, 0x8f, 0x4f, 0x62, 0xea, 0xd3, 0xff,
+ 0xcf, 0xbe, 0x03, 0x1e, 0xb3, 0x7b, 0x63, 0xad, 0x36, 0xf6, 0xc8, 0x98,
+ 0xa4, 0xc9, 0xfc, 0xce, 0xc6, 0xd8, 0x30, 0x96, 0x9f, 0xac, 0xcd, 0x16,
+ 0x1d, 0x69, 0xf3, 0x99, 0xe9, 0xfc, 0xeb, 0x4f, 0xc0, 0xd6, 0xf0, 0xfb,
+ 0xad, 0x2c, 0x70, 0xf6, 0xdd, 0x4b, 0x67, 0xf3, 0xf3, 0x74, 0x02, 0xe5,
+ 0x69, 0x1b, 0xcc, 0x54, 0x77, 0x85, 0x65, 0x0c, 0xbd, 0x16, 0xd1, 0xa0,
+ 0x42, 0x1f, 0x65, 0x73, 0xf8, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x60, 0x4f,
+ 0xbf, 0xda, 0xae, 0xaa, 0x27, 0x59, 0xff, 0xfd, 0xa6, 0xb3, 0xdc, 0x39,
+ 0xaf, 0x7c, 0xd1, 0x5f, 0x9b, 0x16, 0x9f, 0x18, 0xf4, 0xf3, 0x62, 0x25,
+ 0xdc, 0x33, 0x9f, 0xcf, 0xb9, 0x87, 0x1d, 0x8e, 0xb4, 0xfb, 0xfd, 0xaa,
+ 0xea, 0xa2, 0xd9, 0x9f, 0xf0, 0x9a, 0xe6, 0xd1, 0x76, 0xbe, 0xb4, 0x8d,
+ 0x87, 0xe1, 0x46, 0x73, 0xdd, 0xaa, 0xea, 0xa2, 0xe6, 0x91, 0xd6, 0x8f,
+ 0x9b, 0xdb, 0x4b, 0x66, 0x70, 0xeb, 0x48, 0xd8, 0x6e, 0x6d, 0x22, 0x9f,
+ 0x7f, 0xb5, 0x5d, 0x54, 0x5d, 0xf3, 0xf9, 0xe6, 0xbf, 0xfe, 0x56, 0xad,
+ 0x23, 0x61, 0xf3, 0xd1, 0x9c, 0xf1, 0x87, 0xf4, 0x4b, 0x43, 0x37, 0xcf,
+ 0xf9, 0x5b, 0xc3, 0xf4, 0xcb, 0x85, 0x52, 0x95, 0x99, 0xf7, 0x73, 0xc3,
+ 0x56, 0x90, 0x05, 0x0a, 0x5b, 0xc2, 0x73, 0x70, 0x8e, 0x18, 0x9a, 0x7d,
+ 0x7b, 0x9e, 0x9e, 0xb4, 0xff, 0xdc, 0x77, 0x9a, 0xe3, 0x79, 0x80, 0x3a,
+ 0xd3, 0x82, 0x8c, 0xc7, 0xdb, 0xb2, 0x79, 0xfc, 0x16, 0x63, 0xae, 0xd8,
+ 0x75, 0xa7, 0xdf, 0xed, 0x57, 0x55, 0x12, 0xbc, 0xff, 0x82, 0xad, 0xf7,
+ 0x4d, 0x66, 0x5a, 0xb4, 0xff, 0xfc, 0xfc, 0x21, 0x61, 0xcb, 0x77, 0x63,
+ 0xd7, 0x1b, 0x5a, 0x7b, 0x9a, 0xfb, 0xd6, 0x9f, 0xff, 0xc5, 0xba, 0x3d,
+ 0x00, 0xb5, 0x6d, 0x05, 0x9d, 0x2b, 0x16, 0x8f, 0x51, 0x05, 0x44, 0x51,
+ 0xea, 0x67, 0xd8, 0x81, 0xa8, 0x6d, 0xcf, 0xfb, 0x74, 0xfb, 0xe9, 0xbe,
+ 0x37, 0xab, 0x4f, 0xfd, 0xb2, 0x76, 0x5b, 0x71, 0xec, 0x1b, 0x5a, 0x75,
+ 0x3c, 0xcc, 0xa9, 0x8b, 0x0d, 0xaf, 0x1b, 0x8e, 0xcd, 0x86, 0x40, 0x9f,
+ 0xfd, 0x9a, 0x30, 0x67, 0xa4, 0x1b, 0xcd, 0x2d, 0x3b, 0x6d, 0xea, 0x53,
+ 0xff, 0xb5, 0x45, 0xb6, 0x79, 0x7e, 0xce, 0x44, 0x94, 0xfe, 0xae, 0x9b,
+ 0xdf, 0xf9, 0xb3, 0x31, 0xf3, 0x5c, 0x72, 0x46, 0xea, 0xbf, 0x33, 0xca,
+ 0x93, 0xdb, 0x13, 0xb8, 0x56, 0xcf, 0xfe, 0x31, 0xe9, 0xe6, 0xcf, 0xf6,
+ 0xab, 0xaa, 0x89, 0x86, 0x7f, 0xf0, 0x33, 0xb0, 0x6e, 0x0c, 0xe8, 0x3a,
+ 0x7b, 0xbd, 0x69, 0xff, 0xdf, 0xa1, 0x18, 0x7d, 0xbe, 0xd6, 0xbb, 0xd6,
+ 0x9b, 0x0d, 0xea, 0x28, 0x86, 0x56, 0x9f, 0xf9, 0xd1, 0xce, 0x1f, 0xcd,
+ 0x6c, 0x19, 0xeb, 0x4f, 0xe6, 0xab, 0x36, 0x3d, 0x7d, 0x69, 0xf5, 0x7d,
+ 0xf4, 0x75, 0xa0, 0x0f, 0x67, 0x93, 0x39, 0xf8, 0xed, 0x81, 0xbf, 0x25,
+ 0xa5, 0x75, 0xa7, 0xcd, 0x81, 0xbf, 0x25, 0xa7, 0xed, 0x16, 0xef, 0x5c,
+ 0x78, 0x3e, 0x67, 0x0b, 0x8e, 0x21, 0x3f, 0xff, 0xe0, 0xcb, 0x5d, 0x77,
+ 0x9a, 0xf0, 0x19, 0x61, 0x60, 0x70, 0xfb, 0xad, 0x3f, 0xfc, 0xdb, 0x0a,
+ 0x16, 0xb0, 0xbd, 0xe7, 0x77, 0x5a, 0x7e, 0x76, 0x36, 0xc1, 0x84, 0xb4,
+ 0xff, 0xe6, 0xd8, 0x99, 0xf9, 0xc6, 0xec, 0xe6, 0xd5, 0xa1, 0x8f, 0xf0,
+ 0x8b, 0xe7, 0xeb, 0x90, 0xe7, 0xad, 0xad, 0x3f, 0xff, 0xef, 0xe3, 0xb6,
+ 0x0d, 0xf8, 0x18, 0x1b, 0x54, 0x5b, 0x6d, 0xdd, 0x68, 0xe1, 0x13, 0x5f,
+ 0x2d, 0x9e, 0xf0, 0xed, 0xd6, 0xc5, 0xa3, 0x0f, 0x38, 0x72, 0x49, 0xff,
+ 0xf6, 0x83, 0x37, 0xa2, 0xce, 0x37, 0x8e, 0xda, 0xeb, 0x4e, 0x61, 0x0c,
+ 0xb4, 0x61, 0xf8, 0x82, 0xac, 0xf5, 0x0d, 0xee, 0x2d, 0x23, 0x79, 0x8b,
+ 0x92, 0xfe, 0xc2, 0x8b, 0xb0, 0x88, 0x71, 0x57, 0xee, 0x1a, 0x86, 0x58,
+ 0x46, 0x11, 0xb8, 0x49, 0xf2, 0x41, 0x3f, 0xfd, 0xf2, 0xe1, 0xf7, 0x2d,
+ 0xe9, 0xbf, 0xb6, 0x5a, 0x7d, 0xfe, 0xd5, 0x75, 0x51, 0x57, 0x4f, 0xf3,
+ 0xcd, 0x9f, 0xed, 0x57, 0x55, 0x11, 0xe4, 0x8d, 0xea, 0x31, 0xb1, 0x3e,
+ 0x8c, 0xe7, 0xf1, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0xc1, 0x9f, 0xc6, 0xcf,
+ 0xf6, 0xab, 0xaa, 0x8b, 0x2a, 0x7f, 0x1b, 0x3f, 0xda, 0xae, 0xaa, 0x2d,
+ 0x39, 0xfd, 0x97, 0xf1, 0xff, 0xf3, 0xa5, 0xa7, 0xbb, 0x55, 0xd5, 0x45,
+ 0xb9, 0x3f, 0xf3, 0x67, 0xf0, 0x3c, 0x6b, 0x38, 0xb5, 0x68, 0xf9, 0xf9,
+ 0x5c, 0xb6, 0x40, 0xb4, 0xff, 0xc5, 0xee, 0xb9, 0xab, 0xe6, 0x00, 0xeb,
+ 0x46, 0x1e, 0x9e, 0x83, 0xe7, 0xf9, 0x83, 0x93, 0xb5, 0xf6, 0x4b, 0x4f,
+ 0xea, 0xab, 0x3d, 0x6c, 0xfa, 0xd3, 0xfe, 0xa7, 0x9b, 0x3f, 0xda, 0xae,
+ 0xaa, 0x28, 0x79, 0xfc, 0xdf, 0x13, 0x77, 0x0e, 0xb4, 0xff, 0xc7, 0xaf,
+ 0x5b, 0xdd, 0x10, 0x11, 0xd6, 0x9f, 0xfb, 0x97, 0xea, 0xbf, 0xc6, 0xd8,
+ 0xac, 0x5a, 0x7f, 0xdc, 0xfc, 0x5f, 0xa0, 0xde, 0x09, 0x69, 0xfe, 0xc0,
+ 0x0a, 0xd8, 0xcd, 0xd5, 0xa7, 0xd5, 0xc5, 0xf6, 0x4b, 0x46, 0x8f, 0x76,
+ 0xe6, 0xd3, 0xf0, 0x79, 0x99, 0xf6, 0xba, 0xd3, 0xff, 0xf6, 0x7b, 0xa6,
+ 0x18, 0xdb, 0x0a, 0x15, 0xee, 0xc2, 0x4a, 0x7f, 0x6a, 0x84, 0xe0, 0x37,
+ 0xab, 0x48, 0xcf, 0x5c, 0x25, 0xc8, 0x54, 0x75, 0xd4, 0x88, 0x5c, 0x37,
+ 0x39, 0x96, 0x92, 0x68, 0xc4, 0x48, 0x77, 0x46, 0xdc, 0x26, 0xf9, 0x22,
+ 0xf2, 0x30, 0x19, 0x6e, 0x7f, 0x1b, 0x3f, 0xda, 0xae, 0xaa, 0x2f, 0x38,
+ 0x66, 0x6d, 0x33, 0xd4, 0xfd, 0x87, 0xbe, 0x4e, 0x63, 0xf1, 0x1b, 0x77,
+ 0xcd, 0x4e, 0x7d, 0xa3, 0xe0, 0x9c, 0x63, 0x77, 0x0d, 0x59, 0xfc, 0x6c,
+ 0xff, 0x6a, 0xba, 0xa8, 0xa5, 0xa7, 0xdf, 0xed, 0x57, 0x55, 0x16, 0x14,
+ 0xff, 0xf9, 0xb0, 0x3d, 0x6d, 0x37, 0x1b, 0xc0, 0xa3, 0xad, 0x23, 0x62,
+ 0x21, 0x4e, 0x67, 0x3f, 0x8d, 0x9f, 0xed, 0x57, 0x55, 0x16, 0x5c, 0xf1,
+ 0x87, 0xf3, 0x5b, 0xa6, 0x5a, 0x71, 0x86, 0x3a, 0xd2, 0xbf, 0x4f, 0x3b,
+ 0x93, 0x19, 0xf5, 0x7f, 0x07, 0xb1, 0x69, 0xfd, 0x67, 0x17, 0x6f, 0x76,
+ 0x4b, 0x4f, 0x9b, 0x1d, 0xb5, 0xd6, 0x98, 0x1a, 0x8f, 0x72, 0xd3, 0x59,
+ 0xea, 0x7b, 0xfd, 0x5a, 0x7e, 0xaf, 0xb6, 0xeb, 0x4b, 0x4c, 0xd7, 0x5a,
+ 0x3d, 0x3e, 0x2d, 0x11, 0x3b, 0x2b, 0x9f, 0x8a, 0xae, 0x2b, 0xf2, 0xb4,
+ 0xff, 0x7d, 0x9f, 0xba, 0xd5, 0x7a, 0xb4, 0x9e, 0xb4, 0x9e, 0xb4, 0x9e,
+ 0xb4, 0x31, 0xb0, 0x1c, 0x40, 0x84, 0x27, 0xff, 0xdb, 0xb9, 0x77, 0x03,
+ 0xec, 0x19, 0xee, 0x0e, 0xb4, 0xb8, 0x5a, 0x6b, 0xf2, 0xb4, 0x61, 0xfd,
+ 0xdd, 0x4f, 0x62, 0x33, 0x13, 0x2d, 0x3f, 0x03, 0x1c, 0x1b, 0x16, 0x99,
+ 0xec, 0xb4, 0x7a, 0x7a, 0x4e, 0x0a, 0x72, 0x53, 0x3f, 0xff, 0xfd, 0xa6,
+ 0xdd, 0xca, 0xf7, 0x6d, 0xe8, 0x9b, 0xe2, 0x3d, 0x3d, 0xfb, 0x1d, 0x69,
+ 0x98, 0xeb, 0x4f, 0xff, 0xcf, 0x60, 0xe5, 0xef, 0x6d, 0xeb, 0x0e, 0x33,
+ 0x09, 0x69, 0xba, 0x66, 0x5c, 0x49, 0xb0, 0xa7, 0xd8, 0x42, 0x64, 0x23,
+ 0xba, 0x65, 0xf2, 0xda, 0x68, 0x08, 0x54, 0x5e, 0x10, 0x1b, 0x32, 0xf2,
+ 0x7d, 0x18, 0x56, 0x7f, 0xf1, 0x8f, 0x4f, 0x36, 0x7f, 0xb5, 0x5d, 0x54,
+ 0x51, 0x93, 0xe7, 0x6d, 0xf6, 0x12, 0xd3, 0xe0, 0xa1, 0x30, 0xcb, 0x48,
+ 0xcc, 0x79, 0xda, 0x28, 0x87, 0xaf, 0xaa, 0x7e, 0x18, 0x67, 0x28, 0xa9,
+ 0xcd, 0x5b, 0xc3, 0x2b, 0x70, 0xa3, 0x9f, 0xf8, 0xd4, 0xf3, 0x67, 0xfb,
+ 0x55, 0xd5, 0x44, 0x73, 0x3f, 0xf8, 0xc7, 0xa7, 0x9b, 0x3f, 0xda, 0xae,
+ 0xaa, 0x27, 0x29, 0xfc, 0x6c, 0xff, 0x6a, 0xba, 0xa8, 0xb3, 0x27, 0xfb,
+ 0xcd, 0x5e, 0xe1, 0xdb, 0x86, 0x3a, 0xd3, 0xfc, 0x2f, 0xb6, 0xf5, 0x5c,
+ 0x3d, 0x69, 0xfd, 0x97, 0xff, 0xf3, 0x8b, 0xad, 0x23, 0x3a, 0x64, 0x56,
+ 0xb2, 0x0b, 0xce, 0x67, 0xf1, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0xdd, 0x9f,
+ 0xfc, 0x63, 0xd3, 0xcd, 0x9f, 0xed, 0x57, 0x55, 0x14, 0x84, 0xff, 0xc6,
+ 0xa7, 0x9b, 0x3f, 0xda, 0xae, 0xaa, 0x25, 0x28, 0xb1, 0x55, 0x63, 0x89,
+ 0xe7, 0x55, 0x14, 0x3a, 0xc0, 0xef, 0x67, 0xce, 0xaa, 0xb3, 0xfe, 0xa7,
+ 0x9b, 0x3f, 0xda, 0xae, 0xaa, 0x27, 0x69, 0xff, 0xf1, 0x7b, 0xc9, 0xd9,
+ 0xd6, 0xbd, 0x06, 0x0c, 0xea, 0xd2, 0x31, 0xd1, 0x41, 0x49, 0x33, 0xff,
+ 0x51, 0xf5, 0x9d, 0xad, 0x30, 0xcf, 0x5a, 0x7f, 0xe0, 0xcd, 0x55, 0x99,
+ 0x70, 0xae, 0x16, 0x9b, 0xc8, 0xde, 0xa2, 0x16, 0xe8, 0x70, 0x74, 0x70,
+ 0x79, 0x42, 0xb6, 0x7d, 0xfe, 0xd5, 0x75, 0x51, 0x16, 0x4f, 0xfa, 0x9e,
+ 0x6c, 0xff, 0x6a, 0xba, 0xa8, 0x97, 0x67, 0xff, 0xec, 0xf7, 0x4c, 0x31,
+ 0xb6, 0x14, 0x2b, 0xdd, 0x84, 0x94, 0x8d, 0x88, 0xd7, 0x39, 0x9f, 0x92,
+ 0x4c, 0xff, 0xe3, 0x1e, 0x9e, 0x6c, 0xff, 0x6a, 0xba, 0xa8, 0x98, 0xa7,
+ 0xdf, 0xed, 0x57, 0x55, 0x15, 0x4c, 0xb1, 0x68, 0xc3, 0xc2, 0x1c, 0xce,
+ 0x7f, 0xff, 0xf7, 0xeb, 0x5c, 0x3f, 0x36, 0x6d, 0x55, 0xfe, 0x56, 0xef,
+ 0x45, 0xf7, 0xad, 0x06, 0x44, 0xdd, 0x11, 0x4f, 0xfe, 0x31, 0xe9, 0xe6,
+ 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0xd2, 0x7f, 0x15, 0x7d, 0x9f, 0x4e, 0xd6,
+ 0x9f, 0x38, 0xce, 0x35, 0xd6, 0x9f, 0xad, 0xc2, 0x77, 0x80, 0xb4, 0x11,
+ 0xea, 0xdc, 0xa2, 0x71, 0x69, 0x96, 0x31, 0xa1, 0x9f, 0xfb, 0x9b, 0xed,
+ 0xb8, 0x37, 0x2e, 0x11, 0xd6, 0x83, 0x9f, 0x96, 0x8a, 0xa7, 0xfd, 0x4f,
+ 0x36, 0x7f, 0xb5, 0x5d, 0x54, 0x4e, 0xf3, 0xed, 0xf3, 0x47, 0x24, 0xa4,
+ 0x6f, 0x53, 0xac, 0xc8, 0xc6, 0x8e, 0x45, 0x49, 0x33, 0xff, 0x8c, 0x7a,
+ 0x79, 0xb3, 0xfd, 0xaa, 0xea, 0xa2, 0x85, 0x9f, 0xfc, 0x63, 0xd3, 0xcd,
+ 0x9f, 0xed, 0x57, 0x55, 0x14, 0x94, 0xff, 0xfe, 0xcb, 0x98, 0x6c, 0x73,
+ 0x54, 0x7d, 0xe9, 0xb7, 0xc9, 0xd6, 0x8b, 0x17, 0x38, 0xde, 0x71, 0xd8,
+ 0xcc, 0xbe, 0x44, 0x79, 0x40, 0x22, 0x49, 0xe5, 0x57, 0xc9, 0x56, 0x7f,
+ 0x1b, 0x3f, 0xda, 0xae, 0xaa, 0x22, 0x49, 0xff, 0xc6, 0x3d, 0x3c, 0xd9,
+ 0xfe, 0xd5, 0x75, 0x51, 0x2f, 0x4f, 0x7f, 0x9d, 0xdd, 0x69, 0xf7, 0xc4,
+ 0x72, 0xba, 0xd3, 0x84, 0xdb, 0x5a, 0x7f, 0xea, 0x72, 0xec, 0xee, 0xb4,
+ 0xdc, 0x38, 0xb4, 0x7a, 0x8a, 0xc2, 0x23, 0x70, 0x9f, 0xe3, 0x73, 0xfc,
+ 0x54, 0x1c, 0xed, 0xc6, 0x1d, 0x69, 0xf7, 0xfb, 0x55, 0xd5, 0x45, 0x2f,
+ 0x3e, 0x0d, 0xd9, 0x96, 0xad, 0x3f, 0xc2, 0xbf, 0xdb, 0x87, 0x91, 0xd6,
+ 0x9f, 0xea, 0xb3, 0xc5, 0x9c, 0xb8, 0xde, 0x75, 0xa6, 0xc7, 0xb1, 0xfd,
+ 0xf2, 0x73, 0x3f, 0x7c, 0x4d, 0xdc, 0x3a, 0xd3, 0x3f, 0x16, 0x9c, 0xc2,
+ 0xba, 0xd0, 0xc7, 0xb9, 0xe9, 0x65, 0xa2, 0xb3, 0xff, 0x11, 0xeb, 0xd1,
+ 0x9c, 0x7b, 0x07, 0x0b, 0x4f, 0x5c, 0xad, 0xda, 0xd1, 0xa3, 0xe8, 0xda,
+ 0x34, 0xff, 0x56, 0xa9, 0xc2, 0xfb, 0x58, 0xb4, 0xf9, 0xd4, 0x8e, 0xd7,
+ 0x5a, 0x7d, 0x4e, 0xf3, 0xf7, 0x5a, 0x4d, 0xe9, 0xe8, 0x9c, 0xa6, 0x7c,
+ 0x43, 0xdc, 0x5d, 0x5a, 0x46, 0x65, 0x6d, 0x3e, 0x9f, 0x61, 0xcf, 0x06,
+ 0x6e, 0x42, 0x8f, 0x50, 0x89, 0xa8, 0x4c, 0x5c, 0x8b, 0x70, 0x89, 0xf2,
+ 0x28, 0x9f, 0xc6, 0xcf, 0xf6, 0xab, 0xaa, 0x8a, 0x72, 0x7f, 0xc5, 0xfa,
+ 0xbe, 0xb3, 0x03, 0xab, 0x4f, 0xfc, 0x39, 0x71, 0x70, 0xcf, 0x75, 0x56,
+ 0xad, 0x3f, 0xec, 0xd3, 0x7f, 0x0d, 0x6d, 0xb6, 0xa5, 0x31, 0x5a, 0xb4,
+ 0xd6, 0x1b, 0xd4, 0x6b, 0xec, 0xef, 0xc9, 0x19, 0xd5, 0x02, 0x7d, 0xfe,
+ 0xd5, 0x75, 0x51, 0x5e, 0x4f, 0xff, 0xd9, 0xee, 0x98, 0x63, 0x6c, 0x28,
+ 0x57, 0xbb, 0x09, 0x29, 0x1b, 0x11, 0x1d, 0xe4, 0x67, 0x3f, 0xf1, 0xa9,
+ 0xe6, 0xcf, 0xf6, 0xab, 0xaa, 0x89, 0x1e, 0x71, 0x09, 0x96, 0x9d, 0xdc,
+ 0x3a, 0x46, 0x2e, 0xa7, 0xdf, 0xed, 0x57, 0x55, 0x12, 0x44, 0xf1, 0xa9,
+ 0xe6, 0x63, 0xdd, 0xc2, 0xa9, 0xff, 0x8d, 0x4f, 0x36, 0x7f, 0xb5, 0x5d,
+ 0x54, 0x49, 0x53, 0xef, 0xf6, 0xab, 0xaa, 0x8b, 0xc6, 0x7d, 0x7b, 0xef,
+ 0x3a, 0xb4, 0xff, 0x3c, 0xd9, 0xfe, 0xd5, 0x75, 0x51, 0x26, 0xc8, 0xd8,
+ 0x89, 0xef, 0x99, 0xd1, 0x3c, 0x33, 0x26, 0x3e, 0xc3, 0xe7, 0xce, 0x35,
+ 0x7b, 0x0a, 0xa2, 0x8c, 0x55, 0xc8, 0x6f, 0x9c, 0xaf, 0x50, 0xc6, 0xd9,
+ 0xbf, 0x30, 0xed, 0x86, 0x8f, 0xb2, 0x0a, 0xc8, 0xed, 0x9f, 0x2c, 0x47,
+ 0xd9, 0x48, 0x39, 0x79, 0x6c, 0x83, 0xca, 0x69, 0xed, 0xa7, 0x1b, 0xe2,
+ 0x91, 0xb4, 0x53, 0xd6, 0xde, 0x79, 0x41, 0xee, 0x56, 0xad, 0xbf, 0xa6,
+ 0x32, 0x9f, 0x16, 0x5d, 0x9a, 0x9e, 0xbe, 0xaa, 0xd5, 0xfc, 0x53, 0x85,
+ 0x1e, 0x6e, 0x17, 0xc1, 0x49, 0x2b, 0xbd, 0x2b, 0xb7, 0x76, 0x91, 0xaf,
+ 0x9a, 0xcb, 0x4d, 0xdd, 0x20, 0x12, 0xd9, 0x63, 0x9e, 0x51, 0xf7, 0x8d,
+ 0x3b, 0xca, 0xeb, 0x4a, 0x15, 0x80,
};
-static const unsigned kPreloadedHSTSBits = 122689;
+static const unsigned kPreloadedHSTSBits = 128107;
-static const unsigned kHSTSRootPosition = 122099;
+static const unsigned kHSTSRootPosition = 127515;
#endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 750688a..fa9edd5 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -1821,7 +1821,6 @@
{ "name": "madars.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "magneticanvil.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "mimeit.de", "include_subdomains": true, "mode": "force-https" },
- { "name": "miniku.net", "include_subdomains": true, "mode": "force-https" },
{ "name": "mobilcom-debitel-empfehlen.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "morethanadream.lv", "include_subdomains": true, "mode": "force-https" },
{ "name": "narodniki.com", "include_subdomains": true, "mode": "force-https" },
@@ -1844,7 +1843,86 @@
{ "name": "webtalis.nl", "include_subdomains": true, "mode": "force-https" },
{ "name": "wevahoo.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "zentralwolke.de", "include_subdomains": true, "mode": "force-https" },
- { "name": "zhovner.com", "include_subdomains": true, "mode": "force-https" }
+ { "name": "zhovner.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "acus.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "agrimap.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ajouin.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "atishchenko.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bentertain.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bit.voyage", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bzv-fr.eu", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codepoints.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "codepx.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cs50.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cyprus-company-service.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darkpony.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "darom.jp", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidnoren.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "donotcall.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "e-aut.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecg.fr", "include_subdomains": true, "mode": "force-https" },
+ { "name": "exon.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "extendwings.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "federalregister.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "fedorahosted.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "firma-offshore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freesounding.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "freesounding.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ftccomplaintassistant.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getfedora.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "getfittedstore.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hatoko.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hda.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "helpadmin.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "hsr.gov", "include_subdomains": true, "mode": "force-https" },
+ { "name": "iniiter.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ionas-law.ro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "keepa.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "knip.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "laf.in.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "leifdreizler.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "livej.am", "include_subdomains": true, "mode": "force-https" },
+ { "name": "m0wef.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mahamed91.pw", "include_subdomains": true, "mode": "force-https" },
+ { "name": "massivum.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "megaplan.cz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "megaplan.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "miketabor.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mineover.es", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mokote.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mr-hosting.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "msa-aesch.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mutamatic.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "nymphetomania.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "offshore-firma.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "openacademies.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "phoenix.dj", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pmg-offshore-company.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pmg-purchase.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "pmg-purchase.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "polypho.nyc", "include_subdomains": true, "mode": "force-https" },
+ { "name": "puiterwijk.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "redletter.link", "include_subdomains": true, "mode": "force-https" },
+ { "name": "reg.ru", "include_subdomains": true, "mode": "force-https" },
+ { "name": "release-monitoring.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "rika.me", "include_subdomains": true, "mode": "force-https" },
+ { "name": "scrambler.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sjoorm.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "survivalmonkey.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "sychov.pro", "include_subdomains": true, "mode": "force-https" },
+ { "name": "terrty.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "thebimhub.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tmtopup.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "uae-company-service.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wherephoto.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wills.co.tt", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wondershift.biz", "include_subdomains": true, "mode": "force-https" },
+ { "name": "wzrd.in", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xplore-dna.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "xuntier.ch", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yanovich.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yaporn.tv", "include_subdomains": true, "mode": "force-https" },
+ { "name": "yorcom.nl", "include_subdomains": true, "mode": "force-https" }
],
// |ReportUMAOnPinFailure| uses these to report which domain was associated
diff --git a/net/interfaces/BUILD.gn b/net/interfaces/BUILD.gn
index 03a0778..4a5b799 100644
--- a/net/interfaces/BUILD.gn
+++ b/net/interfaces/BUILD.gn
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni")
+import("//mojo/public/tools/bindings/mojom.gni")
mojom("interfaces") {
sources = [
diff --git a/net/interfaces/host_resolver_service.mojom b/net/interfaces/host_resolver_service.mojom
index c8acc38..249fa07 100644
--- a/net/interfaces/host_resolver_service.mojom
+++ b/net/interfaces/host_resolver_service.mojom
@@ -40,7 +40,7 @@
array<IPEndPoint> addresses;
};
-interface HostResolverService {
+interface HostResolver {
// Use a HostResolverRequestClient instead of returning a result so we can
// cancel in-flight requests by destroying the client. IPC requests in Mojo
// cannot be cancelled directly.
diff --git a/net/interfaces/proxy_resolver_service.mojom b/net/interfaces/proxy_resolver_service.mojom
index 2cb7a0b..a2fb70e 100644
--- a/net/interfaces/proxy_resolver_service.mojom
+++ b/net/interfaces/proxy_resolver_service.mojom
@@ -27,7 +27,7 @@
uint16 port;
};
-interface ProxyResolverService {
+interface ProxyResolver {
SetPacScript(string data) => (int32 result);
// Use a ProxyResolverRequestClient instead of returning a result so we can
@@ -43,6 +43,6 @@
interface ProxyResolverFactory {
// TODO(amistry): Add NetLog and ProxyResolverErrorObserver.
- CreateResolver(ProxyResolverService& resolver,
- HostResolverService host_resolver);
+ CreateResolver(ProxyResolver& resolver,
+ HostResolver host_resolver);
};
diff --git a/net/net.gyp b/net/net.gyp
index cd381e0..0fdc518 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -144,8 +144,8 @@
'sources!': [
'http/http_auth_gssapi_posix.cc',
'http/http_auth_gssapi_posix.h',
- 'http/http_auth_handler_negotiate.h',
'http/http_auth_handler_negotiate.cc',
+ 'http/http_auth_handler_negotiate.h',
],
}],
['posix_avoid_mmap==1', {
@@ -172,12 +172,12 @@
'sources!': [
'base/directory_lister.cc',
'base/directory_lister.h',
+ 'url_request/file_protocol_handler.cc',
+ 'url_request/file_protocol_handler.h',
'url_request/url_request_file_dir_job.cc',
'url_request/url_request_file_dir_job.h',
'url_request/url_request_file_job.cc',
'url_request/url_request_file_job.h',
- 'url_request/file_protocol_handler.cc',
- 'url_request/file_protocol_handler.h',
],
}],
['disable_ftp_support==1', {
@@ -220,8 +220,8 @@
'cert/nss_cert_database_chromeos.h',
'cert/nss_profile_filter_chromeos.cc',
'cert/nss_profile_filter_chromeos.h',
- 'cert/sha256_legacy_support_nss_win.cc',
'cert/scoped_nss_types.h',
+ 'cert/sha256_legacy_support_nss_win.cc',
'cert/test_root_certs_nss.cc',
'cert/x509_certificate_nss.cc',
'cert/x509_util_nss.cc',
@@ -279,9 +279,9 @@
'socket/ssl_server_socket_openssl.h',
'socket/ssl_session_cache_openssl.cc',
'socket/ssl_session_cache_openssl.h',
+ 'ssl/openssl_platform_key.h',
'ssl/openssl_platform_key_mac.cc',
'ssl/openssl_platform_key_win.cc',
- 'ssl/openssl_platform_key.h',
'ssl/openssl_ssl_util.cc',
'ssl/openssl_ssl_util.h',
],
@@ -368,10 +368,10 @@
'sources!': [
'cert/cert_verify_proc_nss.cc',
'cert/cert_verify_proc_nss.h',
- 'ssl/client_cert_store_nss.cc',
- 'ssl/client_cert_store_nss.h',
'ssl/client_cert_store_chromeos.cc',
'ssl/client_cert_store_chromeos.h',
+ 'ssl/client_cert_store_nss.cc',
+ 'ssl/client_cert_store_nss.h',
],
}],
[ 'enable_websockets != 1', {
@@ -581,8 +581,8 @@
}],
[ 'use_nss != 1', {
'sources!': [
- 'ssl/client_cert_store_nss_unittest.cc',
'ssl/client_cert_store_chromeos_unittest.cc',
+ 'ssl/client_cert_store_nss_unittest.cc',
],
}],
[ 'use_openssl == 1', {
@@ -642,8 +642,8 @@
# TODO(bulach): Add equivalent tests when the underlying
# functionality is ported to OpenSSL.
'sources!': [
- 'cert/nss_cert_database_unittest.cc',
'cert/nss_cert_database_chromeos_unittest.cc',
+ 'cert/nss_cert_database_unittest.cc',
'cert/nss_profile_filter_chromeos_unittest.cc',
'cert/x509_util_nss_unittest.cc',
'quic/test_tools/crypto_test_utils_nss.cc',
@@ -702,8 +702,21 @@
],
}, { # else: !use_v8_in_net
'sources!': [
- 'proxy/proxy_resolver_v8_unittest.cc',
'proxy/proxy_resolver_v8_tracing_unittest.cc',
+ 'proxy/proxy_resolver_v8_unittest.cc',
+ ],
+ },
+ ],
+
+ [ 'use_v8_in_net==1 and OS != "android"', {
+ 'dependencies': [
+ 'net_with_v8',
+ 'net_browser_services',
+ '../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
+ ],
+ }, { # else
+ 'sources!': [
+ 'dns/mojo_host_resolver_impl_unittest.cc',
],
},
],
@@ -759,15 +772,15 @@
'disk_cache/blockfile/block_files_unittest.cc',
# Need to read input data files.
'filter/gzip_filter_unittest.cc',
- 'socket/ssl_server_socket_unittest.cc',
- 'spdy/fuzzing/hpack_fuzz_util_test.cc',
# Need TestServer.
'proxy/proxy_script_fetcher_impl_unittest.cc',
'socket/ssl_client_socket_unittest.cc',
- 'url_request/url_fetcher_impl_unittest.cc',
- 'url_request/url_request_context_builder_unittest.cc',
+ 'socket/ssl_server_socket_unittest.cc',
+ 'spdy/fuzzing/hpack_fuzz_util_test.cc',
# Needs GetAppOutput().
'test/python_utils_unittest.cc',
+ 'url_request/url_fetcher_impl_unittest.cc',
+ 'url_request/url_request_context_builder_unittest.cc',
# The following tests are disabled because they don't apply to
# iOS.
@@ -954,10 +967,10 @@
'test/python_utils.h',
'test/spawned_test_server/base_test_server.cc',
'test/spawned_test_server/base_test_server.h',
- 'test/spawned_test_server/local_test_server_posix.cc',
- 'test/spawned_test_server/local_test_server_win.cc',
'test/spawned_test_server/local_test_server.cc',
'test/spawned_test_server/local_test_server.h',
+ 'test/spawned_test_server/local_test_server_posix.cc',
+ 'test/spawned_test_server/local_test_server_win.cc',
'test/spawned_test_server/remote_test_server.cc',
'test/spawned_test_server/remote_test_server.h',
'test/spawned_test_server/spawned_test_server.h',
@@ -1137,8 +1150,8 @@
'tools/dump_cache/simple_cache_dumper.h',
'tools/dump_cache/url_to_filename_encoder.cc',
'tools/dump_cache/url_to_filename_encoder.h',
- 'tools/dump_cache/url_utilities.h',
'tools/dump_cache/url_utilities.cc',
+ 'tools/dump_cache/url_utilities.h',
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [4267, ],
@@ -1218,6 +1231,36 @@
'../third_party/mojo/mojom_bindings_generator.gypi',
],
},
+ {
+ # GN version: //net:net_browser_services
+ 'target_name': 'net_browser_services',
+ 'type': 'static_library',
+ 'sources': [
+ 'dns/mojo_host_resolver_impl.cc',
+ 'dns/mojo_host_resolver_impl.h',
+ ],
+ 'dependencies': [
+ 'mojo_type_converters',
+ 'net',
+ 'net_interfaces',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ ],
+ },
+ {
+ # GN version: //net:mojo_type_converters
+ 'target_name': 'mojo_type_converters',
+ 'type': 'static_library',
+ 'sources': [
+ 'dns/mojo_type_converters.cc',
+ 'dns/mojo_type_converters.h',
+ ],
+ 'dependencies': [
+ 'net',
+ 'net_interfaces',
+ '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ ],
+ },
],
}],
['OS != "ios" and OS != "android"', {
@@ -1424,20 +1467,20 @@
'sources': [
'tools/dump_cache/url_to_filename_encoder.cc',
'tools/dump_cache/url_to_filename_encoder.h',
- 'tools/dump_cache/url_utilities.h',
'tools/dump_cache/url_utilities.cc',
- 'tools/flip_server/acceptor_thread.h',
+ 'tools/dump_cache/url_utilities.h',
'tools/flip_server/acceptor_thread.cc',
+ 'tools/flip_server/acceptor_thread.h',
+ 'tools/flip_server/constants.h',
'tools/flip_server/create_listener.cc',
'tools/flip_server/create_listener.h',
- 'tools/flip_server/constants.h',
'tools/flip_server/flip_config.cc',
'tools/flip_server/flip_config.h',
'tools/flip_server/http_interface.cc',
'tools/flip_server/http_interface.h',
'tools/flip_server/loadtime_measurement.h',
- 'tools/flip_server/mem_cache.h',
'tools/flip_server/mem_cache.cc',
+ 'tools/flip_server/mem_cache.h',
'tools/flip_server/output_ordering.cc',
'tools/flip_server/output_ordering.h',
'tools/flip_server/ring_buffer.cc',
@@ -1445,10 +1488,10 @@
'tools/flip_server/sm_connection.cc',
'tools/flip_server/sm_connection.h',
'tools/flip_server/sm_interface.h',
- 'tools/flip_server/spdy_ssl.cc',
- 'tools/flip_server/spdy_ssl.h',
'tools/flip_server/spdy_interface.cc',
'tools/flip_server/spdy_interface.h',
+ 'tools/flip_server/spdy_ssl.cc',
+ 'tools/flip_server/spdy_ssl.h',
'tools/flip_server/spdy_util.cc',
'tools/flip_server/spdy_util.h',
'tools/flip_server/streamer_interface.cc',
@@ -1508,8 +1551,8 @@
'tools/quic/quic_client_session.h',
'tools/quic/quic_default_packet_writer.cc',
'tools/quic/quic_default_packet_writer.h',
- 'tools/quic/quic_dispatcher.h',
'tools/quic/quic_dispatcher.cc',
+ 'tools/quic/quic_dispatcher.h',
'tools/quic/quic_epoll_clock.cc',
'tools/quic/quic_epoll_clock.h',
'tools/quic/quic_epoll_connection_helper.cc',
@@ -1530,8 +1573,8 @@
'tools/quic/quic_spdy_client_stream.h',
'tools/quic/quic_spdy_server_stream.cc',
'tools/quic/quic_spdy_server_stream.h',
- 'tools/quic/quic_time_wait_list_manager.h',
'tools/quic/quic_time_wait_list_manager.cc',
+ 'tools/quic/quic_time_wait_list_manager.h',
],
},
{
diff --git a/net/net.gypi b/net/net.gypi
index e3f0ee1..5a8087d 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -25,14 +25,14 @@
'base/escape.h',
'base/hash_value.cc',
'base/hash_value.h',
- 'base/load_timing_info.cc',
- 'base/load_timing_info.h',
'base/host_port_pair.cc',
'base/host_port_pair.h',
'base/io_buffer.cc',
'base/io_buffer.h',
'base/ip_endpoint.cc',
'base/ip_endpoint.h',
+ 'base/load_timing_info.cc',
+ 'base/load_timing_info.h',
'base/net_error_list.h',
'base/net_errors.cc',
'base/net_errors.h',
@@ -85,9 +85,9 @@
'cert/sha256_legacy_support_win.h',
'cert/signed_certificate_timestamp.cc',
'cert/signed_certificate_timestamp.h',
+ 'cert/signed_tree_head.h',
'cert/single_request_cert_verifier.cc',
'cert/single_request_cert_verifier.h',
- 'cert/signed_tree_head.h',
'cert/x509_cert_types.cc',
'cert/x509_cert_types.h',
'cert/x509_certificate.cc',
@@ -166,13 +166,13 @@
'ssl/ssl_info.h',
],
'net_non_nacl_sources': [
+ 'android/android_private_key.cc',
+ 'android/android_private_key.h',
'android/cert_verify_result_android.cc',
'android/cert_verify_result_android.h',
'android/cert_verify_status_android_list.h',
'android/gurl_utils.cc',
'android/gurl_utils.h',
- 'android/android_private_key.cc',
- 'android/android_private_key.h',
'android/keystore.cc',
'android/keystore.h',
'android/keystore_openssl.cc',
@@ -235,6 +235,9 @@
'base/keygen_handler_nss.cc',
'base/keygen_handler_openssl.cc',
'base/keygen_handler_win.cc',
+ # TODO(tc): gnome-vfs? xdgmime? /etc/mime.types?
+ 'base/layered_network_delegate.cc',
+ 'base/layered_network_delegate.h',
'base/linked_hash_map.h',
'base/load_flags.h',
'base/load_flags_list.h',
@@ -273,7 +276,6 @@
'base/nss_memio.c',
'base/nss_memio.h',
'base/platform_mime_util.h',
- # TODO(tc): gnome-vfs? xdgmime? /etc/mime.types?
'base/platform_mime_util_linux.cc',
'base/platform_mime_util_mac.mm',
'base/platform_mime_util_win.cc',
@@ -312,8 +314,6 @@
'base/winsock_init.h',
'base/winsock_util.cc',
'base/winsock_util.h',
- 'base/layered_network_delegate.cc',
- 'base/layered_network_delegate.h',
'cert/cert_database_android.cc',
'cert/cert_database_ios.cc',
'cert/cert_database_mac.cc',
@@ -502,9 +502,9 @@
'disk_cache/simple/simple_synchronous_entry.cc',
'disk_cache/simple/simple_synchronous_entry.h',
'disk_cache/simple/simple_util.cc',
+ 'disk_cache/simple/simple_util.h',
'disk_cache/simple/simple_util_posix.cc',
'disk_cache/simple/simple_util_win.cc',
- 'disk_cache/simple/simple_util.h',
'disk_cache/simple/simple_version_upgrade.cc',
'disk_cache/simple/simple_version_upgrade.h',
'dns/address_sorter.h',
@@ -760,8 +760,6 @@
'proxy/proxy_server_mac.cc',
'proxy/proxy_service.cc',
'proxy/proxy_service.h',
- 'quic/congestion_control/cube_root.cc',
- 'quic/congestion_control/cube_root.h',
'quic/congestion_control/cubic.cc',
'quic/congestion_control/cubic.h',
'quic/congestion_control/hybrid_slow_start.cc',
@@ -772,8 +770,6 @@
'quic/congestion_control/pacing_sender.h',
'quic/congestion_control/prr_sender.cc',
'quic/congestion_control/prr_sender.h',
- 'quic/congestion_control/receive_algorithm_interface.cc',
- 'quic/congestion_control/receive_algorithm_interface.h',
'quic/congestion_control/rtt_stats.cc',
'quic/congestion_control/rtt_stats.h',
'quic/congestion_control/send_algorithm_interface.cc',
@@ -782,8 +778,6 @@
'quic/congestion_control/tcp_cubic_sender.h',
'quic/congestion_control/tcp_loss_algorithm.cc',
'quic/congestion_control/tcp_loss_algorithm.h',
- 'quic/congestion_control/tcp_receiver.cc',
- 'quic/congestion_control/tcp_receiver.h',
'quic/congestion_control/time_loss_algorithm.cc',
'quic/congestion_control/time_loss_algorithm.h',
'quic/crypto/aead_base_decrypter.h',
@@ -1241,10 +1235,10 @@
'websockets/websocket_frame.h',
'websockets/websocket_frame_parser.cc',
'websockets/websocket_frame_parser.h',
- 'websockets/websocket_handshake_constants.cc',
- 'websockets/websocket_handshake_constants.h',
'websockets/websocket_handshake_challenge.cc',
'websockets/websocket_handshake_challenge.h',
+ 'websockets/websocket_handshake_constants.cc',
+ 'websockets/websocket_handshake_constants.h',
'websockets/websocket_handshake_request_info.cc',
'websockets/websocket_handshake_request_info.h',
'websockets/websocket_handshake_response_info.cc',
@@ -1283,14 +1277,15 @@
'base/ip_endpoint_unittest.cc',
'base/ip_pattern_unittest.cc',
'base/keygen_handler_unittest.cc',
+ 'base/layered_network_delegate_unittest.cc',
'base/mime_sniffer_unittest.cc',
'base/mime_util_unittest.cc',
'base/net_log_logger_unittest.cc',
'base/net_log_unittest.cc',
'base/net_log_unittest.h',
'base/net_log_util_unittest.cc',
- 'base/net_util_unittest.cc',
'base/net_util_icu_unittest.cc',
+ 'base/net_util_unittest.cc',
'base/network_activity_monitor_unittest.cc',
'base/network_change_notifier_unittest.cc',
'base/network_change_notifier_win_unittest.cc',
@@ -1304,7 +1299,6 @@
'base/upload_bytes_element_reader_unittest.cc',
'base/upload_file_element_reader_unittest.cc',
'base/url_util_unittest.cc',
- 'base/layered_network_delegate_unittest.cc',
'cert/cert_policy_enforcer_unittest.cc',
'cert/cert_verify_proc_unittest.cc',
'cert/crl_set_unittest.cc',
@@ -1365,6 +1359,7 @@
'dns/mapped_host_resolver_unittest.cc',
'dns/mdns_cache_unittest.cc',
'dns/mdns_client_unittest.cc',
+ 'dns/mojo_host_resolver_impl_unittest.cc',
'dns/record_parsed_unittest.cc',
'dns/record_rdata_unittest.cc',
'dns/serial_worker_unittest.cc',
@@ -1456,7 +1451,6 @@
'proxy/proxy_script_fetcher_impl_unittest.cc',
'proxy/proxy_server_unittest.cc',
'proxy/proxy_service_unittest.cc',
- 'quic/congestion_control/cube_root_test.cc',
'quic/congestion_control/cubic_test.cc',
'quic/congestion_control/hybrid_slow_start_test.cc',
'quic/congestion_control/pacing_sender_test.cc',
@@ -1466,7 +1460,6 @@
'quic/congestion_control/send_algorithm_simulator.h',
'quic/congestion_control/tcp_cubic_sender_test.cc',
'quic/congestion_control/tcp_loss_algorithm_test.cc',
- 'quic/congestion_control/tcp_receiver_test.cc',
'quic/congestion_control/time_loss_algorithm_test.cc',
'quic/crypto/aes_128_gcm_12_decrypter_test.cc',
'quic/crypto/aes_128_gcm_12_encrypter_test.cc',
@@ -1491,6 +1484,48 @@
'quic/crypto/strike_register_test.cc',
'quic/iovector_test.cc',
'quic/port_suggester_unittest.cc',
+ 'quic/quic_ack_notifier_test.cc',
+ 'quic/quic_address_mismatch_test.cc',
+ 'quic/quic_alarm_test.cc',
+ 'quic/quic_bandwidth_test.cc',
+ 'quic/quic_client_session_test.cc',
+ 'quic/quic_clock_test.cc',
+ 'quic/quic_config_test.cc',
+ 'quic/quic_connection_helper_test.cc',
+ 'quic/quic_connection_logger_unittest.cc',
+ 'quic/quic_connection_test.cc',
+ 'quic/quic_crypto_client_stream_test.cc',
+ 'quic/quic_crypto_server_stream_test.cc',
+ 'quic/quic_crypto_stream_test.cc',
+ 'quic/quic_data_stream_test.cc',
+ 'quic/quic_data_writer_test.cc',
+ 'quic/quic_fec_group_test.cc',
+ 'quic/quic_flow_controller_test.cc',
+ 'quic/quic_framer_test.cc',
+ 'quic/quic_headers_stream_test.cc',
+ 'quic/quic_http_stream_test.cc',
+ 'quic/quic_http_utils_test.cc',
+ 'quic/quic_network_transaction_unittest.cc',
+ 'quic/quic_packet_creator_test.cc',
+ 'quic/quic_packet_generator_test.cc',
+ 'quic/quic_protocol_test.cc',
+ 'quic/quic_received_packet_manager_test.cc',
+ 'quic/quic_reliable_client_stream_test.cc',
+ 'quic/quic_sent_entropy_manager_test.cc',
+ 'quic/quic_sent_packet_manager_test.cc',
+ 'quic/quic_server_id_test.cc',
+ 'quic/quic_server_test.cc',
+ 'quic/quic_session_test.cc',
+ 'quic/quic_socket_address_coder_test.cc',
+ 'quic/quic_stream_factory_test.cc',
+ 'quic/quic_stream_sequencer_test.cc',
+ 'quic/quic_sustained_bandwidth_recorder_test.cc',
+ 'quic/quic_time_test.cc',
+ 'quic/quic_unacked_packet_map_test.cc',
+ 'quic/quic_utils_chromium_test.cc',
+ 'quic/quic_utils_test.cc',
+ 'quic/quic_write_blocked_list_test.cc',
+ 'quic/reliable_quic_stream_test.cc',
'quic/test_tools/crypto_test_utils.cc',
'quic/test_tools/crypto_test_utils.h',
'quic/test_tools/crypto_test_utils_chromium.cc',
@@ -1544,48 +1579,6 @@
'quic/test_tools/simple_quic_framer.h',
'quic/test_tools/test_task_runner.cc',
'quic/test_tools/test_task_runner.h',
- 'quic/quic_ack_notifier_test.cc',
- 'quic/quic_address_mismatch_test.cc',
- 'quic/quic_alarm_test.cc',
- 'quic/quic_bandwidth_test.cc',
- 'quic/quic_client_session_test.cc',
- 'quic/quic_clock_test.cc',
- 'quic/quic_config_test.cc',
- 'quic/quic_connection_helper_test.cc',
- 'quic/quic_connection_logger_unittest.cc',
- 'quic/quic_connection_test.cc',
- 'quic/quic_crypto_client_stream_test.cc',
- 'quic/quic_crypto_server_stream_test.cc',
- 'quic/quic_crypto_stream_test.cc',
- 'quic/quic_data_stream_test.cc',
- 'quic/quic_data_writer_test.cc',
- 'quic/quic_fec_group_test.cc',
- 'quic/quic_flow_controller_test.cc',
- 'quic/quic_framer_test.cc',
- 'quic/quic_headers_stream_test.cc',
- 'quic/quic_http_stream_test.cc',
- 'quic/quic_http_utils_test.cc',
- 'quic/quic_network_transaction_unittest.cc',
- 'quic/quic_packet_creator_test.cc',
- 'quic/quic_packet_generator_test.cc',
- 'quic/quic_protocol_test.cc',
- 'quic/quic_received_packet_manager_test.cc',
- 'quic/quic_reliable_client_stream_test.cc',
- 'quic/quic_sent_entropy_manager_test.cc',
- 'quic/quic_sent_packet_manager_test.cc',
- 'quic/quic_server_id_test.cc',
- 'quic/quic_server_test.cc',
- 'quic/quic_session_test.cc',
- 'quic/quic_socket_address_coder_test.cc',
- 'quic/quic_stream_factory_test.cc',
- 'quic/quic_stream_sequencer_test.cc',
- 'quic/quic_sustained_bandwidth_recorder_test.cc',
- 'quic/quic_time_test.cc',
- 'quic/quic_unacked_packet_map_test.cc',
- 'quic/quic_utils_chromium_test.cc',
- 'quic/quic_utils_test.cc',
- 'quic/quic_write_blocked_list_test.cc',
- 'quic/reliable_quic_stream_test.cc',
'sdch/sdch_owner_unittest.cc',
'server/http_connection_unittest.cc',
'server/http_server_response_info_unittest.cc',
@@ -1673,10 +1666,10 @@
'ssl/ssl_client_auth_cache_unittest.cc',
'ssl/ssl_config_service_unittest.cc',
'ssl/ssl_connection_status_flags_unittest.cc',
- 'test/gtest_util.h',
'test/embedded_test_server/embedded_test_server_unittest.cc',
'test/embedded_test_server/http_request_unittest.cc',
'test/embedded_test_server/http_response_unittest.cc',
+ 'test/gtest_util.h',
'test/python_utils_unittest.cc',
'test/run_all_unittests.cc',
'test/scoped_disable_exit_on_dfatal.cc',
@@ -1689,8 +1682,8 @@
'tools/dump_cache/url_to_filename_encoder.cc',
'tools/dump_cache/url_to_filename_encoder.h',
'tools/dump_cache/url_to_filename_encoder_unittest.cc',
- 'tools/dump_cache/url_utilities.h',
'tools/dump_cache/url_utilities.cc',
+ 'tools/dump_cache/url_utilities.h',
'tools/dump_cache/url_utilities_unittest.cc',
'tools/tld_cleanup/tld_cleanup_util_unittest.cc',
'udp/udp_socket_unittest.cc',
@@ -1725,6 +1718,9 @@
'websockets/websocket_handshake_challenge_test.cc',
'websockets/websocket_handshake_stream_create_helper_test.cc',
'websockets/websocket_inflater_test.cc',
+ 'websockets/websocket_stream_cookie_test.cc',
+ 'websockets/websocket_stream_create_test_base.cc',
+ 'websockets/websocket_stream_create_test_base.h',
'websockets/websocket_stream_test.cc',
'websockets/websocket_test_util.cc',
'websockets/websocket_test_util.h',
@@ -1755,18 +1751,18 @@
'tools/quic/test_tools/quic_client_peer.h',
'tools/quic/test_tools/quic_dispatcher_peer.cc',
'tools/quic/test_tools/quic_dispatcher_peer.h',
- 'tools/quic/test_tools/quic_in_memory_cache_peer.h',
'tools/quic/test_tools/quic_in_memory_cache_peer.cc',
+ 'tools/quic/test_tools/quic_in_memory_cache_peer.h',
'tools/quic/test_tools/quic_server_peer.cc',
'tools/quic/test_tools/quic_server_peer.h',
'tools/quic/test_tools/quic_test_client.cc',
'tools/quic/test_tools/quic_test_client.h',
'tools/quic/test_tools/quic_test_utils.cc',
'tools/quic/test_tools/quic_test_utils.h',
- 'tools/quic/test_tools/server_thread.h',
'tools/quic/test_tools/server_thread.cc',
- 'tools/quic/test_tools/simple_client.h',
+ 'tools/quic/test_tools/server_thread.h',
'tools/quic/test_tools/simple_client.cc',
+ 'tools/quic/test_tools/simple_client.h',
],
'net_base_mac_ios_sources': [
'base/mac/url_conversions.h',
diff --git a/net/net_unittests.isolate b/net/net_unittests.isolate
index 877c21e..8c6cd69 100644
--- a/net/net_unittests.isolate
+++ b/net/net_unittests.isolate
@@ -34,7 +34,7 @@
'read_only': 1,
},
}],
- ['OS=="mac" and asan==1', {
+ ['OS=="mac" and asan==1 and fastbuild==0', {
'variables': {
'files': [
'<(PRODUCT_DIR)/net_unittests.dSYM/',
diff --git a/net/quic/congestion_control/cube_root.cc b/net/quic/congestion_control/cube_root.cc
deleted file mode 100644
index 191cccc..0000000
--- a/net/quic/congestion_control/cube_root.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/congestion_control/cube_root.h"
-
-#include "base/logging.h"
-
-namespace {
-
-// Find last bit in a 64-bit word.
-int FindMostSignificantBit(uint64 x) {
- if (!x) {
- return 0;
- }
- int r = 0;
- if (x & 0xffffffff00000000ull) {
- x >>= 32;
- r += 32;
- }
- if (x & 0xffff0000u) {
- x >>= 16;
- r += 16;
- }
- if (x & 0xff00u) {
- x >>= 8;
- r += 8;
- }
- if (x & 0xf0u) {
- x >>= 4;
- r += 4;
- }
- if (x & 0xcu) {
- x >>= 2;
- r += 2;
- }
- if (x & 0x02u) {
- x >>= 1;
- r++;
- }
- if (x & 0x01u) {
- r++;
- }
- return r;
-}
-
-// 6 bits table [0..63]
-const uint32 cube_root_table[] = {
- 0, 54, 54, 54, 118, 118, 118, 118, 123, 129, 134, 138, 143, 147, 151,
- 156, 157, 161, 164, 168, 170, 173, 176, 179, 181, 185, 187, 190, 192, 194,
- 197, 199, 200, 202, 204, 206, 209, 211, 213, 215, 217, 219, 221, 222, 224,
- 225, 227, 229, 231, 232, 234, 236, 237, 239, 240, 242, 244, 245, 246, 248,
- 250, 251, 252, 254
-};
-} // namespace
-
-namespace net {
-
-// Calculate the cube root using a table lookup followed by one Newton-Raphson
-// iteration.
-uint32 CubeRoot::Root(uint64 a) {
- uint32 msb = FindMostSignificantBit(a);
- DCHECK_LE(msb, 64u);
-
- if (msb < 7) {
- // MSB in our table.
- return ((cube_root_table[a]) + 31) >> 6;
- }
- // MSB 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, ...
- // cubic_shift 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, ...
- uint32 cubic_shift = (msb - 4);
- cubic_shift = ((cubic_shift * 342) >> 10); // Div by 3, biased high.
-
- // 4 to 6 bits accuracy depending on MSB.
- uint64 root =
- ((cube_root_table[a >> (cubic_shift * 3)] + 10) << cubic_shift) >> 6;
-
- // Make one Newton-Raphson iteration.
- // Since x has an error (inaccuracy due to the use of fix point) we get a
- // more accurate result by doing x * (x - 1) instead of x * x.
- root = 2 * root + (a / (root * (root - 1)));
- root = ((root * 341) >> 10); // Div by 3, biased low.
- return static_cast<uint32>(root);
-}
-
-} // namespace net
diff --git a/net/quic/congestion_control/cube_root.h b/net/quic/congestion_control/cube_root.h
deleted file mode 100644
index 293a719..0000000
--- a/net/quic/congestion_control/cube_root.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_CONGESTION_CONTROL_CUBE_ROOT_H_
-#define NET_QUIC_CONGESTION_CONTROL_CUBE_ROOT_H_
-
-#include "base/basictypes.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-class NET_EXPORT_PRIVATE CubeRoot {
- public:
- // Calculates the cube root using a table lookup followed by one Newton-
- // Raphson iteration.
- static uint32 Root(uint64 a);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CubeRoot);
-};
-
-} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_CUBE_ROOT_H_
diff --git a/net/quic/congestion_control/cube_root_test.cc b/net/quic/congestion_control/cube_root_test.cc
deleted file mode 100644
index 8f4729c..0000000
--- a/net/quic/congestion_control/cube_root_test.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "net/quic/congestion_control/cube_root.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace test {
-
-class CubeRootTest : public ::testing::Test {
- protected:
- CubeRootTest() {
- }
-};
-
-TEST_F(CubeRootTest, LowRoot) {
- for (uint32 i = 1; i < 256; ++i) {
- uint64 cube = i * i * i;
- uint8 cube_root = CubeRoot::Root(cube);
- EXPECT_EQ(i, cube_root);
- }
-}
-
-TEST_F(CubeRootTest, HighRoot) {
- // Test the range we will opperate in, 1300 to 130 000.
- // We expect some loss in accuracy, accepting +-0.2%.
- for (uint64 i = 1300; i < 20000; i += 100) {
- uint64 cube = i * i * i;
- uint32 cube_root = CubeRoot::Root(cube);
- uint32 margin = cube_root >> 9; // Calculate 0.2% roughly by
- // dividing by 512.
- EXPECT_LE(i - margin, cube_root);
- EXPECT_GE(i + margin, cube_root);
- }
- for (uint64 i = 20000; i < 130000; i *= 2) {
- uint64 cube = i * i * i;
- uint32 cube_root = CubeRoot::Root(cube);
- uint32 margin = cube_root >> 9;
- EXPECT_LE(i - margin, cube_root);
- EXPECT_GE(i + margin, cube_root);
- }
-}
-
-} // namespace test
-} // namespace net
diff --git a/net/quic/congestion_control/cubic.cc b/net/quic/congestion_control/cubic.cc
index 7b99057..dc6b89b 100644
--- a/net/quic/congestion_control/cubic.cc
+++ b/net/quic/congestion_control/cubic.cc
@@ -10,7 +10,6 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/time/time.h"
-#include "net/quic/congestion_control/cube_root.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_protocol.h"
@@ -136,17 +135,9 @@
time_to_origin_point_ = 0;
origin_point_congestion_window_ = current_congestion_window;
} else {
- if (FLAGS_quic_use_std_cbrt) {
- time_to_origin_point_ = static_cast<uint32>(
- cbrt(kCubeFactor *
- (last_max_congestion_window_ - current_congestion_window)));
- } else {
- // TODO(rjshade): Remove CubeRoot source when removing
- // FLAGS_quic_use_std_cbrt.
- time_to_origin_point_ =
- CubeRoot::Root(kCubeFactor * (last_max_congestion_window_ -
- current_congestion_window));
- }
+ time_to_origin_point_ =
+ static_cast<uint32>(cbrt(kCubeFactor * (last_max_congestion_window_ -
+ current_congestion_window)));
origin_point_congestion_window_ =
last_max_congestion_window_;
}
diff --git a/net/quic/congestion_control/receive_algorithm_interface.cc b/net/quic/congestion_control/receive_algorithm_interface.cc
deleted file mode 100644
index a619dd5..0000000
--- a/net/quic/congestion_control/receive_algorithm_interface.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.
-
-#include "net/quic/congestion_control/receive_algorithm_interface.h"
-
-#include "net/quic/congestion_control/tcp_receiver.h"
-
-namespace net {
-
-// Factory for receive side congestion control algorithm.
-ReceiveAlgorithmInterface* ReceiveAlgorithmInterface::Create() {
- return new TcpReceiver();
-}
-
-} // namespace net
diff --git a/net/quic/congestion_control/receive_algorithm_interface.h b/net/quic/congestion_control/receive_algorithm_interface.h
deleted file mode 100644
index ef4fb60..0000000
--- a/net/quic/congestion_control/receive_algorithm_interface.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.
-//
-// The pure virtual class for receive side congestion algorithm.
-
-#ifndef NET_QUIC_CONGESTION_CONTROL_RECEIVE_ALGORITHM_INTERFACE_H_
-#define NET_QUIC_CONGESTION_CONTROL_RECEIVE_ALGORITHM_INTERFACE_H_
-
-#include "base/basictypes.h"
-#include "net/base/net_export.h"
-#include "net/quic/quic_clock.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/quic_time.h"
-
-namespace net {
-
-class NET_EXPORT_PRIVATE ReceiveAlgorithmInterface {
- public:
- static ReceiveAlgorithmInterface* Create();
-
- virtual ~ReceiveAlgorithmInterface() {}
-
- // Should be called for each incoming packet.
- // bytes: is the packet size in bytes including IP headers.
- // sequence_number: is the unique sequence number from the QUIC packet header.
- // timestamp: is the sent timestamp from the QUIC packet header.
- virtual void RecordIncomingPacket(QuicByteCount bytes,
- QuicPacketSequenceNumber sequence_number,
- QuicTime timestamp) = 0;
-};
-
-} // namespace net
-
-#endif // NET_QUIC_CONGESTION_CONTROL_RECEIVE_ALGORITHM_INTERFACE_H_
diff --git a/net/quic/congestion_control/send_algorithm_simulator.cc b/net/quic/congestion_control/send_algorithm_simulator.cc
index eedebe5..3d6d456 100644
--- a/net/quic/congestion_control/send_algorithm_simulator.cc
+++ b/net/quic/congestion_control/send_algorithm_simulator.cc
@@ -11,7 +11,6 @@
#include "net/quic/crypto/quic_random.h"
using std::list;
-using std::make_pair;
using std::max;
using std::min;
using std::string;
@@ -290,13 +289,13 @@
if (it->sequence_number > sender->last_acked) {
DVLOG(1) << "Lost packet:" << sender->last_acked
<< " dropped by buffer overflow.";
- lost_packets.push_back(make_pair(sender->last_acked, info));
+ lost_packets.push_back(std::make_pair(sender->last_acked, info));
continue;
}
if (it->lost) {
- lost_packets.push_back(make_pair(sender->last_acked, info));
+ lost_packets.push_back(std::make_pair(sender->last_acked, info));
} else {
- acked_packets.push_back(make_pair(sender->last_acked, info));
+ acked_packets.push_back(std::make_pair(sender->last_acked, info));
}
// This packet has been acked or lost, remove it from sent_packets_.
largest_observed = *it;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index 8df0ea8..6cfa6c1 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -8,14 +8,13 @@
#include "base/memory/scoped_ptr.h"
#include "net/quic/congestion_control/rtt_stats.h"
#include "net/quic/congestion_control/tcp_cubic_sender.h"
-#include "net/quic/congestion_control/tcp_receiver.h"
#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/quic_protocol.h"
#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_config_peer.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::make_pair;
using std::min;
namespace net {
@@ -65,7 +64,6 @@
: one_ms_(QuicTime::Delta::FromMilliseconds(1)),
sender_(new TcpCubicSenderPeer(&clock_, true,
kMaxTcpCongestionWindow)),
- receiver_(new TcpReceiver()),
sequence_number_(1),
acked_sequence_number_(0),
bytes_in_flight_(0) {
@@ -98,7 +96,7 @@
for (int i = 0; i < n; ++i) {
++acked_sequence_number_;
acked_packets.push_back(
- make_pair(acked_sequence_number_, standard_packet_));
+ std::make_pair(acked_sequence_number_, standard_packet_));
}
sender_->OnCongestionEvent(
true, bytes_in_flight_, acked_packets, lost_packets);
@@ -112,7 +110,7 @@
for (int i = 0; i < n; ++i) {
++acked_sequence_number_;
lost_packets.push_back(
- make_pair(acked_sequence_number_, standard_packet_));
+ std::make_pair(acked_sequence_number_, standard_packet_));
}
sender_->OnCongestionEvent(
false, bytes_in_flight_, acked_packets, lost_packets);
@@ -123,8 +121,7 @@
void LosePacket(QuicPacketSequenceNumber sequence_number) {
SendAlgorithmInterface::CongestionVector acked_packets;
SendAlgorithmInterface::CongestionVector lost_packets;
- lost_packets.push_back(
- make_pair(sequence_number, standard_packet_));
+ lost_packets.push_back(std::make_pair(sequence_number, standard_packet_));
sender_->OnCongestionEvent(
false, bytes_in_flight_, acked_packets, lost_packets);
bytes_in_flight_ -= kDefaultTCPMSS;
@@ -133,7 +130,6 @@
const QuicTime::Delta one_ms_;
MockClock clock_;
scoped_ptr<TcpCubicSenderPeer> sender_;
- scoped_ptr<TcpReceiver> receiver_;
QuicPacketSequenceNumber sequence_number_;
QuicPacketSequenceNumber acked_sequence_number_;
QuicByteCount bytes_in_flight_;
diff --git a/net/quic/congestion_control/tcp_loss_algorithm_test.cc b/net/quic/congestion_control/tcp_loss_algorithm_test.cc
index bb56d88..a1296cd 100644
--- a/net/quic/congestion_control/tcp_loss_algorithm_test.cc
+++ b/net/quic/congestion_control/tcp_loss_algorithm_test.cc
@@ -35,9 +35,7 @@
}
void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
- packets_.push_back(QuicPacket::NewDataPacket(
- nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
- PACKET_1BYTE_SEQUENCE_NUMBER));
+ packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
packets_.back(), 0, new RetransmittableFrames());
unacked_packets_.AddSentPacket(packet, 0, NOT_RETRANSMISSION, clock_.Now(),
@@ -56,7 +54,7 @@
}
}
- vector<QuicPacket*> packets_;
+ vector<QuicEncryptedPacket*> packets_;
QuicUnackedPacketMap unacked_packets_;
TCPLossAlgorithm loss_algorithm_;
RttStats rtt_stats_;
@@ -80,7 +78,7 @@
// Loss on three acks.
unacked_packets_.RemoveFromInFlight(4);
unacked_packets_.NackPacket(1, 3);
- QuicPacketSequenceNumber lost[] = { 1 };
+ QuicPacketSequenceNumber lost[] = {1};
VerifyLosses(4, lost, arraysize(lost));
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
diff --git a/net/quic/congestion_control/tcp_receiver.cc b/net/quic/congestion_control/tcp_receiver.cc
deleted file mode 100644
index d29c711..0000000
--- a/net/quic/congestion_control/tcp_receiver.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.
-
-#include "base/basictypes.h"
-#include "net/quic/congestion_control/tcp_receiver.h"
-
-namespace net {
-
-// Originally 64K bytes, but increased it to 256K to support higher bitrates.
-// static
-const QuicByteCount TcpReceiver::kReceiveWindowTCP = 256000;
-
-TcpReceiver::TcpReceiver()
- : receive_window_(kReceiveWindowTCP) {
-}
-
-void TcpReceiver::RecordIncomingPacket(QuicByteCount bytes,
- QuicPacketSequenceNumber sequence_number,
- QuicTime timestamp) {
-}
-
-} // namespace net
diff --git a/net/quic/congestion_control/tcp_receiver.h b/net/quic/congestion_control/tcp_receiver.h
deleted file mode 100644
index 8c16584..0000000
--- a/net/quic/congestion_control/tcp_receiver.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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.
-//
-// TCP receiver side congestion algorithm, emulates the behaviour of TCP.
-
-#ifndef NET_QUIC_CONGESTION_CONTROL_TCP_RECEIVER_H_
-#define NET_QUIC_CONGESTION_CONTROL_TCP_RECEIVER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "net/base/net_export.h"
-#include "net/quic/congestion_control/receive_algorithm_interface.h"
-#include "net/quic/quic_clock.h"
-#include "net/quic/quic_protocol.h"
-
-namespace net {
-
-class NET_EXPORT_PRIVATE TcpReceiver : public ReceiveAlgorithmInterface {
- public:
- TcpReceiver();
-
- // Size of the (currently fixed) receive window.
- static const QuicByteCount kReceiveWindowTCP;
-
- void RecordIncomingPacket(QuicByteCount bytes,
- QuicPacketSequenceNumber sequence_number,
- QuicTime timestamp) override;
-
- private:
- QuicByteCount receive_window_;
-
- DISALLOW_COPY_AND_ASSIGN(TcpReceiver);
-};
-
-} // namespace net
-#endif // NET_QUIC_CONGESTION_CONTROL_TCP_RECEIVER_H_
diff --git a/net/quic/congestion_control/tcp_receiver_test.cc b/net/quic/congestion_control/tcp_receiver_test.cc
deleted file mode 100644
index 5ae1a00..0000000
--- a/net/quic/congestion_control/tcp_receiver_test.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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.
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/quic/congestion_control/tcp_receiver.h"
-#include "net/quic/test_tools/mock_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace test {
-
-class QuicTcpReceiverTest : public ::testing::Test {
- protected:
- void SetUp() override { receiver_.reset(new TcpReceiver()); }
- scoped_ptr<TcpReceiver> receiver_;
-};
-
-TEST_F(QuicTcpReceiverTest, SimpleReceiver) {
- QuicTime timestamp(QuicTime::Zero());
- receiver_->RecordIncomingPacket(1, 1, timestamp);
-}
-
-} // namespace test
-} // namespace net
diff --git a/net/quic/congestion_control/time_loss_algorithm_test.cc b/net/quic/congestion_control/time_loss_algorithm_test.cc
index 1e9b7e5..9eec310 100644
--- a/net/quic/congestion_control/time_loss_algorithm_test.cc
+++ b/net/quic/congestion_control/time_loss_algorithm_test.cc
@@ -35,9 +35,7 @@
}
void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
- packets_.push_back(QuicPacket::NewDataPacket(
- nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
- PACKET_1BYTE_SEQUENCE_NUMBER));
+ packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
SerializedPacket packet(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
packets_.back(), 0, new RetransmittableFrames());
unacked_packets_.AddSentPacket(packet, 0, NOT_RETRANSMISSION, clock_.Now(),
@@ -56,7 +54,7 @@
}
}
- vector<QuicPacket*> packets_;
+ vector<QuicEncryptedPacket*> packets_;
QuicUnackedPacketMap unacked_packets_;
TimeLossAlgorithm loss_algorithm_;
RttStats rtt_stats_;
diff --git a/net/quic/crypto/aead_base_decrypter.h b/net/quic/crypto/aead_base_decrypter.h
index 1aeb671..4e74756 100644
--- a/net/quic/crypto/aead_base_decrypter.h
+++ b/net/quic/crypto/aead_base_decrypter.h
@@ -42,9 +42,12 @@
// QuicDecrypter implementation
bool SetKey(base::StringPiece key) override;
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
- QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number,
- base::StringPiece associated_data,
- base::StringPiece ciphertext) override;
+ bool DecryptPacket(QuicPacketSequenceNumber sequence_number,
+ const base::StringPiece& associated_data,
+ const base::StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override;
base::StringPiece GetKey() const override;
base::StringPiece GetNoncePrefix() const override;
@@ -69,17 +72,18 @@
};
virtual void FillAeadParams(base::StringPiece nonce,
- base::StringPiece associated_data,
+ const base::StringPiece& associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const = 0;
#endif // !defined(USE_OPENSSL)
private:
bool Decrypt(base::StringPiece nonce,
- base::StringPiece associated_data,
- base::StringPiece ciphertext,
- unsigned char* output,
- size_t* output_length);
+ const base::StringPiece& associated_data,
+ const base::StringPiece& ciphertext,
+ uint8* output,
+ size_t* output_length,
+ size_t max_output_length);
#if defined(USE_OPENSSL)
const EVP_AEAD* const aead_alg_;
diff --git a/net/quic/crypto/aead_base_decrypter_nss.cc b/net/quic/crypto/aead_base_decrypter_nss.cc
index 2401222..1ed4f3a 100644
--- a/net/quic/crypto/aead_base_decrypter_nss.cc
+++ b/net/quic/crypto/aead_base_decrypter_nss.cc
@@ -48,10 +48,11 @@
}
bool AeadBaseDecrypter::Decrypt(StringPiece nonce,
- StringPiece associated_data,
- StringPiece ciphertext,
+ const StringPiece& associated_data,
+ const StringPiece& ciphertext,
uint8* output,
- size_t* output_length) {
+ size_t* output_length,
+ size_t max_output_length) {
if (ciphertext.length() < auth_tag_size_ ||
nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketSequenceNumber)) {
return false;
@@ -100,8 +101,8 @@
param.len = aead_params.len;
unsigned int output_len;
- if (pk11_decrypt_(aead_key.get(), aead_mechanism_, ¶m,
- output, &output_len, ciphertext.length(),
+ if (pk11_decrypt_(aead_key.get(), aead_mechanism_, ¶m, output,
+ &output_len, max_output_length,
reinterpret_cast<const unsigned char*>(ciphertext.data()),
ciphertext.length()) != SECSuccess) {
return false;
@@ -115,28 +116,24 @@
return true;
}
-QuicData* AeadBaseDecrypter::DecryptPacket(
- QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece ciphertext) {
+bool AeadBaseDecrypter::DecryptPacket(QuicPacketSequenceNumber sequence_number,
+ const StringPiece& associated_data,
+ const StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) {
if (ciphertext.length() < auth_tag_size_) {
- return nullptr;
+ return false;
}
- size_t plaintext_size;
- scoped_ptr<char[]> plaintext(new char[ciphertext.length()]);
uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)];
const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number);
DCHECK_LE(nonce_size, sizeof(nonce));
memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number));
- if (!Decrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size),
- associated_data, ciphertext,
- reinterpret_cast<uint8*>(plaintext.get()),
- &plaintext_size)) {
- return nullptr;
- }
- return new QuicData(plaintext.release(), plaintext_size, true);
+ return Decrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size),
+ associated_data, ciphertext, reinterpret_cast<uint8*>(output),
+ output_length, max_output_length);
}
StringPiece AeadBaseDecrypter::GetKey() const {
diff --git a/net/quic/crypto/aead_base_decrypter_openssl.cc b/net/quic/crypto/aead_base_decrypter_openssl.cc
index 62a6fb8..2311640 100644
--- a/net/quic/crypto/aead_base_decrypter_openssl.cc
+++ b/net/quic/crypto/aead_base_decrypter_openssl.cc
@@ -77,52 +77,49 @@
}
bool AeadBaseDecrypter::Decrypt(StringPiece nonce,
- StringPiece associated_data,
- StringPiece ciphertext,
+ const StringPiece& associated_data,
+ const StringPiece& ciphertext,
uint8* output,
- size_t* output_length) {
+ size_t* output_length,
+ size_t max_output_length) {
if (ciphertext.length() < auth_tag_size_ ||
nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketSequenceNumber)) {
return false;
}
if (!EVP_AEAD_CTX_open(
- ctx_.get(), output, output_length, ciphertext.size(),
- reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
- reinterpret_cast<const uint8_t*>(ciphertext.data()), ciphertext.size(),
- reinterpret_cast<const uint8_t*>(associated_data.data()),
- associated_data.size())) {
+ ctx_.get(), output, output_length, max_output_length,
+ reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
+ reinterpret_cast<const uint8_t*>(ciphertext.data()),
+ ciphertext.size(),
+ reinterpret_cast<const uint8_t*>(associated_data.data()),
+ associated_data.size())) {
// Because QuicFramer does trial decryption, decryption errors are expected
// when encryption level changes. So we don't log decryption errors.
ClearOpenSslErrors();
return false;
}
-
return true;
}
-QuicData* AeadBaseDecrypter::DecryptPacket(
- QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece ciphertext) {
+bool AeadBaseDecrypter::DecryptPacket(QuicPacketSequenceNumber sequence_number,
+ const StringPiece& associated_data,
+ const StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) {
if (ciphertext.length() < auth_tag_size_) {
- return nullptr;
+ return false;
}
- size_t plaintext_size = ciphertext.length();
- scoped_ptr<char[]> plaintext(new char[plaintext_size]);
uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)];
const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number);
DCHECK_LE(nonce_size, sizeof(nonce));
memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number));
- if (!Decrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size),
- associated_data, ciphertext,
- reinterpret_cast<uint8*>(plaintext.get()),
- &plaintext_size)) {
- return nullptr;
- }
- return new QuicData(plaintext.release(), plaintext_size, true);
+ return Decrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size),
+ associated_data, ciphertext, reinterpret_cast<uint8*>(output),
+ output_length, max_output_length);
}
StringPiece AeadBaseDecrypter::GetKey() const {
diff --git a/net/quic/crypto/aead_base_encrypter.h b/net/quic/crypto/aead_base_encrypter.h
index 7d9b6fc..8108744 100644
--- a/net/quic/crypto/aead_base_encrypter.h
+++ b/net/quic/crypto/aead_base_encrypter.h
@@ -46,9 +46,12 @@
base::StringPiece associated_data,
base::StringPiece plaintext,
unsigned char* output) override;
- QuicData* EncryptPacket(QuicPacketSequenceNumber sequence_number,
- base::StringPiece associated_data,
- base::StringPiece plaintext) override;
+ bool EncryptPacket(QuicPacketSequenceNumber sequence_number,
+ base::StringPiece associated_data,
+ base::StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override;
size_t GetKeySize() const override;
size_t GetNoncePrefixSize() const override;
size_t GetMaxPlaintextSize(size_t ciphertext_size) const override;
diff --git a/net/quic/crypto/aead_base_encrypter_nss.cc b/net/quic/crypto/aead_base_encrypter_nss.cc
index 1e408ad..ca2e2a9 100644
--- a/net/quic/crypto/aead_base_encrypter_nss.cc
+++ b/net/quic/crypto/aead_base_encrypter_nss.cc
@@ -110,27 +110,28 @@
return true;
}
-QuicData* AeadBaseEncrypter::EncryptPacket(
- QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece plaintext) {
+bool AeadBaseEncrypter::EncryptPacket(QuicPacketSequenceNumber sequence_number,
+ StringPiece associated_data,
+ StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) {
size_t ciphertext_size = GetCiphertextSize(plaintext.length());
- scoped_ptr<char[]> ciphertext(new char[ciphertext_size]);
-
+ if (max_output_length < ciphertext_size) {
+ return false;
+ }
// TODO(ianswett): Introduce a check to ensure that we don't encrypt with the
// same sequence number twice.
- uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)];
const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number);
- DCHECK_LE(nonce_size, sizeof(nonce));
- memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
- memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number));
- if (!Encrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size),
- associated_data, plaintext,
- reinterpret_cast<unsigned char*>(ciphertext.get()))) {
- return nullptr;
+ memcpy(output, nonce_prefix_, nonce_prefix_size_);
+ memcpy(output + nonce_prefix_size_, &sequence_number,
+ sizeof(sequence_number));
+ if (!Encrypt(StringPiece(output, nonce_size), associated_data, plaintext,
+ reinterpret_cast<unsigned char*>(output))) {
+ return false;
}
-
- return new QuicData(ciphertext.release(), ciphertext_size, true);
+ *output_length = ciphertext_size;
+ return true;
}
size_t AeadBaseEncrypter::GetKeySize() const { return key_size_; }
diff --git a/net/quic/crypto/aead_base_encrypter_openssl.cc b/net/quic/crypto/aead_base_encrypter_openssl.cc
index 25d9967..be4b1e8 100644
--- a/net/quic/crypto/aead_base_encrypter_openssl.cc
+++ b/net/quic/crypto/aead_base_encrypter_openssl.cc
@@ -81,16 +81,12 @@
return false;
}
- size_t len;
+ size_t ciphertext_len;
if (!EVP_AEAD_CTX_seal(
- ctx_.get(),
- output,
- &len,
+ ctx_.get(), output, &ciphertext_len,
plaintext.size() + auth_tag_size_,
- reinterpret_cast<const uint8_t*>(nonce.data()),
- nonce.size(),
- reinterpret_cast<const uint8_t*>(plaintext.data()),
- plaintext.size(),
+ reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(),
+ reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size(),
reinterpret_cast<const uint8_t*>(associated_data.data()),
associated_data.size())) {
DLogOpenSslErrors();
@@ -100,27 +96,28 @@
return true;
}
-QuicData* AeadBaseEncrypter::EncryptPacket(
- QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece plaintext) {
+bool AeadBaseEncrypter::EncryptPacket(QuicPacketSequenceNumber sequence_number,
+ StringPiece associated_data,
+ StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) {
size_t ciphertext_size = GetCiphertextSize(plaintext.length());
- scoped_ptr<char[]> ciphertext(new char[ciphertext_size]);
-
+ if (max_output_length < ciphertext_size) {
+ return false;
+ }
// TODO(ianswett): Introduce a check to ensure that we don't encrypt with the
// same sequence number twice.
- uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)];
const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number);
- DCHECK_LE(nonce_size, sizeof(nonce));
- memcpy(nonce, nonce_prefix_, nonce_prefix_size_);
- memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number));
- if (!Encrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size),
- associated_data, plaintext,
- reinterpret_cast<unsigned char*>(ciphertext.get()))) {
- return nullptr;
+ memcpy(output, nonce_prefix_, nonce_prefix_size_);
+ memcpy(output + nonce_prefix_size_, &sequence_number,
+ sizeof(sequence_number));
+ if (!Encrypt(StringPiece(output, nonce_size), associated_data, plaintext,
+ reinterpret_cast<unsigned char*>(output))) {
+ return false;
}
-
- return new QuicData(ciphertext.release(), ciphertext_size, true);
+ *output_length = ciphertext_size;
+ return true;
}
size_t AeadBaseEncrypter::GetKeySize() const { return key_size_; }
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter.h b/net/quic/crypto/aes_128_gcm_12_decrypter.h
index 0f7f1d1..db4a232 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter.h
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter.h
@@ -29,7 +29,7 @@
protected:
// AeadBaseDecrypter methods:
void FillAeadParams(base::StringPiece nonce,
- base::StringPiece associated_data,
+ const base::StringPiece& associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const override;
#endif
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
index c1dabed..2378d3a 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter_nss.cc
@@ -219,7 +219,7 @@
Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {}
void Aes128Gcm12Decrypter::FillAeadParams(StringPiece nonce,
- StringPiece associated_data,
+ const StringPiece& associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const {
aead_params->len = sizeof(aead_params->data.gcm_params);
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
index 377d2b5..d55bab2 100644
--- a/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -263,7 +263,15 @@
decrypter->SetNoncePrefix(nonce_prefix);
memcpy(&sequence_number, nonce.data() + nonce_prefix.size(),
sizeof(sequence_number));
- return decrypter->DecryptPacket(sequence_number, associated_data, ciphertext);
+ scoped_ptr<char[]> output(new char[ciphertext.length()]);
+ size_t output_length = 0;
+ const bool success = decrypter->DecryptPacket(
+ sequence_number, associated_data, ciphertext, output.get(),
+ &output_length, ciphertext.length());
+ if (!success) {
+ return nullptr;
+ }
+ return new QuicData(output.release(), output_length, true);
}
TEST(Aes128Gcm12DecrypterTest, Decrypt) {
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter.h b/net/quic/crypto/chacha20_poly1305_decrypter.h
index 7d81d70..d244df7 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter.h
+++ b/net/quic/crypto/chacha20_poly1305_decrypter.h
@@ -33,7 +33,7 @@
protected:
// AeadBaseDecrypter methods:
void FillAeadParams(base::StringPiece nonce,
- base::StringPiece associated_data,
+ const base::StringPiece& associated_data,
size_t auth_tag_size,
AeadParams* aead_params) const override;
#endif
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc b/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
index 0d8eff0..b78db05 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
+++ b/net/quic/crypto/chacha20_poly1305_decrypter_nss.cc
@@ -36,10 +36,11 @@
return false;
}
-void ChaCha20Poly1305Decrypter::FillAeadParams(StringPiece nonce,
- StringPiece associated_data,
- size_t auth_tag_size,
- AeadParams* aead_params) const {
+void ChaCha20Poly1305Decrypter::FillAeadParams(
+ StringPiece nonce,
+ const StringPiece& associated_data,
+ size_t auth_tag_size,
+ AeadParams* aead_params) const {
NOTIMPLEMENTED();
}
@@ -60,10 +61,11 @@
return true;
}
-void ChaCha20Poly1305Decrypter::FillAeadParams(StringPiece nonce,
- StringPiece associated_data,
- size_t auth_tag_size,
- AeadParams* aead_params) const {
+void ChaCha20Poly1305Decrypter::FillAeadParams(
+ StringPiece nonce,
+ const StringPiece& associated_data,
+ size_t auth_tag_size,
+ AeadParams* aead_params) const {
aead_params->len = sizeof(aead_params->data.nss_aead_params);
CK_NSS_AEAD_PARAMS* nss_aead_params = &aead_params->data.nss_aead_params;
nss_aead_params->pIv =
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter_test.cc b/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
index 54ca9ff..8a4cec4 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
+++ b/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
@@ -81,7 +81,15 @@
decrypter->SetNoncePrefix(nonce_prefix);
memcpy(&sequence_number, nonce.data() + nonce_prefix.size(),
sizeof(sequence_number));
- return decrypter->DecryptPacket(sequence_number, associated_data, ciphertext);
+ scoped_ptr<char[]> output(new char[ciphertext.length()]);
+ size_t output_length = 0;
+ const bool success = decrypter->DecryptPacket(
+ sequence_number, associated_data, ciphertext, output.get(),
+ &output_length, ciphertext.length());
+ if (!success) {
+ return nullptr;
+ }
+ return new QuicData(output.release(), output_length, true);
}
TEST(ChaCha20Poly1305DecrypterTest, Decrypt) {
diff --git a/net/quic/crypto/crypto_framer.cc b/net/quic/crypto/crypto_framer.cc
index 79e17ed..7f81f36 100644
--- a/net/quic/crypto/crypto_framer.cc
+++ b/net/quic/crypto/crypto_framer.cc
@@ -9,7 +9,6 @@
#include "net/quic/quic_data_writer.h"
using base::StringPiece;
-using std::make_pair;
using std::pair;
using std::vector;
@@ -106,8 +105,8 @@
return nullptr;
}
-
- QuicDataWriter writer(len);
+ scoped_ptr<char[]> buffer(new char[len]);
+ QuicDataWriter writer(len, buffer.get());
if (!writer.WriteUInt32(message.tag())) {
DCHECK(false) << "Failed to write message tag.";
return nullptr;
@@ -181,7 +180,7 @@
}
}
- return new QuicData(writer.take(), len, true);
+ return new QuicData(buffer.release(), len, true);
}
void CryptoFramer::Clear() {
@@ -242,8 +241,8 @@
if (end_offset < last_end_offset) {
return QUIC_CRYPTO_TAGS_OUT_OF_ORDER;
}
- tags_and_lengths_.push_back(
- make_pair(tag, static_cast<size_t>(end_offset - last_end_offset)));
+ tags_and_lengths_.push_back(std::make_pair(
+ tag, static_cast<size_t>(end_offset - last_end_offset)));
last_end_offset = end_offset;
}
values_len_ = last_end_offset;
diff --git a/net/quic/crypto/crypto_secret_boxer.cc b/net/quic/crypto/crypto_secret_boxer.cc
index 445d888..b139a6a 100644
--- a/net/quic/crypto/crypto_secret_boxer.cc
+++ b/net/quic/crypto/crypto_secret_boxer.cc
@@ -88,15 +88,18 @@
return false;
}
decrypter->SetNoncePrefix(nonce_prefix);
- scoped_ptr<QuicData> decrypted(
- decrypter->DecryptPacket(sequence_number, StringPiece(), ciphertext));
- if (!decrypted.get()) {
+ char plaintext[kMaxPacketSize];
+ size_t plaintext_length = 0;
+ const bool success = decrypter->DecryptPacket(
+ sequence_number, StringPiece() /* associated data */, ciphertext,
+ plaintext, &plaintext_length, kMaxPacketSize);
+ if (!success) {
return false;
}
- out_storage->resize(decrypted->length());
- out_storage->assign(decrypted->data(), decrypted->length());
- out->set(out_storage->data(), decrypted->length());
+ out_storage->resize(plaintext_length);
+ out_storage->assign(plaintext, plaintext_length);
+ out->set(out_storage->data(), plaintext_length);
return true;
}
diff --git a/net/quic/crypto/null_decrypter.cc b/net/quic/crypto/null_decrypter.cc
index 4411b7c..8a18172 100644
--- a/net/quic/crypto/null_decrypter.cc
+++ b/net/quic/crypto/null_decrypter.cc
@@ -19,28 +19,31 @@
return nonce_prefix.empty();
}
-QuicData* NullDecrypter::DecryptPacket(QuicPacketSequenceNumber /*seq_number*/,
- StringPiece associated_data,
- StringPiece ciphertext) {
- // It's worth duplicating |Decrypt|, above, in order to save a copy by using
- // the shared-data QuicData constructor directly.
+bool NullDecrypter::DecryptPacket(QuicPacketSequenceNumber /*seq_number*/,
+ const StringPiece& associated_data,
+ const StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) {
QuicDataReader reader(ciphertext.data(), ciphertext.length());
-
uint128 hash;
+
if (!ReadHash(&reader, &hash)) {
- return nullptr;
+ return false;
}
StringPiece plaintext = reader.ReadRemainingPayload();
-
- // TODO(rch): avoid buffer copy here
- string buffer = associated_data.as_string();
- plaintext.AppendToString(&buffer);
-
- if (hash != ComputeHash(buffer)) {
- return nullptr;
+ if (plaintext.length() > max_output_length) {
+ LOG(DFATAL) << "Output buffer must be larger than the plaintext.";
+ return false;
}
- return new QuicData(plaintext.data(), plaintext.length());
+ if (hash != ComputeHash(associated_data, plaintext)) {
+ return false;
+ }
+ // Copy the plaintext to output.
+ memcpy(output, plaintext.data(), plaintext.length());
+ *output_length = plaintext.length();
+ return true;
}
StringPiece NullDecrypter::GetKey() const { return StringPiece(); }
@@ -60,8 +63,10 @@
return true;
}
-uint128 NullDecrypter::ComputeHash(const string& data) const {
- uint128 correct_hash = QuicUtils::FNV1a_128_Hash(data.data(), data.length());
+uint128 NullDecrypter::ComputeHash(const StringPiece& data1,
+ const StringPiece& data2) const {
+ uint128 correct_hash = QuicUtils::FNV1a_128_Hash_Two(
+ data1.data(), data1.length(), data2.data(), data2.length());
uint128 mask(GG_UINT64_C(0x0), GG_UINT64_C(0xffffffff));
mask <<= 96;
correct_hash &= ~mask;
diff --git a/net/quic/crypto/null_decrypter.h b/net/quic/crypto/null_decrypter.h
index db98a99..cd188d9 100644
--- a/net/quic/crypto/null_decrypter.h
+++ b/net/quic/crypto/null_decrypter.h
@@ -24,15 +24,19 @@
// QuicDecrypter implementation
bool SetKey(base::StringPiece key) override;
bool SetNoncePrefix(base::StringPiece nonce_prefix) override;
- QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number,
- base::StringPiece associated_data,
- base::StringPiece ciphertext) override;
+ bool DecryptPacket(QuicPacketSequenceNumber sequence_number,
+ const base::StringPiece& associated_data,
+ const base::StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override;
base::StringPiece GetKey() const override;
base::StringPiece GetNoncePrefix() const override;
private:
bool ReadHash(QuicDataReader* reader, uint128* hash);
- uint128 ComputeHash(const std::string& data) const;
+ uint128 ComputeHash(const base::StringPiece& data1,
+ const base::StringPiece& data2) const;
DISALLOW_COPY_AND_ASSIGN(NullDecrypter);
};
diff --git a/net/quic/crypto/null_decrypter_test.cc b/net/quic/crypto/null_decrypter_test.cc
index 173ecde..4c8bae4 100644
--- a/net/quic/crypto/null_decrypter_test.cc
+++ b/net/quic/crypto/null_decrypter_test.cc
@@ -26,10 +26,12 @@
const char* data = reinterpret_cast<const char*>(expected);
size_t len = arraysize(expected);
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(
- decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len)));
- ASSERT_TRUE(decrypted.get());
- EXPECT_EQ("goodbye!", decrypted->AsStringPiece());
+ char buffer[256];
+ size_t length = 0;
+ ASSERT_TRUE(decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len),
+ buffer, &length, 256));
+ EXPECT_LT(0u, length);
+ EXPECT_EQ("goodbye!", StringPiece(buffer, length));
}
TEST_F(NullDecrypterTest, BadHash) {
@@ -45,9 +47,10 @@
const char* data = reinterpret_cast<const char*>(expected);
size_t len = arraysize(expected);
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(
- decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len)));
- ASSERT_FALSE(decrypted.get());
+ char buffer[256];
+ size_t length = 0;
+ ASSERT_FALSE(decrypter.DecryptPacket(
+ 0, "hello world!", StringPiece(data, len), buffer, &length, 256));
}
TEST_F(NullDecrypterTest, ShortInput) {
@@ -60,9 +63,10 @@
const char* data = reinterpret_cast<const char*>(expected);
size_t len = arraysize(expected);
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(
- decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len)));
- ASSERT_FALSE(decrypted.get());
+ char buffer[256];
+ size_t length = 0;
+ ASSERT_FALSE(decrypter.DecryptPacket(
+ 0, "hello world!", StringPiece(data, len), buffer, &length, 256));
}
} // namespace test
diff --git a/net/quic/crypto/null_encrypter.cc b/net/quic/crypto/null_encrypter.cc
index 5f1a85b..286694a 100644
--- a/net/quic/crypto/null_encrypter.cc
+++ b/net/quic/crypto/null_encrypter.cc
@@ -34,14 +34,20 @@
return true;
}
-QuicData* NullEncrypter::EncryptPacket(
- QuicPacketSequenceNumber /*sequence_number*/,
- StringPiece associated_data,
- StringPiece plaintext) {
+bool NullEncrypter::EncryptPacket(QuicPacketSequenceNumber /*sequence_number*/,
+ StringPiece associated_data,
+ StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) {
const size_t len = plaintext.size() + GetHashLength();
- uint8* buffer = new uint8[len];
- Encrypt(StringPiece(), associated_data, plaintext, buffer);
- return new QuicData(reinterpret_cast<char*>(buffer), len, true);
+ if (max_output_length < len) {
+ return false;
+ }
+ Encrypt(StringPiece(), associated_data, plaintext,
+ reinterpret_cast<unsigned char*>(output));
+ *output_length = len;
+ return true;
}
size_t NullEncrypter::GetKeySize() const { return 0; }
diff --git a/net/quic/crypto/null_encrypter.h b/net/quic/crypto/null_encrypter.h
index b52bd9c..40bcacc 100644
--- a/net/quic/crypto/null_encrypter.h
+++ b/net/quic/crypto/null_encrypter.h
@@ -26,9 +26,12 @@
base::StringPiece associated_data,
base::StringPiece plaintext,
unsigned char* output) override;
- QuicData* EncryptPacket(QuicPacketSequenceNumber sequence_number,
- base::StringPiece associated_data,
- base::StringPiece plaintext) override;
+ bool EncryptPacket(QuicPacketSequenceNumber sequence_number,
+ base::StringPiece associated_data,
+ base::StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override;
size_t GetKeySize() const override;
size_t GetNoncePrefixSize() const override;
size_t GetMaxPlaintextSize(size_t ciphertext_size) const override;
diff --git a/net/quic/crypto/null_encrypter_test.cc b/net/quic/crypto/null_encrypter_test.cc
index 4f4dae7..e9ae773 100644
--- a/net/quic/crypto/null_encrypter_test.cc
+++ b/net/quic/crypto/null_encrypter_test.cc
@@ -24,13 +24,13 @@
'b', 'y', 'e', '!',
};
NullEncrypter encrypter;
- scoped_ptr<QuicData> encrypted(
- encrypter.EncryptPacket(0, "hello world!", "goodbye!"));
- ASSERT_TRUE(encrypted.get());
+ char encrypted[256];
+ size_t encrypted_len = 0;
+ ASSERT_TRUE(encrypter.EncryptPacket(0, "hello world!", "goodbye!", encrypted,
+ &encrypted_len, 256));
test::CompareCharArraysWithHexError(
- "encrypted data", encrypted->data(), encrypted->length(),
- reinterpret_cast<const char*>(expected),
- arraysize(expected));
+ "encrypted data", encrypted, encrypted_len,
+ reinterpret_cast<const char*>(expected), arraysize(expected));
}
TEST_F(NullEncrypterTest, GetMaxPlaintextSize) {
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc
index 1e12424..9ec19fd 100644
--- a/net/quic/crypto/quic_crypto_client_config.cc
+++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -23,8 +23,6 @@
#include "net/quic/quic_utils.h"
using base::StringPiece;
-using std::find;
-using std::make_pair;
using std::map;
using std::string;
using std::vector;
@@ -324,7 +322,7 @@
}
CachedState* cached = new CachedState;
- cached_states_.insert(make_pair(server_id, cached));
+ cached_states_.insert(std::make_pair(server_id, cached));
bool cache_populated = PopulateFromCanonicalConfig(server_id, cached);
UMA_HISTOGRAM_BOOLEAN(
"Net.QuicCryptoClientConfig.PopulatedFromCanonicalConfig",
@@ -545,16 +543,19 @@
}
const QuicData& cetv_plaintext = cetv.GetSerialized();
- scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket(
- 0 /* sequence number */,
- StringPiece() /* associated data */,
- cetv_plaintext.AsStringPiece()));
- if (!cetv_ciphertext.get()) {
+ const size_t encrypted_len =
+ crypters.encrypter->GetCiphertextSize(cetv_plaintext.length());
+ scoped_ptr<char[]> output(new char[encrypted_len]);
+ size_t output_size = 0;
+ if (!crypters.encrypter->EncryptPacket(
+ 0 /* sequence number */, StringPiece() /* associated data */,
+ cetv_plaintext.AsStringPiece(), output.get(), &output_size,
+ encrypted_len)) {
*error_details = "Packet encryption failed";
return QUIC_ENCRYPTION_FAILURE;
}
- out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece());
+ out->SetStringPiece(kCETV, StringPiece(output.get(), output_size));
out->MarkDirty();
out->set_minimum_size(orig_min_size);
@@ -837,7 +838,7 @@
if (aead.size() <= 1) {
return;
}
- QuicTagVector::iterator pos = find(aead.begin(), aead.end(), kAESG);
+ QuicTagVector::iterator pos = std::find(aead.begin(), aead.end(), kAESG);
if (pos != aead.end()) {
aead.erase(pos);
aead.insert(aead.begin(), kAESG);
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc
index 7f6a3af..7c76ba8 100644
--- a/net/quic/crypto/quic_crypto_server_config.cc
+++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -452,7 +452,7 @@
reinterpret_cast<const char *>(config->orbit), kOrbitSize)
<< " primary_time " << config->primary_time.ToUNIXSeconds()
<< " priority " << config->priority;
- new_configs.insert(make_pair(config->id, config));
+ new_configs.insert(std::make_pair(config->id, config));
}
}
@@ -684,16 +684,17 @@
return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
}
- scoped_ptr<QuicData> cetv_plaintext(crypters.decrypter->DecryptPacket(
+ char plaintext[kMaxPacketSize];
+ size_t plaintext_length = 0;
+ const bool success = crypters.decrypter->DecryptPacket(
0 /* sequence number */, StringPiece() /* associated data */,
- cetv_ciphertext));
- if (!cetv_plaintext.get()) {
+ cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
+ if (!success) {
*error_details = "CETV decryption failure";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ return QUIC_PACKET_TOO_LARGE;
}
-
- scoped_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
- cetv_plaintext->AsStringPiece()));
+ scoped_ptr<CryptoHandshakeMessage> cetv(
+ CryptoFramer::ParseMessage(StringPiece(plaintext, plaintext_length)));
if (!cetv.get()) {
*error_details = "CETV parse error";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
@@ -835,7 +836,7 @@
return;
}
- sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
+ std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
Config* best_candidate = configs[0].get();
diff --git a/net/quic/crypto/quic_crypto_server_config_test.cc b/net/quic/crypto/quic_crypto_server_config_test.cc
index ac7f3e0..5134f50 100644
--- a/net/quic/crypto/quic_crypto_server_config_test.cc
+++ b/net/quic/crypto/quic_crypto_server_config_test.cc
@@ -21,7 +21,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
-using std::make_pair;
using std::map;
using std::pair;
using std::string;
@@ -152,7 +151,7 @@
// varargs will promote the value to an int so we have to read that from
// the stack and cast down.
const bool is_primary = static_cast<bool>(va_arg(ap, int));
- expected.push_back(make_pair(server_config_id, is_primary));
+ expected.push_back(std::make_pair(server_config_id, is_primary));
}
va_end(ap);
diff --git a/net/quic/crypto/quic_decrypter.h b/net/quic/crypto/quic_decrypter.h
index 9e6e1d2..9e02a16 100644
--- a/net/quic/crypto/quic_decrypter.h
+++ b/net/quic/crypto/quic_decrypter.h
@@ -39,15 +39,20 @@
// packet sequence number, even when retransmitting a lost packet.
virtual bool SetNoncePrefix(base::StringPiece nonce_prefix) = 0;
- // Returns a newly created QuicData object containing the decrypted
- // |ciphertext| or nullptr if there is an error. |sequence_number| is
+ // Populates |output| with the decrypted |ciphertext| and populates
+ // |output_length| with the length. Returns 0 if there is an error.
+ // |output| size is specified by |max_output_length| and must be
+ // at least as large as the ciphertext. |sequence_number| is
// appended to the |nonce_prefix| value provided in SetNoncePrefix()
// to form the nonce.
// TODO(wtc): add a way for DecryptPacket to report decryption failure due
// to non-authentic inputs, as opposed to other reasons for failure.
- virtual QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number,
- base::StringPiece associated_data,
- base::StringPiece ciphertext) = 0;
+ virtual bool DecryptPacket(QuicPacketSequenceNumber sequence_number,
+ const base::StringPiece& associated_data,
+ const base::StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) = 0;
// For use by unit tests only.
virtual base::StringPiece GetKey() const = 0;
diff --git a/net/quic/crypto/quic_encrypter.h b/net/quic/crypto/quic_encrypter.h
index 5cb40a1..2e565c5 100644
--- a/net/quic/crypto/quic_encrypter.h
+++ b/net/quic/crypto/quic_encrypter.h
@@ -53,9 +53,12 @@
// |plaintext| as well as a MAC over both |plaintext| and |associated_data|,
// or nullptr if there is an error. |sequence_number| is appended to the
// |nonce_prefix| value provided in SetNoncePrefix() to form the nonce.
- virtual QuicData* EncryptPacket(QuicPacketSequenceNumber sequence_number,
- base::StringPiece associated_data,
- base::StringPiece plaintext) = 0;
+ virtual bool EncryptPacket(QuicPacketSequenceNumber sequence_number,
+ base::StringPiece associated_data,
+ base::StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) = 0;
// GetKeySize() and GetNoncePrefixSize() tell the HKDF class how many bytes
// of key material needs to be derived from the master secret.
diff --git a/net/quic/crypto/quic_server_info.h b/net/quic/crypto/quic_server_info.h
index 2ea7525..1e4e1bd 100644
--- a/net/quic/crypto/quic_server_info.h
+++ b/net/quic/crypto/quic_server_info.h
@@ -45,6 +45,10 @@
// but, obviously, a callback will never be made.
virtual int WaitForDataReady(const CompletionCallback& callback) = 0;
+ // Reset's WaitForDataReady callback. This method shouldn't have any side
+ // effects (could be called even if HttpCache doesn't exist).
+ virtual void ResetWaitForDataReadyCallback() = 0;
+
// Cancel's WaitForDataReady callback. |callback| passed in WaitForDataReady
// will not be called.
virtual void CancelWaitForDataReadyCallback() = 0;
diff --git a/net/quic/crypto/strike_register.cc b/net/quic/crypto/strike_register.cc
index fd5dc4f..c36d370 100644
--- a/net/quic/crypto/strike_register.cc
+++ b/net/quic/crypto/strike_register.cc
@@ -8,7 +8,6 @@
#include "base/logging.h"
-using std::make_pair;
using std::max;
using std::min;
using std::pair;
@@ -324,7 +323,7 @@
uint32 current_time_internal) const {
if (current_time_internal < horizon_) {
// Empty valid range.
- return make_pair(std::numeric_limits<uint32>::max(), 0);
+ return std::make_pair(std::numeric_limits<uint32>::max(), 0);
}
uint32 lower_bound;
@@ -344,7 +343,7 @@
current_time_internal + min(current_time_internal - horizon_,
window_secs_);
- return make_pair(lower_bound, upper_bound);
+ return std::make_pair(lower_bound, upper_bound);
}
uint32 StrikeRegister::ExternalTimeToInternal(uint32 external_time) const {
diff --git a/net/quic/crypto/strike_register_test.cc b/net/quic/crypto/strike_register_test.cc
index df72357..73a6b2f 100644
--- a/net/quic/crypto/strike_register_test.cc
+++ b/net/quic/crypto/strike_register_test.cc
@@ -15,7 +15,6 @@
using net::InsertStatus;
using net::StrikeRegister;
-using std::make_pair;
using std::min;
using std::pair;
using std::set;
@@ -232,9 +231,8 @@
return net::NONCE_INVALID_TIME_FAILURE;
}
- pair<uint32, string> nonce = make_pair(
- nonce_time,
- string(reinterpret_cast<const char*>(nonce_bytes), 32));
+ pair<uint32, string> nonce = std::make_pair(
+ nonce_time, string(reinterpret_cast<const char*>(nonce_bytes), 32));
set<pair<uint32, string> >::const_iterator it = nonces_.find(nonce);
if (it != nonces_.end()) {
diff --git a/net/quic/quic_ack_notifier.cc b/net/quic/quic_ack_notifier.cc
index b399a61..48ee23d 100644
--- a/net/quic/quic_ack_notifier.cc
+++ b/net/quic/quic_ack_notifier.cc
@@ -29,21 +29,18 @@
QuicAckNotifier::~QuicAckNotifier() {
}
-void QuicAckNotifier::AddSequenceNumber(
- const QuicPacketSequenceNumber& sequence_number,
- int packet_payload_size) {
+void QuicAckNotifier::OnSerializedPacket() {
++unacked_packets_;
- DVLOG(1) << "AckNotifier waiting for packet: " << sequence_number;
}
-bool QuicAckNotifier::OnAck(QuicPacketSequenceNumber sequence_number,
- QuicTime::Delta delta_largest_observed) {
+bool QuicAckNotifier::OnAck(QuicTime::Delta delta_largest_observed) {
if (unacked_packets_ <= 0) {
- LOG(DFATAL) << "Acked more packets than were tracked.";
+ LOG(DFATAL) << "Acked more packets than were tracked."
+ << " unacked_packets:" << unacked_packets_;
return true;
}
--unacked_packets_;
- if (IsEmpty()) {
+ if (!HasUnackedPackets()) {
// We have seen all the sequence numbers we were waiting for, trigger
// callback notification.
delegate_->OnAckNotification(retransmitted_packet_count_,
@@ -54,6 +51,16 @@
return false;
}
+bool QuicAckNotifier::OnPacketAbandoned() {
+ if (unacked_packets_ <= 0) {
+ LOG(DFATAL) << "Abandoned more packets than were tracked."
+ << " unacked_packets:" << unacked_packets_;
+ return true;
+ }
+ --unacked_packets_;
+ return unacked_packets_ == 0;
+}
+
void QuicAckNotifier::OnPacketRetransmitted(int packet_payload_size) {
++retransmitted_packet_count_;
retransmitted_byte_count_ += packet_payload_size;
diff --git a/net/quic/quic_ack_notifier.h b/net/quic/quic_ack_notifier.h
index 160108e..602d86f 100644
--- a/net/quic/quic_ack_notifier.h
+++ b/net/quic/quic_ack_notifier.h
@@ -40,22 +40,22 @@
explicit QuicAckNotifier(DelegateInterface* delegate);
virtual ~QuicAckNotifier();
- // Register a sequence number that this AckNotifier should be interested in.
- void AddSequenceNumber(const QuicPacketSequenceNumber& sequence_number,
- int packet_payload_size);
+ // Register a serialized packet the notifier should track.
+ void OnSerializedPacket();
- // Called by the QuicConnection on receipt of new ACK frame, with the sequence
- // number referenced by the ACK frame.
- // Deletes the matching sequence number from the stored set of sequence
- // numbers. If this set is now empty, call the stored delegate's
- // OnAckNotification method.
+ // Called on receipt of new ACK frame for an unacked packet.
+ // Decrements the number of unacked packets and if there are none left, calls
+ // the stored delegate's OnAckNotification method.
//
- // Returns true if the provided sequence_number caused the delegate to be
- // called, false otherwise.
- bool OnAck(QuicPacketSequenceNumber sequence_number,
- QuicTime::Delta delta_largest_observed);
+ // Returns true if the delegate was called, false otherwise.
+ bool OnAck(QuicTime::Delta delta_largest_observed);
- bool IsEmpty() { return unacked_packets_ == 0; }
+ // Called when we've given up waiting for a sequence number, typically when
+ // the connection is torn down.
+ // Returns true if there are no more unacked packets being tracked.
+ bool OnPacketAbandoned();
+
+ bool HasUnackedPackets() const { return unacked_packets_ > 0; }
// If a packet is retransmitted by the connection, it will be sent with a
// different sequence number.
diff --git a/net/quic/quic_ack_notifier_manager.cc b/net/quic/quic_ack_notifier_manager.cc
index 0d37752..73e3c8e 100644
--- a/net/quic/quic_ack_notifier_manager.cc
+++ b/net/quic/quic_ack_notifier_manager.cc
@@ -20,7 +20,13 @@
AckNotifierManager::AckNotifierManager() {}
AckNotifierManager::~AckNotifierManager() {
- STLDeleteElements(&ack_notifiers_);
+ for (const auto& pair : ack_notifier_map_) {
+ for (QuicAckNotifier* notifier : pair.second) {
+ if (notifier->OnPacketAbandoned()) {
+ delete notifier;
+ }
+ }
+ }
}
void AckNotifierManager::OnPacketAcked(QuicPacketSequenceNumber sequence_number,
@@ -34,14 +40,10 @@
// One or more AckNotifiers are registered as interested in this sequence
// number. Iterate through them and call OnAck on each.
- AckNotifierList& ack_notifier_list = map_it->second;
- for (QuicAckNotifier* ack_notifier : ack_notifier_list) {
- ack_notifier->OnAck(sequence_number, delta_largest_observed);
-
- // If this has resulted in an empty AckNotifer, erase it.
- if (ack_notifier->IsEmpty()) {
+ for (QuicAckNotifier* ack_notifier : map_it->second) {
+ if (ack_notifier->OnAck(delta_largest_observed)) {
+ // If this has resulted in an empty AckNotifer, erase it.
delete ack_notifier;
- ack_notifiers_.erase(ack_notifier);
}
}
@@ -75,21 +77,19 @@
void AckNotifierManager::OnSerializedPacket(
const SerializedPacket& serialized_packet) {
if (FLAGS_quic_attach_ack_notifiers_to_packets) {
- // Inform each attached AckNotifier of the packet's sequence number.
+ // Inform each attached AckNotifier of the packet's serialization.
+ AckNotifierList& notifier_list =
+ ack_notifier_map_[serialized_packet.sequence_number];
for (QuicAckNotifier* notifier : serialized_packet.notifiers) {
if (notifier == nullptr) {
LOG(DFATAL) << "AckNotifier should not be nullptr.";
continue;
}
- notifier->AddSequenceNumber(serialized_packet.sequence_number,
- serialized_packet.packet->length());
+ notifier->OnSerializedPacket();
// Update the mapping in the other direction, from sequence number to
// AckNotifier.
- ack_notifier_map_[serialized_packet.sequence_number].push_back(notifier);
-
- // Take ownership of the AckNotifier.
- ack_notifiers_.insert(notifier);
+ notifier_list.push_back(notifier);
}
} else {
// AckNotifiers can only be attached to retransmittable frames.
@@ -107,15 +107,11 @@
}
QuicAckNotifier* notifier = quic_frame.stream_frame->notifier;
- notifier->AddSequenceNumber(serialized_packet.sequence_number,
- serialized_packet.packet->length());
+ notifier->OnSerializedPacket();
// Update the mapping in the other direction, from sequence number to
// AckNotifier.
ack_notifier_map_[serialized_packet.sequence_number].push_back(notifier);
-
- // Take ownership of the AckNotifier.
- ack_notifiers_.insert(notifier);
}
}
}
diff --git a/net/quic/quic_ack_notifier_manager.h b/net/quic/quic_ack_notifier_manager.h
index bf4d574..d4d97ad 100644
--- a/net/quic/quic_ack_notifier_manager.h
+++ b/net/quic/quic_ack_notifier_manager.h
@@ -48,22 +48,14 @@
private:
typedef std::list<QuicAckNotifier*> AckNotifierList;
- typedef base::hash_set<QuicAckNotifier*> AckNotifierSet;
// TODO(ianswett): Further improvement may come from changing this to a deque.
typedef base::hash_map<QuicPacketSequenceNumber, AckNotifierList>
AckNotifierMap;
- // On every ACK frame received by the connection, all the ack_notifiers_ will
- // be told which sequeunce numbers were ACKed.
- // Once a given QuicAckNotifier has seen all the sequence numbers it is
- // interested in, it will be deleted, and removed from this set.
- // Owns the AckNotifiers in this set.
- AckNotifierSet ack_notifiers_;
-
// Maps from sequence number to the AckNotifiers which are registered
// for that sequence number. On receipt of an ACK for a given sequence
// number, call OnAck for all mapped AckNotifiers.
- // Does not own the AckNotifiers.
+ // When the last reference is removed from the map, the notifier is deleted.
AckNotifierMap ack_notifier_map_;
DISALLOW_COPY_AND_ASSIGN(AckNotifierManager);
diff --git a/net/quic/quic_ack_notifier_test.cc b/net/quic/quic_ack_notifier_test.cc
index 21c8766..7e9d652 100644
--- a/net/quic/quic_ack_notifier_test.cc
+++ b/net/quic/quic_ack_notifier_test.cc
@@ -22,9 +22,9 @@
delegate_ = new MockAckNotifierDelegate;
notifier_.reset(new QuicAckNotifier(delegate_));
- notifier_->AddSequenceNumber(26, 100);
- notifier_->AddSequenceNumber(99, 20);
- notifier_->AddSequenceNumber(1234, 3);
+ notifier_->OnSerializedPacket();
+ notifier_->OnSerializedPacket();
+ notifier_->OnSerializedPacket();
}
MockAckNotifierDelegate* delegate_;
@@ -35,17 +35,26 @@
// Should trigger callback when we receive acks for all the registered seqnums.
TEST_F(QuicAckNotifierTest, TriggerCallback) {
EXPECT_CALL(*delegate_, OnAckNotification(0, 0, zero_)).Times(1);
- EXPECT_FALSE(notifier_->OnAck(26, zero_));
- EXPECT_FALSE(notifier_->OnAck(99, zero_));
- EXPECT_TRUE(notifier_->OnAck(1234, zero_));
+ EXPECT_FALSE(notifier_->OnAck(zero_));
+ EXPECT_FALSE(notifier_->OnAck(zero_));
+ EXPECT_TRUE(notifier_->OnAck(zero_));
}
// Should not trigger callback if we never provide all the seqnums.
TEST_F(QuicAckNotifierTest, DoesNotTrigger) {
// Should not trigger callback as not all packets have been seen.
EXPECT_CALL(*delegate_, OnAckNotification(_, _, _)).Times(0);
- EXPECT_FALSE(notifier_->OnAck(26, zero_));
- EXPECT_FALSE(notifier_->OnAck(99, zero_));
+ EXPECT_FALSE(notifier_->OnAck(zero_));
+ EXPECT_FALSE(notifier_->OnAck(zero_));
+}
+
+// Should not trigger callback if we abandon all three packets.
+TEST_F(QuicAckNotifierTest, AbandonDoesNotTrigger) {
+ // Should not trigger callback as not all packets have been seen.
+ EXPECT_CALL(*delegate_, OnAckNotification(_, _, _)).Times(0);
+ EXPECT_FALSE(notifier_->OnPacketAbandoned());
+ EXPECT_FALSE(notifier_->OnPacketAbandoned());
+ EXPECT_TRUE(notifier_->OnPacketAbandoned());
}
// Should trigger even after updating sequence numbers and receiving ACKs for
@@ -56,9 +65,9 @@
notifier_->OnPacketRetransmitted(3);
EXPECT_CALL(*delegate_, OnAckNotification(2, 20 + 3, _)).Times(1);
- EXPECT_FALSE(notifier_->OnAck(26, zero_)); // original
- EXPECT_FALSE(notifier_->OnAck(3000, zero_)); // updated
- EXPECT_TRUE(notifier_->OnAck(3001, zero_)); // updated
+ EXPECT_FALSE(notifier_->OnAck(zero_)); // original
+ EXPECT_FALSE(notifier_->OnAck(zero_)); // updated
+ EXPECT_TRUE(notifier_->OnAck(zero_)); // updated
}
// Make sure the delegate is called with the delta time from the last ACK.
@@ -68,9 +77,9 @@
const QuicTime::Delta third_delta = QuicTime::Delta::FromSeconds(10);
EXPECT_CALL(*delegate_, OnAckNotification(0, 0, third_delta)).Times(1);
- EXPECT_FALSE(notifier_->OnAck(26, first_delta));
- EXPECT_FALSE(notifier_->OnAck(99, second_delta));
- EXPECT_TRUE(notifier_->OnAck(1234, third_delta));
+ EXPECT_FALSE(notifier_->OnAck(first_delta));
+ EXPECT_FALSE(notifier_->OnAck(second_delta));
+ EXPECT_TRUE(notifier_->OnAck(third_delta));
}
} // namespace
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 1b59a40..a2f9179 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -177,12 +177,16 @@
going_away_(false),
weak_factory_(this) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
- tracked_objects::ScopedTracker tracking_profile(
+ tracked_objects::ScopedTracker tracking_profile1(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "422516 QuicClientSession::QuicClientSession"));
+ "422516 QuicClientSession::QuicClientSession1"));
connection->set_debug_visitor(logger_);
IPEndPoint address;
+ // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
+ tracked_objects::ScopedTracker tracking_profile2(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "422516 QuicClientSession::QuicClientSession2"));
if (socket && socket->GetLocalAddress(&address) == OK &&
address.GetFamily() == ADDRESS_FAMILY_IPV6) {
connection->set_max_packet_length(
diff --git a/net/quic/quic_config.cc b/net/quic/quic_config.cc
index 9d0a7c9b..803ae7f 100644
--- a/net/quic/quic_config.cc
+++ b/net/quic/quic_config.cc
@@ -9,7 +9,6 @@
#include "base/logging.h"
#include "net/quic/crypto/crypto_handshake_message.h"
#include "net/quic/crypto/crypto_protocol.h"
-#include "net/quic/quic_flags.h"
#include "net/quic/quic_utils.h"
using std::min;
@@ -594,9 +593,8 @@
// TODO(ianswett): Add the negotiated parameters once and iterate over all
// of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
// ProcessServerHello.
- return congestion_feedback_.negotiated() &&
- idle_connection_state_lifetime_seconds_.negotiated() &&
- max_streams_per_connection_.negotiated();
+ return idle_connection_state_lifetime_seconds_.negotiated() &&
+ max_streams_per_connection_.negotiated();
}
void QuicConfig::SetDefaults() {
@@ -609,11 +607,7 @@
congestion_feedback_.set(congestion_feedback, kQBIC);
idle_connection_state_lifetime_seconds_.set(kMaximumIdleTimeoutSecs,
kDefaultIdleTimeoutSecs);
- if (FLAGS_quic_allow_silent_close) {
- silent_close_.set(1, 0);
- } else {
- silent_close_.set(0, 0);
- }
+ silent_close_.set(1, 0);
SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection,
kDefaultMaxStreamsPerConnection);
max_time_before_crypto_handshake_ =
@@ -647,10 +641,6 @@
QuicErrorCode error = QUIC_NO_ERROR;
if (error == QUIC_NO_ERROR) {
- error = congestion_feedback_.ProcessPeerHello(
- peer_hello, hello_type, error_details);
- }
- if (error == QUIC_NO_ERROR) {
error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
peer_hello, hello_type, error_details);
}
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 454a15b..a441c1b 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -272,6 +272,9 @@
framer_.set_received_entropy_calculator(&received_packet_manager_);
stats_.connection_creation_time = clock_->ApproximateNow();
sent_packet_manager_.set_network_change_visitor(this);
+ if (FLAGS_quic_small_default_packet_size && is_server_) {
+ set_max_packet_length(kDefaultServerMaxPacketSize);
+ }
}
QuicConnection::~QuicConnection() {
@@ -291,7 +294,7 @@
if (config.negotiated()) {
SetNetworkTimeouts(QuicTime::Delta::Infinite(),
config.IdleConnectionStateLifetime());
- if (FLAGS_quic_allow_silent_close && config.SilentClose()) {
+ if (config.SilentClose()) {
silent_close_enabled_ = true;
}
} else {
@@ -969,18 +972,16 @@
}
}
-QuicAckFrame* QuicConnection::CreateAckFrame() {
- QuicAckFrame* outgoing_ack = new QuicAckFrame();
- received_packet_manager_.UpdateReceivedPacketInfo(
- outgoing_ack, clock_->ApproximateNow());
- DVLOG(1) << ENDPOINT << "Creating ack frame: " << *outgoing_ack;
- return outgoing_ack;
+void QuicConnection::PopulateAckFrame(QuicAckFrame* ack) {
+ received_packet_manager_.UpdateReceivedPacketInfo(ack,
+ clock_->ApproximateNow());
}
-QuicStopWaitingFrame* QuicConnection::CreateStopWaitingFrame() {
- QuicStopWaitingFrame stop_waiting;
- UpdateStopWaiting(&stop_waiting);
- return new QuicStopWaitingFrame(stop_waiting);
+void QuicConnection::PopulateStopWaitingFrame(
+ QuicStopWaitingFrame* stop_waiting) {
+ stop_waiting->least_unacked = GetLeastUnacked();
+ stop_waiting->entropy_hash = sent_entropy_manager_.GetCumulativeEntropy(
+ stop_waiting->least_unacked - 1);
}
bool QuicConnection::ShouldLastPacketInstigateAck() const {
@@ -1123,29 +1124,22 @@
}
const QuicConnectionStats& QuicConnection::GetStats() {
- if (!FLAGS_quic_use_initial_rtt_for_stats) {
- stats_.min_rtt_us =
- sent_packet_manager_.GetRttStats()->min_rtt().ToMicroseconds();
- stats_.srtt_us =
- sent_packet_manager_.GetRttStats()->smoothed_rtt().ToMicroseconds();
- } else {
- const RttStats* rtt_stats = sent_packet_manager_.GetRttStats();
+ const RttStats* rtt_stats = sent_packet_manager_.GetRttStats();
- // Update rtt and estimated bandwidth.
- QuicTime::Delta min_rtt = rtt_stats->min_rtt();
- if (min_rtt.IsZero()) {
- // If min RTT has not been set, use initial RTT instead.
- min_rtt = QuicTime::Delta::FromMicroseconds(rtt_stats->initial_rtt_us());
- }
- stats_.min_rtt_us = min_rtt.ToMicroseconds();
-
- QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
- if (srtt.IsZero()) {
- // If SRTT has not been set, use initial RTT instead.
- srtt = QuicTime::Delta::FromMicroseconds(rtt_stats->initial_rtt_us());
- }
- stats_.srtt_us = srtt.ToMicroseconds();
+ // Update rtt and estimated bandwidth.
+ QuicTime::Delta min_rtt = rtt_stats->min_rtt();
+ if (min_rtt.IsZero()) {
+ // If min RTT has not been set, use initial RTT instead.
+ min_rtt = QuicTime::Delta::FromMicroseconds(rtt_stats->initial_rtt_us());
}
+ stats_.min_rtt_us = min_rtt.ToMicroseconds();
+
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+ if (srtt.IsZero()) {
+ // If SRTT has not been set, use initial RTT instead.
+ srtt = QuicTime::Delta::FromMicroseconds(rtt_stats->initial_rtt_us());
+ }
+ stats_.srtt_us = srtt.ToMicroseconds();
stats_.estimated_bandwidth = sent_packet_manager_.BandwidthEstimate();
stats_.max_packet_size = packet_generator_.max_packet_length();
@@ -1316,8 +1310,13 @@
// does not require the creator to be flushed.
packet_generator_.FlushAllQueuedFrames();
SerializedPacket serialized_packet = packet_generator_.ReserializeAllFrames(
- pending.retransmittable_frames.frames(),
- pending.sequence_number_length);
+ pending.retransmittable_frames, pending.sequence_number_length);
+ if (serialized_packet.packet == nullptr) {
+ // We failed to serialize the packet, so close the connection.
+ // CloseConnection does not send close packet, so no infinite loop here.
+ CloseConnection(QUIC_ENCRYPTION_FAILURE, false);
+ return;
+ }
DVLOG(1) << ENDPOINT << "Retransmitting " << pending.sequence_number
<< " as " << serialized_packet.sequence_number;
@@ -1403,7 +1402,8 @@
return true;
}
// Connection close packets are encrypted and saved, so don't exit early.
- if (writer_->IsWriteBlocked() && !IsConnectionClose(*packet)) {
+ const bool is_connection_close = IsConnectionClose(*packet);
+ if (writer_->IsWriteBlocked() && !is_connection_close) {
return false;
}
@@ -1412,32 +1412,19 @@
DCHECK_LE(sequence_number_of_last_sent_packet_, sequence_number);
sequence_number_of_last_sent_packet_ = sequence_number;
- QuicEncryptedPacket* encrypted = framer_.EncryptPacket(
- packet->encryption_level,
- sequence_number,
- *packet->serialized_packet.packet);
- if (encrypted == nullptr) {
- LOG(DFATAL) << ENDPOINT << "Failed to encrypt packet number "
- << sequence_number;
- // CloseConnection does not send close packet, so no infinite loop here.
- CloseConnection(QUIC_ENCRYPTION_FAILURE, false);
- return false;
- }
-
+ QuicEncryptedPacket* encrypted = packet->serialized_packet.packet;
// Connection close packets are eventually owned by TimeWaitListManager.
// Others are deleted at the end of this call.
- scoped_ptr<QuicEncryptedPacket> encrypted_deleter;
- if (IsConnectionClose(*packet)) {
+ if (is_connection_close) {
DCHECK(connection_close_packet_.get() == nullptr);
connection_close_packet_.reset(encrypted);
+ packet->serialized_packet.packet = nullptr;
// This assures we won't try to write *forced* packets when blocked.
// Return true to stop processing.
if (writer_->IsWriteBlocked()) {
visitor_->OnWriteBlocked();
return true;
}
- } else {
- encrypted_deleter.reset(encrypted);
}
if (!FLAGS_quic_allow_oversized_packets_for_test) {
@@ -1445,18 +1432,15 @@
}
DCHECK_LE(encrypted->length(), packet_generator_.max_packet_length());
DVLOG(1) << ENDPOINT << "Sending packet " << sequence_number << " : "
- << (packet->serialized_packet.packet->is_fec_packet() ? "FEC " :
- (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
- ? "data bearing " : " ack only "))
- << ", encryption level: "
+ << (packet->serialized_packet.is_fec_packet
+ ? "FEC "
+ : (IsRetransmittable(*packet) == HAS_RETRANSMITTABLE_DATA
+ ? "data bearing "
+ : " ack only ")) << ", encryption level: "
<< QuicUtils::EncryptionLevelToString(packet->encryption_level)
- << ", length:"
- << packet->serialized_packet.packet->length()
- << ", encrypted length:"
- << encrypted->length();
+ << ", encrypted length:" << encrypted->length();
DVLOG(2) << ENDPOINT << "packet(" << sequence_number << "): " << std::endl
- << QuicUtils::StringToHexASCIIDump(
- packet->serialized_packet.packet->AsStringPiece());
+ << QuicUtils::StringToHexASCIIDump(encrypted->AsStringPiece());
QuicTime packet_send_time = QuicTime::Zero();
if (FLAGS_quic_record_send_time_before_write) {
@@ -1542,6 +1526,10 @@
if (result.status == WRITE_STATUS_ERROR) {
OnWriteError(result.error_code);
+ DLOG(ERROR) << ENDPOINT << "failed writing " << encrypted->length()
+ << "bytes "
+ << " from host " << self_address().ToStringWithoutPort()
+ << " to address " << peer_address().ToString();
return false;
}
@@ -1589,24 +1577,19 @@
void QuicConnection::OnSerializedPacket(
const SerializedPacket& serialized_packet) {
- // If a forward-secure encrypter is available but is not being used and this
- // packet's sequence number is after the first packet which requires
- // forward security, start using the forward-secure encrypter.
- if (encryption_level_ != ENCRYPTION_FORWARD_SECURE &&
- has_forward_secure_encrypter_ &&
- serialized_packet.sequence_number >=
- first_required_forward_secure_packet_) {
- SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ if (serialized_packet.packet == nullptr) {
+ // We failed to serialize the packet, so close the connection.
+ // CloseConnection does not send close packet, so no infinite loop here.
+ CloseConnection(QUIC_ENCRYPTION_FAILURE, false);
+ return;
}
if (serialized_packet.retransmittable_frames) {
serialized_packet.retransmittable_frames->
set_encryption_level(encryption_level_);
- if (FLAGS_quic_ack_notifier_informed_on_serialized) {
- sent_packet_manager_.OnSerializedPacket(serialized_packet);
- }
+ sent_packet_manager_.OnSerializedPacket(serialized_packet);
}
- if (serialized_packet.packet->is_fec_packet() && fec_alarm_->IsSet()) {
+ if (serialized_packet.is_fec_packet && fec_alarm_->IsSet()) {
// If an FEC packet is serialized with the FEC alarm set, cancel the alarm.
fec_alarm_->Cancel();
}
@@ -1653,12 +1636,16 @@
if (!WritePacket(&packet)) {
queued_packets_.push_back(packet);
}
-}
-void QuicConnection::UpdateStopWaiting(QuicStopWaitingFrame* stop_waiting) {
- stop_waiting->least_unacked = GetLeastUnacked();
- stop_waiting->entropy_hash = sent_entropy_manager_.GetCumulativeEntropy(
- stop_waiting->least_unacked - 1);
+ // If a forward-secure encrypter is available but is not being used and the
+ // next sequence number is the first packet which requires
+ // forward security, start using the forward-secure encrypter.
+ if (encryption_level_ != ENCRYPTION_FORWARD_SECURE &&
+ has_forward_secure_encrypter_ &&
+ packet.serialized_packet.sequence_number >=
+ first_required_forward_secure_packet_ - 1) {
+ SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ }
}
void QuicConnection::SendPing() {
@@ -2104,15 +2091,14 @@
}
}
-bool QuicConnection::IsConnectionClose(
- QueuedPacket packet) {
- RetransmittableFrames* retransmittable_frames =
+bool QuicConnection::IsConnectionClose(const QueuedPacket& packet) {
+ const RetransmittableFrames* retransmittable_frames =
packet.serialized_packet.retransmittable_frames;
- if (!retransmittable_frames) {
+ if (retransmittable_frames == nullptr) {
return false;
}
- for (size_t i = 0; i < retransmittable_frames->frames().size(); ++i) {
- if (retransmittable_frames->frames()[i].type == CONNECTION_CLOSE_FRAME) {
+ for (const QuicFrame& frame : retransmittable_frames->frames()) {
+ if (frame.type == CONNECTION_CLOSE_FRAME) {
return true;
}
}
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 8afd79d..e944aea 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -370,8 +370,8 @@
bool ShouldGeneratePacket(TransmissionType transmission_type,
HasRetransmittableData retransmittable,
IsHandshake handshake) override;
- QuicAckFrame* CreateAckFrame() override;
- QuicStopWaitingFrame* CreateStopWaitingFrame() override;
+ void PopulateAckFrame(QuicAckFrame* ack) override;
+ void PopulateStopWaitingFrame(QuicStopWaitingFrame* stop_waiting) override;
void OnSerializedPacket(const SerializedPacket& packet) override;
// QuicSentPacketManager::NetworkChangeVisitor
@@ -629,9 +629,6 @@
void ProcessStopWaitingFrame(const QuicStopWaitingFrame& stop_waiting);
- // Update |stop_waiting| for an outgoing ack.
- void UpdateStopWaiting(QuicStopWaitingFrame* stop_waiting);
-
// Queues an ack or sets the ack alarm when an incoming packet arrives that
// should be acked.
void MaybeQueueAck();
@@ -670,7 +667,7 @@
const IPEndPoint& peer_address);
HasRetransmittableData IsRetransmittable(const QueuedPacket& packet);
- bool IsConnectionClose(QueuedPacket packet);
+ bool IsConnectionClose(const QueuedPacket& packet);
QuicFramer framer_;
QuicConnectionHelperInterface* helper_; // Not owned.
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc
index 8b4e8b9..8a9c3a7 100644
--- a/net/quic/quic_connection_logger.cc
+++ b/net/quic/quic_connection_logger.cc
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "net/base/net_log.h"
@@ -267,6 +268,11 @@
}
const char* GetConnectionDescriptionString() {
+ // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "422516 QuicConnectionLogger GetConnectionDescriptionString"));
+
NetworkChangeNotifier::ConnectionType type =
NetworkChangeNotifier::GetConnectionType();
const char* description = NetworkChangeNotifier::ConnectionTypeToString(type);
@@ -326,9 +332,11 @@
session_(session),
last_received_packet_sequence_number_(0),
last_received_packet_size_(0),
+ previous_received_packet_size_(0),
largest_received_packet_sequence_number_(0),
largest_received_missing_packet_sequence_number_(0),
num_out_of_order_received_packets_(0),
+ num_out_of_order_large_received_packets_(0),
num_packets_received_(0),
num_truncated_acks_sent_(0),
num_truncated_acks_received_(0),
@@ -345,6 +353,8 @@
QuicConnectionLogger::~QuicConnectionLogger() {
UMA_HISTOGRAM_COUNTS("Net.QuicSession.OutOfOrderPacketsReceived",
num_out_of_order_received_packets_);
+ UMA_HISTOGRAM_COUNTS("Net.QuicSession.OutOfOrderLargePacketsReceived",
+ num_out_of_order_large_received_packets_);
UMA_HISTOGRAM_COUNTS("Net.QuicSession.TruncatedAcksSent",
num_truncated_acks_sent_);
UMA_HISTOGRAM_COUNTS("Net.QuicSession.TruncatedAcksReceived",
@@ -496,6 +506,7 @@
ADDRESS_FAMILY_LAST);
}
+ previous_received_packet_size_ = last_received_packet_size_;
last_received_packet_size_ = packet.length();
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED,
@@ -546,6 +557,8 @@
}
if (header.packet_sequence_number < last_received_packet_sequence_number_) {
++num_out_of_order_received_packets_;
+ if (previous_received_packet_size_ < last_received_packet_size_)
+ ++num_out_of_order_large_received_packets_;
UMA_HISTOGRAM_COUNTS(
"Net.QuicSession.OutOfOrderGapReceived",
static_cast<base::HistogramBase::Sample>(
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h
index 09e3c46..8f6b7ff 100644
--- a/net/quic/quic_connection_logger.h
+++ b/net/quic/quic_connection_logger.h
@@ -118,6 +118,8 @@
QuicPacketSequenceNumber last_received_packet_sequence_number_;
// The size of the most recently received packet.
size_t last_received_packet_size_;
+ // The size of the previously received packet.
+ size_t previous_received_packet_size_;
// The largest packet sequence number received. In the case where a packet is
// received late (out of order), this value will not be updated.
QuicPacketSequenceNumber largest_received_packet_sequence_number_;
@@ -127,6 +129,11 @@
// Number of times that the current received packet sequence number is
// smaller than the last received packet sequence number.
size_t num_out_of_order_received_packets_;
+ // Number of times that the current received packet sequence number is
+ // smaller than the last received packet sequence number and where the
+ // size of the current packet is larger than the size of the previous
+ // packet.
+ size_t num_out_of_order_large_received_packets_;
// The number of times that OnPacketHeader was called.
// If the network replicates packets, then this number may be slightly
// different from the real number of distinct packets received.
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 091dc9e..0dc817c 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -9,7 +9,6 @@
#include "base/stl_util.h"
#include "net/base/net_errors.h"
#include "net/quic/congestion_control/loss_detection_interface.h"
-#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
#include "net/quic/crypto/null_encrypter.h"
#include "net/quic/crypto/quic_decrypter.h"
@@ -64,17 +63,6 @@
const int kDefaultRetransmissionTimeMs = 500;
-class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
- public:
- TestReceiveAlgorithm() {}
-
- MOCK_METHOD3(RecordIncomingPacket,
- void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestReceiveAlgorithm);
-};
-
// TaggingEncrypter appends kTagSize bytes of |tag| to the end of each message.
class TaggingEncrypter : public QuicEncrypter {
public:
@@ -99,13 +87,20 @@
return true;
}
- QuicData* EncryptPacket(QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece plaintext) override {
+ bool EncryptPacket(QuicPacketSequenceNumber sequence_number,
+ StringPiece associated_data,
+ StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override {
const size_t len = plaintext.size() + kTagSize;
- uint8* buffer = new uint8[len];
- Encrypt(StringPiece(), associated_data, plaintext, buffer);
- return new QuicData(reinterpret_cast<char*>(buffer), len, true);
+ if (max_output_length < len) {
+ return false;
+ }
+ Encrypt(StringPiece(), associated_data, plaintext,
+ reinterpret_cast<unsigned char*>(output));
+ *output_length = len;
+ return true;
}
size_t GetKeySize() const override { return 0; }
@@ -144,20 +139,21 @@
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece ciphertext) override {
+ bool DecryptPacket(QuicPacketSequenceNumber sequence_number,
+ const StringPiece& associated_data,
+ const StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override {
if (ciphertext.size() < kTagSize) {
- return nullptr;
+ return false;
}
if (!CheckTag(ciphertext, GetTag(ciphertext))) {
- return nullptr;
+ return false;
}
- const size_t len = ciphertext.size() - kTagSize;
- uint8* buf = new uint8[len];
- memcpy(buf, ciphertext.data(), len);
- return new QuicData(reinterpret_cast<char*>(buf), len,
- true /* owns buffer */);
+ *output_length = ciphertext.size() - kTagSize;
+ memcpy(output, ciphertext.data(), *output_length);
+ return true;
}
StringPiece GetKey() const override { return StringPiece(); }
@@ -408,10 +404,6 @@
QuicConnectionPeer::SendAck(this);
}
- void SetReceiveAlgorithm(TestReceiveAlgorithm* receive_algorithm) {
- QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
- }
-
void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
}
@@ -430,9 +422,13 @@
retransmittable == HAS_RETRANSMITTABLE_DATA
? new RetransmittableFrames()
: nullptr;
- OnSerializedPacket(
- SerializedPacket(sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
- packet, entropy_hash, retransmittable_frames));
+ QuicEncryptedPacket* encrypted =
+ QuicConnectionPeer::GetFramer(this)
+ ->EncryptPacket(ENCRYPTION_NONE, sequence_number, *packet);
+ delete packet;
+ OnSerializedPacket(SerializedPacket(sequence_number,
+ PACKET_6BYTE_SEQUENCE_NUMBER, encrypted,
+ entropy_hash, retransmittable_frames));
}
QuicConsumedData SendStreamDataWithString(
@@ -603,7 +599,6 @@
peer_creator_(connection_id_, &framer_, &random_generator_),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
loss_algorithm_(new MockLossAlgorithm()),
- receive_algorithm_(new TestReceiveAlgorithm),
helper_(new TestConnectionHelper(&clock_, &random_generator_)),
writer_(new TestPacketWriter(version(), &clock_)),
factory_(writer_.get()),
@@ -624,12 +619,9 @@
connection_.SetSendAlgorithm(send_algorithm_);
connection_.SetLossAlgorithm(loss_algorithm_);
framer_.set_received_entropy_calculator(&entropy_calculator_);
- connection_.SetReceiveAlgorithm(receive_algorithm_);
EXPECT_CALL(
*send_algorithm_, TimeUntilSend(_, _, _)).WillRepeatedly(Return(
QuicTime::Delta::Zero()));
- EXPECT_CALL(*receive_algorithm_,
- RecordIncomingPacket(_, _, _)).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
@@ -662,14 +654,13 @@
}
QuicAckFrame* outgoing_ack() {
- outgoing_ack_.reset(QuicConnectionPeer::CreateAckFrame(&connection_));
- return outgoing_ack_.get();
+ QuicConnectionPeer::PopulateAckFrame(&connection_, &ack_);
+ return &ack_;
}
QuicStopWaitingFrame* stop_waiting() {
- stop_waiting_.reset(
- QuicConnectionPeer::CreateStopWaitingFrame(&connection_));
- return stop_waiting_.get();
+ QuicConnectionPeer::PopulateStopWaitingFrame(&connection_, &stop_waiting_);
+ return &stop_waiting_;
}
QuicPacketSequenceNumber least_unacked() {
@@ -695,10 +686,7 @@
connection_.is_server());
SerializedPacket serialized_packet =
peer_creator_.SerializeAllFrames(frames);
- scoped_ptr<QuicPacket> packet(serialized_packet.packet);
- scoped_ptr<QuicEncryptedPacket> encrypted(
- framer_.EncryptPacket(ENCRYPTION_NONE,
- serialized_packet.sequence_number, *packet));
+ scoped_ptr<QuicEncryptedPacket> encrypted(serialized_packet.packet);
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
return serialized_packet.entropy_hash;
}
@@ -796,7 +784,7 @@
fec_data.redundancy = data_packet->FecProtectedData();
scoped_ptr<QuicPacket> fec_packet(
- framer_.BuildFecPacket(header_, fec_data).packet);
+ framer_.BuildFecPacket(header_, fec_data));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, number, *fec_packet));
@@ -861,8 +849,7 @@
QuicFrames frames;
QuicFrame frame(&frame1_);
frames.push_back(frame);
- QuicPacket* packet =
- BuildUnsizedDataPacket(&framer_, header_, frames).packet;
+ QuicPacket* packet = BuildUnsizedDataPacket(&framer_, header_, frames);
EXPECT_TRUE(packet != nullptr);
return packet;
}
@@ -882,8 +869,7 @@
QuicFrames frames;
QuicFrame frame(&ping);
frames.push_back(frame);
- QuicPacket* packet =
- BuildUnsizedDataPacket(&framer_, header_, frames).packet;
+ QuicPacket* packet = BuildUnsizedDataPacket(&framer_, header_, frames);
EXPECT_TRUE(packet != nullptr);
return packet;
}
@@ -905,8 +891,7 @@
QuicFrames frames;
QuicFrame frame(&qccf);
frames.push_back(frame);
- QuicPacket* packet =
- BuildUnsizedDataPacket(&framer_, header_, frames).packet;
+ QuicPacket* packet = BuildUnsizedDataPacket(&framer_, header_, frames);
EXPECT_TRUE(packet != nullptr);
return packet;
}
@@ -991,7 +976,6 @@
MockSendAlgorithm* send_algorithm_;
MockLossAlgorithm* loss_algorithm_;
- TestReceiveAlgorithm* receive_algorithm_;
MockClock clock_;
MockRandom random_generator_;
scoped_ptr<TestConnectionHelper> helper_;
@@ -1006,8 +990,8 @@
QuicPacketHeader header_;
QuicStreamFrame frame1_;
QuicStreamFrame frame2_;
- scoped_ptr<QuicAckFrame> outgoing_ack_;
- scoped_ptr<QuicStopWaitingFrame> stop_waiting_;
+ QuicAckFrame ack_;
+ QuicStopWaitingFrame stop_waiting_;
QuicSequenceNumberLength sequence_number_length_;
QuicConnectionIdLength connection_id_length_;
@@ -1020,6 +1004,64 @@
QuicConnectionTest,
::testing::ValuesIn(QuicSupportedVersions()));
+TEST_P(QuicConnectionTest, MaxPacketSize) {
+ EXPECT_FALSE(connection_.is_server());
+ EXPECT_EQ(1350u, connection_.max_packet_length());
+}
+
+TEST_P(QuicConnectionTest, SmallerServerMaxPacketSize) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_small_default_packet_size, true);
+ QuicConnectionId connection_id = 42;
+ bool kIsServer = true;
+ TestConnection connection(connection_id, IPEndPoint(), helper_.get(),
+ factory_, kIsServer, version());
+ EXPECT_TRUE(connection.is_server());
+ EXPECT_EQ(1000u, connection.max_packet_length());
+}
+
+TEST_P(QuicConnectionTest, ServerMaxPacketSize) {
+ ValueRestore<bool> old_flag(&FLAGS_quic_small_default_packet_size, false);
+ QuicConnectionId connection_id = 42;
+ bool kIsServer = true;
+ TestConnection connection(connection_id, IPEndPoint(), helper_.get(),
+ factory_, kIsServer, version());
+ EXPECT_TRUE(connection.is_server());
+ EXPECT_EQ(1350u, connection.max_packet_length());
+}
+
+TEST_P(QuicConnectionTest, IncreaseServerMaxPacketSize) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+ connection_.set_is_server(true);
+ connection_.set_max_packet_length(1000);
+
+ QuicPacketHeader header;
+ header.public_header.connection_id = connection_id_;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = true;
+ header.entropy_flag = false;
+ header.fec_flag = false;
+ header.packet_sequence_number = 1;
+ header.fec_group = 0;
+
+ QuicFrames frames;
+ QuicPaddingFrame padding;
+ frames.push_back(QuicFrame(&frame1_));
+ frames.push_back(QuicFrame(&padding));
+
+ scoped_ptr<QuicPacket> packet(
+ BuildUnsizedDataPacket(&framer_, header, frames));
+ scoped_ptr<QuicEncryptedPacket> encrypted(
+ framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
+ EXPECT_EQ(kMaxPacketSize, encrypted->length());
+
+ framer_.set_version(version());
+ EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(1);
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+
+ EXPECT_EQ(kMaxPacketSize, connection_.max_packet_length());
+}
+
TEST_P(QuicConnectionTest, PacketsInOrder) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3157,7 +3199,6 @@
TEST_P(QuicConnectionTest, TimeoutAfterSendSilentClose) {
// Same test as above, but complete a handshake which enables silent close,
// causing no connection close packet to be sent.
- ValueRestore<bool> old_flag(&FLAGS_quic_allow_silent_close, true);
EXPECT_TRUE(connection_.connected());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _, _));
QuicConfig config;
@@ -3701,7 +3742,7 @@
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer_, header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
@@ -3739,7 +3780,7 @@
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer_, header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
@@ -3784,7 +3825,7 @@
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer_, header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
@@ -3829,7 +3870,7 @@
QuicFrame frame(&frame1_);
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer_, header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames));
encrypted.reset(framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -3974,7 +4015,7 @@
frames.push_back(stream_frame);
frames.push_back(close_frame);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer_, header_, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header_, frames));
EXPECT_TRUE(nullptr != packet.get());
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
ENCRYPTION_NONE, 1, *packet));
@@ -4268,8 +4309,7 @@
ack_header.is_in_fec_group = IN_FEC_GROUP;
ack_header.fec_group = 1;
- QuicPacket* packet =
- BuildUnsizedDataPacket(&framer_, ack_header, frames).packet;
+ QuicPacket* packet = BuildUnsizedDataPacket(&framer_, ack_header, frames);
// Take the packet which contains the ACK frame, and construct and deliver an
// FEC packet which allows the ACK packet to be recovered.
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index 26bd171..c7c0291 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -87,7 +87,9 @@
channel_id_source_callback_run_(false),
channel_id_source_callback_(nullptr),
verify_context_(verify_context),
- proof_verify_callback_(nullptr) {}
+ proof_verify_callback_(nullptr) {
+ DCHECK(!session->connection()->is_server());
+}
QuicCryptoClientStream::~QuicCryptoClientStream() {
if (channel_id_source_callback_) {
@@ -196,7 +198,7 @@
break;
case STATE_SEND_CHLO:
DoSendCHLO(in, cached);
- return;
+ return; // return waiting to hear from server.
case STATE_RECV_REJ:
DoReceiveREJ(in, cached);
break;
@@ -638,7 +640,7 @@
return false;
}
const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
- if (!scfg) { // scfg may be null when we send an inchoate CHLO.
+ if (!scfg) { // scfg may be null then we send an inchoate CHLO.
return false;
}
const QuicTag* their_proof_demands;
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index a39ab4f..454d930 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -30,10 +30,12 @@
class QuicCryptoClientStreamTest : public ::testing::Test {
public:
QuicCryptoClientStreamTest()
- : connection_(new PacketSavingConnection(false)),
+ : connection_(new PacketSavingConnection(/*is_server=*/false)),
session_(new TestClientSession(connection_, DefaultQuicConfig())),
server_id_(kServerHostname, kServerPort, false, PRIVACY_MODE_DISABLED),
- stream_(new QuicCryptoClientStream(server_id_, session_.get(), nullptr,
+ stream_(new QuicCryptoClientStream(server_id_,
+ session_.get(),
+ nullptr,
&crypto_config_)) {
session_->SetCryptoStream(stream_.get());
// Advance the time, because timers do not like uninitialized times.
@@ -121,7 +123,7 @@
// Seed the config with a cached server config.
CompleteCryptoHandshake();
- connection_ = new PacketSavingConnection(true);
+ connection_ = new PacketSavingConnection(/*is_server=*/false);
session_.reset(new TestClientSession(connection_, DefaultQuicConfig()));
stream_.reset(new QuicCryptoClientStream(server_id_, session_.get(), nullptr,
&crypto_config_));
@@ -135,7 +137,7 @@
stream_->CryptoConnect();
// Check that a client hello was sent.
- ASSERT_EQ(1u, connection_->packets_.size());
+ ASSERT_EQ(1u, connection_->encrypted_packets_.size());
}
TEST_F(QuicCryptoClientStreamTest, ServerConfigUpdate) {
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index 3ec65b0..8e04298 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -32,7 +32,9 @@
crypto_config_(crypto_config),
validate_client_hello_cb_(nullptr),
num_handshake_messages_(0),
- num_server_config_update_messages_sent_(0) {}
+ num_server_config_update_messages_sent_(0) {
+ DCHECK(session->connection()->is_server());
+}
QuicCryptoServerStream::~QuicCryptoServerStream() {
CancelOutstandingCallbacks();
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index d15ff2d..2b885fa 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -56,7 +56,7 @@
class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> {
public:
QuicCryptoServerStreamTest()
- : connection_(new PacketSavingConnection(true)),
+ : connection_(new PacketSavingConnection(/*is_server=*/true)),
session_(connection_, DefaultQuicConfig()),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance()),
@@ -133,8 +133,10 @@
}
TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
- PacketSavingConnection* client_conn = new PacketSavingConnection(false);
- PacketSavingConnection* server_conn = new PacketSavingConnection(false);
+ PacketSavingConnection* client_conn =
+ new PacketSavingConnection(/*is_server=*/false);
+ PacketSavingConnection* server_conn =
+ new PacketSavingConnection(/*is_server=*/true);
client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
@@ -152,7 +154,7 @@
// Do a first handshake in order to prime the client config with the server's
// information.
client->CryptoConnect();
- CHECK_EQ(1u, client_conn->packets_.size());
+ CHECK_EQ(1u, client_conn->encrypted_packets_.size());
scoped_ptr<TestSession> server_session(new TestSession(server_conn, config_));
scoped_ptr<QuicCryptoServerStream> server(
@@ -166,8 +168,8 @@
// Now do another handshake, hopefully in 0-RTT.
LOG(INFO) << "Resetting for 0-RTT handshake attempt";
- client_conn = new PacketSavingConnection(false);
- server_conn = new PacketSavingConnection(false);
+ client_conn = new PacketSavingConnection(/*is_server=*/false);
+ server_conn = new PacketSavingConnection(/*is_server=*/true);
// We need to advance time past the strike-server window so that it's
// authoritative in this time span.
client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
diff --git a/net/quic/quic_data_writer.cc b/net/quic/quic_data_writer.cc
index be8b357..1c6e47f 100644
--- a/net/quic/quic_data_writer.cc
+++ b/net/quic/quic_data_writer.cc
@@ -16,22 +16,15 @@
namespace net {
-QuicDataWriter::QuicDataWriter(size_t size)
- : buffer_(new char[size]),
- capacity_(size),
- length_(0) {
+QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
+ : buffer_(buffer), capacity_(size), length_(0) {
}
QuicDataWriter::~QuicDataWriter() {
- delete[] buffer_;
}
-char* QuicDataWriter::take() {
- char* rv = buffer_;
- buffer_ = nullptr;
- capacity_ = 0;
- length_ = 0;
- return rv;
+char* QuicDataWriter::data() {
+ return buffer_;
}
bool QuicDataWriter::WriteUInt8(uint8 value) {
diff --git a/net/quic/quic_data_writer.h b/net/quic/quic_data_writer.h
index 8204c3a..4b5958e 100644
--- a/net/quic/quic_data_writer.h
+++ b/net/quic/quic_data_writer.h
@@ -20,20 +20,20 @@
// This class provides facilities for packing QUIC data.
//
// The QuicDataWriter supports appending primitive values (int, string, etc)
-// to a frame instance. The QuicDataWriter grows its internal memory buffer
-// dynamically to hold the sequence of primitive values. The internal memory
-// buffer is exposed as the "data" of the QuicDataWriter.
+// to a frame instance. The internal memory buffer is exposed as the "data"
+// of the QuicDataWriter.
class NET_EXPORT_PRIVATE QuicDataWriter {
public:
- explicit QuicDataWriter(size_t length);
+ // Creates a QuicDataWriter where |buffer| is not owned.
+ QuicDataWriter(size_t size, char* buffer);
~QuicDataWriter();
// Returns the size of the QuicDataWriter's data.
size_t length() const { return length_; }
- // Takes the buffer from the QuicDataWriter.
- char* take();
+ // Retrieves the buffer from the QuicDataWriter without changing ownership.
+ char* data();
// Methods for adding to the payload. These values are appended to the end
// of the QuicDataWriter payload. Note - binary integers are written in
diff --git a/net/quic/quic_data_writer_test.cc b/net/quic/quic_data_writer_test.cc
index 07346c7..01b3c6d 100644
--- a/net/quic/quic_data_writer_test.cc
+++ b/net/quic/quic_data_writer_test.cc
@@ -14,7 +14,8 @@
namespace {
TEST(QuicDataWriterTest, WriteUInt8ToOffset) {
- QuicDataWriter writer(4);
+ char buffer[4];
+ QuicDataWriter writer(4, buffer);
writer.WriteUInt32(0xfefdfcfb);
EXPECT_TRUE(writer.WriteUInt8ToOffset(1, 0));
@@ -22,16 +23,15 @@
EXPECT_TRUE(writer.WriteUInt8ToOffset(3, 2));
EXPECT_TRUE(writer.WriteUInt8ToOffset(4, 3));
- scoped_ptr<char[]> data(writer.take());
-
- EXPECT_EQ(1, data[0]);
- EXPECT_EQ(2, data[1]);
- EXPECT_EQ(3, data[2]);
- EXPECT_EQ(4, data[3]);
+ EXPECT_EQ(1, writer.data()[0]);
+ EXPECT_EQ(2, writer.data()[1]);
+ EXPECT_EQ(3, writer.data()[2]);
+ EXPECT_EQ(4, writer.data()[3]);
}
TEST(QuicDataWriterDeathTest, WriteUInt8ToOffset) {
- QuicDataWriter writer(4);
+ char buffer[4];
+ QuicDataWriter writer(4, buffer);
EXPECT_DFATAL(EXPECT_FALSE(writer.WriteUInt8ToOffset(5, 4)),
"offset: 4 >= capacity: 4");
@@ -80,10 +80,10 @@
int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
for (int i = 0; i < num_test_cases; ++i) {
- QuicDataWriter writer(2);
+ char buffer[2];
+ QuicDataWriter writer(2, buffer);
EXPECT_TRUE(writer.WriteUFloat16(test_cases[i].decoded));
- scoped_ptr<char[]> data(writer.take());
- EXPECT_EQ(test_cases[i].encoded, *reinterpret_cast<uint16*>(data.get()));
+ EXPECT_EQ(test_cases[i].encoded, *reinterpret_cast<uint16*>(writer.data()));
}
}
@@ -144,17 +144,18 @@
// Check we're always within the promised range.
EXPECT_LT(value, GG_UINT64_C(0x3FFC0000000));
previous_value = value;
- QuicDataWriter writer(6);
+ char buffer[6];
+ QuicDataWriter writer(6, buffer);
EXPECT_TRUE(writer.WriteUFloat16(value - 1));
EXPECT_TRUE(writer.WriteUFloat16(value));
EXPECT_TRUE(writer.WriteUFloat16(value + 1));
- scoped_ptr<char[]> data(writer.take());
// Check minimal decoding (previous decoding has previous encoding).
- EXPECT_EQ(i-1, *reinterpret_cast<uint16*>(data.get()));
+ EXPECT_EQ(i - 1, *reinterpret_cast<uint16*>(writer.data()));
// Check roundtrip.
- EXPECT_EQ(i, *reinterpret_cast<uint16*>(data.get() + 2));
+ EXPECT_EQ(i, *reinterpret_cast<uint16*>(writer.data() + 2));
// Check next decoding.
- EXPECT_EQ(i < 4096? i+1 : i, *reinterpret_cast<uint16*>(data.get() + 4));
+ EXPECT_EQ(i < 4096 ? i + 1 : i,
+ *reinterpret_cast<uint16*>(writer.data() + 4));
}
}
diff --git a/net/quic/quic_dispatcher.cc b/net/quic/quic_dispatcher.cc
index ee2c0c6..f750bfa 100644
--- a/net/quic/quic_dispatcher.cc
+++ b/net/quic/quic_dispatcher.cc
@@ -204,6 +204,13 @@
const QuicPacketPublicHeader& header) {
QuicSession* session = nullptr;
+ // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
+ // Given that we can't even send a reply rejecting the packet, just black hole
+ // it.
+ if (current_client_address_.port() == 0) {
+ return false;
+ }
+
QuicConnectionId connection_id = header.connection_id;
SessionMap::iterator it = session_map_.find(connection_id);
if (it == session_map_.end()) {
@@ -242,7 +249,7 @@
return HandlePacketForTimeWait(header);
}
DVLOG(1) << "Created new session for " << connection_id;
- session_map_.insert(make_pair(connection_id, session));
+ session_map_.insert(std::make_pair(connection_id, session));
} else {
session = it->second;
}
@@ -337,7 +344,7 @@
// infinite loops in OnCanWrite.
return;
}
- write_blocked_list_.insert(make_pair(blocked_writer, true));
+ write_blocked_list_.insert(std::make_pair(blocked_writer, true));
}
void QuicDispatcher::OnConnectionAddedToTimeWaitList(
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc
index 8eb6ec1..e4514cb 100644
--- a/net/quic/quic_flags.cc
+++ b/net/quic/quic_flags.cc
@@ -39,22 +39,12 @@
// If true, QUIC congestion control will be paced. If false, pacing may be
// controlled by QUIC connection options in the config or by enabling BBR
// congestion control.
-bool FLAGS_quic_enable_pacing = false;
-
-// If true, the silent close option will be honored.
-bool FLAGS_quic_allow_silent_close = true;
-
-// If true, use std::cbrt instead of custom cube root.
-bool FLAGS_quic_use_std_cbrt = true;
+bool FLAGS_quic_enable_pacing = true;
// If true, then the source address tokens generated for QUIC connects will
// store multiple addresses.
bool FLAGS_quic_use_multiple_address_in_source_tokens = false;
-// If true, if min RTT and/or SRTT have not yet been set then initial RTT is
-// used to initialize them in a call to QuicConnection::GetStats.
-bool FLAGS_quic_use_initial_rtt_for_stats = true;
-
// If true, uses the last sent packet for the RTO timer instead of the earliest.
bool FLAGS_quic_rto_uses_last_sent = true;
@@ -62,10 +52,6 @@
// frames.
bool FLAGS_quic_attach_ack_notifiers_to_packets = true;
-// If true, the AckNotifierManager is informed about new packets as soon as they
-// are serialized.
-bool FLAGS_quic_ack_notifier_informed_on_serialized = true;
-
// If true, QUIC will use the new RTO that waits until an ack arrives to adjust
// the congestion window.
bool FLAGS_quic_use_new_rto = true;
@@ -87,3 +73,6 @@
// If true, limit the number of connections on the quic time-wait list using a
// flag.
bool FLAGS_quic_limit_time_wait_list_size = true;
+
+// Use small QUIC packet sizes by default.
+bool FLAGS_quic_small_default_packet_size = true;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h
index 58f0408..decdcb1 100644
--- a/net/quic/quic_flags.h
+++ b/net/quic/quic_flags.h
@@ -19,16 +19,13 @@
NET_EXPORT_PRIVATE
extern bool FLAGS_quic_enable_bandwidth_resumption_experiment;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_pacing;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_allow_silent_close;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_std_cbrt;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_multiple_address_in_source_tokens;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_initial_rtt_for_stats;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_rto_uses_last_sent;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_attach_ack_notifiers_to_packets;
-NET_EXPORT_PRIVATE extern bool FLAGS_quic_ack_notifier_informed_on_serialized;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_new_rto;
NET_EXPORT_PRIVATE extern int64 FLAGS_quic_time_wait_list_seconds;
NET_EXPORT_PRIVATE extern int64 FLAGS_quic_time_wait_list_max_connections;
NET_EXPORT_PRIVATE extern bool FLAGS_quic_limit_time_wait_list_size;
+NET_EXPORT_PRIVATE extern bool FLAGS_quic_small_default_packet_size;
#endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index 5cde3c2..4ff23a4 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -17,7 +17,6 @@
#include "net/quic/quic_socket_address_coder.h"
using base::StringPiece;
-using std::make_pair;
using std::map;
using std::max;
using std::min;
@@ -310,33 +309,31 @@
QuicFramer::AckFrameInfo::~AckFrameInfo() {}
+// static
QuicPacketEntropyHash QuicFramer::GetPacketEntropyHash(
- const QuicPacketHeader& header) const {
+ const QuicPacketHeader& header) {
return header.entropy_flag << (header.packet_sequence_number % 8);
}
-SerializedPacket QuicFramer::BuildDataPacket(
- const QuicPacketHeader& header,
- const QuicFrames& frames,
- size_t packet_size) {
- QuicDataWriter writer(packet_size);
- const SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0,
- nullptr);
+QuicPacket* QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
+ const QuicFrames& frames,
+ char* buffer,
+ size_t packet_length) {
+ QuicDataWriter writer(packet_length, buffer);
if (!AppendPacketHeader(header, &writer)) {
LOG(DFATAL) << "AppendPacketHeader failed";
- return kNoPacket;
+ return nullptr;
}
- for (size_t i = 0; i < frames.size(); ++i) {
- const QuicFrame& frame = frames[i];
-
+ size_t i = 0;
+ for (const QuicFrame& frame : frames) {
// Determine if we should write stream frame length in header.
const bool no_stream_frame_length =
(header.is_in_fec_group == NOT_IN_FEC_GROUP) &&
(i == frames.size() - 1);
if (!AppendTypeByte(frame, no_stream_frame_length, &writer)) {
LOG(DFATAL) << "AppendTypeByte failed";
- return kNoPacket;
+ return nullptr;
}
switch (frame.type) {
@@ -347,21 +344,21 @@
if (!AppendStreamFrame(
*frame.stream_frame, no_stream_frame_length, &writer)) {
LOG(DFATAL) << "AppendStreamFrame failed";
- return kNoPacket;
+ return nullptr;
}
break;
case ACK_FRAME:
if (!AppendAckFrameAndTypeByte(
header, *frame.ack_frame, &writer)) {
LOG(DFATAL) << "AppendAckFrameAndTypeByte failed";
- return kNoPacket;
+ return nullptr;
}
break;
case STOP_WAITING_FRAME:
if (!AppendStopWaitingFrame(
header, *frame.stop_waiting_frame, &writer)) {
LOG(DFATAL) << "AppendStopWaitingFrame failed";
- return kNoPacket;
+ return nullptr;
}
break;
case PING_FRAME:
@@ -370,89 +367,79 @@
case RST_STREAM_FRAME:
if (!AppendRstStreamFrame(*frame.rst_stream_frame, &writer)) {
LOG(DFATAL) << "AppendRstStreamFrame failed";
- return kNoPacket;
+ return nullptr;
}
break;
case CONNECTION_CLOSE_FRAME:
if (!AppendConnectionCloseFrame(
*frame.connection_close_frame, &writer)) {
LOG(DFATAL) << "AppendConnectionCloseFrame failed";
- return kNoPacket;
+ return nullptr;
}
break;
case GOAWAY_FRAME:
if (!AppendGoAwayFrame(*frame.goaway_frame, &writer)) {
LOG(DFATAL) << "AppendGoAwayFrame failed";
- return kNoPacket;
+ return nullptr;
}
break;
case WINDOW_UPDATE_FRAME:
if (!AppendWindowUpdateFrame(*frame.window_update_frame, &writer)) {
LOG(DFATAL) << "AppendWindowUpdateFrame failed";
- return kNoPacket;
+ return nullptr;
}
break;
case BLOCKED_FRAME:
if (!AppendBlockedFrame(*frame.blocked_frame, &writer)) {
LOG(DFATAL) << "AppendBlockedFrame failed";
- return kNoPacket;
+ return nullptr;
}
break;
default:
RaiseError(QUIC_INVALID_FRAME_DATA);
LOG(DFATAL) << "QUIC_INVALID_FRAME_DATA";
- return kNoPacket;
+ return nullptr;
}
+ ++i;
}
- // Save the length before writing, because take clears it.
- const size_t len = writer.length();
- // Less than or equal because truncated acks end up with max_plaintex_size
- // length, even though they're typically slightly shorter.
- DCHECK_LE(len, packet_size);
- QuicPacket* packet = QuicPacket::NewDataPacket(
- writer.take(), len, true, header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.sequence_number_length);
+ QuicPacket* packet =
+ new QuicPacket(writer.data(), writer.length(), false,
+ header.public_header.connection_id_length,
+ header.public_header.version_flag,
+ header.public_header.sequence_number_length);
if (fec_builder_) {
fec_builder_->OnBuiltFecProtectedPayload(header,
packet->FecProtectedData());
}
- return SerializedPacket(header.packet_sequence_number,
- header.public_header.sequence_number_length, packet,
- GetPacketEntropyHash(header), nullptr);
+ return packet;
}
-SerializedPacket QuicFramer::BuildFecPacket(const QuicPacketHeader& header,
- const QuicFecData& fec) {
+QuicPacket* QuicFramer::BuildFecPacket(const QuicPacketHeader& header,
+ const QuicFecData& fec) {
DCHECK_EQ(IN_FEC_GROUP, header.is_in_fec_group);
DCHECK_NE(0u, header.fec_group);
size_t len = GetPacketHeaderSize(header);
len += fec.redundancy.length();
- QuicDataWriter writer(len);
- const SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0,
- nullptr);
+ scoped_ptr<char[]> buffer(new char[len]);
+ QuicDataWriter writer(len, buffer.get());
if (!AppendPacketHeader(header, &writer)) {
LOG(DFATAL) << "AppendPacketHeader failed";
- return kNoPacket;
+ return nullptr;
}
if (!writer.WriteBytes(fec.redundancy.data(), fec.redundancy.length())) {
LOG(DFATAL) << "Failed to add FEC";
- return kNoPacket;
+ return nullptr;
}
- return SerializedPacket(
- header.packet_sequence_number,
- header.public_header.sequence_number_length,
- QuicPacket::NewFecPacket(writer.take(), len, true,
- header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.sequence_number_length),
- GetPacketEntropyHash(header), nullptr);
+ return new QuicPacket(buffer.release(), len, true,
+ header.public_header.connection_id_length,
+ header.public_header.version_flag,
+ header.public_header.sequence_number_length);
}
// static
@@ -477,7 +464,8 @@
size_t len =
kPublicFlagsSize + PACKET_8BYTE_CONNECTION_ID + reset_serialized.length();
- QuicDataWriter writer(len);
+ scoped_ptr<char[]> buffer(new char[len]);
+ QuicDataWriter writer(len, buffer.get());
uint8 flags = static_cast<uint8>(PACKET_PUBLIC_FLAGS_RST |
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID);
@@ -493,7 +481,7 @@
return nullptr;
}
- return new QuicEncryptedPacket(writer.take(), len, true);
+ return new QuicEncryptedPacket(buffer.release(), len, true);
}
QuicEncryptedPacket* QuicFramer::BuildVersionNegotiationPacket(
@@ -501,7 +489,8 @@
const QuicVersionVector& supported_versions) {
DCHECK(header.version_flag);
size_t len = GetVersionNegotiationPacketSize(supported_versions.size());
- QuicDataWriter writer(len);
+ scoped_ptr<char[]> buffer(new char[len]);
+ QuicDataWriter writer(len, buffer.get());
uint8 flags = static_cast<uint8>(PACKET_PUBLIC_FLAGS_VERSION |
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID);
@@ -519,7 +508,7 @@
}
}
- return new QuicEncryptedPacket(writer.take(), len, true);
+ return new QuicEncryptedPacket(buffer.release(), len, true);
}
bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
@@ -555,8 +544,16 @@
rv = ProcessVersionNegotiationPacket(&public_header);
} else if (public_header.reset_flag) {
rv = ProcessPublicResetPacket(public_header);
+ } else if (packet.length() <= kMaxPacketSize) {
+ char buffer[kMaxPacketSize];
+ rv = ProcessDataPacket(public_header, packet, buffer, kMaxPacketSize);
} else {
- rv = ProcessDataPacket(public_header, packet);
+ scoped_ptr<char[]> large_buffer(new char[packet.length()]);
+ rv = ProcessDataPacket(public_header, packet, large_buffer.get(),
+ packet.length());
+ LOG_IF(DFATAL, rv) << "QUIC should never successfully process packets "
+ << "larger than kMaxPacketSize. packet size:"
+ << packet.length();
}
reader_.reset(nullptr);
@@ -580,11 +577,12 @@
return true;
}
-bool QuicFramer::ProcessDataPacket(
- const QuicPacketPublicHeader& public_header,
- const QuicEncryptedPacket& packet) {
+bool QuicFramer::ProcessDataPacket(const QuicPacketPublicHeader& public_header,
+ const QuicEncryptedPacket& packet,
+ char* decrypted_buffer,
+ size_t buffer_length) {
QuicPacketHeader header(public_header);
- if (!ProcessPacketHeader(&header, packet)) {
+ if (!ProcessPacketHeader(&header, packet, decrypted_buffer, buffer_length)) {
DLOG(WARNING) << "Unable to process data packet header.";
return false;
}
@@ -998,9 +996,10 @@
return ack_info;
}
-bool QuicFramer::ProcessPacketHeader(
- QuicPacketHeader* header,
- const QuicEncryptedPacket& packet) {
+bool QuicFramer::ProcessPacketHeader(QuicPacketHeader* header,
+ const QuicEncryptedPacket& packet,
+ char* decrypted_buffer,
+ size_t buffer_length) {
if (!ProcessPacketSequenceNumber(header->public_header.sequence_number_length,
&header->packet_sequence_number)) {
set_detailed_error("Unable to read sequence number.");
@@ -1016,7 +1015,7 @@
return false;
}
- if (!DecryptPayload(*header, packet)) {
+ if (!DecryptPayload(*header, packet, decrypted_buffer, buffer_length)) {
set_detailed_error("Unable to decrypt payload.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
@@ -1407,7 +1406,7 @@
last_timestamp_ = CalculateTimestampFromWire(time_delta_us);
ack_frame->received_packet_times.push_back(
- make_pair(seq_num, creation_time_.Add(last_timestamp_)));
+ std::make_pair(seq_num, creation_time_.Add(last_timestamp_)));
for (uint8 i = 1; i < num_received_packets; ++i) {
if (!reader_->ReadBytes(&delta_from_largest_observed,
@@ -1429,7 +1428,7 @@
last_timestamp_ = last_timestamp_.Add(
QuicTime::Delta::FromMicroseconds(incremental_time_delta_us));
ack_frame->received_packet_times.push_back(
- make_pair(seq_num, creation_time_.Add(last_timestamp_)));
+ std::make_pair(seq_num, creation_time_.Add(last_timestamp_)));
}
}
}
@@ -1623,19 +1622,27 @@
const QuicPacket& packet) {
DCHECK(encrypter_[level].get() != nullptr);
- scoped_ptr<QuicData> out(encrypter_[level]->EncryptPacket(
- packet_sequence_number, packet.AssociatedData(), packet.Plaintext()));
- if (out.get() == nullptr) {
+ // Allocate a large enough buffer for the header and the encrypted data.
+ const size_t encrypted_len =
+ encrypter_[level]->GetCiphertextSize(packet.Plaintext().length());
+ StringPiece header_data = packet.BeforePlaintext();
+ const size_t len = header_data.length() + encrypted_len;
+ // TODO(ianswett): Consider allocating this on the stack in the typical case.
+ char* buffer = new char[len];
+ // Copy in the header, because the encrypter only populates the encrypted
+ // plaintext content.
+ memcpy(buffer, header_data.data(), header_data.length());
+ // Encrypt the plaintext into the buffer.
+ size_t output_length = 0;
+ if (!encrypter_[level]->EncryptPacket(
+ packet_sequence_number, packet.AssociatedData(), packet.Plaintext(),
+ buffer + header_data.length(), &output_length, encrypted_len)) {
RaiseError(QUIC_ENCRYPTION_FAILURE);
return nullptr;
}
- StringPiece header_data = packet.BeforePlaintext();
- size_t len = header_data.length() + out->length();
- char* buffer = new char[len];
- // TODO(rch): eliminate this buffer copy by passing in a buffer to Encrypt().
- memcpy(buffer, header_data.data(), header_data.length());
- memcpy(buffer + header_data.length(), out->data(), out->length());
- return new QuicEncryptedPacket(buffer, len, true);
+
+ return new QuicEncryptedPacket(buffer, header_data.length() + output_length,
+ true);
}
size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) {
@@ -1656,32 +1663,26 @@
}
bool QuicFramer::DecryptPayload(const QuicPacketHeader& header,
- const QuicEncryptedPacket& packet) {
- StringPiece encrypted;
- if (!reader_->ReadStringPiece(&encrypted, reader_->BytesRemaining())) {
- return false;
- }
+ const QuicEncryptedPacket& packet,
+ char* decrypted_buffer,
+ size_t buffer_length) {
+ StringPiece encrypted = reader_->ReadRemainingPayload();
DCHECK(decrypter_.get() != nullptr);
- decrypted_.reset(decrypter_->DecryptPacket(
- header.packet_sequence_number,
- GetAssociatedDataFromEncryptedPacket(
- packet,
- header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.sequence_number_length),
- encrypted));
- if (decrypted_.get() != nullptr) {
+ const StringPiece& associated_data = GetAssociatedDataFromEncryptedPacket(
+ packet, header.public_header.connection_id_length,
+ header.public_header.version_flag,
+ header.public_header.sequence_number_length);
+ size_t decrypted_length = 0;
+ bool success = decrypter_->DecryptPacket(
+ header.packet_sequence_number, associated_data, encrypted,
+ decrypted_buffer, &decrypted_length, buffer_length);
+ if (success) {
visitor_->OnDecryptedPacket(decrypter_level_);
} else if (alternative_decrypter_.get() != nullptr) {
- decrypted_.reset(alternative_decrypter_->DecryptPacket(
- header.packet_sequence_number,
- GetAssociatedDataFromEncryptedPacket(
- packet,
- header.public_header.connection_id_length,
- header.public_header.version_flag,
- header.public_header.sequence_number_length),
- encrypted));
- if (decrypted_.get() != nullptr) {
+ success = alternative_decrypter_->DecryptPacket(
+ header.packet_sequence_number, associated_data, encrypted,
+ decrypted_buffer, &decrypted_length, buffer_length);
+ if (success) {
visitor_->OnDecryptedPacket(alternative_decrypter_level_);
if (alternative_decrypter_latch_) {
// Switch to the alternative decrypter and latch so that we cannot
@@ -1699,13 +1700,13 @@
}
}
- if (decrypted_.get() == nullptr) {
+ if (!success) {
DLOG(WARNING) << "DecryptPacket failed for sequence_number:"
<< header.packet_sequence_number;
return false;
}
- reader_.reset(new QuicDataReader(decrypted_->data(), decrypted_->length()));
+ reader_.reset(new QuicDataReader(decrypted_buffer, decrypted_length));
return true;
}
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h
index 0504d3d..3cfaa88 100644
--- a/net/quic/quic_framer.h
+++ b/net/quic/quic_framer.h
@@ -301,18 +301,19 @@
bool includes_version,
QuicSequenceNumberLength sequence_number_length);
- // Returns a SerializedPacket whose |packet| member is owned by the caller,
- // is created from the first |num_frames| frames, or is nullptr if the packet
- // could not be created. The packet must be of size |packet_size|.
- SerializedPacket BuildDataPacket(const QuicPacketHeader& header,
- const QuicFrames& frames,
- size_t packet_size);
+ // Returns a QuicPacket* that is owned by the caller, is created from
+ // |frames|. Returns nullptr if the packet could not be created.
+ // The packet must be of size |packet_size|.
+ QuicPacket* BuildDataPacket(const QuicPacketHeader& header,
+ const QuicFrames& frames,
+ char* buffer,
+ size_t packet_length);
- // Returns a SerializedPacket whose |packet| member is owned by the caller,
- // and is populated with the fields in |header| and |fec|, or is nullptr if
- // the packet could not be created.
- SerializedPacket BuildFecPacket(const QuicPacketHeader& header,
- const QuicFecData& fec);
+ // Returns a QuicPacket* that is owned by the caller, and is populated with
+ // the fields in |header| and |fec|. Returns nullptr if the packet could
+ // not be created.
+ QuicPacket* BuildFecPacket(const QuicPacketHeader& header,
+ const QuicFecData& fec);
// Returns a new public reset packet, owned by the caller.
static QuicEncryptedPacket* BuildPublicResetPacket(
@@ -371,6 +372,9 @@
bool is_server() const { return is_server_; }
+ static QuicPacketEntropyHash GetPacketEntropyHash(
+ const QuicPacketHeader& header);
+
private:
friend class test::QuicFramerPeer;
@@ -386,11 +390,10 @@
NackRangeMap nack_ranges;
};
- QuicPacketEntropyHash GetPacketEntropyHash(
- const QuicPacketHeader& header) const;
-
bool ProcessDataPacket(const QuicPacketPublicHeader& public_header,
- const QuicEncryptedPacket& packet);
+ const QuicEncryptedPacket& packet,
+ char* decrypted_buffer,
+ size_t buffer_length);
bool ProcessPublicResetPacket(const QuicPacketPublicHeader& public_header);
@@ -398,8 +401,12 @@
bool ProcessPublicHeader(QuicPacketPublicHeader* header);
+ // |decrypted_buffer| must be allocated to be large enough to hold the
+ // unencrypted contents of |packet|.
bool ProcessPacketHeader(QuicPacketHeader* header,
- const QuicEncryptedPacket& packet);
+ const QuicEncryptedPacket& packet,
+ char* decrypted_buffer,
+ size_t buffer_length);
bool ProcessPacketSequenceNumber(
QuicSequenceNumberLength sequence_number_length,
@@ -417,7 +424,9 @@
bool ProcessBlockedFrame(QuicBlockedFrame* frame);
bool DecryptPayload(const QuicPacketHeader& header,
- const QuicEncryptedPacket& packet);
+ const QuicEncryptedPacket& packet,
+ char* decrypted_buffer,
+ size_t buffer_length);
// Returns the full packet sequence number from the truncated
// wire format version and the last seen packet sequence number.
@@ -497,8 +506,6 @@
QuicPacketSequenceNumber last_sequence_number_;
// Updated by WritePacketHeader.
QuicConnectionId last_serialized_connection_id_;
- // Buffer containing decrypted payload data during parsing.
- scoped_ptr<QuicData> decrypted_;
// Version of the protocol being used.
QuicVersion quic_version_;
// This vector contains QUIC versions which we currently support.
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index 0fa4ce9..69373e0 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -113,13 +113,18 @@
CHECK(false) << "Not implemented";
return false;
}
- QuicData* EncryptPacket(QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece plaintext) override {
+ bool EncryptPacket(QuicPacketSequenceNumber sequence_number,
+ StringPiece associated_data,
+ StringPiece plaintext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override {
sequence_number_ = sequence_number;
associated_data_ = associated_data.as_string();
plaintext_ = plaintext.as_string();
- return new QuicData(plaintext.data(), plaintext.length());
+ memcpy(output, plaintext.data(), plaintext.length());
+ *output_length = plaintext.length();
+ return true;
}
size_t GetKeySize() const override { return 0; }
size_t GetNoncePrefixSize() const override { return 0; }
@@ -141,13 +146,18 @@
~TestDecrypter() override {}
bool SetKey(StringPiece key) override { return true; }
bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; }
- QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number,
- StringPiece associated_data,
- StringPiece ciphertext) override {
+ bool DecryptPacket(QuicPacketSequenceNumber sequence_number,
+ const StringPiece& associated_data,
+ const StringPiece& ciphertext,
+ char* output,
+ size_t* output_length,
+ size_t max_output_length) override {
sequence_number_ = sequence_number;
associated_data_ = associated_data.as_string();
ciphertext_ = ciphertext.as_string();
- return new QuicData(ciphertext.data(), ciphertext.length());
+ memcpy(output, ciphertext.data(), ciphertext.length());
+ *output_length = ciphertext.length();
+ return true;
}
StringPiece GetKey() const override { return StringPiece(); }
StringPiece GetNoncePrefix() const override { return StringPiece(); }
@@ -176,6 +186,8 @@
STLDeleteElements(&stop_waiting_frames_);
STLDeleteElements(&ping_frames_);
STLDeleteElements(&fec_data_);
+ STLDeleteElements(&stream_data_);
+ STLDeleteElements(&fec_data_redundancy_);
}
void OnError(QuicFramer* f) override {
@@ -223,7 +235,14 @@
bool OnStreamFrame(const QuicStreamFrame& frame) override {
++frame_count_;
- stream_frames_.push_back(new QuicStreamFrame(frame));
+ // Save a copy of the data so it is valid after the packet is processed.
+ stream_data_.push_back(frame.GetDataAsString());
+ QuicStreamFrame* stream_frame = new QuicStreamFrame(frame);
+ // Make sure that the stream frame points to this data.
+ stream_frame->data.Clear();
+ stream_frame->data.Append(const_cast<char*>(stream_data_.back()->data()),
+ stream_data_.back()->size());
+ stream_frames_.push_back(stream_frame);
return true;
}
@@ -251,7 +270,13 @@
void OnFecData(const QuicFecData& fec) override {
++fec_count_;
- fec_data_.push_back(new QuicFecData(fec));
+ QuicFecData* fec_data = new QuicFecData();
+ fec_data->fec_group = fec.fec_group;
+ // Save a copy of the data so it is valid after the packet is processed.
+ string* redundancy = new string(fec.redundancy.as_string());
+ fec_data_redundancy_.push_back(redundancy);
+ fec_data->redundancy = StringPiece(*redundancy);
+ fec_data_.push_back(fec_data);
}
void OnPacketComplete() override { ++complete_packets_; }
@@ -307,6 +332,8 @@
QuicGoAwayFrame goaway_frame_;
QuicWindowUpdateFrame window_update_frame_;
QuicBlockedFrame blocked_frame_;
+ vector<string*> stream_data_;
+ vector<string*> fec_data_redundancy_;
};
class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
@@ -449,7 +476,13 @@
QuicPacket* BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames) {
- return BuildUnsizedDataPacket(&framer_, header, frames).packet;
+ return BuildUnsizedDataPacket(&framer_, header, frames);
+ }
+
+ QuicPacket* BuildDataPacket(const QuicPacketHeader& header,
+ const QuicFrames& frames,
+ size_t packet_size) {
+ return BuildUnsizedDataPacket(&framer_, header, frames, packet_size);
}
test::TestEncrypter* encrypter_;
@@ -1312,8 +1345,7 @@
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
- EXPECT_EQ(GG_UINT64_C(0x00020304),
- visitor_.stream_frames_[0]->stream_id);
+ EXPECT_EQ(GG_UINT64_C(0x00020304), visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
@@ -3367,8 +3399,7 @@
0x00,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildDataPacket(header, frames, kMaxPacketSize).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3430,8 +3461,7 @@
0x00,
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildDataPacket(header, frames, 37u).packet);
+ scoped_ptr<QuicPacket> data(BuildDataPacket(header, frames, 37u));
ASSERT_TRUE(data != nullptr);
// Expect 1 byte unused since at least 2 bytes are needed to fit more nacks.
EXPECT_EQ(36u, data->length());
@@ -3904,8 +3934,7 @@
'm', 'n', 'o', 'p',
};
- scoped_ptr<QuicPacket> data(
- framer_.BuildFecPacket(header, fec_data).packet);
+ scoped_ptr<QuicPacket> data(framer_.BuildFecPacket(header, fec_data));
ASSERT_TRUE(data != nullptr);
test::CompareCharArraysWithHexError("constructed packet",
@@ -3936,10 +3965,9 @@
'm', 'n', 'o', 'p',
};
- scoped_ptr<QuicPacket> raw(
- QuicPacket::NewDataPacket(AsChars(packet), arraysize(packet), false,
- PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion,
- PACKET_6BYTE_SEQUENCE_NUMBER));
+ scoped_ptr<QuicPacket> raw(new QuicPacket(
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ !kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, sequence_number, *raw));
@@ -3972,10 +4000,9 @@
'm', 'n', 'o', 'p',
};
- scoped_ptr<QuicPacket> raw(
- QuicPacket::NewDataPacket(AsChars(packet), arraysize(packet), false,
- PACKET_8BYTE_CONNECTION_ID, kIncludeVersion,
- PACKET_6BYTE_SEQUENCE_NUMBER));
+ scoped_ptr<QuicPacket> raw(new QuicPacket(
+ AsChars(packet), arraysize(packet), false, PACKET_8BYTE_CONNECTION_ID,
+ kIncludeVersion, PACKET_6BYTE_SEQUENCE_NUMBER));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(ENCRYPTION_NONE, sequence_number, *raw));
@@ -4002,8 +4029,7 @@
frames.push_back(frame);
// Build an ack packet with truncation due to limit in number of nack ranges.
- scoped_ptr<QuicPacket> raw_ack_packet(
- framer_.BuildDataPacket(header, frames, kMaxPacketSize).packet);
+ scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames));
ASSERT_TRUE(raw_ack_packet != nullptr);
scoped_ptr<QuicEncryptedPacket> ack_packet(
framer_.EncryptPacket(ENCRYPTION_NONE, header.packet_sequence_number,
@@ -4042,8 +4068,7 @@
frames.push_back(frame);
// Build an ack packet with truncation due to limit in number of nack ranges.
- scoped_ptr<QuicPacket> raw_ack_packet(
- framer_.BuildDataPacket(header, frames, 500).packet);
+ scoped_ptr<QuicPacket> raw_ack_packet(BuildDataPacket(header, frames, 500));
ASSERT_TRUE(raw_ack_packet != nullptr);
scoped_ptr<QuicEncryptedPacket> ack_packet(
framer_.EncryptPacket(ENCRYPTION_NONE, header.packet_sequence_number,
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index a22bb74..5b69e46 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -13,7 +13,6 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_response_headers.h"
#include "net/http/transport_security_state.h"
-#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/crypto/quic_decrypter.h"
@@ -74,16 +73,6 @@
void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
}
-
- void SetReceiveAlgorithm(ReceiveAlgorithmInterface* receive_algorithm) {
- QuicConnectionPeer::SetReceiveAlgorithm(this, receive_algorithm);
- }
-};
-
-class TestReceiveAlgorithm : public ReceiveAlgorithmInterface {
- public:
- MOCK_METHOD3(RecordIncomingPacket,
- void(QuicByteCount, QuicPacketSequenceNumber, QuicTime));
};
// Subclass of QuicHttpStream that closes itself when the first piece of data
@@ -198,9 +187,6 @@
socket->Connect(peer_addr_);
runner_ = new TestTaskRunner(&clock_);
send_algorithm_ = new MockSendAlgorithm();
- receive_algorithm_ = new TestReceiveAlgorithm();
- EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _)).
- Times(AnyNumber());
EXPECT_CALL(*send_algorithm_,
OnPacketSent(_, _, _, _, _)).WillRepeatedly(Return(true));
EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
@@ -220,7 +206,6 @@
helper_.get(), writer_factory);
connection_->set_visitor(&visitor_);
connection_->SetSendAlgorithm(send_algorithm_);
- connection_->SetReceiveAlgorithm(receive_algorithm_);
session_.reset(
new QuicClientSession(connection_,
scoped_ptr<DatagramClientSocket>(socket),
@@ -307,7 +292,6 @@
BoundNetLog net_log_;
bool use_closing_stream_;
MockSendAlgorithm* send_algorithm_;
- TestReceiveAlgorithm* receive_algorithm_;
scoped_refptr<TestTaskRunner> runner_;
scoped_ptr<MockWrite[]> mock_writes_;
MockClock clock_;
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index c9f1d24..e91efa2 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_data_writer.h"
#include "net/quic/quic_fec_group.h"
#include "net/quic/quic_utils.h"
@@ -262,28 +263,33 @@
}
SerializedPacket QuicPacketCreator::ReserializeAllFrames(
- const QuicFrames& frames,
+ const RetransmittableFrames& frames,
QuicSequenceNumberLength original_length) {
DCHECK(fec_group_.get() == nullptr);
const QuicSequenceNumberLength saved_length = sequence_number_length_;
const QuicSequenceNumberLength saved_next_length =
next_sequence_number_length_;
const bool saved_should_fec_protect = should_fec_protect_;
+ const EncryptionLevel default_encryption_level = encryption_level_;
- // Temporarily set the sequence number length and stop FEC protection.
+ // Temporarily set the sequence number length, stop FEC protection,
+ // and change the encryption level.
sequence_number_length_ = original_length;
next_sequence_number_length_ = original_length;
should_fec_protect_ = false;
+ encryption_level_ = frames.encryption_level();
// Serialize the packet and restore the FEC and sequence number length state.
- SerializedPacket serialized_packet = SerializeAllFrames(frames);
+ SerializedPacket serialized_packet = SerializeAllFrames(frames.frames());
sequence_number_length_ = saved_length;
next_sequence_number_length_ = saved_next_length;
should_fec_protect_ = saved_should_fec_protect;
+ encryption_level_ = default_encryption_level;
return serialized_packet;
}
+// TODO(ianswett): Remove this method, because it's test only.
SerializedPacket QuicPacketCreator::SerializeAllFrames(
const QuicFrames& frames) {
// TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued
@@ -292,8 +298,8 @@
DCHECK_EQ(0u, queued_frames_.size());
LOG_IF(DFATAL, frames.empty())
<< "Attempt to serialize empty packet";
- for (size_t i = 0; i < frames.size(); ++i) {
- bool success = AddFrame(frames[i], false);
+ for (const QuicFrame& frame : frames) {
+ bool success = AddFrame(frame, false);
DCHECK(success);
}
SerializedPacket packet = SerializePacket();
@@ -367,19 +373,43 @@
bool possibly_truncated_by_length = packet_size_ == max_plaintext_size &&
queued_frames_.size() == 1 &&
queued_frames_.back().type == ACK_FRAME;
- SerializedPacket serialized =
- framer_->BuildDataPacket(header, queued_frames_, packet_size_);
- LOG_IF(DFATAL, !serialized.packet)
- << "Failed to serialize " << queued_frames_.size() << " frames.";
+ char buffer[kMaxPacketSize];
+ scoped_ptr<QuicPacket> packet;
+ // Use the packet_size_ instead of the buffer size to ensure smaller
+ // packet sizes are properly used.
+ scoped_ptr<char[]> large_buffer;
+ if (packet_size_ <= kMaxPacketSize) {
+ packet.reset(
+ framer_->BuildDataPacket(header, queued_frames_, buffer, packet_size_));
+ } else {
+ large_buffer.reset(new char[packet_size_]);
+ packet.reset(framer_->BuildDataPacket(header, queued_frames_,
+ large_buffer.get(), packet_size_));
+ }
+ LOG_IF(DFATAL, packet == nullptr) << "Failed to serialize "
+ << queued_frames_.size() << " frames.";
// Because of possible truncation, we can't be confident that our
// packet size calculation worked correctly.
if (!possibly_truncated_by_length) {
- DCHECK_EQ(packet_size_, serialized.packet->length());
+ DCHECK_EQ(packet_size_, packet->length());
}
+ // Immediately encrypt the packet, to ensure we don't encrypt the same packet
+ // sequence number multiple times.
+ QuicEncryptedPacket* encrypted =
+ framer_->EncryptPacket(encryption_level_, sequence_number_, *packet);
+ if (encrypted == nullptr) {
+ LOG(DFATAL) << "Failed to encrypt packet number " << sequence_number_;
+ SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0,
+ nullptr);
+ return kNoPacket;
+ }
+
packet_size_ = 0;
queued_frames_.clear();
- serialized.retransmittable_frames = queued_retransmittable_frames_.release();
- return serialized;
+ return SerializedPacket(header.packet_sequence_number,
+ header.public_header.sequence_number_length,
+ encrypted, QuicFramer::GetPacketEntropyHash(header),
+ queued_retransmittable_frames_.release());
}
SerializedPacket QuicPacketCreator::SerializeFec() {
@@ -396,12 +426,27 @@
QuicFecData fec_data;
fec_data.fec_group = fec_group_->min_protected_packet();
fec_data.redundancy = fec_group_->payload_parity();
- SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data);
+ scoped_ptr<QuicPacket> packet(framer_->BuildFecPacket(header, fec_data));
fec_group_.reset(nullptr);
packet_size_ = 0;
- LOG_IF(DFATAL, !serialized.packet)
+ LOG_IF(DFATAL, packet == nullptr)
<< "Failed to serialize fec packet for group:" << fec_data.fec_group;
- DCHECK_GE(max_packet_length_, serialized.packet->length());
+ DCHECK_GE(max_packet_length_, packet->length());
+ // Immediately encrypt the packet, to ensure we don't encrypt the same packet
+ // sequence number multiple times.
+ QuicEncryptedPacket* encrypted =
+ framer_->EncryptPacket(encryption_level_, sequence_number_, *packet);
+ if (encrypted == nullptr) {
+ LOG(DFATAL) << "Failed to encrypt packet number " << sequence_number_;
+ SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0,
+ nullptr);
+ return kNoPacket;
+ }
+ SerializedPacket serialized(
+ header.packet_sequence_number,
+ header.public_header.sequence_number_length, encrypted,
+ QuicFramer::GetPacketEntropyHash(header), nullptr);
+ serialized.is_fec_packet = true;
return serialized;
}
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h
index 5ff6582..a473835 100644
--- a/net/quic/quic_packet_creator.h
+++ b/net/quic/quic_packet_creator.h
@@ -98,7 +98,7 @@
// Caller must ensure that any open FEC group is closed before calling this
// method.
SerializedPacket ReserializeAllFrames(
- const QuicFrames& frames,
+ const RetransmittableFrames& frames,
QuicSequenceNumberLength original_length);
// Returns true if there are frames pending to be serialized.
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 241c42b..84632cf 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -89,10 +89,7 @@
~QuicPacketCreatorTest() override {}
- void ProcessPacket(QuicPacket* packet) {
- scoped_ptr<QuicEncryptedPacket> encrypted(
- server_framer_.EncryptPacket(ENCRYPTION_NONE, sequence_number_,
- *packet));
+ void ProcessPacket(QuicEncryptedPacket* encrypted) {
server_framer_.ProcessPacket(*encrypted);
}
@@ -441,15 +438,18 @@
creator_.set_next_sequence_number_length(PACKET_4BYTE_SEQUENCE_NUMBER);
QuicPacketCreatorPeer::SetSequenceNumberLength(&creator_,
PACKET_2BYTE_SEQUENCE_NUMBER);
- frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
+ QuicStreamFrame* stream_frame =
+ new QuicStreamFrame(kCryptoStreamId, /*fin=*/false, 0u, IOVector());
+ RetransmittableFrames frames;
+ frames.set_encryption_level(ENCRYPTION_NONE);
+ frames.AddStreamFrame(stream_frame);
SerializedPacket serialized =
- creator_.ReserializeAllFrames(frames_, PACKET_1BYTE_SEQUENCE_NUMBER);
+ creator_.ReserializeAllFrames(frames, PACKET_1BYTE_SEQUENCE_NUMBER);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
creator_.next_sequence_number_length());
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
QuicPacketCreatorPeer::GetSequenceNumberLength(&creator_));
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
- delete frames_[0].stream_frame;
{
InSequence s;
@@ -466,16 +466,15 @@
}
TEST_P(QuicPacketCreatorTest, ReserializeFramesWithPadding) {
- scoped_ptr<QuicStreamFrame> stream_frame(
- new QuicStreamFrame(kCryptoStreamId, /*fin=*/ false, /*offset=*/ 0,
- MakeIOVector("fake handshake message data")));
- frames_.push_back(QuicFrame(stream_frame.get()));
- SerializedPacket serialized =
- creator_.ReserializeAllFrames(frames_,
- creator_.next_sequence_number_length());
-
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize),
- serialized.packet->length());
+ QuicStreamFrame* stream_frame =
+ new QuicStreamFrame(kCryptoStreamId, /*fin=*/false, /*offset=*/0,
+ MakeIOVector("fake handshake message data"));
+ RetransmittableFrames frames;
+ frames.set_encryption_level(ENCRYPTION_NONE);
+ frames.AddStreamFrame(stream_frame);
+ SerializedPacket serialized = creator_.ReserializeAllFrames(
+ frames, creator_.next_sequence_number_length());
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized.packet->length());
delete serialized.packet;
}
@@ -487,23 +486,22 @@
string data(capacity + delta, 'A');
size_t bytes_free = 0 - delta;
- scoped_ptr<QuicStreamFrame> stream_frame(
- new QuicStreamFrame(kCryptoStreamId, /*fin=*/ false, kOffset,
- MakeIOVector(data)));
- frames_.push_back(QuicFrame(stream_frame.get()));
- SerializedPacket serialized =
- creator_.ReserializeAllFrames(frames_,
- creator_.next_sequence_number_length());
+ QuicStreamFrame* stream_frame = new QuicStreamFrame(
+ kCryptoStreamId, /*fin=*/false, kOffset, MakeIOVector(data));
+ RetransmittableFrames frames;
+ frames.set_encryption_level(ENCRYPTION_NONE);
+ frames.AddStreamFrame(stream_frame);
+ SerializedPacket serialized = creator_.ReserializeAllFrames(
+ frames, creator_.next_sequence_number_length());
// If there is not enough space in the packet to fit a padding frame
// (1 byte) and to expand the stream frame (another 2 bytes) the packet
// will not be padded.
if (bytes_free < 3) {
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize)
- - bytes_free, serialized.packet->length());
- } else {
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize),
+ EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
serialized.packet->length());
+ } else {
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized.packet->length());
}
delete serialized.packet;
@@ -740,11 +738,10 @@
// (1 byte) and to expand the stream frame (another 2 bytes) the packet
// will not be padded.
if (bytes_free < 3) {
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize)
- - bytes_free, serialized_packet.packet->length());
- } else {
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize),
+ EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
serialized_packet.packet->length());
+ } else {
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet.packet->length());
}
delete serialized_packet.packet;
delete serialized_packet.retransmittable_frames;
@@ -770,11 +767,10 @@
SerializedPacket serialized_packet = creator_.SerializePacket();
ASSERT_TRUE(serialized_packet.packet);
if (bytes_free > 0) {
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize)
- - bytes_free, serialized_packet.packet->length());
- } else {
- EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize),
+ EXPECT_EQ(kDefaultMaxPacketSize - bytes_free,
serialized_packet.packet->length());
+ } else {
+ EXPECT_EQ(kDefaultMaxPacketSize, serialized_packet.packet->length());
}
delete serialized_packet.packet;
delete serialized_packet.retransmittable_frames;
@@ -956,8 +952,6 @@
creator_.StopSendingVersion();
}
creator_.set_max_packet_length(kMaxPacketSize);
- const size_t max_plaintext_size =
- client_framer_.GetMaxPlaintextSize(creator_.max_packet_length());
// Serialized length of ack frame with 2000 nack ranges should be limited by
// the number of nack ranges that can be fit in an ack frame.
@@ -966,12 +960,12 @@
QuicFrame(&ack_frame), creator_.BytesFree(), true, true,
NOT_IN_FEC_GROUP, PACKET_1BYTE_SEQUENCE_NUMBER);
EXPECT_GT(creator_.BytesFree(), frame_len);
- EXPECT_GT(max_plaintext_size, creator_.PacketSize());
+ EXPECT_GT(creator_.max_packet_length(), creator_.PacketSize());
// Add ack frame to creator.
EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(&ack_frame)));
EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_GT(max_plaintext_size, creator_.PacketSize());
+ EXPECT_GT(creator_.max_packet_length(), creator_.PacketSize());
EXPECT_LT(0u, creator_.BytesFree());
// Make sure that an additional stream frame can be added to the packet.
@@ -990,7 +984,8 @@
size_t est_packet_size = creator_.PacketSize();
SerializedPacket serialized = creator_.SerializePacket();
ASSERT_TRUE(serialized.packet);
- EXPECT_EQ(est_packet_size, serialized.packet->length());
+ EXPECT_EQ(est_packet_size,
+ client_framer_.GetMaxPlaintextSize(serialized.packet->length()));
delete serialized.retransmittable_frames;
delete serialized.packet;
}
@@ -1016,7 +1011,8 @@
// Add ack frame to creator.
EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(&ack_frame)));
EXPECT_TRUE(creator_.HasPendingFrames());
- EXPECT_EQ(max_plaintext_size, creator_.PacketSize());
+ EXPECT_EQ(client_framer_.GetMaxPlaintextSize(creator_.max_packet_length()),
+ creator_.PacketSize());
EXPECT_EQ(0u, creator_.BytesFree());
// Ensure the packet is successfully created, and the packet size estimate
@@ -1026,7 +1022,8 @@
size_t est_packet_size = creator_.PacketSize();
SerializedPacket serialized = creator_.SerializePacket();
ASSERT_TRUE(serialized.packet);
- EXPECT_GE(est_packet_size, serialized.packet->length());
+ EXPECT_GE(est_packet_size,
+ client_framer_.GetMaxPlaintextSize(serialized.packet->length()));
delete serialized.packet;
}
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc
index bfecf5d..3b5cc70 100644
--- a/net/quic/quic_packet_generator.cc
+++ b/net/quic/quic_packet_generator.cc
@@ -46,7 +46,9 @@
fec_timeout_(QuicTime::Delta::Zero()),
should_fec_protect_(false),
should_send_ack_(false),
- should_send_stop_waiting_(false) {
+ should_send_stop_waiting_(false),
+ ack_queued_(false),
+ stop_waiting_queued_(false) {
}
QuicPacketGenerator::~QuicPacketGenerator() {
@@ -101,12 +103,12 @@
}
void QuicPacketGenerator::SetShouldSendAck(bool also_send_stop_waiting) {
- if (pending_ack_frame_ != nullptr) {
+ if (ack_queued_) {
// Ack already queued, nothing to do.
return;
}
- if (also_send_stop_waiting && pending_stop_waiting_frame_ != nullptr) {
+ if (also_send_stop_waiting && stop_waiting_queued_) {
LOG(DFATAL) << "Should only ever be one pending stop waiting frame.";
return;
}
@@ -360,19 +362,21 @@
bool QuicPacketGenerator::AddNextPendingFrame() {
if (should_send_ack_) {
- pending_ack_frame_.reset(delegate_->CreateAckFrame());
+ delegate_->PopulateAckFrame(&pending_ack_frame_);
+ ack_queued_ = true;
// If we can't this add the frame now, then we still need to do so later.
- should_send_ack_ = !AddFrame(QuicFrame(pending_ack_frame_.get()));
+ should_send_ack_ = !AddFrame(QuicFrame(&pending_ack_frame_));
// Return success if we have cleared out this flag (i.e., added the frame).
// If we still need to send, then the frame is full, and we have failed.
return !should_send_ack_;
}
if (should_send_stop_waiting_) {
- pending_stop_waiting_frame_.reset(delegate_->CreateStopWaitingFrame());
+ delegate_->PopulateStopWaitingFrame(&pending_stop_waiting_frame_);
+ stop_waiting_queued_ = true;
// If we can't this add the frame now, then we still need to do so later.
should_send_stop_waiting_ =
- !AddFrame(QuicFrame(pending_stop_waiting_frame_.get()));
+ !AddFrame(QuicFrame(&pending_stop_waiting_frame_));
// Return success if we have cleared out this flag (i.e., added the frame).
// If we still need to send, then the frame is full, and we have failed.
return !should_send_stop_waiting_;
@@ -409,9 +413,9 @@
delegate_->OnSerializedPacket(serialized_packet);
MaybeSendFecPacketAndCloseGroup(/*force=*/false);
- // The packet has now been serialized, safe to delete pending frames.
- pending_ack_frame_.reset();
- pending_stop_waiting_frame_.reset();
+ // The packet has now been serialized, so the frames are no longer queued.
+ ack_queued_ = false;
+ stop_waiting_queued_ = false;
}
void QuicPacketGenerator::StopSendingVersion() {
@@ -436,7 +440,7 @@
}
SerializedPacket QuicPacketGenerator::ReserializeAllFrames(
- const QuicFrames& frames,
+ const RetransmittableFrames& frames,
QuicSequenceNumberLength original_length) {
return packet_creator_.ReserializeAllFrames(frames, original_length);
}
diff --git a/net/quic/quic_packet_generator.h b/net/quic/quic_packet_generator.h
index 0da94f0..b165844 100644
--- a/net/quic/quic_packet_generator.h
+++ b/net/quic/quic_packet_generator.h
@@ -75,8 +75,9 @@
virtual bool ShouldGeneratePacket(TransmissionType transmission_type,
HasRetransmittableData retransmittable,
IsHandshake handshake) = 0;
- virtual QuicAckFrame* CreateAckFrame() = 0;
- virtual QuicStopWaitingFrame* CreateStopWaitingFrame() = 0;
+ virtual void PopulateAckFrame(QuicAckFrame* ack) = 0;
+ virtual void PopulateStopWaitingFrame(
+ QuicStopWaitingFrame* stop_waiting) = 0;
// Takes ownership of |packet.packet| and |packet.retransmittable_frames|.
virtual void OnSerializedPacket(const SerializedPacket& packet) = 0;
virtual void CloseConnection(QuicErrorCode error, bool from_peer) = 0;
@@ -158,7 +159,7 @@
// Caller must ensure that any open FEC group is closed before calling this
// method.
SerializedPacket ReserializeAllFrames(
- const QuicFrames& frames,
+ const RetransmittableFrames& frames,
QuicSequenceNumberLength original_length);
// Update the sequence number length to use in future packets as soon as it
@@ -254,8 +255,12 @@
// have to hold a reference to it until we flush (and serialize it).
// Retransmittable frames are referenced elsewhere so that they
// can later be (optionally) retransmitted.
- scoped_ptr<QuicAckFrame> pending_ack_frame_;
- scoped_ptr<QuicStopWaitingFrame> pending_stop_waiting_frame_;
+ QuicAckFrame pending_ack_frame_;
+ QuicStopWaitingFrame pending_stop_waiting_frame_;
+ // True if an ack or stop waiting frame is already queued, and should not be
+ // re-added.
+ bool ack_queued_;
+ bool stop_waiting_queued_;
// Stores notifiers that should be attached to the next serialized packet.
std::list<QuicAckNotifier*> ack_notifiers_;
diff --git a/net/quic/quic_packet_generator_test.cc b/net/quic/quic_packet_generator_test.cc
index 1ab7ca5..26f1658 100644
--- a/net/quic/quic_packet_generator_test.cc
+++ b/net/quic/quic_packet_generator_test.cc
@@ -43,8 +43,8 @@
bool(TransmissionType transmission_type,
HasRetransmittableData retransmittable,
IsHandshake handshake));
- MOCK_METHOD0(CreateAckFrame, QuicAckFrame*());
- MOCK_METHOD0(CreateStopWaitingFrame, QuicStopWaitingFrame*());
+ MOCK_METHOD1(PopulateAckFrame, void(QuicAckFrame*));
+ MOCK_METHOD1(PopulateStopWaitingFrame, void(QuicStopWaitingFrame*));
MOCK_METHOD1(OnSerializedPacket, void(const SerializedPacket& packet));
MOCK_METHOD2(CloseConnection, void(QuicErrorCode, bool));
@@ -137,18 +137,6 @@
delete packet8_.retransmittable_frames;
}
- QuicAckFrame* CreateAckFrame() {
- // TODO(rch): Initialize this so it can be verified later.
- return new QuicAckFrame(MakeAckFrame(0));
- }
-
- QuicStopWaitingFrame* CreateStopWaitingFrame() {
- QuicStopWaitingFrame* frame = new QuicStopWaitingFrame();
- frame->entropy_hash = 0;
- frame->least_unacked = 0;
- return frame;
- }
-
QuicRstStreamFrame* CreateRstStreamFrame() {
return new QuicRstStreamFrame(1, QUIC_STREAM_NO_ERROR, 0);
}
@@ -256,7 +244,7 @@
delegate_.SetCanWriteOnlyNonRetransmittable();
generator_.StartBatchOperations();
- EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, PopulateAckFrame(_));
EXPECT_CALL(debug_delegate, OnFrameAddedToPacket(_)).Times(1);
generator_.SetShouldSendAck(false);
@@ -266,7 +254,7 @@
TEST_F(QuicPacketGeneratorTest, ShouldSendAck_WritableAndShouldFlush) {
delegate_.SetCanWriteOnlyNonRetransmittable();
- EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, PopulateAckFrame(_));
EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(SaveArg<0>(&packet_));
generator_.SetShouldSendAck(false);
@@ -285,9 +273,7 @@
delegate_.SetCanWriteAnything();
// Only one AckFrame should be created.
- EXPECT_CALL(delegate_, CreateAckFrame())
- .Times(1)
- .WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, PopulateAckFrame(_)).Times(1);
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.Times(1)
.WillOnce(SaveArg<0>(&packet_));
@@ -871,9 +857,8 @@
generator_.StartBatchOperations();
// Set up frames to write into the creator when control frames are written.
- EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
- EXPECT_CALL(delegate_, CreateStopWaitingFrame()).WillOnce(
- Return(CreateStopWaitingFrame()));
+ EXPECT_CALL(delegate_, PopulateAckFrame(_));
+ EXPECT_CALL(delegate_, PopulateStopWaitingFrame(_));
// Generator should have queued control frames, and creator should be empty.
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -1026,7 +1011,7 @@
generator_.StartBatchOperations();
// When the first write operation is invoked, the ack frame will be returned.
- EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, PopulateAckFrame(_));
// Send some data and a control frame
generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, MAY_FEC_PROTECT,
@@ -1058,7 +1043,7 @@
generator_.StartBatchOperations();
// When the first write operation is invoked, the ack frame will be returned.
- EXPECT_CALL(delegate_, CreateAckFrame()).WillOnce(Return(CreateAckFrame()));
+ EXPECT_CALL(delegate_, PopulateAckFrame(_));
{
InSequence dummy;
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 56dfa97..6ad0743 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -509,11 +509,9 @@
bool owns_buffer,
QuicConnectionIdLength connection_id_length,
bool includes_version,
- QuicSequenceNumberLength sequence_number_length,
- bool is_fec_packet)
+ QuicSequenceNumberLength sequence_number_length)
: QuicData(buffer, length, owns_buffer),
buffer_(buffer),
- is_fec_packet_(is_fec_packet),
connection_id_length_(connection_id_length),
includes_version_(includes_version),
sequence_number_length_(sequence_number_length) {
@@ -632,14 +630,15 @@
SerializedPacket::SerializedPacket(
QuicPacketSequenceNumber sequence_number,
QuicSequenceNumberLength sequence_number_length,
- QuicPacket* packet,
+ QuicEncryptedPacket* packet,
QuicPacketEntropyHash entropy_hash,
RetransmittableFrames* retransmittable_frames)
: sequence_number(sequence_number),
sequence_number_length(sequence_number_length),
packet(packet),
entropy_hash(entropy_hash),
- retransmittable_frames(retransmittable_frames) {
+ retransmittable_frames(retransmittable_frames),
+ is_fec_packet(false) {
}
SerializedPacket::~SerializedPacket() {}
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index 3daf917..058e548 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -48,9 +48,10 @@
// QuicPriority is uint32. Use SpdyPriority when we change the QUIC_VERSION.
typedef uint32 QuicPriority;
-// TODO(rch): Consider Quic specific names for these constants.
// Default and initial maximum size in bytes of a QUIC packet.
const QuicByteCount kDefaultMaxPacketSize = 1350;
+// Default initial maximum size in bytes of a QUIC packet for servers.
+const QuicByteCount kDefaultServerMaxPacketSize = 1000;
// The maximum packet size of any QUIC packet, based on ethernet's max size,
// minus the IP and UDP headers. IPv6 has a 40 byte header, UPD adds an
// additional 8 bytes. This is a total overhead of 48 bytes. Ethernet's
@@ -513,6 +514,8 @@
QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS = 68,
// The connection has too many outstanding received packets.
QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS = 69,
+ // The quic connection job to load server config is cancelled.
+ QUIC_CONNECTION_CANCELLED = 70,
// Crypto errors.
@@ -570,7 +573,7 @@
QUIC_VERSION_NEGOTIATION_MISMATCH = 55,
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 70,
+ QUIC_LAST_ERROR = 71,
};
struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
@@ -918,48 +921,22 @@
class NET_EXPORT_PRIVATE QuicPacket : public QuicData {
public:
- static QuicPacket* NewDataPacket(
- char* buffer,
- size_t length,
- bool owns_buffer,
- QuicConnectionIdLength connection_id_length,
- bool includes_version,
- QuicSequenceNumberLength sequence_number_length) {
- return new QuicPacket(buffer, length, owns_buffer, connection_id_length,
- includes_version, sequence_number_length, false);
- }
-
- static QuicPacket* NewFecPacket(
- char* buffer,
- size_t length,
- bool owns_buffer,
- QuicConnectionIdLength connection_id_length,
- bool includes_version,
- QuicSequenceNumberLength sequence_number_length) {
- return new QuicPacket(buffer, length, owns_buffer, connection_id_length,
- includes_version, sequence_number_length, true);
- }
+ QuicPacket(char* buffer,
+ size_t length,
+ bool owns_buffer,
+ QuicConnectionIdLength connection_id_length,
+ bool includes_version,
+ QuicSequenceNumberLength sequence_number_length);
base::StringPiece FecProtectedData() const;
base::StringPiece AssociatedData() const;
base::StringPiece BeforePlaintext() const;
base::StringPiece Plaintext() const;
- bool is_fec_packet() const { return is_fec_packet_; }
-
char* mutable_data() { return buffer_; }
private:
- QuicPacket(char* buffer,
- size_t length,
- bool owns_buffer,
- QuicConnectionIdLength connection_id_length,
- bool includes_version,
- QuicSequenceNumberLength sequence_number_length,
- bool is_fec_packet);
-
char* buffer_;
- const bool is_fec_packet_;
const QuicConnectionIdLength connection_id_length_;
const bool includes_version_;
const QuicSequenceNumberLength sequence_number_length_;
@@ -1021,16 +998,17 @@
struct NET_EXPORT_PRIVATE SerializedPacket {
SerializedPacket(QuicPacketSequenceNumber sequence_number,
QuicSequenceNumberLength sequence_number_length,
- QuicPacket* packet,
+ QuicEncryptedPacket* packet,
QuicPacketEntropyHash entropy_hash,
RetransmittableFrames* retransmittable_frames);
~SerializedPacket();
QuicPacketSequenceNumber sequence_number;
QuicSequenceNumberLength sequence_number_length;
- QuicPacket* packet;
+ QuicEncryptedPacket* packet;
QuicPacketEntropyHash entropy_hash;
RetransmittableFrames* retransmittable_frames;
+ bool is_fec_packet;
// Optional notifiers which will be informed when this packet has been ACKed.
std::list<QuicAckNotifier*> notifiers;
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc
index 38ceec6..dcc7823 100644
--- a/net/quic/quic_received_packet_manager.cc
+++ b/net/quic/quic_received_packet_manager.cc
@@ -13,7 +13,6 @@
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/quic_connection_stats.h"
-using std::make_pair;
using std::max;
using std::min;
using std::numeric_limits;
@@ -81,13 +80,13 @@
if (sequence_number > largest_observed_) {
for (QuicPacketSequenceNumber i = 0;
i < (sequence_number - largest_observed_ - 1); ++i) {
- packets_entropy_.push_back(make_pair(0, false));
+ packets_entropy_.push_back(std::make_pair(0, false));
}
- packets_entropy_.push_back(make_pair(entropy_hash, true));
+ packets_entropy_.push_back(std::make_pair(entropy_hash, true));
largest_observed_ = sequence_number;
} else {
packets_entropy_[sequence_number - first_gap_] =
- make_pair(entropy_hash, true);
+ std::make_pair(entropy_hash, true);
AdvanceFirstGapAndGarbageCollectEntropyMap();
}
@@ -135,7 +134,6 @@
QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats)
: peer_least_packet_awaiting_ack_(0),
time_largest_observed_(QuicTime::Zero()),
- receive_algorithm_(ReceiveAlgorithmInterface::Create()),
stats_(stats) {
ack_frame_.largest_observed = 0;
ack_frame_.entropy_hash = 0;
@@ -178,9 +176,6 @@
entropy_tracker_.RecordPacketEntropyHash(sequence_number,
header.entropy_hash);
- receive_algorithm_->RecordIncomingPacket(
- bytes, sequence_number, receipt_time);
-
received_packet_times_.push_back(
std::make_pair(sequence_number, receipt_time));
@@ -237,8 +232,8 @@
// Remove all packets that are too far from largest_observed to express.
received_packet_times_.remove_if(isTooLarge(ack_frame_.largest_observed));
- ack_frame->received_packet_times = received_packet_times_;
- received_packet_times_.clear();
+ ack_frame->received_packet_times.clear();
+ ack_frame->received_packet_times.swap(received_packet_times_);
}
QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
diff --git a/net/quic/quic_received_packet_manager.h b/net/quic/quic_received_packet_manager.h
index 94bd3d5..b16af55 100644
--- a/net/quic/quic_received_packet_manager.h
+++ b/net/quic/quic_received_packet_manager.h
@@ -10,7 +10,6 @@
#include <deque>
-#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"
@@ -166,8 +165,6 @@
// Needed for calculating delta_time_largest_observed.
QuicTime time_largest_observed_;
- scoped_ptr<ReceiveAlgorithmInterface> receive_algorithm_;
-
QuicConnectionStats* stats_;
PacketTimeList received_packet_times_;
diff --git a/net/quic/quic_received_packet_manager_test.cc b/net/quic/quic_received_packet_manager_test.cc
index b64025b..d91e4e0 100644
--- a/net/quic/quic_received_packet_manager_test.cc
+++ b/net/quic/quic_received_packet_manager_test.cc
@@ -12,7 +12,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using std::make_pair;
using std::pair;
using std::vector;
@@ -214,17 +213,17 @@
TEST_F(QuicReceivedPacketManagerTest, ReceivedPacketEntropyHash) {
vector<pair<QuicPacketSequenceNumber, QuicPacketEntropyHash> > entropies;
- entropies.push_back(make_pair(1, 12));
- entropies.push_back(make_pair(7, 1));
- entropies.push_back(make_pair(2, 33));
- entropies.push_back(make_pair(5, 3));
- entropies.push_back(make_pair(8, 34));
+ entropies.push_back(std::make_pair(1, 12));
+ entropies.push_back(std::make_pair(7, 1));
+ entropies.push_back(std::make_pair(2, 33));
+ entropies.push_back(std::make_pair(5, 3));
+ entropies.push_back(std::make_pair(8, 34));
for (size_t i = 0; i < entropies.size(); ++i) {
RecordPacketReceipt(entropies[i].first, entropies[i].second);
}
- sort(entropies.begin(), entropies.end());
+ std::sort(entropies.begin(), entropies.end());
QuicPacketEntropyHash hash = 0;
size_t index = 0;
@@ -256,12 +255,12 @@
TEST_F(QuicReceivedPacketManagerTest, SetCumulativeEntropyUpTo) {
vector<pair<QuicPacketSequenceNumber, QuicPacketEntropyHash> > entropies;
- entropies.push_back(make_pair(1, 12));
- entropies.push_back(make_pair(2, 1));
- entropies.push_back(make_pair(3, 33));
- entropies.push_back(make_pair(4, 3));
- entropies.push_back(make_pair(6, 34));
- entropies.push_back(make_pair(7, 29));
+ entropies.push_back(std::make_pair(1, 12));
+ entropies.push_back(std::make_pair(2, 1));
+ entropies.push_back(std::make_pair(3, 33));
+ entropies.push_back(std::make_pair(4, 3));
+ entropies.push_back(std::make_pair(6, 34));
+ entropies.push_back(std::make_pair(7, 29));
QuicPacketEntropyHash entropy_hash = 0;
for (size_t i = 0; i < entropies.size(); ++i) {
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc
index 34bb972..60fd0f5 100644
--- a/net/quic/quic_sent_packet_manager.cc
+++ b/net/quic/quic_sent_packet_manager.cc
@@ -15,7 +15,6 @@
#include "net/quic/quic_flags.h"
#include "net/quic/quic_utils_chromium.h"
-using std::make_pair;
using std::max;
using std::min;
@@ -329,7 +328,7 @@
// If data is associated with the most recent transmission of this
// packet, then inform the caller.
if (it->in_flight) {
- packets_acked_.push_back(make_pair(sequence_number, *it));
+ packets_acked_.push_back(std::make_pair(sequence_number, *it));
}
MarkPacketHandled(sequence_number, *it, delta_largest_observed);
}
@@ -561,12 +560,7 @@
DCHECK(!unacked_packets_.IsUnacked(sequence_number));
LOG_IF(DFATAL, bytes == 0) << "Cannot send empty packets.";
- if (original_sequence_number == 0) {
- if (!FLAGS_quic_ack_notifier_informed_on_serialized &&
- serialized_packet->retransmittable_frames) {
- ack_notifier_manager_.OnSerializedPacket(*serialized_packet);
- }
- } else {
+ if (original_sequence_number != 0) {
PendingRetransmissionMap::iterator it =
pending_retransmissions_.find(original_sequence_number);
if (it != pending_retransmissions_.end()) {
@@ -598,8 +592,8 @@
// Since FEC packets should also be counted towards the congestion window,
// consider them as retransmittable for the purposes of congestion control.
HasRetransmittableData has_congestion_controlled_data =
- serialized_packet->packet->is_fec_packet() ?
- HAS_RETRANSMITTABLE_DATA : has_retransmittable_data;
+ serialized_packet->is_fec_packet ? HAS_RETRANSMITTABLE_DATA
+ : has_retransmittable_data;
const bool in_flight =
send_algorithm_->OnPacketSent(sent_time,
unacked_packets_.bytes_in_flight(),
@@ -793,7 +787,7 @@
// should be recorded as a loss to the send algorithm, but not retransmitted
// until it's known whether the FEC packet arrived.
++stats_->packets_lost;
- packets_lost_.push_back(make_pair(sequence_number, transmission_info));
+ packets_lost_.push_back(std::make_pair(sequence_number, transmission_info));
DVLOG(1) << ENDPOINT << "Lost packet " << sequence_number;
if (transmission_info.retransmittable_frames != nullptr) {
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc
index e9b169b..82d45d6 100644
--- a/net/quic/quic_sent_packet_manager_test.cc
+++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -176,20 +176,18 @@
SerializedPacket CreatePacket(QuicPacketSequenceNumber sequence_number,
bool retransmittable) {
- packets_.push_back(QuicPacket::NewDataPacket(
- nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
- PACKET_6BYTE_SEQUENCE_NUMBER));
+ packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
return SerializedPacket(
sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER, packets_.back(), 0u,
retransmittable ? new RetransmittableFrames() : nullptr);
}
SerializedPacket CreateFecPacket(QuicPacketSequenceNumber sequence_number) {
- packets_.push_back(QuicPacket::NewFecPacket(
- nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
- PACKET_6BYTE_SEQUENCE_NUMBER));
- return SerializedPacket(sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
- packets_.back(), 0u, nullptr);
+ packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
+ SerializedPacket serialized(sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
+ packets_.back(), 0u, nullptr);
+ serialized.is_fec_packet = true;
+ return serialized;
}
void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
@@ -256,7 +254,7 @@
}
QuicSentPacketManager manager_;
- vector<QuicPacket*> packets_;
+ vector<QuicEncryptedPacket*> packets_;
MockClock clock_;
QuicConnectionStats stats_;
MockSendAlgorithm* send_algorithm_;
@@ -1156,6 +1154,8 @@
EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange());
EXPECT_CALL(*network_change_visitor_, OnRttChange());
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _, _));
+ EXPECT_CALL(*send_algorithm_, PacingRate())
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
manager_.SetFromConfig(client_config);
EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_));
@@ -1723,6 +1723,8 @@
QuicConfig client_config;
QuicConfigPeer::SetReceivedSocketReceiveBuffer(&client_config, 1024);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _, _));
+ EXPECT_CALL(*send_algorithm_, PacingRate())
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange());
EXPECT_CALL(*network_change_visitor_, OnRttChange());
manager_.SetFromConfig(client_config);
diff --git a/net/quic/quic_server.cc b/net/quic/quic_server.cc
index 2e2d5b2..610b305 100644
--- a/net/quic/quic_server.cc
+++ b/net/quic/quic_server.cc
@@ -8,7 +8,6 @@
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/quic/congestion_control/tcp_receiver.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_crypto_stream.h"
@@ -94,7 +93,7 @@
// because the default usage of QuicServer is as a test server with one or
// two clients. Adjust higher for use with many clients.
rc = socket->SetReceiveBufferSize(
- static_cast<int32>(TcpReceiver::kReceiveWindowTCP));
+ static_cast<int32>(kDefaultSocketReceiveBuffer));
if (rc < 0) {
LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToString(rc);
return rc;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 3e0f4e3..34f5aaa 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -21,7 +21,6 @@
#include "net/dns/host_resolver.h"
#include "net/dns/single_request_host_resolver.h"
#include "net/http/http_server_properties.h"
-#include "net/quic/congestion_control/tcp_receiver.h"
#include "net/quic/crypto/channel_id_chromium.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/quic_random.h"
@@ -141,7 +140,7 @@
bool is_https,
bool was_alternate_protocol_recently_broken,
PrivacyMode privacy_mode,
- base::StringPiece method,
+ bool is_post,
QuicServerInfo* server_info,
const BoundNetLog& net_log);
@@ -167,15 +166,15 @@
void OnIOComplete(int rv);
+ void RunAuxilaryJob();
+
+ void Cancel();
+
void CancelWaitForDataReadyCallback();
- CompletionCallback callback() {
- return callback_;
- }
+ const QuicServerId server_id() const { return server_id_; }
- const QuicServerId server_id() const {
- return server_id_;
- }
+ base::WeakPtr<Job> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
private:
enum IoState {
@@ -196,6 +195,7 @@
bool is_post_;
bool was_alternate_protocol_recently_broken_;
scoped_ptr<QuicServerInfo> server_info_;
+ bool started_another_job_;
const BoundNetLog net_log_;
QuicClientSession* session_;
CompletionCallback callback_;
@@ -212,20 +212,22 @@
bool is_https,
bool was_alternate_protocol_recently_broken,
PrivacyMode privacy_mode,
- base::StringPiece method,
+ bool is_post,
QuicServerInfo* server_info,
const BoundNetLog& net_log)
: io_state_(STATE_RESOLVE_HOST),
factory_(factory),
host_resolver_(host_resolver),
server_id_(host_port_pair, is_https, privacy_mode),
- is_post_(method == "POST"),
+ is_post_(is_post),
was_alternate_protocol_recently_broken_(
was_alternate_protocol_recently_broken),
server_info_(server_info),
+ started_another_job_(false),
net_log_(net_log),
session_(nullptr),
- weak_factory_(this) {}
+ weak_factory_(this) {
+}
QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
HostResolver* host_resolver,
@@ -235,13 +237,18 @@
factory_(factory),
host_resolver_(host_resolver), // unused
server_id_(server_id),
- is_post_(false), // unused
+ is_post_(false), // unused
was_alternate_protocol_recently_broken_(false), // unused
- net_log_(session->net_log()), // unused
+ started_another_job_(false), // unused
+ net_log_(session->net_log()), // unused
session_(session),
- weak_factory_(this) {}
+ weak_factory_(this) {
+}
QuicStreamFactory::Job::~Job() {
+ // If disk cache has a pending WaitForDataReadyCallback, cancel that callback.
+ if (server_info_)
+ server_info_->ResetWaitForDataReadyCallback();
}
int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
@@ -307,6 +314,19 @@
}
}
+void QuicStreamFactory::Job::RunAuxilaryJob() {
+ int rv = Run(base::Bind(&QuicStreamFactory::OnJobComplete,
+ base::Unretained(factory_), this));
+ if (rv != ERR_IO_PENDING)
+ factory_->OnJobComplete(this, rv);
+}
+
+void QuicStreamFactory::Job::Cancel() {
+ callback_.Reset();
+ if (session_)
+ session_->connection()->SendConnectionClose(QUIC_CONNECTION_CANCELLED);
+}
+
void QuicStreamFactory::Job::CancelWaitForDataReadyCallback() {
// If we are waiting for WaitForDataReadyCallback, then cancel the callback.
if (io_state_ != STATE_LOAD_SERVER_INFO_COMPLETE)
@@ -329,11 +349,9 @@
io_state_ = STATE_RESOLVE_HOST_COMPLETE;
dns_resolution_start_time_ = base::TimeTicks::Now();
return host_resolver_.Resolve(
- HostResolver::RequestInfo(server_id_.host_port_pair()),
- DEFAULT_PRIORITY,
+ HostResolver::RequestInfo(server_id_.host_port_pair()), DEFAULT_PRIORITY,
&address_list_,
- base::Bind(&QuicStreamFactory::Job::OnIOComplete,
- weak_factory_.GetWeakPtr()),
+ base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()),
net_log_);
}
@@ -356,7 +374,10 @@
return OK;
}
- io_state_ = STATE_LOAD_SERVER_INFO;
+ if (server_info_)
+ io_state_ = STATE_LOAD_SERVER_INFO;
+ else
+ io_state_ = STATE_CONNECT;
return OK;
}
@@ -368,8 +389,7 @@
io_state_ = STATE_LOAD_SERVER_INFO_COMPLETE;
- if (!server_info_)
- return OK;
+ DCHECK(server_info_);
// To mitigate the effects of disk cache taking too long to load QUIC server
// information, set up a timer to cancel WaitForDataReady's callback.
@@ -385,14 +405,20 @@
factory_->task_runner_->PostDelayedTask(
FROM_HERE,
base::Bind(&QuicStreamFactory::Job::CancelWaitForDataReadyCallback,
- weak_factory_.GetWeakPtr()),
+ GetWeakPtr()),
base::TimeDelta::FromMilliseconds(load_server_info_timeout_ms));
}
disk_cache_load_start_time_ = base::TimeTicks::Now();
- return server_info_->WaitForDataReady(
- base::Bind(&QuicStreamFactory::Job::OnIOComplete,
- weak_factory_.GetWeakPtr()));
+ int rv = server_info_->WaitForDataReady(
+ base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()));
+ if (rv == ERR_IO_PENDING && factory_->enable_connection_racing()) {
+ // If we are waiting to load server config from the disk cache, then start
+ // another job.
+ started_another_job_ = true;
+ factory_->CreateAuxilaryJob(server_id_, is_post_, net_log_);
+ }
+ return rv;
}
int QuicStreamFactory::Job::DoLoadServerInfoComplete(int rv) {
@@ -401,13 +427,20 @@
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"422516 QuicStreamFactory::Job::DoLoadServerInfoComplete"));
- if (server_info_) {
- UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
- base::TimeTicks::Now() - disk_cache_load_start_time_);
- }
+ UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheWaitForDataReadyTime",
+ base::TimeTicks::Now() - disk_cache_load_start_time_);
- if (rv != OK) {
+ if (rv != OK)
server_info_.reset();
+
+ if (started_another_job_ &&
+ (!server_info_ || server_info_->state().server_config.empty() ||
+ !factory_->CryptoConfigCacheIsEmpty(server_id_))) {
+ // If we have started another job and if we didn't load the server config
+ // from the disk cache or if we have received a new server config from the
+ // server, then cancel the current job.
+ io_state_ = STATE_NONE;
+ return ERR_CONNECTION_CLOSED;
}
io_state_ = STATE_CONNECT;
@@ -454,8 +487,7 @@
rv = session_->CryptoConnect(
require_confirmation,
- base::Bind(&QuicStreamFactory::Job::OnIOComplete,
- base::Unretained(this)));
+ base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()));
return rv;
}
@@ -468,8 +500,7 @@
io_state_ = STATE_CONNECT_COMPLETE;
int rv = session_->ResumeCryptoConnect(
- base::Bind(&QuicStreamFactory::Job::OnIOComplete,
- base::Unretained(this)));
+ base::Bind(&QuicStreamFactory::Job::OnIOComplete, GetWeakPtr()));
return rv;
}
@@ -564,6 +595,7 @@
int load_server_info_timeout,
float load_server_info_timeout_srtt_multiplier,
bool enable_truncated_connection_ids,
+ bool enable_connection_racing,
const QuicTagVector& connection_options)
: require_confirmation_(true),
host_resolver_(host_resolver),
@@ -585,11 +617,16 @@
load_server_info_timeout_srtt_multiplier_(
load_server_info_timeout_srtt_multiplier),
enable_truncated_connection_ids_(enable_truncated_connection_ids),
+ enable_connection_racing_(enable_connection_racing),
port_seed_(random_generator_->RandUint64()),
check_persisted_supports_quic_(true),
task_runner_(nullptr),
weak_factory_(this) {
DCHECK(transport_security_state_);
+ // TODO(michaeln): Remove ScopedTracker below once crbug.com/454983 is fixed
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "454983 QuicStreamFactory::QuicStreamFactory"));
crypto_config_.set_user_agent_id(user_agent_id);
crypto_config_.AddCanonicalSuffix(".c.youtube.com");
crypto_config_.AddCanonicalSuffix(".googlevideo.com");
@@ -610,7 +647,11 @@
delete all_sessions_.begin()->first;
all_sessions_.erase(all_sessions_.begin());
}
- STLDeleteValues(&active_jobs_);
+ while (!active_jobs_.empty()) {
+ const QuicServerId server_id = active_jobs_.begin()->first;
+ STLDeleteElements(&(active_jobs_[server_id]));
+ active_jobs_.erase(server_id);
+ }
}
void QuicStreamFactory::set_require_confirmation(bool require_confirmation) {
@@ -634,12 +675,16 @@
}
if (HasActiveJob(server_id)) {
- Job* job = active_jobs_[server_id];
- active_requests_[request] = job;
- job_requests_map_[job].insert(request);
+ active_requests_[request] = server_id;
+ job_requests_map_[server_id].insert(request);
return ERR_IO_PENDING;
}
+ // TODO(rtenneti): |task_runner_| is used by the Job. Initialize task_runner_
+ // in the constructor after WebRequestActionWithThreadsTest.* tests are fixed.
+ if (!task_runner_)
+ task_runner_ = base::MessageLoop::current()->message_loop_proxy().get();
+
QuicServerInfo* quic_server_info = nullptr;
if (quic_server_info_factory_) {
bool load_from_disk_cache = true;
@@ -654,34 +699,22 @@
load_from_disk_cache = false;
}
}
- if (load_from_disk_cache) {
- QuicCryptoClientConfig::CachedState* cached =
- crypto_config_.LookupOrCreate(server_id);
- DCHECK(cached);
- if (cached->IsEmpty()) {
- quic_server_info = quic_server_info_factory_->GetForServer(server_id);
- }
+ if (load_from_disk_cache && CryptoConfigCacheIsEmpty(server_id)) {
+ quic_server_info = quic_server_info_factory_->GetForServer(server_id);
}
}
- // TODO(rtenneti): Initialize task_runner_ in the constructor after
- // WebRequestActionWithThreadsTest.* tests are fixed.
- if (!task_runner_)
- task_runner_ = base::MessageLoop::current()->message_loop_proxy().get();
- bool was_alternate_protocol_recently_broken =
- http_server_properties_ &&
- http_server_properties_->WasAlternateProtocolRecentlyBroken(
- server_id.host_port_pair());
scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair, is_https,
- was_alternate_protocol_recently_broken,
- privacy_mode, method, quic_server_info, net_log));
+ WasAlternateProtocolRecentlyBroken(server_id),
+ privacy_mode, method == "POST" /* is_post */,
+ quic_server_info, net_log));
int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
base::Unretained(this), job.get()));
-
if (rv == ERR_IO_PENDING) {
- active_requests_[request] = job.get();
- job_requests_map_[job.get()].insert(request);
- active_jobs_[server_id] = job.release();
+ active_requests_[request] = server_id;
+ job_requests_map_[server_id].insert(request);
+ active_jobs_[server_id].insert(job.release());
+ return rv;
}
if (rv == OK) {
DCHECK(HasActiveSession(server_id));
@@ -690,6 +723,19 @@
return rv;
}
+void QuicStreamFactory::CreateAuxilaryJob(const QuicServerId server_id,
+ bool is_post,
+ const BoundNetLog& net_log) {
+ Job* aux_job = new Job(this, host_resolver_, server_id.host_port_pair(),
+ server_id.is_https(),
+ WasAlternateProtocolRecentlyBroken(server_id),
+ server_id.privacy_mode(), is_post, nullptr, net_log);
+ active_jobs_[server_id].insert(aux_job);
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&QuicStreamFactory::Job::RunAuxilaryJob,
+ aux_job->GetWeakPtr()));
+}
+
bool QuicStreamFactory::OnResolution(
const QuicServerId& server_id,
const AddressList& address_list) {
@@ -715,6 +761,19 @@
}
void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
+ QuicServerId server_id = job->server_id();
+ if (rv != OK) {
+ JobSet* jobs = &(active_jobs_[server_id]);
+ if (jobs->size() > 1) {
+ // If there is another pending job, then we can delete this job and let
+ // the other job handle the request.
+ job->Cancel();
+ jobs->erase(job);
+ delete job;
+ return;
+ }
+ }
+
if (rv == OK) {
// TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
tracked_objects::ScopedTracker tracking_profile1(
@@ -725,11 +784,9 @@
set_require_confirmation(false);
// Create all the streams, but do not notify them yet.
- for (RequestSet::iterator it = job_requests_map_[job].begin();
- it != job_requests_map_[job].end() ; ++it) {
- DCHECK(HasActiveSession(job->server_id()));
- (*it)->set_stream(CreateIfSessionExists(job->server_id(),
- (*it)->net_log()));
+ for (QuicStreamRequest* request : job_requests_map_[server_id]) {
+ DCHECK(HasActiveSession(server_id));
+ request->set_stream(CreateIfSessionExists(server_id, request->net_log()));
}
}
@@ -738,10 +795,10 @@
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"422516 QuicStreamFactory::OnJobComplete2"));
- while (!job_requests_map_[job].empty()) {
- RequestSet::iterator it = job_requests_map_[job].begin();
+ while (!job_requests_map_[server_id].empty()) {
+ RequestSet::iterator it = job_requests_map_[server_id].begin();
QuicStreamRequest* request = *it;
- job_requests_map_[job].erase(it);
+ job_requests_map_[server_id].erase(it);
active_requests_.erase(request);
// Even though we're invoking callbacks here, we don't need to worry
// about |this| being deleted, because the factory is owned by the
@@ -754,10 +811,14 @@
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"422516 QuicStreamFactory::OnJobComplete3"));
- active_jobs_.erase(job->server_id());
- job_requests_map_.erase(job);
- delete job;
- return;
+ for (Job* other_job : active_jobs_[server_id]) {
+ if (other_job != job)
+ other_job->Cancel();
+ }
+
+ STLDeleteElements(&(active_jobs_[server_id]));
+ active_jobs_.erase(server_id);
+ job_requests_map_.erase(server_id);
}
// Returns a newly created QuicHttpStream owned by the caller, if a
@@ -836,7 +897,7 @@
QuicServerId server_id = *aliases.begin();
session_aliases_.erase(session);
Job* job = new Job(this, host_resolver_, session, server_id);
- active_jobs_[server_id] = job;
+ active_jobs_[server_id].insert(job);
int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
base::Unretained(this), job));
DCHECK_EQ(ERR_IO_PENDING, rv);
@@ -844,8 +905,8 @@
void QuicStreamFactory::CancelRequest(QuicStreamRequest* request) {
DCHECK(ContainsKey(active_requests_, request));
- Job* job = active_requests_[request];
- job_requests_map_[job].erase(request);
+ QuicServerId server_id = active_requests_[request];
+ job_requests_map_[server_id].erase(request);
active_requests_.erase(request);
}
@@ -915,6 +976,10 @@
return ContainsKey(active_sessions_, server_id);
}
+bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const {
+ return ContainsKey(active_jobs_, key);
+}
+
int QuicStreamFactory::CreateSession(
const QuicServerId& server_id,
scoped_ptr<QuicServerInfo> server_info,
@@ -978,7 +1043,7 @@
// does not consume "too much" memory. If we see bursty packet loss, we may
// revisit this setting and test for its impact.
const int32 kSocketBufferSize =
- static_cast<int32>(TcpReceiver::kReceiveWindowTCP);
+ static_cast<int32>(kDefaultSocketReceiveBuffer);
rv = socket->SetReceiveBufferSize(kSocketBufferSize);
if (rv != OK) {
HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER);
@@ -1098,7 +1163,7 @@
}
// TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
- tracked_objects::ScopedTracker tracking_profile6(
+ tracked_objects::ScopedTracker tracking_profile61(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"422516 QuicStreamFactory::CreateSession61"));
@@ -1107,6 +1172,12 @@
server_info.Pass(), config,
base::MessageLoop::current()->message_loop_proxy().get(),
net_log.net_log());
+
+ // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
+ tracked_objects::ScopedTracker tracking_profile62(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "422516 QuicStreamFactory::CreateSession62"));
+
all_sessions_[*session] = server_id; // owning pointer
// TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
@@ -1129,10 +1200,6 @@
return OK;
}
-bool QuicStreamFactory::HasActiveJob(const QuicServerId& key) const {
- return ContainsKey(active_jobs_, key);
-}
-
void QuicStreamFactory::ActivateSession(
const QuicServerId& server_id,
QuicClientSession* session) {
@@ -1158,6 +1225,20 @@
return stats->srtt.InMicroseconds();
}
+bool QuicStreamFactory::WasAlternateProtocolRecentlyBroken(
+ const QuicServerId& server_id) const {
+ return http_server_properties_ &&
+ http_server_properties_->WasAlternateProtocolRecentlyBroken(
+ server_id.host_port_pair());
+}
+
+bool QuicStreamFactory::CryptoConfigCacheIsEmpty(
+ const QuicServerId& server_id) {
+ QuicCryptoClientConfig::CachedState* cached =
+ crypto_config_.LookupOrCreate(server_id);
+ return cached->IsEmpty();
+}
+
void QuicStreamFactory::InitializeCachedStateInCryptoConfig(
const QuicServerId& server_id,
const scoped_ptr<QuicServerInfo>& server_info) {
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index f13156a..1b9946d 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -107,6 +107,7 @@
int load_server_info_timeout,
float load_server_info_timeout_srtt_multiplier,
bool enable_truncated_connection_ids,
+ bool enable_connection_racing,
const QuicTagVector& connection_options);
~QuicStreamFactory() override;
@@ -178,6 +179,11 @@
quic_server_info_factory_ = quic_server_info_factory;
}
+ bool enable_connection_racing() const { return enable_connection_racing_; }
+ void set_enable_connection_racing(bool enable_connection_racing) {
+ enable_connection_racing_ = enable_connection_racing;
+ }
+
private:
class Job;
friend class test::QuicStreamFactoryPeer;
@@ -204,10 +210,17 @@
typedef std::set<QuicClientSession*> SessionSet;
typedef std::map<IpAliasKey, SessionSet> IPAliasMap;
typedef std::map<QuicServerId, QuicCryptoClientConfig*> CryptoConfigMap;
- typedef std::map<QuicServerId, Job*> JobMap;
- typedef std::map<QuicStreamRequest*, Job*> RequestMap;
+ typedef std::set<Job*> JobSet;
+ typedef std::map<QuicServerId, JobSet> JobMap;
+ typedef std::map<QuicStreamRequest*, QuicServerId> RequestMap;
typedef std::set<QuicStreamRequest*> RequestSet;
- typedef std::map<Job*, RequestSet> JobRequestsMap;
+ typedef std::map<QuicServerId, RequestSet> ServerIDRequestsMap;
+
+ // Creates a job which doesn't wait for server config to be loaded from the
+ // disk cache. This job is started via a PostTask.
+ void CreateAuxilaryJob(const QuicServerId server_id,
+ bool is_post,
+ const BoundNetLog& net_log);
// Returns a newly created QuicHttpStream owned by the caller, if a
// matching session already exists. Returns NULL otherwise.
@@ -233,6 +246,10 @@
int64 GetServerNetworkStatsSmoothedRttInMicroseconds(
const QuicServerId& server_id) const;
+ // Helped methods.
+ bool WasAlternateProtocolRecentlyBroken(const QuicServerId& server_id) const;
+ bool CryptoConfigCacheIsEmpty(const QuicServerId& server_id);
+
// Initializes the cached state associated with |server_id| in
// |crypto_config_| with the information in |server_info|.
void InitializeCachedStateInCryptoConfig(
@@ -274,7 +291,7 @@
QuicCryptoClientConfig crypto_config_;
JobMap active_jobs_;
- JobRequestsMap job_requests_map_;
+ ServerIDRequestsMap job_requests_map_;
RequestMap active_requests_;
QuicVersionVector supported_versions_;
@@ -305,6 +322,11 @@
// Set this for setting config's BytesForConnectionIdToSend (TCID param) to 0.
bool enable_truncated_connection_ids_;
+ // Set if we want to race connections - one connection that sends
+ // INCHOATE_HELLO and another connection that sends CHLO after loading server
+ // config from the disk cache.
+ bool enable_connection_racing_;
+
// Each profile will (probably) have a unique port_seed_ value. This value is
// used to help seed a pseudo-random number generator (PortSuggester) so that
// we consistently (within this profile) suggest the same ephemeral port when
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 2ce6ef4..3905084 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -34,6 +34,7 @@
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
+using std::ostream;
using std::string;
using std::vector;
@@ -43,6 +44,34 @@
namespace {
const char kDefaultServerHostName[] = "www.google.com";
const int kDefaultServerPort = 443;
+
+// Run all tests with all the combinations of versions and
+// enable_connection_racing.
+struct TestParams {
+ TestParams(const QuicVersion version, bool enable_connection_racing)
+ : version(version), enable_connection_racing(enable_connection_racing) {}
+
+ friend ostream& operator<<(ostream& os, const TestParams& p) {
+ os << "{ version: " << QuicVersionToString(p.version);
+ os << " enable_connection_racing: " << p.enable_connection_racing << " }";
+ return os;
+ }
+
+ QuicVersion version;
+ bool enable_connection_racing;
+};
+
+// Constructs various test permutations.
+vector<TestParams> GetTestParams() {
+ vector<TestParams> params;
+ QuicVersionVector all_supported_versions = QuicSupportedVersions();
+ for (const QuicVersion version : all_supported_versions) {
+ params.push_back(TestParams(version, false));
+ params.push_back(TestParams(version, true));
+ }
+ return params;
+}
+
} // namespace anonymous
class QuicStreamFactoryPeer {
@@ -100,6 +129,16 @@
size_t load_server_info_timeout) {
factory->load_server_info_timeout_ms_ = load_server_info_timeout;
}
+
+ static void SetEnableConnectionRacing(QuicStreamFactory* factory,
+ bool enable_connection_racing) {
+ factory->enable_connection_racing_ = enable_connection_racing;
+ }
+
+ static size_t GetNumberOfActiveJobs(QuicStreamFactory* factory,
+ const QuicServerId& server_id) {
+ return (factory->active_jobs_[server_id]).size();
+ }
};
class MockQuicServerInfo : public QuicServerInfo {
@@ -114,6 +153,8 @@
return ERR_IO_PENDING;
}
+ void ResetWaitForDataReadyCallback() override {}
+
void CancelWaitForDataReadyCallback() override {}
bool IsDataReady() override { return false; }
@@ -135,14 +176,13 @@
}
};
-
-class QuicStreamFactoryTest : public ::testing::TestWithParam<QuicVersion> {
+class QuicStreamFactoryTest : public ::testing::TestWithParam<TestParams> {
protected:
QuicStreamFactoryTest()
: random_generator_(0),
clock_(new MockClock()),
runner_(new TestTaskRunner(clock_)),
- maker_(GetParam(), 0, clock_),
+ maker_(GetParam().version, 0, clock_),
cert_verifier_(CertVerifier::CreateDefault()),
channel_id_service_(
new ChannelIDService(new DefaultChannelIDStore(nullptr),
@@ -158,19 +198,22 @@
clock_,
kDefaultMaxPacketSize,
std::string(),
- SupportedVersions(GetParam()),
+ SupportedVersions(GetParam().version),
/*enable_port_selection=*/true,
/*always_require_handshake_confirmation=*/false,
/*disable_connection_pooling=*/false,
/*load_server_info_timeout=*/0u,
/*load_server_info_timeout_srtt_multiplier=*/0.0f,
/*enable_truncated_connection_ids=*/true,
+ /*enable_connection_racing=*/false,
QuicTagVector()),
host_port_pair_(kDefaultServerHostName, kDefaultServerPort),
is_https_(false),
privacy_mode_(PRIVACY_MODE_DISABLED) {
factory_.set_require_confirmation(false);
clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
+ QuicStreamFactoryPeer::SetEnableConnectionRacing(
+ &factory_, GetParam().enable_connection_racing);
}
scoped_ptr<QuicHttpStream> CreateIfSessionExists(
@@ -244,7 +287,7 @@
QuicStreamId stream_id = kClientDataStreamId1;
return maker_.MakeRstPacket(
1, true, stream_id,
- AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam()));
+ AdjustErrorForVersion(QUIC_RST_ACKNOWLEDGEMENT, GetParam().version));
}
MockQuicServerInfoFactory quic_server_info_factory_;
@@ -266,8 +309,9 @@
TestCompletionCallback callback_;
};
-INSTANTIATE_TEST_CASE_P(Version, QuicStreamFactoryTest,
- ::testing::ValuesIn(QuicSupportedVersions()));
+INSTANTIATE_TEST_CASE_P(Version,
+ QuicStreamFactoryTest,
+ ::testing::ValuesIn(GetTestParams()));
TEST_P(QuicStreamFactoryTest, CreateIfSessionExists) {
EXPECT_EQ(nullptr, CreateIfSessionExists(host_port_pair_, net_log_).get());
@@ -1562,6 +1606,10 @@
}
TEST_P(QuicStreamFactoryTest, CancelWaitForDataReady) {
+ // Don't race quic connections when testing cancel reading of server config
+ // from disk cache.
+ if (GetParam().enable_connection_racing)
+ return;
factory_.set_quic_server_info_factory(&quic_server_info_factory_);
QuicStreamFactoryPeer::SetTaskRunner(&factory_, runner_.get());
const size_t kLoadServerInfoTimeoutMs = 50;
@@ -1604,5 +1652,52 @@
EXPECT_TRUE(socket_data.at_write_eof());
}
+TEST_P(QuicStreamFactoryTest, RacingConnections) {
+ if (!GetParam().enable_connection_racing)
+ return;
+ factory_.set_quic_server_info_factory(&quic_server_info_factory_);
+ QuicStreamFactoryPeer::SetTaskRunner(&factory_, runner_.get());
+ const size_t kLoadServerInfoTimeoutMs = 50;
+ QuicStreamFactoryPeer::SetLoadServerInfoTimeout(&factory_,
+ kLoadServerInfoTimeoutMs);
+
+ MockRead reads[] = {
+ MockRead(ASYNC, OK, 0) // EOF
+ };
+ DeterministicSocketData socket_data(reads, arraysize(reads), nullptr, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+ socket_data.StopAfter(1);
+
+ MockRead reads2[] = {
+ MockRead(ASYNC, 0, 0) // EOF
+ };
+ DeterministicSocketData socket_data2(reads2, arraysize(reads2), nullptr, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+ socket_data2.StopAfter(1);
+
+ crypto_client_stream_factory_.set_handshake_mode(
+ MockCryptoClientStream::ZERO_RTT);
+ host_resolver_.set_synchronous_mode(true);
+ host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+ "192.168.0.1", "");
+
+ QuicStreamRequest request(&factory_);
+ QuicServerId server_id(host_port_pair_, is_https_, privacy_mode_);
+ EXPECT_EQ(ERR_IO_PENDING,
+ request.Request(host_port_pair_, is_https_, privacy_mode_, "GET",
+ net_log_, callback_.callback()));
+ EXPECT_EQ(2u,
+ QuicStreamFactoryPeer::GetNumberOfActiveJobs(&factory_, server_id));
+
+ runner_->RunNextTask();
+
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ EXPECT_TRUE(stream.get());
+ EXPECT_TRUE(socket_data.at_read_eof());
+ EXPECT_TRUE(socket_data.at_write_eof());
+ EXPECT_EQ(0u,
+ QuicStreamFactoryPeer::GetNumberOfActiveJobs(&factory_, server_id));
+}
+
} // namespace test
} // namespace net
diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc
index ceeaa94..7f06ec4 100644
--- a/net/quic/quic_stream_sequencer.cc
+++ b/net/quic/quic_stream_sequencer.cc
@@ -11,7 +11,6 @@
#include "base/metrics/sparse_histogram.h"
#include "net/quic/reliable_quic_stream.h"
-using std::make_pair;
using std::min;
using std::numeric_limits;
using std::string;
@@ -25,7 +24,8 @@
blocked_(false),
num_bytes_buffered_(0),
num_frames_received_(0),
- num_duplicate_frames_received_(0) {
+ num_duplicate_frames_received_(0),
+ num_early_frames_received_(0) {
}
QuicStreamSequencer::~QuicStreamSequencer() {
@@ -64,6 +64,10 @@
IOVector data;
data.AppendIovec(frame.data.iovec(), frame.data.Size());
+ if (byte_offset > num_bytes_consumed_) {
+ ++num_early_frames_received_;
+ }
+
// If the frame has arrived in-order then we can process it immediately, only
// buffering if the stream is unable to process it.
if (!blocked_ && byte_offset == num_bytes_consumed_) {
@@ -98,7 +102,7 @@
for (size_t i = 0; i < data.Size(); ++i) {
DVLOG(1) << "Buffering stream data at offset " << byte_offset;
const iovec& iov = data.iovec()[i];
- buffered_frames_.insert(make_pair(
+ buffered_frames_.insert(std::make_pair(
byte_offset, string(static_cast<char*>(iov.iov_base), iov.iov_len)));
byte_offset += iov.iov_len;
num_bytes_buffered_ += iov.iov_len;
@@ -190,8 +194,8 @@
}
// We've finished copying. If we have a partial frame, update it.
if (frame_offset != 0) {
- buffered_frames_.insert(
- make_pair(it->first + frame_offset, it->second.substr(frame_offset)));
+ buffered_frames_.insert(std::make_pair(it->first + frame_offset,
+ it->second.substr(frame_offset)));
buffered_frames_.erase(buffered_frames_.begin());
RecordBytesConsumed(frame_offset);
}
@@ -278,7 +282,7 @@
} else {
string new_data = it->second.substr(bytes_consumed);
buffered_frames_.erase(it);
- buffered_frames_.insert(make_pair(num_bytes_consumed_, new_data));
+ buffered_frames_.insert(std::make_pair(num_bytes_consumed_, new_data));
return;
}
}
diff --git a/net/quic/quic_stream_sequencer.h b/net/quic/quic_stream_sequencer.h
index f34d735..3570d3b 100644
--- a/net/quic/quic_stream_sequencer.h
+++ b/net/quic/quic_stream_sequencer.h
@@ -75,6 +75,8 @@
return num_duplicate_frames_received_;
}
+ int num_early_frames_received() const { return num_early_frames_received_; }
+
private:
friend class test::QuicStreamSequencerPeer;
@@ -122,6 +124,10 @@
// Count of the number of duplicate frames received.
int num_duplicate_frames_received_;
+ // Count of the number of frames received before all previous frames were
+ // received.
+ int num_early_frames_received_;
+
DISALLOW_COPY_AND_ASSIGN(QuicStreamSequencer);
};
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index 8a71c4c..6e3d57d 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -226,6 +226,7 @@
EXPECT_EQ(1u, buffered_frames_->size());
EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
EXPECT_EQ("abc", buffered_frames_->find(0)->second);
+ EXPECT_EQ(0, sequencer_->num_early_frames_received());
}
TEST_F(QuicStreamSequencerTest, FutureFrameNotProcessed) {
@@ -233,6 +234,7 @@
EXPECT_EQ(1u, buffered_frames_->size());
EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
EXPECT_EQ("abc", buffered_frames_->find(3)->second);
+ EXPECT_EQ(1, sequencer_->num_early_frames_received());
}
TEST_F(QuicStreamSequencerTest, OutOfOrderFrameProcessed) {
@@ -336,7 +338,7 @@
while (remaining_payload != 0) {
int size = min(OneToN(6), remaining_payload);
int index = payload_size - remaining_payload;
- list_.push_back(make_pair(index, string(kPayload + index, size)));
+ list_.push_back(std::make_pair(index, string(kPayload + index, size)));
remaining_payload -= size;
}
}
@@ -400,7 +402,7 @@
// Add a buffered frame.
buffered_frames->insert(
- make_pair(kBufferedOffset, string(kBufferedDataLength, '.')));
+ std::make_pair(kBufferedOffset, string(kBufferedDataLength, '.')));
// New byte range partially overlaps with buffered frame, start offset
// preceeding buffered frame.
diff --git a/net/quic/quic_time_wait_list_manager.cc b/net/quic/quic_time_wait_list_manager.cc
index 52ee2da..2e3e16d 100644
--- a/net/quic/quic_time_wait_list_manager.cc
+++ b/net/quic/quic_time_wait_list_manager.cc
@@ -22,7 +22,6 @@
#include "net/quic/quic_utils.h"
using base::StringPiece;
-using std::make_pair;
namespace net {
@@ -122,7 +121,7 @@
version,
helper_->GetClock()->ApproximateNow(),
close_packet);
- connection_id_map_.insert(make_pair(connection_id, data));
+ connection_id_map_.insert(std::make_pair(connection_id, data));
if (new_connection_id) {
visitor_->OnConnectionAddedToTimeWaitList(connection_id);
}
diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc
index 76a31da..25e2a8a 100644
--- a/net/quic/quic_unacked_packet_map.cc
+++ b/net/quic/quic_unacked_packet_map.cc
@@ -53,8 +53,7 @@
packet.sequence_number_length,
transmission_type,
sent_time);
- DCHECK(packet.packet != nullptr);
- info.is_fec_packet = packet.packet->is_fec_packet();
+ info.is_fec_packet = packet.is_fec_packet;
if (old_sequence_number == 0) {
if (packet.retransmittable_frames != nullptr &&
diff --git a/net/quic/quic_unacked_packet_map_test.cc b/net/quic/quic_unacked_packet_map_test.cc
index 7840495..a93874c 100644
--- a/net/quic/quic_unacked_packet_map_test.cc
+++ b/net/quic/quic_unacked_packet_map_test.cc
@@ -30,18 +30,14 @@
SerializedPacket CreateRetransmittablePacket(
QuicPacketSequenceNumber sequence_number) {
- packets_.push_back(QuicPacket::NewDataPacket(
- nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
- PACKET_1BYTE_SEQUENCE_NUMBER));
+ packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
return SerializedPacket(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
packets_.back(), 0, new RetransmittableFrames());
}
SerializedPacket CreateNonRetransmittablePacket(
QuicPacketSequenceNumber sequence_number) {
- packets_.push_back(QuicPacket::NewDataPacket(
- nullptr, kDefaultLength, false, PACKET_8BYTE_CONNECTION_ID, false,
- PACKET_1BYTE_SEQUENCE_NUMBER));
+ packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength));
return SerializedPacket(sequence_number, PACKET_1BYTE_SEQUENCE_NUMBER,
packets_.back(), 0, nullptr);
}
@@ -105,7 +101,7 @@
<< " packets[" << i << "]:" << packets[i];
}
}
- vector<QuicPacket*> packets_;
+ vector<QuicEncryptedPacket*> packets_;
QuicUnackedPacketMap unacked_packets_;
QuicTime now_;
};
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc
index f8b31c4..17e7461 100644
--- a/net/quic/quic_utils.cc
+++ b/net/quic/quic_utils.cc
@@ -42,23 +42,36 @@
// static
uint128 QuicUtils::FNV1a_128_Hash(const char* data, int len) {
- // The following two constants are defined as part of the hash algorithm.
+ return FNV1a_128_Hash_Two(data, len, nullptr, 0);
+}
+
+// static
+uint128 QuicUtils::FNV1a_128_Hash_Two(const char* data1,
+ int len1,
+ const char* data2,
+ int len2) {
+ // The two constants are defined as part of the hash algorithm.
// see http://www.isthe.com/chongo/tech/comp/fnv/
- // 309485009821345068724781371
- const uint128 kPrime(16777216, 315);
// 144066263297769815596495629667062367629
const uint128 kOffset(GG_UINT64_C(7809847782465536322),
GG_UINT64_C(7113472399480571277));
+ uint128 hash = IncrementalHash(kOffset, data1, len1);
+ if (data2 == nullptr) {
+ return hash;
+ }
+ return IncrementalHash(hash, data2, len2);
+}
+
+// static
+uint128 QuicUtils::IncrementalHash(uint128 hash, const char* data, size_t len) {
+ // 309485009821345068724781371
+ const uint128 kPrime(16777216, 315);
const uint8* octets = reinterpret_cast<const uint8*>(data);
-
- uint128 hash = kOffset;
-
- for (int i = 0; i < len; ++i) {
+ for (size_t i = 0; i < len; ++i) {
hash = hash ^ uint128(0, octets[i]);
hash = hash * kPrime;
}
-
return hash;
}
@@ -221,6 +234,7 @@
RETURN_STRING_LITERAL(QUIC_VERSION_NEGOTIATION_MISMATCH);
RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS);
RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS);
+ RETURN_STRING_LITERAL(QUIC_CONNECTION_CANCELLED);
RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
// Intentionally have no default case, so we'll break the build
// if we add errors and don't put them here.
diff --git a/net/quic/quic_utils.h b/net/quic/quic_utils.h
index 2c34ec4..5e76a0d 100644
--- a/net/quic/quic_utils.h
+++ b/net/quic/quic_utils.h
@@ -28,7 +28,18 @@
// returns the 128 bit FNV1a hash of the data. See
// http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
- static uint128 FNV1a_128_Hash(const char* data, int len);
+ static uint128 FNV1a_128_Hash(const char* data1, int len1);
+
+ // returns the 128 bit FNV1a hash of the two sequences of data. See
+ // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
+ static uint128 FNV1a_128_Hash_Two(const char* data1,
+ int len1,
+ const char* data2,
+ int len2);
+
+ // returns the 128 bit FNV1a hash of the |data|, starting with the
+ // previous hash.
+ static uint128 IncrementalHash(uint128 hash, const char* data, size_t len);
// FindMutualTag sets |out_result| to the first tag in the priority list that
// is also in the other list and returns true. If there is no intersection it
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 5661676..d6238bd 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -199,7 +199,7 @@
server_session.SetCryptoStream(&server);
// The client's handshake must have been started already.
- CHECK_NE(0u, client_conn->packets_.size());
+ CHECK_NE(0u, client_conn->encrypted_packets_.size());
CommunicateHandshakeMessages(client_conn, client, server_conn, &server);
@@ -244,7 +244,7 @@
client_session.SetCryptoStream(&client);
client.CryptoConnect();
- CHECK_EQ(1u, client_conn->packets_.size());
+ CHECK_EQ(1u, client_conn->encrypted_packets_.size());
CommunicateHandshakeMessagesAndRunCallbacks(
client_conn, &client, server_conn, server, async_channel_id_source);
@@ -295,17 +295,17 @@
CallbackSource* callback_source) {
size_t a_i = 0, b_i = 0;
while (!a->handshake_confirmed()) {
- ASSERT_GT(a_conn->packets_.size(), a_i);
- LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
- << " packets a->b";
+ ASSERT_GT(a_conn->encrypted_packets_.size(), a_i);
+ VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
+ << " packets a->b";
MovePackets(a_conn, &a_i, b, b_conn);
if (callback_source) {
callback_source->RunPendingCallbacks();
}
- ASSERT_GT(b_conn->packets_.size(), b_i);
- LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
- << " packets b->a";
+ ASSERT_GT(b_conn->encrypted_packets_.size(), b_i);
+ VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
+ << " packets b->a";
MovePackets(b_conn, &b_i, a, a_conn);
if (callback_source) {
callback_source->RunPendingCallbacks();
@@ -321,18 +321,18 @@
PacketSavingConnection* b_conn,
QuicCryptoStream* b,
size_t b_i) {
- LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
- << " packets a->b";
+ VLOG(1) << "Processing " << a_conn->encrypted_packets_.size() - a_i
+ << " packets a->b";
MovePackets(a_conn, &a_i, b, b_conn);
- LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
- << " packets b->a";
- if (b_conn->packets_.size() - b_i == 2) {
- LOG(INFO) << "here";
+ VLOG(1) << "Processing " << b_conn->encrypted_packets_.size() - b_i
+ << " packets b->a";
+ if (b_conn->encrypted_packets_.size() - b_i == 2) {
+ VLOG(1) << "here";
}
MovePackets(b_conn, &b_i, a, a_conn);
- return make_pair(a_i, b_i);
+ return std::make_pair(a_i, b_i);
}
// static
diff --git a/net/quic/test_tools/quic_config_peer.cc b/net/quic/test_tools/quic_config_peer.cc
index 53ca554..05f7538 100644
--- a/net/quic/test_tools/quic_config_peer.cc
+++ b/net/quic/test_tools/quic_config_peer.cc
@@ -45,10 +45,5 @@
config->bytes_for_connection_id_.SetReceivedValue(bytes);
}
-// static
-QuicTag QuicConfigPeer::CongestionFeedback(QuicConfig* config) {
- return config->congestion_feedback_.GetTag();
-}
-
} // namespace test
} // namespace net
diff --git a/net/quic/test_tools/quic_config_peer.h b/net/quic/test_tools/quic_config_peer.h
index 410c818..ca2a339 100644
--- a/net/quic/test_tools/quic_config_peer.h
+++ b/net/quic/test_tools/quic_config_peer.h
@@ -30,8 +30,6 @@
static void SetReceivedBytesForConnectionId(QuicConfig* config, uint32 bytes);
- static QuicTag CongestionFeedback(QuicConfig* config);
-
private:
DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer);
};
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index 9253e55..201d451 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -5,7 +5,6 @@
#include "net/quic/test_tools/quic_connection_peer.h"
#include "base/stl_util.h"
-#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_packet_writer.h"
@@ -23,14 +22,6 @@
}
// static
-void QuicConnectionPeer::SetReceiveAlgorithm(
- QuicConnection* connection,
- ReceiveAlgorithmInterface* receive_algorithm) {
- connection->received_packet_manager_.receive_algorithm_.reset(
- receive_algorithm);
-}
-
-// static
void QuicConnectionPeer::SetSendAlgorithm(
QuicConnection* connection,
SendAlgorithmInterface* send_algorithm) {
@@ -38,14 +29,16 @@
}
// static
-QuicAckFrame* QuicConnectionPeer::CreateAckFrame(QuicConnection* connection) {
- return connection->CreateAckFrame();
+void QuicConnectionPeer::PopulateAckFrame(QuicConnection* connection,
+ QuicAckFrame* ack) {
+ connection->PopulateAckFrame(ack);
}
// static
-QuicStopWaitingFrame* QuicConnectionPeer::CreateStopWaitingFrame(
- QuicConnection* connection) {
- return connection->CreateStopWaitingFrame();
+void QuicConnectionPeer::PopulateStopWaitingFrame(
+ QuicConnection* connection,
+ QuicStopWaitingFrame* stop_waiting) {
+ connection->PopulateStopWaitingFrame(stop_waiting);
}
// static
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 7cbbb1f..086e353 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -26,7 +26,6 @@
class QuicPacketWriter;
class QuicReceivedPacketManager;
class QuicSentPacketManager;
-class ReceiveAlgorithmInterface;
class SendAlgorithmInterface;
namespace test {
@@ -36,16 +35,13 @@
public:
static void SendAck(QuicConnection* connection);
- static void SetReceiveAlgorithm(QuicConnection* connection,
- ReceiveAlgorithmInterface* receive_algorithm);
-
static void SetSendAlgorithm(QuicConnection* connection,
SendAlgorithmInterface* send_algorithm);
- static QuicAckFrame* CreateAckFrame(QuicConnection* connection);
+ static void PopulateAckFrame(QuicConnection* connection, QuicAckFrame* ack);
- static QuicStopWaitingFrame* CreateStopWaitingFrame(
- QuicConnection* connection);
+ static void PopulateStopWaitingFrame(QuicConnection* connection,
+ QuicStopWaitingFrame* stop_waiting);
static QuicConnectionVisitorInterface* GetVisitor(
QuicConnection* connection);
diff --git a/net/quic/test_tools/quic_test_packet_maker.cc b/net/quic/test_tools/quic_test_packet_maker.cc
index 1b97bda..ecdd6bf 100644
--- a/net/quic/test_tools/quic_test_packet_maker.cc
+++ b/net/quic/test_tools/quic_test_packet_maker.cc
@@ -84,7 +84,7 @@
QuicFramer framer(SupportedVersions(version_), clock_->Now(), false);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer, header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames));
return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
ENCRYPTION_NONE, header.packet_sequence_number, *packet));
}
@@ -137,7 +137,7 @@
frames.push_back(QuicFrame(&stop_waiting));
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer, header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames));
return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
ENCRYPTION_NONE, header.packet_sequence_number, *packet));
}
@@ -238,7 +238,7 @@
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer, header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames));
return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
ENCRYPTION_NONE, header.packet_sequence_number, *packet));
}
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index c8b6a40..b504b75 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -13,6 +13,7 @@
#include "net/quic/crypto/null_encrypter.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
+#include "net/quic/quic_data_writer.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_utils.h"
@@ -60,9 +61,9 @@
return ack;
}
-SerializedPacket BuildUnsizedDataPacket(QuicFramer* framer,
- const QuicPacketHeader& header,
- const QuicFrames& frames) {
+QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer,
+ const QuicPacketHeader& header,
+ const QuicFrames& frames) {
const size_t max_plaintext_size = framer->GetMaxPlaintextSize(kMaxPacketSize);
size_t packet_size = GetPacketHeaderSize(header);
for (size_t i = 0; i < frames.size(); ++i) {
@@ -76,7 +77,22 @@
DCHECK(frame_size);
packet_size += frame_size;
}
- return framer->BuildDataPacket(header, frames, packet_size);
+ return BuildUnsizedDataPacket(framer, header, frames, packet_size);
+}
+
+QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer,
+ const QuicPacketHeader& header,
+ const QuicFrames& frames,
+ size_t packet_size) {
+ char* buffer = new char[packet_size];
+ scoped_ptr<QuicPacket> packet(
+ framer->BuildDataPacket(header, frames, buffer, packet_size));
+ DCHECK(packet.get() != nullptr);
+ // Now I have to re-construct the data packet with data ownership.
+ return new QuicPacket(buffer, packet->length(), true,
+ header.public_header.connection_id_length,
+ header.public_header.version_flag,
+ header.public_header.sequence_number_length);
}
uint64 SimpleRandom::RandUint64() {
@@ -298,17 +314,11 @@
}
PacketSavingConnection::~PacketSavingConnection() {
- STLDeleteElements(&packets_);
STLDeleteElements(&encrypted_packets_);
}
void PacketSavingConnection::SendOrQueuePacket(QueuedPacket packet) {
- packets_.push_back(packet.serialized_packet.packet);
- QuicEncryptedPacket* encrypted = QuicConnectionPeer::GetFramer(this)->
- EncryptPacket(packet.encryption_level,
- packet.serialized_packet.sequence_number,
- *packet.serialized_packet.packet);
- encrypted_packets_.push_back(encrypted);
+ encrypted_packets_.push_back(packet.serialized_packet.packet);
// Transfer ownership of the packet to the SentPacketManager and the
// ack notifier to the AckNotifierManager.
sent_packet_manager_.OnPacketSent(
@@ -481,7 +491,7 @@
frames.push_back(frame);
QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer, header, frames).packet);
+ BuildUnsizedDataPacket(&framer, header, frames));
EXPECT_TRUE(packet != nullptr);
QuicEncryptedPacket* encrypted = framer.EncryptPacket(ENCRYPTION_NONE,
sequence_number,
@@ -558,7 +568,7 @@
QuicFrame frame(&stream_frame);
QuicFrames frames;
frames.push_back(frame);
- return BuildUnsizedDataPacket(&quic_framer, header, frames).packet;
+ return BuildUnsizedDataPacket(&quic_framer, header, frames);
}
QuicPacket* ConstructHandshakePacket(QuicConnectionId connection_id,
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index cf56b66..5282d62 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -103,12 +103,17 @@
QuicAckFrame MakeAckFrameWithNackRanges(size_t num_nack_ranges,
QuicPacketSequenceNumber least_unacked);
-// Returns a SerializedPacket whose |packet| member is owned by the caller, and
+// Returns a QuicPacket that is owned by the caller, and
// is populated with the fields in |header| and |frames|, or is nullptr if the
// packet could not be created.
-SerializedPacket BuildUnsizedDataPacket(QuicFramer* framer,
- const QuicPacketHeader& header,
- const QuicFrames& frames);
+QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer,
+ const QuicPacketHeader& header,
+ const QuicFrames& frames);
+// Returns a QuicPacket that is owned by the caller, and of size |packet_size|.
+QuicPacket* BuildUnsizedDataPacket(QuicFramer* framer,
+ const QuicPacketHeader& header,
+ const QuicFrames& frames,
+ size_t packet_size);
template<typename SaveType>
class ValueRestore {
@@ -345,7 +350,6 @@
void SendOrQueuePacket(QueuedPacket packet) override;
- std::vector<QuicPacket*> packets_;
std::vector<QuicEncryptedPacket*> encrypted_packets_;
private:
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 4052828..c3ecd0d 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -8,7 +8,6 @@
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
-#include "base/metrics/stats_counters.h"
#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@@ -1244,7 +1243,6 @@
pool->connect_job_factory_->NewConnectJob(
group_name, *pending_requests_.FirstMax().value(), pool);
backup_job->net_log().AddEvent(NetLog::TYPE_BACKUP_CONNECT_JOB_CREATED);
- SIMPLE_STATS_COUNTER("socket.backup_created");
int rv = backup_job->Connect();
pool->connecting_socket_count_++;
ConnectJob* raw_backup_job = backup_job.get();
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index c4af957..c6752d4 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -18,7 +18,6 @@
#include "base/environment.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
-#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
@@ -473,20 +472,23 @@
int rv = Init();
if (rv != OK) {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
- UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error", std::abs(rv));
return rv;
}
// Set SSL to client mode. Handshake happens in the loop below.
SSL_set_connect_state(ssl_);
+ // Enable fastradio padding.
+ SSL_enable_fastradio_padding(ssl_,
+ ssl_config_.fastradio_padding_enabled &&
+ ssl_config_.fastradio_padding_eligible);
+
GotoState(STATE_HANDSHAKE);
rv = DoHandshakeLoop(OK);
if (rv == ERR_IO_PENDING) {
user_connect_callback_ = callback;
} else {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
- UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error", std::abs(rv));
if (rv < OK)
OnHandshakeCompletion();
}
@@ -1087,6 +1089,7 @@
}
int SSLClientSocketOpenSSL::DoChannelIDLookup() {
+ net_log_.AddEvent(NetLog::TYPE_SSL_CHANNEL_ID_REQUESTED);
GotoState(STATE_CHANNEL_ID_LOOKUP_COMPLETE);
return channel_id_service_->GetOrCreateChannelID(
host_and_port_.host(),
@@ -1133,6 +1136,7 @@
// Return to the handshake.
set_channel_id_sent(true);
+ net_log_.AddEvent(NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED);
GotoState(STATE_HANDSHAKE);
return OK;
}
@@ -1366,7 +1370,6 @@
int rv = DoHandshakeLoop(result);
if (rv != ERR_IO_PENDING) {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
- UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error", std::abs(rv));
DoConnectCallback(rv);
}
}
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index bfc37e6..db28bec 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -552,6 +552,12 @@
}
}
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error", std::abs(result));
+ if (params_->ssl_config().fastradio_padding_eligible) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSL_Connection_Error_FastRadioPadding",
+ std::abs(result));
+ }
+
if (result == OK || IsCertificateError(result)) {
SetSocket(ssl_socket_.Pass());
} else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
diff --git a/net/socket/tcp_socket_libevent.cc b/net/socket/tcp_socket_libevent.cc
index d7fa9fa..c5d30e1 100644
--- a/net/socket/tcp_socket_libevent.cc
+++ b/net/socket/tcp_socket_libevent.cc
@@ -9,9 +9,10 @@
#include <sys/socket.h>
#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "base/metrics/stats_counters.h"
#include "base/posix/eintr_wrapper.h"
#include "base/task_runner_util.h"
#include "base/threading/worker_pool.h"
@@ -538,9 +539,6 @@
}
void TCPSocketLibevent::LogConnectBegin(const AddressList& addresses) const {
- base::StatsCounter connects("tcp.connect");
- connects.Increment();
-
net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
addresses.CreateNetLogCallback());
}
@@ -597,9 +595,6 @@
CreateNetLogSocketErrorCallback(rv, errno));
return rv;
}
-
- base::StatsCounter read_bytes("tcp.read_bytes");
- read_bytes.Add(rv);
net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
buf->data());
NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv);
@@ -631,9 +626,6 @@
CreateNetLogSocketErrorCallback(rv, errno));
return rv;
}
-
- base::StatsCounter write_bytes("tcp.write_bytes");
- write_bytes.Add(rv);
net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv,
buf->data());
NetworkActivityMonitor::GetInstance()->IncrementBytesSent(rv);
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index 538c8d7..d9ec0d5 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -9,7 +9,6 @@
#include "base/callback_helpers.h"
#include "base/logging.h"
-#include "base/metrics/stats_counters.h"
#include "base/profiler/scoped_tracker.h"
#include "base/win/windows_version.h"
#include "net/base/address_list.h"
@@ -524,9 +523,6 @@
DCHECK_GT(buf_len, 0);
DCHECK(!core_->write_iobuffer_.get());
- base::StatsCounter writes("tcp.writes");
- writes.Increment();
-
WSABUF write_buffer;
write_buffer.len = buf_len;
write_buffer.buf = buf->data();
@@ -546,8 +542,6 @@
<< " bytes, but " << rv << " bytes reported.";
return ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES;
}
- base::StatsCounter write_bytes("tcp.write_bytes");
- write_bytes.Add(rv);
net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, rv,
buf->data());
NetworkActivityMonitor::GetInstance()->IncrementBytesSent(rv);
@@ -889,9 +883,6 @@
}
void TCPSocketWin::LogConnectBegin(const AddressList& addresses) {
- base::StatsCounter connects("tcp.connect");
- connects.Increment();
-
net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
addresses.CreateNetLogCallback());
}
@@ -942,9 +933,6 @@
return net_error;
}
} else {
- base::StatsCounter read_bytes("tcp.read_bytes");
- if (rv > 0)
- read_bytes.Add(rv);
net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, rv,
buf->data());
NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(rv);
@@ -1030,8 +1018,6 @@
<< " bytes reported.";
rv = ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES;
} else {
- base::StatsCounter write_bytes("tcp.write_bytes");
- write_bytes.Add(num_bytes);
net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes,
core_->write_iobuffer_->data());
NetworkActivityMonitor::GetInstance()->IncrementBytesSent(num_bytes);
diff --git a/net/spdy/spdy_buffer.cc b/net/spdy/spdy_buffer.cc
index f7cd378..a1fd8c8 100644
--- a/net/spdy/spdy_buffer.cc
+++ b/net/spdy/spdy_buffer.cc
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/logging.h"
+#include "base/profiler/scoped_tracker.h"
#include "net/base/io_buffer.h"
#include "net/spdy/spdy_protocol.h"
@@ -88,6 +89,9 @@
}
void SpdyBuffer::Consume(size_t consume_size) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457517 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("457517 SpdyBuffer::Consume"));
ConsumeHelper(consume_size, CONSUME);
};
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index a02cb2e..e7603ff 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -6,7 +6,6 @@
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
-#include "base/metrics/stats_counters.h"
#include "base/third_party/valgrind/memcheck.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_frame_reader.h"
@@ -3246,11 +3245,6 @@
LOG(DFATAL) << "Could not obtain compressor.";
return;
}
-
- base::StatsCounter compressed_frames("spdy.CompressedFrames");
- base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
- base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
-
// Create an output frame.
// Since we'll be performing lots of flushes when compressing the data,
// zlib's lower bounds may be insufficient.
@@ -3287,11 +3281,6 @@
int compressed_size = compressed_max_size - compressor->avail_out;
builder->Seek(compressed_size);
builder->RewriteLength(*this);
-
- pre_compress_bytes.Add(uncompressed_len);
- post_compress_bytes.Add(compressed_size);
-
- compressed_frames.Increment();
}
} // namespace net
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index a6478df..58e4af7 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -15,7 +15,6 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
-#include "base/metrics/stats_counters.h"
#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -718,9 +717,6 @@
// requires re-working CreateFakeSpdySession(), though.
DCHECK(connection->socket());
- base::StatsCounter spdy_sessions("spdy.sessions");
- spdy_sessions.Increment();
-
connection_ = connection.Pass();
is_secure_ = is_secure;
certificate_error_code_ = certificate_error_code;
@@ -1084,8 +1080,6 @@
syn_frame.reset(buffered_spdy_framer_->SerializeFrame(headers));
}
- base::StatsCounter spdy_requests("spdy.requests");
- spdy_requests.Increment();
streams_initiated_count_++;
if (net_log().IsLogging()) {
@@ -1468,6 +1462,9 @@
}
void SpdySession::PumpWriteLoop(WriteState expected_write_state, int result) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457517 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("457517 SpdySession::PumpWriteLoop"));
CHECK(!in_io_loop_);
DCHECK_EQ(write_state_, expected_write_state);
@@ -1519,6 +1516,9 @@
}
int SpdySession::DoWrite() {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457517 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("457517 SpdySession::DoWrite"));
CHECK(in_io_loop_);
DCHECK(buffered_spdy_framer_);
@@ -1582,6 +1582,9 @@
}
int SpdySession::DoWriteComplete(int result) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457517 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("457517 SpdySession::DoWriteComplete"));
CHECK(in_io_loop_);
DCHECK_NE(result, ERR_IO_PENDING);
DCHECK_GT(in_flight_write_->GetRemainingSize(), 0u);
@@ -1649,6 +1652,9 @@
void SpdySession::StartGoingAway(SpdyStreamId last_good_stream_id,
Error status) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457517 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("457517 SpdySession::StartGoingAway"));
DCHECK_GE(availability_state_, STATE_GOING_AWAY);
// The loops below are carefully written to avoid reentrancy problems.
@@ -1768,13 +1774,9 @@
DCHECK_GT(it->first, 0u);
LogAbandonedStream(it->second.stream, status);
++streams_abandoned_count_;
- base::StatsCounter abandoned_streams("spdy.abandoned_streams");
- abandoned_streams.Increment();
if (it->second.stream->type() == SPDY_PUSH_STREAM &&
unclaimed_pushed_streams_.find(it->second.stream->url()) !=
unclaimed_pushed_streams_.end()) {
- base::StatsCounter abandoned_push_streams("spdy.abandoned_push_streams");
- abandoned_push_streams.Increment();
}
}
@@ -1962,8 +1964,6 @@
}
base::WeakPtr<SpdyStream> SpdySession::GetActivePushStream(const GURL& url) {
- base::StatsCounter used_push_streams("spdy.claimed_push_streams");
-
PushedStreamMap::iterator unclaimed_it = unclaimed_pushed_streams_.find(url);
if (unclaimed_it == unclaimed_pushed_streams_.end())
return base::WeakPtr<SpdyStream>();
@@ -1980,7 +1980,6 @@
net_log_.AddEvent(NetLog::TYPE_SPDY_STREAM_ADOPTED_PUSH_STREAM,
base::Bind(&NetLogSpdyAdoptedPushStreamCallback,
active_it->second.stream->stream_id(), &url));
- used_push_streams.Increment();
return active_it->second.stream->GetWeakPtr();
}
@@ -2255,14 +2254,9 @@
return;
}
- if (OnInitialResponseHeadersReceived(response_headers,
- response_time,
- recv_first_byte_time,
- active_it->second.stream) != OK)
- return;
-
- base::StatsCounter push_requests("spdy.pushed_streams");
- push_requests.Increment();
+ OnInitialResponseHeadersReceived(response_headers, response_time,
+ recv_first_byte_time,
+ active_it->second.stream);
}
void SpdySession::DeleteExpiredPushedStreams() {
@@ -2758,9 +2752,6 @@
// TODO(baranovich): pass parent stream id priority?
if (!TryCreatePushStream(promised_stream_id, stream_id, 0, headers))
return;
-
- base::StatsCounter push_requests("spdy.pushed_streams");
- push_requests.Increment();
}
void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id,
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index ddcc574..a2d2ed6 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/values.h"
#include "net/base/address_list.h"
#include "net/http/http_network_session.h"
@@ -64,6 +65,10 @@
HostPortPair::FromString(trusted_spdy_proxy)) {
DCHECK(default_protocol_ >= kProtoSPDYMinimumVersion &&
default_protocol_ <= kProtoSPDYMaximumVersion);
+ // TODO(michaeln): Remove ScopedTracker below once crbug.com/454983 is fixed
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "454983 SpdySessionPool::SpdySessionPool"));
NetworkChangeNotifier::AddIPAddressObserver(this);
if (ssl_config_service_.get())
ssl_config_service_->AddObserver(this);
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index e7dcd5b..1059223 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -8,6 +8,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
@@ -528,6 +529,10 @@
void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type,
size_t frame_size) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/457517 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "457517 SpdyStream::OnFrameWriteComplete"));
DCHECK_NE(type_, SPDY_PUSH_STREAM);
if (frame_size < session_->GetFrameMinimumSize() ||
diff --git a/net/ssl/openssl_ssl_util.cc b/net/ssl/openssl_ssl_util.cc
index eabf35d..f7acd62 100644
--- a/net/ssl/openssl_ssl_util.cc
+++ b/net/ssl/openssl_ssl_util.cc
@@ -67,7 +67,6 @@
case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
case SSL_R_UNKNOWN_CIPHER_TYPE:
case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
- case SSL_R_UNKNOWN_PKEY_TYPE:
case SSL_R_UNKNOWN_SSL_VERSION:
return ERR_NOT_IMPLEMENTED;
case SSL_R_UNSUPPORTED_SSL_VERSION:
@@ -114,7 +113,6 @@
case SSL_R_EXTRA_DATA_IN_MESSAGE:
case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
case SSL_R_INVALID_COMMAND:
- case SSL_R_INVALID_STATUS_RESPONSE:
case SSL_R_INVALID_TICKET_KEYS_LENGTH:
// SSL_do_handshake reports this error when the server responds to a
// ClientHello with a fatal close_notify alert.
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc
index 56cb75c..781898b 100644
--- a/net/ssl/ssl_config.cc
+++ b/net/ssl/ssl_config.cc
@@ -29,7 +29,9 @@
send_client_cert(false),
verify_ev_cert(false),
version_fallback(false),
- cert_io_enabled(true) {
+ cert_io_enabled(true),
+ fastradio_padding_enabled(false),
+ fastradio_padding_eligible(false) {
}
SSLConfig::~SSLConfig() {}
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h
index 2cbc995..c3dc9b9 100644
--- a/net/ssl/ssl_config.h
+++ b/net/ssl/ssl_config.h
@@ -159,6 +159,16 @@
NextProtoVector next_protos;
scoped_refptr<X509Certificate> client_cert;
+
+ // Information about how to proceed with fastradio padding.
+ // |fastradio_padding_enabled| determines if the feature is enabled globally.
+ // |fastradio_padding_eligible| determines if the endpoint associated with
+ // this config should use it.
+ // |fastradio_padding_eligible| can be true when |fastradio_padding_enabled|
+ // is false: in this case, fastradio padding would not be enabled, but
+ // metrics can be collected for experiments.
+ bool fastradio_padding_enabled;
+ bool fastradio_padding_eligible;
};
} // namespace net
diff --git a/net/ssl/ssl_config_service.cc b/net/ssl/ssl_config_service.cc
index 4661930..8a63332 100644
--- a/net/ssl/ssl_config_service.cc
+++ b/net/ssl/ssl_config_service.cc
@@ -77,6 +77,10 @@
FOR_EACH_OBSERVER(Observer, observer_list_, OnSSLConfigChanged());
}
+bool SSLConfigService::SupportsFastradioPadding(const GURL& url) {
+ return false;
+}
+
SSLConfigService::~SSLConfigService() {
}
diff --git a/net/ssl/ssl_config_service.h b/net/ssl/ssl_config_service.h
index e074309..dd3236d 100644
--- a/net/ssl/ssl_config_service.h
+++ b/net/ssl/ssl_config_service.h
@@ -14,6 +14,8 @@
#include "net/cert/ct_ev_whitelist.h"
#include "net/ssl/ssl_config.h"
+class GURL;
+
namespace net {
// The interface for retrieving the SSL configuration. This interface
@@ -66,6 +68,9 @@
// called on the IO thread.
void NotifySSLConfigChange();
+ // Returns true if the |url| should use fastradio padding.
+ virtual bool SupportsFastradioPadding(const GURL& url);
+
protected:
friend class base::RefCountedThreadSafe<SSLConfigService>;
diff --git a/net/test/embedded_test_server/http_request.cc b/net/test/embedded_test_server/http_request.cc
index 3156e51..51d6f06 100644
--- a/net/test/embedded_test_server/http_request.cc
+++ b/net/test/embedded_test_server/http_request.cc
@@ -10,6 +10,7 @@
#include "base/strings/string_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "net/http/http_chunked_decoder.h"
namespace net {
namespace test_server {
@@ -140,6 +141,13 @@
http_request_->headers["Content-Length"],
&declared_content_length_);
DCHECK(success) << "Malformed Content-Length header's value.";
+ } else if (http_request_->headers.count("Transfer-Encoding") > 0) {
+ if (http_request_->headers["Transfer-Encoding"] == "chunked") {
+ http_request_->has_content = true;
+ chunked_decoder_.reset(new HttpChunkedDecoder());
+ state_ = STATE_CONTENT;
+ return WAITING;
+ }
}
if (declared_content_length_ == 0) {
// No content data, so parsing is finished.
@@ -155,6 +163,25 @@
HttpRequestParser::ParseResult HttpRequestParser::ParseContent() {
const size_t available_bytes = buffer_.size() - buffer_position_;
+ if (chunked_decoder_.get()) {
+ int bytes_written = chunked_decoder_->FilterBuf(
+ const_cast<char*>(buffer_.data()) + buffer_position_, available_bytes);
+ http_request_->content.append(buffer_.data() + buffer_position_,
+ bytes_written);
+
+ if (chunked_decoder_->reached_eof()) {
+ buffer_ =
+ buffer_.substr(buffer_.size() - chunked_decoder_->bytes_after_eof());
+ buffer_position_ = 0;
+ state_ = STATE_ACCEPTED;
+ return ACCEPTED;
+ }
+ buffer_ = "";
+ buffer_position_ = 0;
+ state_ = STATE_CONTENT;
+ return WAITING;
+ }
+
const size_t fetch_bytes = std::min(
available_bytes,
declared_content_length_ - http_request_->content.size());
diff --git a/net/test/embedded_test_server/http_request.h b/net/test/embedded_test_server/http_request.h
index fcbf54c..3cd1ac7 100644
--- a/net/test/embedded_test_server/http_request.h
+++ b/net/test/embedded_test_server/http_request.h
@@ -13,6 +13,9 @@
#include "base/strings/string_piece.h"
namespace net {
+
+class HttpChunkedDecoder;
+
namespace test_server {
// Methods of HTTP requests supported by the test HTTP server.
@@ -93,7 +96,7 @@
ParseResult ParseHeaders();
// Parses request's content data and returns ACCEPTED if all of it have been
- // processed. Chunked Transfer Encoding *is not* supported.
+ // processed. Chunked Transfer Encoding is supported.
ParseResult ParseContent();
// Fetches the next line from the buffer. Result does not contain \r\n.
@@ -108,6 +111,8 @@
// Content length of the request currently being parsed.
size_t declared_content_length_;
+ scoped_ptr<net::HttpChunkedDecoder> chunked_decoder_;
+
DISALLOW_COPY_AND_ASSIGN(HttpRequestParser);
};
diff --git a/net/test/embedded_test_server/http_request_unittest.cc b/net/test/embedded_test_server/http_request_unittest.cc
index 56121bb..ff2ae3c 100644
--- a/net/test/embedded_test_server/http_request_unittest.cc
+++ b/net/test/embedded_test_server/http_request_unittest.cc
@@ -4,6 +4,7 @@
#include "net/test/embedded_test_server/http_request.h"
+#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -76,6 +77,48 @@
EXPECT_EQ("0", request->headers["Content-Length"]);
}
+TEST(HttpRequestTest, ParseRequestWithChunkedBody) {
+ HttpRequestParser parser;
+
+ parser.ProcessChunk("POST /foobar.html HTTP/1.1\r\n");
+ parser.ProcessChunk("Transfer-Encoding: chunked\r\n\r\n");
+ parser.ProcessChunk("5\r\nhello\r\n");
+ parser.ProcessChunk("1\r\n \r\n");
+ parser.ProcessChunk("5\r\nworld\r\n");
+ parser.ProcessChunk("0\r\n\r\n");
+ ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
+
+ scoped_ptr<HttpRequest> request = parser.GetRequest();
+ EXPECT_EQ("hello world", request->content);
+ EXPECT_TRUE(request->has_content);
+ EXPECT_EQ(1u, request->headers.count("Transfer-Encoding"));
+ EXPECT_EQ("chunked", request->headers["Transfer-Encoding"]);
+}
+
+TEST(HttpRequestTest, ParseRequestWithChunkedBodySlow) {
+ HttpRequestParser parser;
+
+ parser.ProcessChunk("POST /foobar.html HTTP/1.1\r\n");
+ parser.ProcessChunk("Transfer-Encoding: chunked\r\n\r\n");
+ std::string chunked_body = "5\r\nhello\r\n0\r\n\r\n";
+
+ // Send one character at a time, and make the parser parse the request.
+ for (size_t i = 0; i < chunked_body.size(); i++) {
+ parser.ProcessChunk(chunked_body.substr(i, 1));
+ // Except for the last pass, ParseRequest() should give WAITING.
+ if (i != chunked_body.size() - 1) {
+ ASSERT_EQ(HttpRequestParser::WAITING, parser.ParseRequest());
+ }
+ }
+ // All chunked data has been sent, the last ParseRequest should give ACCEPTED.
+ ASSERT_EQ(HttpRequestParser::ACCEPTED, parser.ParseRequest());
+ scoped_ptr<HttpRequest> request = parser.GetRequest();
+ EXPECT_EQ("hello", request->content);
+ EXPECT_TRUE(request->has_content);
+ EXPECT_EQ(1u, request->headers.count("Transfer-Encoding"));
+ EXPECT_EQ("chunked", request->headers["Transfer-Encoding"]);
+}
+
TEST(HttpRequestTest, ParseRequestWithoutBody) {
HttpRequestParser parser;
diff --git a/net/test/run_all_unittests.cc b/net/test/run_all_unittests.cc
index e86487e..d9cf354 100644
--- a/net/test/run_all_unittests.cc
+++ b/net/test/run_all_unittests.cc
@@ -27,6 +27,10 @@
#include "gin/public/isolate_holder.h"
#endif
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "third_party/mojo/src/mojo/edk/embedder/test_embedder.h"
+#endif
+
using net::internal::ClientSocketPoolBaseHelper;
using net::SpdySession;
@@ -69,6 +73,10 @@
net::ProxyResolverV8::EnsureIsolateCreated();
#endif
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ mojo::embedder::test::InitWithSimplePlatformSupport();
+#endif
+
return base::LaunchUnitTests(
argc, argv, base::Bind(&NetTestSuite::Run,
base::Unretained(&test_suite)));
diff --git a/net/third_party/nss/ssl.gyp b/net/third_party/nss/ssl.gyp
index 64d8551..1d2bab8 100644
--- a/net/third_party/nss/ssl.gyp
+++ b/net/third_party/nss/ssl.gyp
@@ -25,7 +25,9 @@
'type': '<(component)',
'product_name': 'crssl', # Don't conflict with OpenSSL's libssl
'sources': [
+ 'ssl/SSLerrs.h',
'ssl/authcert.c',
+ 'ssl/bodge/secitem_array.c',
'ssl/cmpcert.c',
'ssl/derive.c',
'ssl/dtlscon.c',
@@ -45,7 +47,6 @@
'ssl/sslenum.c',
'ssl/sslerr.c',
'ssl/sslerr.h',
- 'ssl/SSLerrs.h',
'ssl/sslerrstrs.c',
'ssl/sslgathr.c',
'ssl/sslimpl.h',
@@ -67,7 +68,6 @@
'ssl/unix_err.h',
'ssl/win32err.c',
'ssl/win32err.h',
- 'ssl/bodge/secitem_array.c',
],
'sources!': [
'ssl/os2_err.c',
diff --git a/net/third_party/nss/ssl/BUILD.gn b/net/third_party/nss/ssl/BUILD.gn
index 918e453..002bace 100644
--- a/net/third_party/nss/ssl/BUILD.gn
+++ b/net/third_party/nss/ssl/BUILD.gn
@@ -14,7 +14,9 @@
output_name = "crssl"
sources = [
+ "SSLerrs.h",
"authcert.c",
+ "bodge/secitem_array.c",
"cmpcert.c",
"derive.c",
"dtlscon.c",
@@ -32,7 +34,6 @@
"sslenum.c",
"sslerr.c",
"sslerr.h",
- "SSLerrs.h",
"sslerrstrs.c",
"sslgathr.c",
"sslimpl.h",
@@ -54,7 +55,6 @@
"unix_err.h",
"win32err.c",
"win32err.h",
- "bodge/secitem_array.c",
]
public_configs = [ ":ssl_config" ]
diff --git a/net/tools/dump_cache/cache_dumper.cc b/net/tools/dump_cache/cache_dumper.cc
index 99e3dcd..8820798 100644
--- a/net/tools/dump_cache/cache_dumper.cc
+++ b/net/tools/dump_cache/cache_dumper.cc
@@ -69,7 +69,7 @@
}
DiskDumper::DiskDumper(const base::FilePath& path)
- : path_(path), entry_(NULL) {
+ : path_(path.AsEndingWithSeparator()), entry_(NULL) {
base::CreateDirectory(path);
}
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index fa9a8e7..9e7605f 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -319,6 +319,8 @@
// and TestWriterFactory when Initialize() is executed.
client_writer_ = new PacketDroppingTestWriter();
server_writer_ = new PacketDroppingTestWriter();
+ // TODO(ianswett): Remove this once it's fully rolled out.
+ FLAGS_quic_enable_pacing = false;
}
void TearDown() override { StopServer(); }
@@ -1406,8 +1408,6 @@
// demonstrates that retransmissions do not break this functionality.
ValueRestore<bool> old_flag(&FLAGS_quic_attach_ack_notifiers_to_packets,
true);
- ValueRestore<bool> old_flag2(&FLAGS_quic_ack_notifier_informed_on_serialized,
- true);
SetPacketLossPercentage(5);
ASSERT_TRUE(Initialize());
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index 29d11bc..000a686 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -12,7 +12,6 @@
#include <unistd.h>
#include "base/logging.h"
-#include "net/quic/congestion_control/tcp_receiver.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_data_reader.h"
@@ -138,12 +137,11 @@
}
if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
- TcpReceiver::kReceiveWindowTCP)) {
+ kDefaultSocketReceiveBuffer)) {
return false;
}
- if (!QuicSocketUtils::SetSendBufferSize(fd_,
- TcpReceiver::kReceiveWindowTCP)) {
+ if (!QuicSocketUtils::SetSendBufferSize(fd_, kDefaultSocketReceiveBuffer)) {
return false;
}
diff --git a/net/tools/quic/quic_client_session.cc b/net/tools/quic/quic_client_session.cc
index 815fdfd..92eec04 100644
--- a/net/tools/quic/quic_client_session.cc
+++ b/net/tools/quic/quic_client_session.cc
@@ -16,7 +16,7 @@
QuicClientSession::QuicClientSession(const QuicConfig& config,
QuicConnection* connection)
- : QuicClientSessionBase(connection, config) {
+ : QuicClientSessionBase(connection, config), respect_goaway_(true) {
}
QuicClientSession::~QuicClientSession() {
@@ -46,7 +46,7 @@
<< "Already " << GetNumOpenStreams() << " open.";
return nullptr;
}
- if (goaway_received()) {
+ if (goaway_received() && respect_goaway_) {
DVLOG(1) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
return nullptr;
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h
index 7532552..3438a23 100644
--- a/net/tools/quic/quic_client_session.h
+++ b/net/tools/quic/quic_client_session.h
@@ -48,6 +48,10 @@
// than the number of round-trips needed for the handshake.
int GetNumSentClientHellos() const;
+ void set_respect_goaway(bool respect_goaway) {
+ respect_goaway_ = respect_goaway;
+ }
+
protected:
// QuicSession methods:
QuicDataStream* CreateIncomingDataStream(QuicStreamId id) override;
@@ -55,6 +59,10 @@
private:
scoped_ptr<QuicCryptoClientStream> crypto_stream_;
+ // If this is set to false, the client will ignore server GOAWAYs and allow
+ // the creation of streams regardless of the high chance they will fail.
+ bool respect_goaway_;
+
DISALLOW_COPY_AND_ASSIGN(QuicClientSession);
};
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc
index 1771026..8f19cf4 100644
--- a/net/tools/quic/quic_dispatcher.cc
+++ b/net/tools/quic/quic_dispatcher.cc
@@ -24,7 +24,6 @@
namespace tools {
using base::StringPiece;
-using std::make_pair;
class DeleteSessionsAlarm : public EpollAlarm {
public:
@@ -209,6 +208,13 @@
const QuicPacketPublicHeader& header) {
QuicSession* session = nullptr;
+ // Port zero is only allowed for unidirectional UDP, so is disallowed by QUIC.
+ // Given that we can't even send a reply rejecting the packet, just black hole
+ // it.
+ if (current_client_address_.port() == 0) {
+ return false;
+ }
+
QuicConnectionId connection_id = header.connection_id;
SessionMap::iterator it = session_map_.find(connection_id);
if (it == session_map_.end()) {
@@ -247,7 +253,7 @@
return HandlePacketForTimeWait(header);
}
DVLOG(1) << "Created new session for " << connection_id;
- session_map_.insert(make_pair(connection_id, session));
+ session_map_.insert(std::make_pair(connection_id, session));
} else {
session = it->second;
}
@@ -345,7 +351,7 @@
// infinite loops in OnCanWrite.
return;
}
- write_blocked_list_.insert(make_pair(blocked_writer, true));
+ write_blocked_list_.insert(std::make_pair(blocked_writer, true));
}
void QuicDispatcher::OnConnectionAddedToTimeWaitList(
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index fc1e10d..6ef1b16 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -97,12 +97,29 @@
return *session;
}
+class MockTimeWaitListManager : public QuicTimeWaitListManager {
+ public:
+ MockTimeWaitListManager(QuicPacketWriter* writer,
+ QuicServerSessionVisitor* visitor,
+ EpollServer* eps)
+ : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
+ }
+
+ MOCK_METHOD5(ProcessPacket,
+ void(const IPEndPoint& server_address,
+ const IPEndPoint& client_address,
+ QuicConnectionId connection_id,
+ QuicPacketSequenceNumber sequence_number,
+ const QuicEncryptedPacket& packet));
+};
+
class QuicDispatcherTest : public ::testing::Test {
public:
QuicDispatcherTest()
: crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance()),
dispatcher_(config_, crypto_config_, &eps_),
+ time_wait_list_manager_(nullptr),
session1_(nullptr),
session2_(nullptr) {
dispatcher_.Initialize(1);
@@ -133,11 +150,20 @@
EXPECT_EQ(data_, packet.AsStringPiece());
}
+ void CreateTimeWaitListManager() {
+ time_wait_list_manager_ = new MockTimeWaitListManager(
+ QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
+ // dispatcher takes the ownership of time_wait_list_manager.
+ QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
+ time_wait_list_manager_);
+ }
+
EpollServer eps_;
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
IPEndPoint server_address_;
TestDispatcher dispatcher_;
+ MockTimeWaitListManager* time_wait_list_manager_;
MockSession* session1_;
MockSession* session2_;
string data_;
@@ -184,28 +210,9 @@
dispatcher_.Shutdown();
}
-class MockTimeWaitListManager : public QuicTimeWaitListManager {
- public:
- MockTimeWaitListManager(QuicPacketWriter* writer,
- QuicServerSessionVisitor* visitor,
- EpollServer* eps)
- : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
- }
-
- MOCK_METHOD5(ProcessPacket, void(const IPEndPoint& server_address,
- const IPEndPoint& client_address,
- QuicConnectionId connection_id,
- QuicPacketSequenceNumber sequence_number,
- const QuicEncryptedPacket& packet));
-};
-
TEST_F(QuicDispatcherTest, TimeWaitListManager) {
- MockTimeWaitListManager* time_wait_list_manager =
- new MockTimeWaitListManager(
- QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
- // dispatcher takes the ownership of time_wait_list_manager.
- QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
- time_wait_list_manager);
+ CreateTimeWaitListManager();
+
// Create a new session.
IPEndPoint client_address(net::test::Loopback4(), 1);
QuicConnectionId connection_id = 1;
@@ -233,34 +240,44 @@
reinterpret_cast<MockConnection*>(session1_->connection()),
&MockConnection::ReallyProcessUdpPacket));
dispatcher_.ProcessPacket(IPEndPoint(), client_address, *encrypted);
- EXPECT_TRUE(time_wait_list_manager->IsConnectionIdInTimeWait(connection_id));
+ EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id));
// Dispatcher forwards subsequent packets for this connection_id to the time
// wait list manager.
- EXPECT_CALL(*time_wait_list_manager,
+ EXPECT_CALL(*time_wait_list_manager_,
ProcessPacket(_, _, connection_id, _, _)).Times(1);
ProcessPacket(client_address, connection_id, true, "foo");
}
TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
- MockTimeWaitListManager* time_wait_list_manager =
- new MockTimeWaitListManager(
- QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
- // dispatcher takes the ownership of time_wait_list_manager.
- QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
- time_wait_list_manager);
+ CreateTimeWaitListManager();
IPEndPoint client_address(net::test::Loopback4(), 1);
QuicConnectionId connection_id = 1;
// Dispatcher forwards all packets for this connection_id to the time wait
// list manager.
EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
- EXPECT_CALL(*time_wait_list_manager,
+ EXPECT_CALL(*time_wait_list_manager_,
ProcessPacket(_, _, connection_id, _, _)).Times(1);
string data = "foo";
ProcessPacket(client_address, connection_id, false, "foo");
}
+TEST_F(QuicDispatcherTest, ProcessPacketWithBogusPort) {
+ CreateTimeWaitListManager();
+
+ IPEndPoint client_address(net::test::Loopback4(), 0);
+ IPAddressNumber any4;
+ CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
+ server_address_ = IPEndPoint(any4, 5);
+
+ EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _)).Times(0);
+ ProcessPacket(client_address, 1, true, "foo");
+ EXPECT_EQ(client_address, dispatcher_.current_client_address());
+ EXPECT_EQ(server_address_, dispatcher_.current_server_address());
+}
+
class BlockingWriter : public QuicPacketWriterWrapper {
public:
BlockingWriter() : write_blocked_(false) {}
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index 7635b53..341daf8 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -12,7 +12,6 @@
#include <sys/socket.h>
#include "net/base/ip_endpoint.h"
-#include "net/quic/congestion_control/tcp_receiver.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_clock.h"
@@ -130,12 +129,11 @@
// because the default usage of QuicServer is as a test server with one or
// two clients. Adjust higher for use with many clients.
if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
- TcpReceiver::kReceiveWindowTCP)) {
+ kDefaultSocketReceiveBuffer)) {
return false;
}
- if (!QuicSocketUtils::SetSendBufferSize(fd_,
- TcpReceiver::kReceiveWindowTCP)) {
+ if (!QuicSocketUtils::SetSendBufferSize(fd_, kDefaultSocketReceiveBuffer)) {
return false;
}
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index 1cb86a5..c9e589c 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -22,7 +22,6 @@
#include "net/tools/quic/quic_server_session.h"
using base::StringPiece;
-using std::make_pair;
namespace net {
namespace tools {
@@ -127,7 +126,7 @@
version,
clock_.ApproximateNow(),
close_packet);
- connection_id_map_.insert(make_pair(connection_id, data));
+ connection_id_map_.insert(std::make_pair(connection_id, data));
if (new_connection_id) {
visitor_->OnConnectionAddedToTimeWaitList(connection_id);
}
diff --git a/net/tools/quic/quic_time_wait_list_manager_test.cc b/net/tools/quic/quic_time_wait_list_manager_test.cc
index 0bb9f82..bddcc17 100644
--- a/net/tools/quic/quic_time_wait_list_manager_test.cc
+++ b/net/tools/quic/quic_time_wait_list_manager_test.cc
@@ -152,7 +152,7 @@
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
- BuildUnsizedDataPacket(&framer_, header, frames).packet);
+ BuildUnsizedDataPacket(&framer_, header, frames));
EXPECT_TRUE(packet != nullptr);
QuicEncryptedPacket* encrypted = framer_.EncryptPacket(ENCRYPTION_NONE,
sequence_number,
diff --git a/net/tools/quic/test_tools/packet_dropping_test_writer.h b/net/tools/quic/test_tools/packet_dropping_test_writer.h
index 6dcb1b9..cdd8efc 100644
--- a/net/tools/quic/test_tools/packet_dropping_test_writer.h
+++ b/net/tools/quic/test_tools/packet_dropping_test_writer.h
@@ -85,8 +85,7 @@
fake_packet_reorder_percentage_ = fake_packet_reorder_percentage;
}
- // The percent of time WritePacket will block and set WriteResult's status
- // to WRITE_STATUS_BLOCKED.
+ // The delay before writing this packet.
void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) {
DCHECK(clock_);
base::AutoLock locked(config_mutex_);
diff --git a/net/tools/tld_cleanup/tld_cleanup.gyp b/net/tools/tld_cleanup/tld_cleanup.gyp
index c698550..dc0c45f 100644
--- a/net/tools/tld_cleanup/tld_cleanup.gyp
+++ b/net/tools/tld_cleanup/tld_cleanup.gyp
@@ -15,8 +15,8 @@
'../../../url/url.gyp:url_lib',
],
'sources': [
- 'tld_cleanup_util.h',
'tld_cleanup_util.cc',
+ 'tld_cleanup_util.h',
],
},
],
diff --git a/net/udp/udp_socket_libevent.cc b/net/udp/udp_socket_libevent.cc
index 8dd102a..6fdb94e 100644
--- a/net/udp/udp_socket_libevent.cc
+++ b/net/udp/udp_socket_libevent.cc
@@ -16,7 +16,6 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/sparse_histogram.h"
-#include "base/metrics/stats_counters.h"
#include "base/posix/eintr_wrapper.h"
#include "base/rand_util.h"
#include "net/base/io_buffer.h"
@@ -127,8 +126,7 @@
ok = write_socket_watcher_.StopWatchingFileDescriptor();
DCHECK(ok);
- if (IGNORE_EINTR(close(socket_)) < 0)
- PLOG(ERROR) << "close";
+ PCHECK(0 == IGNORE_EINTR(close(socket_)));
socket_ = kInvalidSocket;
addr_family_ = 0;
@@ -428,8 +426,6 @@
is_address_valid ? &address : NULL));
}
- base::StatsCounter read_bytes("udp.read_bytes");
- read_bytes.Add(result);
NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
}
@@ -460,8 +456,6 @@
CreateNetLogUDPDataTranferCallback(result, bytes, address));
}
- base::StatsCounter write_bytes("udp.write_bytes");
- write_bytes.Add(result);
NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result);
}
diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc
index 90ce661..928de4a 100644
--- a/net/udp/udp_socket_win.cc
+++ b/net/udp/udp_socket_win.cc
@@ -13,7 +13,6 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
-#include "base/metrics/stats_counters.h"
#include "base/profiler/scoped_tracker.h"
#include "base/rand_util.h"
#include "net/base/io_buffer.h"
@@ -699,8 +698,6 @@
CreateNetLogUDPDataTranferCallback(result, bytes, address));
}
- base::StatsCounter read_bytes("udp.read_bytes");
- read_bytes.Add(result);
NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
}
@@ -718,8 +715,6 @@
CreateNetLogUDPDataTranferCallback(result, bytes, address));
}
- base::StatsCounter write_bytes("udp.write_bytes");
- write_bytes.Add(result);
NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result);
}
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc
index 4007912..23857ad 100644
--- a/net/url_request/url_fetcher_core.cc
+++ b/net/url_request/url_fetcher_core.cc
@@ -541,6 +541,10 @@
}
void URLFetcherCore::StartOnIOThread() {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/456327 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "456327 URLFetcherCore::StartOnIOThread"));
DCHECK(network_task_runner_->BelongsToCurrentThread());
if (!response_writer_)
@@ -553,6 +557,10 @@
}
void URLFetcherCore::StartURLRequest() {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/456327 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "456327 URLFetcherCore::StartURLRequest"));
DCHECK(network_task_runner_->BelongsToCurrentThread());
if (was_cancelled_) {
@@ -669,8 +677,13 @@
DCHECK(request_context_getter_.get());
- int64 delay = INT64_C(0);
+ int64 delay = 0;
if (!original_url_throttler_entry_.get()) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/456327 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile1(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "456327 URLFetcherCore::StartURLRequestWhenAppropriate1"));
URLRequestThrottlerManager* manager =
request_context_getter_->GetURLRequestContext()->throttler_manager();
if (manager) {
@@ -679,11 +692,16 @@
}
}
if (original_url_throttler_entry_.get()) {
+ // TODO(pkasting): Remove ScopedTracker below once crbug.com/456327 is
+ // fixed.
+ tracked_objects::ScopedTracker tracking_profile2(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "456327 URLFetcherCore::StartURLRequestWhenAppropriate2"));
delay = original_url_throttler_entry_->ReserveSendingTimeForNextRequest(
GetBackoffReleaseTime());
}
- if (delay == INT64_C(0)) {
+ if (delay == 0) {
StartURLRequest();
} else {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index d7203a4..8777c06 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -12,7 +12,6 @@
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "base/message_loop/message_loop.h"
-#include "base/metrics/stats_counters.h"
#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -470,26 +469,6 @@
method_ = method;
}
-// static
-std::string URLRequest::ComputeMethodForRedirect(
- const std::string& method,
- int http_status_code) {
- // For 303 redirects, all request methods except HEAD are converted to GET,
- // as per the latest httpbis draft. The draft also allows POST requests to
- // be converted to GETs when following 301/302 redirects, for historical
- // reasons. Most major browsers do this and so shall we. Both RFC 2616 and
- // the httpbis draft say to prompt the user to confirm the generation of new
- // requests, other than GET and HEAD requests, but IE omits these prompts and
- // so shall we.
- // See: https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3
- if ((http_status_code == 303 && method != "HEAD") ||
- ((http_status_code == 301 || http_status_code == 302) &&
- method == "POST")) {
- return "GET";
- }
- return method;
-}
-
void URLRequest::SetReferrer(const std::string& referrer) {
DCHECK(!is_pending_);
GURL referrer_url(referrer);
@@ -573,8 +552,6 @@
creation_time_(base::TimeTicks::Now()),
notified_before_network_start_(false),
cookie_store_(cookie_store ? cookie_store : context->cookie_store()) {
- SIMPLE_STATS_COUNTER("URLRequestCount");
-
// Sanity check out environment.
DCHECK(base::MessageLoop::current())
<< "The current base::MessageLoop must exist";
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 20aab60..0d5b06f 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -281,12 +281,6 @@
const std::string& method() const { return method_; }
void set_method(const std::string& method);
- // Determines the new method of the request afer following a redirect.
- // |method| is the method used to arrive at the redirect,
- // |http_status_code| is the status code associated with the redirect.
- static std::string ComputeMethodForRedirect(const std::string& method,
- int http_status_code);
-
// The referrer URL for the request. This header may actually be suppressed
// from the underlying network request for security reasons (e.g., a HTTPS
// URL will not be sent as the referrer for a HTTP request). The referrer
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 4247d83..098ef85 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -9,8 +9,6 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
-#include "base/debug/alias.h"
-#include "base/debug/dump_without_crashing.h"
#include "base/file_version_info.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
@@ -209,18 +207,11 @@
base::Unretained(this))),
awaiting_callback_(false),
http_user_agent_settings_(http_user_agent_settings),
- transaction_state_(TRANSACTION_WAS_NOT_INITIALIZED),
weak_factory_(this) {
URLRequestThrottlerManager* manager = request->context()->throttler_manager();
if (manager)
throttling_entry_ = manager->RegisterRequestUrl(request->url());
- // TODO(battre) Remove this overriding once crbug.com/289715 has been
- // resolved.
- on_headers_received_callback_ =
- base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallbackForDebugging,
- weak_factory_.GetWeakPtr());
-
ResetTimer();
}
@@ -290,12 +281,6 @@
}
void URLRequestHttpJob::Kill() {
- if (awaiting_callback_) {
- // TODO(battre) crbug.com/289715
- // Simulate a crash to see who kills the job while it is waiting for a
- // callback. This should not happen, see URLRequest::OrphanJob().
- base::debug::DumpWithoutCrashing();
- }
if (!transaction_.get())
return;
@@ -422,7 +407,6 @@
DoneWithRequest(ABORTED);
transaction_.reset();
- transaction_state_ = TRANSACTION_WAS_DESTROYED;
response_info_ = NULL;
receive_headers_end_ = base::TimeTicks();
}
@@ -484,8 +468,6 @@
rv = request_->context()->http_transaction_factory()->CreateTransaction(
priority_, &transaction_);
- if (rv == OK)
- transaction_state_ = TRANSACTION_WAS_INITIALIZED;
if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
base::SupportsUserData::Data* data = request_->GetUserData(
@@ -951,19 +933,6 @@
}
}
-// TODO(battre) Use URLRequestHttpJob::OnHeadersReceivedCallback again, once
-// crbug.com/289715 has been resolved.
-// static
-void URLRequestHttpJob::OnHeadersReceivedCallbackForDebugging(
- base::WeakPtr<net::URLRequestHttpJob> job,
- int result) {
- CHECK(job.get());
- net::URLRequestHttpJob::TransactionState state = job->transaction_state_;
- base::debug::Alias(&state);
- CHECK(job->transaction_.get());
- job->OnHeadersReceivedCallback(result);
-}
-
void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
awaiting_callback_ = false;
@@ -1047,7 +1016,10 @@
if (!response_info_)
return false;
- return GetResponseHeaders()->GetMimeType(mime_type);
+ HttpResponseHeaders* headers = GetResponseHeaders();
+ if (!headers)
+ return false;
+ return headers->GetMimeType(mime_type);
}
bool URLRequestHttpJob::GetCharset(std::string* charset) {
@@ -1483,88 +1455,6 @@
}
}
-// The common type of histogram we use for all compression-tracking histograms.
-#define COMPRESSION_HISTOGRAM(name, sample) \
- do { \
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Compress." name, sample, \
- 500, 1000000, 100); \
- } while (0)
-
-void URLRequestHttpJob::RecordCompressionHistograms() {
- DCHECK(request_);
- if (!request_)
- return;
-
- if (is_cached_content_ || // Don't record cached content
- !GetStatus().is_success() || // Don't record failed content
- !IsCompressibleContent() || // Only record compressible content
- !prefilter_bytes_read()) // Zero-byte responses aren't useful.
- return;
-
- // Miniature requests aren't really compressible. Don't count them.
- const int kMinSize = 16;
- if (prefilter_bytes_read() < kMinSize)
- return;
-
- // Only record for http or https urls.
- bool is_http = request_->url().SchemeIs("http");
- bool is_https = request_->url().SchemeIs("https");
- if (!is_http && !is_https)
- return;
-
- int compressed_B = prefilter_bytes_read();
- int decompressed_B = postfilter_bytes_read();
- bool was_filtered = HasFilter();
-
- // We want to record how often downloaded resources are compressed.
- // But, we recognize that different protocols may have different
- // properties. So, for each request, we'll put it into one of 3
- // groups:
- // a) SSL resources
- // Proxies cannot tamper with compression headers with SSL.
- // b) Non-SSL, loaded-via-proxy resources
- // In this case, we know a proxy might have interfered.
- // c) Non-SSL, loaded-without-proxy resources
- // In this case, we know there was no explicit proxy. However,
- // it is possible that a transparent proxy was still interfering.
- //
- // For each group, we record the same 3 histograms.
-
- if (is_https) {
- if (was_filtered) {
- COMPRESSION_HISTOGRAM("SSL.BytesBeforeCompression", compressed_B);
- COMPRESSION_HISTOGRAM("SSL.BytesAfterCompression", decompressed_B);
- } else {
- COMPRESSION_HISTOGRAM("SSL.ShouldHaveBeenCompressed", decompressed_B);
- }
- return;
- }
-
- if (request_->was_fetched_via_proxy()) {
- if (was_filtered) {
- COMPRESSION_HISTOGRAM("Proxy.BytesBeforeCompression", compressed_B);
- COMPRESSION_HISTOGRAM("Proxy.BytesAfterCompression", decompressed_B);
- } else {
- COMPRESSION_HISTOGRAM("Proxy.ShouldHaveBeenCompressed", decompressed_B);
- }
- return;
- }
-
- if (was_filtered) {
- COMPRESSION_HISTOGRAM("NoProxy.BytesBeforeCompression", compressed_B);
- COMPRESSION_HISTOGRAM("NoProxy.BytesAfterCompression", decompressed_B);
- } else {
- COMPRESSION_HISTOGRAM("NoProxy.ShouldHaveBeenCompressed", decompressed_B);
- }
-}
-
-bool URLRequestHttpJob::IsCompressibleContent() const {
- std::string mime_type;
- return GetMimeType(&mime_type) &&
- (IsSupportedJavascriptMimeType(mime_type.c_str()) ||
- IsSupportedNonImageMimeType(mime_type.c_str()));
-}
-
void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
if (start_time_.is_null())
return;
@@ -1600,7 +1490,6 @@
RecordPerfHistograms(reason);
if (reason == FINISHED) {
request_->set_received_response_content_length(prefilter_bytes_read());
- RecordCompressionHistograms();
}
}
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index d222357..2b942fa 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -88,11 +88,6 @@
// Processes the Public-Key-Pins header, if one exists.
void ProcessPublicKeyPinsHeader();
- // TODO(battre) Remove this when crbug.com/289715 is fixed.
- static void OnHeadersReceivedCallbackForDebugging(
- base::WeakPtr<URLRequestHttpJob> job,
- int result);
-
// |result| should be net::OK, or the request is canceled.
void OnHeadersReceivedCallback(int result);
void OnStartCompleted(int result);
@@ -141,9 +136,6 @@
void UpdatePacketReadTimes() override;
void RecordPacketStats(FilterContext::StatisticSelector statistic) const;
- void RecordCompressionHistograms();
- bool IsCompressibleContent() const;
-
// Starts the transaction if extensions using the webrequest API do not
// object.
void StartTransaction();
@@ -272,14 +264,6 @@
const HttpUserAgentSettings* http_user_agent_settings_;
- // TODO(battre) Remove this when crbug.com/289715 is fixed.
- enum TransactionState {
- TRANSACTION_WAS_NOT_INITIALIZED,
- TRANSACTION_WAS_INITIALIZED,
- TRANSACTION_WAS_DESTROYED
- };
- TransactionState transaction_state_;
-
base::WeakPtrFactory<URLRequestHttpJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(URLRequestHttpJob);
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 3fae14f..6f84bab 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -21,19 +21,38 @@
#include "net/filter/filter.h"
#include "net/http/http_response_headers.h"
+namespace net {
+
namespace {
// Callback for TYPE_URL_REQUEST_FILTERS_SET net-internals event.
-base::Value* FiltersSetCallback(net::Filter* filter,
- enum net::NetLog::LogLevel /* log_level */) {
+base::Value* FiltersSetCallback(Filter* filter,
+ NetLog::LogLevel /* log_level */) {
base::DictionaryValue* event_params = new base::DictionaryValue();
event_params->SetString("filters", filter->OrderedFilterList());
return event_params;
}
-} // namespace
+std::string ComputeMethodForRedirect(const std::string& method,
+ int http_status_code) {
+ // For 303 redirects, all request methods except HEAD are converted to GET,
+ // as per the latest httpbis draft. The draft also allows POST requests to
+ // be converted to GETs when following 301/302 redirects, for historical
+ // reasons. Most major browsers do this and so shall we. Both RFC 2616 and
+ // the httpbis draft say to prompt the user to confirm the generation of new
+ // requests, other than GET and HEAD requests, but IE omits these prompts and
+ // so shall we.
+ // See:
+ // https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3
+ if ((http_status_code == 303 && method != "HEAD") ||
+ ((http_status_code == 301 || http_status_code == 302) &&
+ method == "POST")) {
+ return "GET";
+ }
+ return method;
+}
-namespace net {
+} // namespace
URLRequestJob::URLRequestJob(URLRequest* request,
NetworkDelegate* network_delegate)
@@ -907,8 +926,8 @@
redirect_info.status_code = http_status_code;
// The request method may change, depending on the status code.
- redirect_info.new_method = URLRequest::ComputeMethodForRedirect(
- request_->method(), http_status_code);
+ redirect_info.new_method =
+ ComputeMethodForRedirect(request_->method(), http_status_code);
// Move the reference fragment of the old location to the new one if the
// new one has none. This duplicates mozilla's behavior.
diff --git a/net/websockets/websocket_stream.cc b/net/websockets/websocket_stream.cc
index 002d511..b5012bc 100644
--- a/net/websockets/websocket_stream.cc
+++ b/net/websockets/websocket_stream.cc
@@ -9,6 +9,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/profiler/scoped_tracker.h"
+#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/load_flags.h"
@@ -135,6 +136,20 @@
connect_delegate_->OnSuccess(create_helper_->Upgrade());
}
+ std::string FailureMessageFromNetError() {
+ int error = url_request_->status().error();
+ if (error == ERR_TUNNEL_CONNECTION_FAILED) {
+ // This error is common and confusing, so special-case it.
+ // TODO(ricea): Include the HostPortPair of the selected proxy server in
+ // the error message. This is not currently possible because it isn't set
+ // in HttpResponseInfo when a ERR_TUNNEL_CONNECTION_FAILED error happens.
+ return "Establishing a tunnel via proxy server failed.";
+ } else {
+ return std::string("Error in connection establishment: ") +
+ ErrorToString(url_request_->status().error());
+ }
+ }
+
void ReportFailure() {
DCHECK(timer_);
timer_->Stop();
@@ -150,9 +165,7 @@
failure_message_ = "WebSocket opening handshake was canceled";
break;
case URLRequestStatus::FAILED:
- failure_message_ =
- std::string("Error in connection establishment: ") +
- ErrorToString(url_request_->status().error());
+ failure_message_ = FailureMessageFromNetError();
break;
}
}
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc
new file mode 100644
index 0000000..9b819b5
--- /dev/null
+++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -0,0 +1,503 @@
+// 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 <string>
+
+#include "base/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
+#include "net/cookies/cookie_store.h"
+#include "net/socket/socket_test_util.h"
+#include "net/websockets/websocket_stream_create_test_base.h"
+#include "net/websockets/websocket_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+namespace {
+
+using ::testing::TestWithParam;
+using ::testing::ValuesIn;
+
+const char kNoCookieHeader[] = "";
+
+class TestBase : public WebSocketStreamCreateTestBase {
+ public:
+ void CreateAndConnect(const GURL& url,
+ const std::string& origin,
+ const std::string& cookie_header,
+ const std::string& response_body) {
+ // We assume cookie_header ends with CRLF if not empty, as
+ // WebSocketStandardRequestWithCookies requires. Use AddCRLFIfNotEmpty
+ // in a call site.
+ CHECK(cookie_header.empty() || EndsWith(cookie_header, "\r\n", true));
+
+ url_request_context_host_.SetExpectations(
+ WebSocketStandardRequestWithCookies(url.path(), url.host(), origin,
+ cookie_header, std::string()),
+ response_body);
+ CreateAndConnectStream(url.spec(), NoSubProtocols(), origin, nullptr);
+ }
+
+ std::string AddCRLFIfNotEmpty(const std::string& s) {
+ return s.empty() ? s : s + "\r\n";
+ }
+};
+
+struct ClientUseCookieParameter {
+ // The URL for the WebSocket connection.
+ const char* const url;
+ // The URL for the previously set cookies.
+ const char* const cookie_url;
+ // The previously set cookies contents.
+ const char* const cookie_line;
+ // The Cookie: HTTP header expected to appear in the WS request. An empty
+ // string means there is no Cookie: header.
+ const char* const cookie_header;
+};
+
+class WebSocketStreamClientUseCookieTest
+ : public TestBase,
+ public TestWithParam<ClientUseCookieParameter> {
+ public:
+ ~WebSocketStreamClientUseCookieTest() override {
+ // Permit any endpoint locks to be released.
+ stream_request_.reset();
+ stream_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ static void SetCookieHelperFunction(const base::Closure& task,
+ base::WeakPtr<bool> weak_is_called,
+ base::WeakPtr<bool> weak_result,
+ bool success) {
+ *weak_is_called = true;
+ *weak_result = success;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
+ }
+};
+
+struct ServerSetCookieParameter {
+ // The URL for the WebSocket connection.
+ const char* const url;
+ // The URL used to query cookies after the response received.
+ const char* const cookie_url;
+ // The cookies expected to appear for |cookie_url| inquiry.
+ const char* const cookie_line;
+ // The Set-Cookie: HTTP header attached to the response.
+ const char* const cookie_header;
+};
+
+class WebSocketStreamServerSetCookieTest
+ : public TestBase,
+ public TestWithParam<ServerSetCookieParameter> {
+ public:
+ ~WebSocketStreamServerSetCookieTest() override {
+ // Permit any endpoint locks to be released.
+ stream_request_.reset();
+ stream_.reset();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ static void GetCookiesHelperFunction(const base::Closure& task,
+ base::WeakPtr<bool> weak_is_called,
+ base::WeakPtr<std::string> weak_result,
+ const std::string& cookies) {
+ *weak_is_called = true;
+ *weak_result = cookies;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task);
+ }
+};
+
+TEST_P(WebSocketStreamClientUseCookieTest, ClientUseCookie) {
+ // For wss tests.
+ ssl_data_.push_back(new SSLSocketDataProvider(ASYNC, OK));
+
+ CookieStore* store =
+ url_request_context_host_.GetURLRequestContext()->cookie_store();
+
+ const GURL url(GetParam().url);
+ const GURL cookie_url(GetParam().cookie_url);
+ const std::string origin("http://www.example.com");
+ const std::string cookie_line(GetParam().cookie_line);
+ const std::string cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header));
+
+ bool is_called = false;
+ bool set_cookie_result = false;
+ base::WeakPtrFactory<bool> weak_is_called(&is_called);
+ base::WeakPtrFactory<bool> weak_set_cookie_result(&set_cookie_result);
+
+ base::RunLoop run_loop;
+ store->SetCookieWithOptionsAsync(
+ cookie_url, cookie_line, CookieOptions(),
+ base::Bind(&SetCookieHelperFunction, run_loop.QuitClosure(),
+ weak_is_called.GetWeakPtr(),
+ weak_set_cookie_result.GetWeakPtr()));
+ run_loop.Run();
+ ASSERT_TRUE(is_called);
+ ASSERT_TRUE(set_cookie_result);
+
+ CreateAndConnect(url, origin, cookie_header, WebSocketStandardResponse(""));
+ WaitUntilConnectDone();
+ EXPECT_FALSE(has_failed());
+}
+
+TEST_P(WebSocketStreamServerSetCookieTest, ServerSetCookie) {
+ // For wss tests.
+ ssl_data_.push_back(new SSLSocketDataProvider(ASYNC, OK));
+
+ const GURL url(GetParam().url);
+ const GURL cookie_url(GetParam().cookie_url);
+ const std::string origin("http://www.example.com");
+ const std::string cookie_line(GetParam().cookie_line);
+ const std::string cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header));
+
+ const std::string response = base::StringPrintf(
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "%s"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "\r\n",
+ cookie_header.c_str());
+
+ CookieStore* store =
+ url_request_context_host_.GetURLRequestContext()->cookie_store();
+
+ CreateAndConnect(url, origin, "", response);
+ WaitUntilConnectDone();
+ EXPECT_FALSE(has_failed());
+
+ bool is_called = false;
+ std::string get_cookies_result;
+ base::WeakPtrFactory<bool> weak_is_called(&is_called);
+ base::WeakPtrFactory<std::string> weak_get_cookies_result(
+ &get_cookies_result);
+ base::RunLoop run_loop;
+ store->GetCookiesWithOptionsAsync(
+ cookie_url, CookieOptions(),
+ base::Bind(&GetCookiesHelperFunction, run_loop.QuitClosure(),
+ weak_is_called.GetWeakPtr(),
+ weak_get_cookies_result.GetWeakPtr()));
+ run_loop.Run();
+ EXPECT_TRUE(is_called);
+ EXPECT_EQ(cookie_line, get_cookies_result);
+}
+
+// Test parameters definitions follow...
+
+const ClientUseCookieParameter kClientUseCookieParameters[] = {
+ // Non-secure cookies for ws
+ {"ws://www.example.com",
+ "http://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "https://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "ws://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "wss://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ // Non-secure cookies for wss
+ {"wss://www.example.com",
+ "http://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "https://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "ws://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "wss://www.example.com",
+ "test-cookie",
+ "Cookie: test-cookie"},
+
+ // Secure-cookies for ws
+ {"ws://www.example.com",
+ "https://www.example.com",
+ "test-cookie; secure",
+ kNoCookieHeader},
+
+ {"ws://www.example.com",
+ "wss://www.example.com",
+ "test-cookie; secure",
+ kNoCookieHeader},
+
+ // Secure-cookies for wss
+ {"wss://www.example.com",
+ "https://www.example.com",
+ "test-cookie; secure",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "wss://www.example.com",
+ "test-cookie; secure",
+ "Cookie: test-cookie"},
+
+ // Non-secure cookies for ws (sharing domain)
+ {"ws://www.example.com",
+ "http://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "https://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "ws://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ // Non-secure cookies for wss (sharing domain)
+ {"wss://www.example.com",
+ "http://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "https://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "ws://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie; Domain=example.com",
+ "Cookie: test-cookie"},
+
+ // Secure-cookies for ws (sharing domain)
+ {"ws://www.example.com",
+ "https://www2.example.com",
+ "test-cookie; Domain=example.com; secure",
+ kNoCookieHeader},
+
+ {"ws://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie; Domain=example.com; secure",
+ kNoCookieHeader},
+
+ // Secure-cookies for wss (sharing domain)
+ {"wss://www.example.com",
+ "https://www2.example.com",
+ "test-cookie; Domain=example.com; secure",
+ "Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie; Domain=example.com; secure",
+ "Cookie: test-cookie"},
+
+ // Non-matching cookies for ws
+ {"ws://www.example.com",
+ "http://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+
+ {"ws://www.example.com",
+ "https://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+
+ {"ws://www.example.com",
+ "ws://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+
+ {"ws://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+
+ // Non-matching cookies for wss
+ {"wss://www.example.com",
+ "http://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+
+ {"wss://www.example.com",
+ "https://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+
+ {"wss://www.example.com",
+ "ws://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+
+ {"wss://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie",
+ kNoCookieHeader},
+};
+
+INSTANTIATE_TEST_CASE_P(WebSocketStreamClientUseCookieTest,
+ WebSocketStreamClientUseCookieTest,
+ ValuesIn(kClientUseCookieParameters));
+
+const ServerSetCookieParameter kServerSetCookieParameters[] = {
+ // Cookies coming from ws
+ {"ws://www.example.com",
+ "http://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "https://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "ws://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "wss://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ // Cookies coming from wss
+ {"wss://www.example.com",
+ "http://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "https://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "ws://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "wss://www.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie"},
+
+ // cookies coming from ws (sharing domain)
+ {"ws://www.example.com",
+ "http://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ {"ws://www.example.com",
+ "https://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ {"ws://www.example.com",
+ "ws://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ {"ws://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ // cookies coming from wss (sharing domain)
+ {"wss://www.example.com",
+ "http://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ {"wss://www.example.com",
+ "https://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ {"wss://www.example.com",
+ "ws://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ {"wss://www.example.com",
+ "wss://www2.example.com",
+ "test-cookie",
+ "Set-Cookie: test-cookie; Domain=example.com"},
+
+ // Non-matching cookies coming from ws
+ {"ws://www.example.com",
+ "http://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "https://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "ws://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+
+ {"ws://www.example.com",
+ "wss://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+
+ // Non-matching cookies coming from wss
+ {"wss://www.example.com",
+ "http://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "https://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "ws://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+
+ {"wss://www.example.com",
+ "wss://www2.example.com",
+ "",
+ "Set-Cookie: test-cookie"},
+};
+
+INSTANTIATE_TEST_CASE_P(WebSocketStreamServerSetCookieTest,
+ WebSocketStreamServerSetCookieTest,
+ ValuesIn(kServerSetCookieParameters));
+
+} // namespace
+} // namespace net
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc
new file mode 100644
index 0000000..900b1af
--- /dev/null
+++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -0,0 +1,150 @@
+// 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 "net/websockets/websocket_stream_create_test_base.h"
+
+#include "base/callback.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/websockets/websocket_basic_handshake_stream.h"
+#include "net/websockets/websocket_handshake_request_info.h"
+#include "net/websockets/websocket_handshake_response_info.h"
+#include "net/websockets/websocket_handshake_stream_create_helper.h"
+#include "net/websockets/websocket_stream.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace net {
+
+using HeaderKeyValuePair = WebSocketStreamCreateTestBase::HeaderKeyValuePair;
+
+// A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a
+// deterministic key to use in the WebSocket handshake.
+class DeterministicKeyWebSocketHandshakeStreamCreateHelper
+ : public WebSocketHandshakeStreamCreateHelper {
+ public:
+ DeterministicKeyWebSocketHandshakeStreamCreateHelper(
+ WebSocketStream::ConnectDelegate* connect_delegate,
+ const std::vector<std::string>& requested_subprotocols)
+ : WebSocketHandshakeStreamCreateHelper(connect_delegate,
+ requested_subprotocols) {}
+
+ void OnStreamCreated(WebSocketBasicHandshakeStream* stream) override {
+ stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ==");
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(
+ DeterministicKeyWebSocketHandshakeStreamCreateHelper);
+};
+
+class WebSocketStreamCreateTestBase::TestConnectDelegate
+ : public WebSocketStream::ConnectDelegate {
+ public:
+ TestConnectDelegate(WebSocketStreamCreateTestBase* owner,
+ const base::Closure& done_callback)
+ : owner_(owner), done_callback_(done_callback) {}
+
+ void OnSuccess(scoped_ptr<WebSocketStream> stream) override {
+ stream.swap(owner_->stream_);
+ done_callback_.Run();
+ }
+
+ void OnFailure(const std::string& message) override {
+ owner_->has_failed_ = true;
+ owner_->failure_message_ = message;
+ done_callback_.Run();
+ }
+
+ void OnStartOpeningHandshake(
+ scoped_ptr<WebSocketHandshakeRequestInfo> request) override {
+ // Can be called multiple times (in the case of HTTP auth). Last call
+ // wins.
+ owner_->request_info_ = request.Pass();
+ }
+
+ void OnFinishOpeningHandshake(
+ scoped_ptr<WebSocketHandshakeResponseInfo> response) override {
+ if (owner_->response_info_)
+ ADD_FAILURE();
+ owner_->response_info_ = response.Pass();
+ }
+
+ void OnSSLCertificateError(
+ scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks>
+ ssl_error_callbacks,
+ const SSLInfo& ssl_info,
+ bool fatal) override {
+ owner_->ssl_error_callbacks_ = ssl_error_callbacks.Pass();
+ owner_->ssl_info_ = ssl_info;
+ owner_->ssl_fatal_ = fatal;
+ }
+
+ private:
+ WebSocketStreamCreateTestBase* owner_;
+ base::Closure done_callback_;
+ DISALLOW_COPY_AND_ASSIGN(TestConnectDelegate);
+};
+
+WebSocketStreamCreateTestBase::WebSocketStreamCreateTestBase()
+ : has_failed_(false), ssl_fatal_(false) {
+}
+
+WebSocketStreamCreateTestBase::~WebSocketStreamCreateTestBase() {
+}
+
+void WebSocketStreamCreateTestBase::CreateAndConnectStream(
+ const std::string& socket_url,
+ const std::vector<std::string>& sub_protocols,
+ const std::string& origin,
+ scoped_ptr<base::Timer> timer) {
+ for (size_t i = 0; i < ssl_data_.size(); ++i) {
+ scoped_ptr<SSLSocketDataProvider> ssl_data(ssl_data_[i]);
+ url_request_context_host_.AddSSLSocketDataProvider(ssl_data.Pass());
+ }
+ ssl_data_.weak_clear();
+ scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate(
+ new TestConnectDelegate(this, connect_run_loop_.QuitClosure()));
+ WebSocketStream::ConnectDelegate* delegate = connect_delegate.get();
+ scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper(
+ new DeterministicKeyWebSocketHandshakeStreamCreateHelper(delegate,
+ sub_protocols));
+ stream_request_ = CreateAndConnectStreamForTesting(
+ GURL(socket_url), create_helper.Pass(), url::Origin(origin),
+ url_request_context_host_.GetURLRequestContext(), BoundNetLog(),
+ connect_delegate.Pass(),
+ timer ? timer.Pass()
+ : scoped_ptr<base::Timer>(new base::Timer(false, false)));
+}
+
+std::vector<HeaderKeyValuePair>
+WebSocketStreamCreateTestBase::RequestHeadersToVector(
+ const HttpRequestHeaders& headers) {
+ HttpRequestHeaders::Iterator it(headers);
+ std::vector<HeaderKeyValuePair> result;
+ while (it.GetNext())
+ result.push_back(HeaderKeyValuePair(it.name(), it.value()));
+ return result;
+}
+
+std::vector<HeaderKeyValuePair>
+WebSocketStreamCreateTestBase::ResponseHeadersToVector(
+ const HttpResponseHeaders& headers) {
+ void* iter = NULL;
+ std::string name, value;
+ std::vector<HeaderKeyValuePair> result;
+ while (headers.EnumerateHeaderLines(&iter, &name, &value))
+ result.push_back(HeaderKeyValuePair(name, value));
+ return result;
+}
+
+void WebSocketStreamCreateTestBase::WaitUntilConnectDone() {
+ connect_run_loop_.Run();
+}
+
+std::vector<std::string> WebSocketStreamCreateTestBase::NoSubProtocols() {
+ return std::vector<std::string>();
+}
+
+} // namespace net
diff --git a/net/websockets/websocket_stream_create_test_base.h b/net/websockets/websocket_stream_create_test_base.h
new file mode 100644
index 0000000..2388325
--- /dev/null
+++ b/net/websockets/websocket_stream_create_test_base.h
@@ -0,0 +1,87 @@
+// 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 NET_WEBSOCKETS_WEBSOCKET_STREAM_CREATE_TEST_BASE_H_
+#define NET_WEBSOCKETS_WEBSOCKET_STREAM_CREATE_TEST_BASE_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/run_loop.h"
+#include "base/timer/timer.h"
+#include "net/base/net_export.h"
+#include "net/socket/socket_test_util.h"
+#include "net/ssl/ssl_info.h"
+#include "net/websockets/websocket_event_interface.h"
+#include "net/websockets/websocket_test_util.h"
+
+namespace net {
+
+class HttpRequestHeaders;
+class HttpResponseHeaders;
+class WebSocketStream;
+class WebSocketStreamRequest;
+struct WebSocketHandshakeRequestInfo;
+struct WebSocketHandshakeResponseInfo;
+
+class WebSocketStreamCreateTestBase {
+ public:
+ using HeaderKeyValuePair = std::pair<std::string, std::string>;
+
+ WebSocketStreamCreateTestBase();
+ virtual ~WebSocketStreamCreateTestBase();
+
+ // A wrapper for CreateAndConnectStreamForTesting that knows about our default
+ // parameters.
+ void CreateAndConnectStream(const std::string& socket_url,
+ const std::vector<std::string>& sub_protocols,
+ const std::string& origin,
+ scoped_ptr<base::Timer> timer);
+
+ static std::vector<HeaderKeyValuePair> RequestHeadersToVector(
+ const HttpRequestHeaders& headers);
+ static std::vector<HeaderKeyValuePair> ResponseHeadersToVector(
+ const HttpResponseHeaders& headers);
+
+ const std::string& failure_message() const { return failure_message_; }
+ bool has_failed() const { return has_failed_; }
+
+ // Runs |connect_run_loop_|. It will stop when the connection establishes or
+ // fails.
+ void WaitUntilConnectDone();
+
+ // A simple function to make the tests more readable.
+ std::vector<std::string> NoSubProtocols();
+
+ protected:
+ WebSocketTestURLRequestContextHost url_request_context_host_;
+ scoped_ptr<WebSocketStreamRequest> stream_request_;
+ // Only set if the connection succeeded.
+ scoped_ptr<WebSocketStream> stream_;
+ // Only set if the connection failed.
+ std::string failure_message_;
+ bool has_failed_;
+ scoped_ptr<WebSocketHandshakeRequestInfo> request_info_;
+ scoped_ptr<WebSocketHandshakeResponseInfo> response_info_;
+ scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> ssl_error_callbacks_;
+ SSLInfo ssl_info_;
+ bool ssl_fatal_;
+ ScopedVector<SSLSocketDataProvider> ssl_data_;
+
+ // This temporarily sets WebSocketEndpointLockManager unlock delay to zero
+ // during tests.
+ ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_;
+ base::RunLoop connect_run_loop_;
+
+ private:
+ class TestConnectDelegate;
+ DISALLOW_COPY_AND_ASSIGN(WebSocketStreamCreateTestBase);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_STREAM_CREATE_TEST_BASE_H_
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc
index 713af37..56f2e64 100644
--- a/net/websockets/websocket_stream_test.cc
+++ b/net/websockets/websocket_stream_test.cc
@@ -22,15 +22,14 @@
#include "net/base/test_data_directory.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
+#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/socket_test_util.h"
#include "net/test/cert_test_util.h"
#include "net/url_request/url_request_test_util.h"
#include "net/websockets/websocket_basic_handshake_stream.h"
#include "net/websockets/websocket_frame.h"
-#include "net/websockets/websocket_handshake_request_info.h"
-#include "net/websockets/websocket_handshake_response_info.h"
-#include "net/websockets/websocket_handshake_stream_create_helper.h"
+#include "net/websockets/websocket_stream_create_test_base.h"
#include "net/websockets/websocket_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -39,25 +38,6 @@
namespace net {
namespace {
-typedef std::pair<std::string, std::string> HeaderKeyValuePair;
-
-std::vector<HeaderKeyValuePair> ToVector(const HttpRequestHeaders& headers) {
- HttpRequestHeaders::Iterator it(headers);
- std::vector<HeaderKeyValuePair> result;
- while (it.GetNext())
- result.push_back(HeaderKeyValuePair(it.name(), it.value()));
- return result;
-}
-
-std::vector<HeaderKeyValuePair> ToVector(const HttpResponseHeaders& headers) {
- void* iter = NULL;
- std::string name, value;
- std::vector<HeaderKeyValuePair> result;
- while (headers.EnumerateHeaderLines(&iter, &name, &value))
- result.push_back(HeaderKeyValuePair(name, value));
- return result;
-}
-
// Simple builder for a DeterministicSocketData object to save repetitive code.
// It always sets the connect data to MockConnect(SYNCHRONOUS, OK), so it cannot
// be used in tests where the connect fails. In practice, those tests never have
@@ -88,30 +68,14 @@
: MockTimer(retain_user_task, is_repeating) {}
};
-// A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a
-// deterministic key to use in the WebSocket handshake.
-class DeterministicKeyWebSocketHandshakeStreamCreateHelper
- : public WebSocketHandshakeStreamCreateHelper {
+class WebSocketStreamCreateTest : public ::testing::Test,
+ public WebSocketStreamCreateTestBase {
public:
- DeterministicKeyWebSocketHandshakeStreamCreateHelper(
- WebSocketStream::ConnectDelegate* connect_delegate,
- const std::vector<std::string>& requested_subprotocols)
- : WebSocketHandshakeStreamCreateHelper(connect_delegate,
- requested_subprotocols) {}
-
- void OnStreamCreated(WebSocketBasicHandshakeStream* stream) override {
- stream->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ==");
- }
-};
-
-class WebSocketStreamCreateTest : public ::testing::Test {
- public:
- WebSocketStreamCreateTest() : has_failed_(false), ssl_fatal_(false) {}
~WebSocketStreamCreateTest() override {
// Permit any endpoint locks to be released.
stream_request_.reset();
stream_.reset();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
void CreateAndConnectCustomResponse(
@@ -161,100 +125,6 @@
void AddRawExpectations(scoped_ptr<DeterministicSocketData> socket_data) {
url_request_context_host_.AddRawExpectations(socket_data.Pass());
}
-
- // A wrapper for CreateAndConnectStreamForTesting that knows about our default
- // parameters.
- void CreateAndConnectStream(const std::string& socket_url,
- const std::vector<std::string>& sub_protocols,
- const std::string& origin,
- scoped_ptr<base::Timer> timer) {
- for (size_t i = 0; i < ssl_data_.size(); ++i) {
- scoped_ptr<SSLSocketDataProvider> ssl_data(ssl_data_[i]);
- ssl_data_[i] = NULL;
- url_request_context_host_.AddSSLSocketDataProvider(ssl_data.Pass());
- }
- ssl_data_.clear();
- scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate(
- new TestConnectDelegate(this));
- WebSocketStream::ConnectDelegate* delegate = connect_delegate.get();
- scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper(
- new DeterministicKeyWebSocketHandshakeStreamCreateHelper(
- delegate, sub_protocols));
- stream_request_ = ::net::CreateAndConnectStreamForTesting(
- GURL(socket_url),
- create_helper.Pass(),
- url::Origin(origin),
- url_request_context_host_.GetURLRequestContext(),
- BoundNetLog(),
- connect_delegate.Pass(),
- timer ? timer.Pass() : scoped_ptr<base::Timer>(
- new base::Timer(false, false)));
- }
-
- static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
-
- // A simple function to make the tests more readable. Creates an empty vector.
- static std::vector<std::string> NoSubProtocols() {
- return std::vector<std::string>();
- }
-
- const std::string& failure_message() const { return failure_message_; }
- bool has_failed() const { return has_failed_; }
-
- class TestConnectDelegate : public WebSocketStream::ConnectDelegate {
- public:
- explicit TestConnectDelegate(WebSocketStreamCreateTest* owner)
- : owner_(owner) {}
-
- void OnSuccess(scoped_ptr<WebSocketStream> stream) override {
- stream.swap(owner_->stream_);
- }
-
- void OnFailure(const std::string& message) override {
- owner_->has_failed_ = true;
- owner_->failure_message_ = message;
- }
-
- void OnStartOpeningHandshake(
- scoped_ptr<WebSocketHandshakeRequestInfo> request) override {
- // Can be called multiple times (in the case of HTTP auth). Last call
- // wins.
- owner_->request_info_ = request.Pass();
- }
- void OnFinishOpeningHandshake(
- scoped_ptr<WebSocketHandshakeResponseInfo> response) override {
- if (owner_->response_info_)
- ADD_FAILURE();
- owner_->response_info_ = response.Pass();
- }
- void OnSSLCertificateError(
- scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks>
- ssl_error_callbacks,
- const SSLInfo& ssl_info,
- bool fatal) override {
- owner_->ssl_error_callbacks_ = ssl_error_callbacks.Pass();
- owner_->ssl_info_ = ssl_info;
- owner_->ssl_fatal_ = fatal;
- }
-
- private:
- WebSocketStreamCreateTest* owner_;
- };
-
- WebSocketTestURLRequestContextHost url_request_context_host_;
- scoped_ptr<WebSocketStreamRequest> stream_request_;
- // Only set if the connection succeeded.
- scoped_ptr<WebSocketStream> stream_;
- // Only set if the connection failed.
- std::string failure_message_;
- bool has_failed_;
- scoped_ptr<WebSocketHandshakeRequestInfo> request_info_;
- scoped_ptr<WebSocketHandshakeResponseInfo> response_info_;
- scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> ssl_error_callbacks_;
- SSLInfo ssl_info_;
- bool ssl_fatal_;
- ScopedVector<SSLSocketDataProvider> ssl_data_;
- ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_;
};
// There are enough tests of the Sec-WebSocket-Extensions header that they
@@ -270,7 +140,7 @@
"ws://localhost/testing_path", "localhost", "/testing_path",
NoSubProtocols(), "http://localhost", "",
"Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n");
- RunUntilIdle();
+ WaitUntilConnectDone();
}
};
@@ -429,7 +299,7 @@
NoSubProtocols(), "http://localhost", "", "");
EXPECT_FALSE(request_info_);
EXPECT_FALSE(response_info_);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
EXPECT_TRUE(request_info_);
@@ -452,12 +322,12 @@
kResponse);
EXPECT_FALSE(request_info_);
EXPECT_FALSE(response_info_);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(stream_);
ASSERT_TRUE(request_info_);
ASSERT_TRUE(response_info_);
std::vector<HeaderKeyValuePair> request_headers =
- ToVector(request_info_->headers);
+ RequestHeadersToVector(request_info_->headers);
// We examine the contents of request_info_ and response_info_
// mainly only in this test case.
EXPECT_EQ(GURL("ws://localhost/"), request_info_->url);
@@ -486,7 +356,7 @@
request_headers[11]);
std::vector<HeaderKeyValuePair> response_headers =
- ToVector(*response_info_->headers.get());
+ ResponseHeadersToVector(*response_info_->headers.get());
ASSERT_EQ(6u, response_headers.size());
// Sort the headers for ease of verification.
std::sort(response_headers.begin(), response_headers.end());
@@ -512,7 +382,7 @@
CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
"/testing_path", NoSubProtocols(),
"http://localhost", "", "");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
}
@@ -522,7 +392,7 @@
CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
"/testing_path", NoSubProtocols(),
"http://google.com", "", "");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
}
@@ -537,7 +407,7 @@
"Sec-WebSocket-Protocol: chatv11.chromium.org, "
"chatv20.chromium.org\r\n",
"Sec-WebSocket-Protocol: chatv20.chromium.org\r\n");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(stream_);
EXPECT_FALSE(has_failed());
EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol());
@@ -549,7 +419,7 @@
"/testing_path", NoSubProtocols(),
"http://google.com", "",
"Sec-WebSocket-Protocol: chatv20.chromium.org\r\n");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(stream_);
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
@@ -565,7 +435,7 @@
CreateAndConnectStandard("ws://localhost/testing_path", "localhost",
"/testing_path", sub_protocols, "http://localhost",
"Sec-WebSocket-Protocol: chat.example.com\r\n", "");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(stream_);
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
@@ -585,7 +455,7 @@
"chatv20.chromium.org\r\n",
"Sec-WebSocket-Protocol: chatv11.chromium.org, "
"chatv20.chromium.org\r\n");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(stream_);
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
@@ -604,7 +474,7 @@
"Sec-WebSocket-Protocol: chatv11.chromium.org, "
"chatv20.chromium.org\r\n",
"Sec-WebSocket-Protocol: chatv21.chromium.org\r\n");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(stream_);
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
@@ -642,7 +512,7 @@
"\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes)
"\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed
9));
- RunUntilIdle();
+ WaitUntilConnectDone();
ASSERT_TRUE(stream_);
ScopedVector<WebSocketFrame> frames;
@@ -819,7 +689,7 @@
CreateAndConnectStandard(
"ws://localhost/", "localhost", "/", NoSubProtocols(), "http://localhost",
"", "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(stream_);
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
@@ -839,7 +709,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kInvalidStatusCodeResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200",
failure_message());
@@ -859,7 +729,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kRedirectResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302",
failure_message());
@@ -880,7 +750,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kMalformedResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: Invalid status line",
failure_message());
@@ -896,7 +766,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kMissingUpgradeResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing",
failure_message());
@@ -907,7 +777,7 @@
CreateAndConnectStandard("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
"Upgrade: HTTP/2.0\r\n");
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
"'Upgrade' header must not appear more than once in a response",
@@ -925,7 +795,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kMissingUpgradeResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
"'Upgrade' header value is not 'WebSocket': hogefuga",
@@ -942,7 +812,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kMissingConnectionResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
"'Connection' header is missing",
@@ -960,7 +830,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kMissingConnectionResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
"'Connection' header value must contain 'Upgrade'",
@@ -978,7 +848,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kAdditionalConnectionTokenResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
}
@@ -993,7 +863,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kMissingAcceptResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
"'Sec-WebSocket-Accept' header is missing",
@@ -1011,7 +881,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kIncorrectAcceptResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error during WebSocket handshake: "
"Incorrect 'Sec-WebSocket-Accept' header value",
@@ -1023,7 +893,8 @@
CreateAndConnectStandard("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "", "");
stream_request_.reset();
- RunUntilIdle();
+ // WaitUntilConnectDone doesn't work in this case.
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(has_failed());
EXPECT_FALSE(stream_);
EXPECT_FALSE(request_info_);
@@ -1037,7 +908,7 @@
MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
"http://localhost", socket_data.Pass());
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED",
failure_message());
@@ -1052,7 +923,7 @@
MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT));
CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
"http://localhost", socket_data.Pass());
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT",
failure_message());
@@ -1074,7 +945,7 @@
EXPECT_TRUE(weak_timer->IsRunning());
weak_timer->Fire();
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("WebSocket opening handshake timed out", failure_message());
@@ -1093,7 +964,7 @@
ASSERT_TRUE(weak_timer);
EXPECT_TRUE(weak_timer->IsRunning());
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
ASSERT_TRUE(weak_timer);
@@ -1115,7 +986,7 @@
ASSERT_TRUE(weak_timer.get());
EXPECT_TRUE(weak_timer->IsRunning());
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED",
failure_message());
@@ -1132,7 +1003,8 @@
"http://localhost",
socket_data.Pass());
stream_request_.reset();
- RunUntilIdle();
+ // WaitUntilConnectDone doesn't work in this case.
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(has_failed());
EXPECT_FALSE(stream_);
}
@@ -1153,7 +1025,8 @@
make_scoped_ptr(socket_data));
socket_data->Run();
stream_request_.reset();
- RunUntilIdle();
+ // WaitUntilConnectDone doesn't work in this case.
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(has_failed());
EXPECT_FALSE(stream_);
EXPECT_TRUE(request_info_);
@@ -1178,7 +1051,8 @@
socket_data.Pass());
socket_data_raw_ptr->Run();
stream_request_.reset();
- RunUntilIdle();
+ // WaitUntilConnectDone doesn't work in this case.
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(has_failed());
EXPECT_FALSE(stream_);
EXPECT_TRUE(request_info_);
@@ -1198,7 +1072,7 @@
CreateAndConnectStandard("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
set_cookie_headers);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_FALSE(response_info_);
}
@@ -1237,12 +1111,13 @@
NoSubProtocols(),
"http://localhost",
raw_socket_data.Pass());
- RunUntilIdle();
+ // WaitUntilConnectDone doesn't work in this case.
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(has_failed());
ASSERT_TRUE(ssl_error_callbacks_);
ssl_error_callbacks_->CancelSSLRequest(ERR_CERT_AUTHORITY_INVALID,
&ssl_info_);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
}
@@ -1258,10 +1133,11 @@
url_request_context_host_.AddRawExpectations(BuildNullSocketData());
CreateAndConnectStandard("wss://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "", "");
- RunUntilIdle();
+ // WaitUntilConnectDone doesn't work in this case.
+ base::RunLoop().RunUntilIdle();
ASSERT_TRUE(ssl_error_callbacks_);
ssl_error_callbacks_->ContinueSSLRequest();
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
}
@@ -1272,7 +1148,7 @@
CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/",
NoSubProtocols(), "http://localhost", "",
kUnauthorizedResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_EQ("HTTP Authentication failed; no valid credentials available",
failure_message());
@@ -1283,7 +1159,7 @@
CreateAndConnectAuthHandshake("ws://foo:bar@localhost/",
"Zm9vOmJhcg==",
WebSocketStandardResponse(std::string()));
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
ASSERT_TRUE(response_info_);
@@ -1293,7 +1169,7 @@
TEST_F(WebSocketStreamCreateBasicAuthTest, FailureIncorrectPasswordInUrl) {
CreateAndConnectAuthHandshake(
"ws://foo:baz@localhost/", "Zm9vOmJheg==", kUnauthorizedResponse);
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
EXPECT_TRUE(response_info_);
}
@@ -1310,7 +1186,7 @@
"http://localhost",
helper_.BuildSocketData2(kAuthorizedRequest,
WebSocketStandardResponse(std::string())));
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_FALSE(has_failed());
EXPECT_TRUE(stream_);
ASSERT_TRUE(response_info_);
@@ -1347,7 +1223,7 @@
creation.CreateAndConnectStandard("ws://localhost/", "localhost", "/",
creation.NoSubProtocols(),
"http://localhost", "", "");
- creation.RunUntilIdle();
+ creation.WaitUntilConnectDone();
}
scoped_ptr<base::HistogramSamples> samples(GetSamples(name));
@@ -1375,7 +1251,7 @@
creation.CreateAndConnectCustomResponse(
"ws://localhost/", "localhost", "/", creation.NoSubProtocols(),
"http://localhost", "", kInvalidStatusCodeResponse);
- creation.RunUntilIdle();
+ creation.WaitUntilConnectDone();
}
scoped_ptr<base::HistogramSamples> samples(GetSamples(name));
@@ -1408,9 +1284,37 @@
socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
"http://localhost", socket_data.Pass());
- RunUntilIdle();
+ WaitUntilConnectDone();
EXPECT_TRUE(has_failed());
}
+TEST_F(WebSocketStreamCreateTest, HandleErrTunnelConnectionFailed) {
+ static const char kConnectRequest[] =
+ "CONNECT localhost:80 HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "Proxy-Connection: keep-alive\r\n"
+ "\r\n";
+
+ static const char kProxyResponse[] =
+ "HTTP/1.1 403 Forbidden\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 9\r\n"
+ "Connection: keep-alive\r\n"
+ "\r\n"
+ "Forbidden";
+
+ MockRead reads[] = {MockRead(SYNCHRONOUS, 1, kProxyResponse)};
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, kConnectRequest)};
+ scoped_ptr<DeterministicSocketData> socket_data(
+ BuildSocketData(reads, writes));
+ url_request_context_host_.SetProxyConfig("https=proxy:8000");
+ CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
+ "http://localhost", socket_data.Pass());
+ WaitUntilConnectDone();
+ EXPECT_TRUE(has_failed());
+ EXPECT_EQ("Establishing a tunnel via proxy server failed.",
+ failure_message());
+}
+
} // namespace
} // namespace net
diff --git a/net/websockets/websocket_test_util.cc b/net/websockets/websocket_test_util.cc
index 6091c9e..3f963bf 100644
--- a/net/websockets/websocket_test_util.cc
+++ b/net/websockets/websocket_test_util.cc
@@ -11,6 +11,7 @@
#include "base/memory/scoped_vector.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
+#include "net/proxy/proxy_service.h"
#include "net/socket/socket_test_util.h"
namespace net {
@@ -36,6 +37,16 @@
const std::string& host,
const std::string& origin,
const std::string& extra_headers) {
+ return WebSocketStandardRequestWithCookies(path, host, origin, std::string(),
+ extra_headers);
+}
+
+std::string WebSocketStandardRequestWithCookies(
+ const std::string& path,
+ const std::string& host,
+ const std::string& origin,
+ const std::string& cookies,
+ const std::string& extra_headers) {
// Unrelated changes in net/http may change the order and default-values of
// HTTP headers, causing WebSocket tests to fail. It is safe to update this
// string in that case.
@@ -51,10 +62,12 @@
"User-Agent:\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Accept-Language: en-us,fr\r\n"
+ "%s"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n"
"%s\r\n",
- path.c_str(), host.c_str(), origin.c_str(), extra_headers.c_str());
+ path.c_str(), host.c_str(), origin.c_str(), cookies.c_str(),
+ extra_headers.c_str());
}
std::string WebSocketStandardResponse(const std::string& extra_headers) {
@@ -151,6 +164,13 @@
maker_.AddSSLSocketDataProvider(ssl_socket_data.Pass());
}
+void WebSocketTestURLRequestContextHost::SetProxyConfig(
+ const std::string& proxy_rules) {
+ DCHECK(!url_request_context_initialized_);
+ proxy_service_.reset(ProxyService::CreateFixed(proxy_rules));
+ url_request_context_.set_proxy_service(proxy_service_.get());
+}
+
TestURLRequestContext*
WebSocketTestURLRequestContextHost::GetURLRequestContext() {
if (!url_request_context_initialized_) {
diff --git a/net/websockets/websocket_test_util.h b/net/websockets/websocket_test_util.h
index 5c7db80..0230f5c 100644
--- a/net/websockets/websocket_test_util.h
+++ b/net/websockets/websocket_test_util.h
@@ -27,6 +27,7 @@
class BoundNetLog;
class DeterministicMockClientSocketFactory;
class DeterministicSocketData;
+class ProxyService;
class URLRequestContext;
class WebSocketHandshakeStreamCreateHelper;
struct SSLSocketDataProvider;
@@ -44,27 +45,37 @@
// use only. The differences are the use of a |create_helper| argument in place
// of |requested_subprotocols| and taking |timer| as the handshake timeout
// timer. Implemented in websocket_stream.cc.
-NET_EXPORT_PRIVATE extern scoped_ptr<WebSocketStreamRequest>
- CreateAndConnectStreamForTesting(
- const GURL& socket_url,
- scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
- const url::Origin& origin,
- URLRequestContext* url_request_context,
- const BoundNetLog& net_log,
- scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
- scoped_ptr<base::Timer> timer);
+NET_EXPORT_PRIVATE scoped_ptr<WebSocketStreamRequest>
+CreateAndConnectStreamForTesting(
+ const GURL& socket_url,
+ scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
+ const url::Origin& origin,
+ URLRequestContext* url_request_context,
+ const BoundNetLog& net_log,
+ scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
+ scoped_ptr<base::Timer> timer);
// Generates a standard WebSocket handshake request. The challenge key used is
// "dGhlIHNhbXBsZSBub25jZQ==". Each header in |extra_headers| must be terminated
// with "\r\n".
-extern std::string WebSocketStandardRequest(const std::string& path,
- const std::string& host,
- const std::string& origin,
- const std::string& extra_headers);
+std::string WebSocketStandardRequest(const std::string& path,
+ const std::string& host,
+ const std::string& origin,
+ const std::string& extra_headers);
+
+// Generates a standard WebSocket handshake request. The challenge key used is
+// "dGhlIHNhbXBsZSBub25jZQ==". |cookies| must be empty or terminated with
+// "\r\n". Each header in |extra_headers| must be terminated with "\r\n".
+std::string WebSocketStandardRequestWithCookies(
+ const std::string& path,
+ const std::string& host,
+ const std::string& origin,
+ const std::string& cookies,
+ const std::string& extra_headers);
// A response with the appropriate accept header to match the above challenge
// key. Each header in |extra_headers| must be terminated with "\r\n".
-extern std::string WebSocketStandardResponse(const std::string& extra_headers);
+std::string WebSocketStandardResponse(const std::string& extra_headers);
// This class provides a convenient way to construct a
// DeterministicMockClientSocketFactory for WebSocket tests.
@@ -123,6 +134,12 @@
void AddSSLSocketDataProvider(
scoped_ptr<SSLSocketDataProvider> ssl_socket_data);
+ // Allow a proxy to be set. Usage:
+ // SetProxyConfig("proxy1:8000");
+ // Any syntax accepted by net::ProxyConfig::ParseFromString() will work.
+ // Do not call after GetURLRequestContext() has been called.
+ void SetProxyConfig(const std::string& proxy_rules);
+
// Call after calling one of SetExpections() or AddRawExpectations(). The
// returned pointer remains owned by this object.
TestURLRequestContext* GetURLRequestContext();
@@ -131,6 +148,7 @@
WebSocketDeterministicMockClientSocketFactoryMaker maker_;
TestURLRequestContext url_request_context_;
TestNetworkDelegate network_delegate_;
+ scoped_ptr<ProxyService> proxy_service_;
bool url_request_context_initialized_;
DISALLOW_COPY_AND_ASSIGN(WebSocketTestURLRequestContextHost);
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn
index 64940f1..8b18a3a 100644
--- a/sandbox/linux/BUILD.gn
+++ b/sandbox/linux/BUILD.gn
@@ -66,6 +66,8 @@
# The main sandboxing test target.
test("sandbox_linux_unittests") {
sources = [
+ "services/proc_util_unittest.cc",
+ "services/resource_limits_unittests.cc",
"services/scoped_process_unittest.cc",
"services/syscall_wrappers_unittest.cc",
"services/thread_helpers_unittests.cc",
@@ -101,11 +103,12 @@
}
if (use_seccomp_bpf) {
sources += [
- "bpf_dsl/bpf_dsl_more_unittest.cc",
"bpf_dsl/bpf_dsl_unittest.cc",
"bpf_dsl/codegen_unittest.cc",
"bpf_dsl/cons_unittest.cc",
"bpf_dsl/syscall_set_unittest.cc",
+ "integration_tests/bpf_dsl_seccomp_unittest.cc",
+ "integration_tests/seccomp_broker_process_unittest.cc",
"seccomp-bpf-helpers/baseline_policy_unittest.cc",
"seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc",
"seccomp-bpf/bpf_tests_unittest.cc",
@@ -116,11 +119,10 @@
}
if (compile_credentials) {
sources += [
+ "integration_tests/namespace_unix_domain_socket_unittest.cc",
"services/credentials_unittest.cc",
"services/namespace_sandbox_unittest.cc",
"services/namespace_utils_unittest.cc",
- "services/proc_util_unittest.cc",
- "services/unix_domain_socket_unittest.cc",
]
}
}
@@ -154,10 +156,12 @@
"bpf_dsl/cons.h",
"bpf_dsl/dump_bpf.cc",
"bpf_dsl/dump_bpf.h",
+ "bpf_dsl/linux_syscall_ranges.h",
"bpf_dsl/policy.cc",
"bpf_dsl/policy.h",
"bpf_dsl/policy_compiler.cc",
"bpf_dsl/policy_compiler.h",
+ "bpf_dsl/seccomp_macros.h",
"bpf_dsl/syscall_set.cc",
"bpf_dsl/syscall_set.h",
"bpf_dsl/trap_registry.h",
@@ -165,7 +169,6 @@
"seccomp-bpf/die.h",
"seccomp-bpf/errorcode.cc",
"seccomp-bpf/errorcode.h",
- "seccomp-bpf/linux_seccomp.h",
"seccomp-bpf/sandbox_bpf.cc",
"seccomp-bpf/sandbox_bpf.h",
"seccomp-bpf/syscall.cc",
@@ -230,14 +233,18 @@
sources = [
"services/init_process_reaper.cc",
"services/init_process_reaper.h",
+ "services/proc_util.cc",
+ "services/proc_util.h",
+ "services/resource_limits.cc",
+ "services/resource_limits.h",
"services/scoped_process.cc",
"services/scoped_process.h",
"services/syscall_wrappers.cc",
"services/syscall_wrappers.h",
"services/thread_helpers.cc",
"services/thread_helpers.h",
- "services/yama.h",
"services/yama.cc",
+ "services/yama.h",
"syscall_broker/broker_channel.cc",
"syscall_broker/broker_channel.h",
"syscall_broker/broker_client.cc",
@@ -263,8 +270,6 @@
"services/namespace_sandbox.h",
"services/namespace_utils.cc",
"services/namespace_utils.h",
- "services/proc_util.cc",
- "services/proc_util.h",
]
# For capabilities.cc.
@@ -278,16 +283,17 @@
source_set("sandbox_services_headers") {
sources = [
- "services/android_arm_ucontext.h",
- "services/android_arm64_ucontext.h",
- "services/android_futex.h",
- "services/android_ucontext.h",
- "services/android_i386_ucontext.h",
- "services/arm_linux_syscalls.h",
- "services/arm64_linux_syscalls.h",
- "services/linux_syscalls.h",
- "services/x86_32_linux_syscalls.h",
- "services/x86_64_linux_syscalls.h",
+ "system_headers/android_arm64_ucontext.h",
+ "system_headers/android_arm_ucontext.h",
+ "system_headers/android_futex.h",
+ "system_headers/android_i386_ucontext.h",
+ "system_headers/android_ucontext.h",
+ "system_headers/arm64_linux_syscalls.h",
+ "system_headers/arm_linux_syscalls.h",
+ "system_headers/linux_seccomp.h",
+ "system_headers/linux_syscalls.h",
+ "system_headers/x86_32_linux_syscalls.h",
+ "system_headers/x86_64_linux_syscalls.h",
]
}
diff --git a/sandbox/linux/bpf_dsl/DEPS b/sandbox/linux/bpf_dsl/DEPS
index 8333218..be37a12 100644
--- a/sandbox/linux/bpf_dsl/DEPS
+++ b/sandbox/linux/bpf_dsl/DEPS
@@ -1,6 +1,5 @@
include_rules = [
# TODO(mdempsky): Eliminate cyclic dependency on seccomp-bpf.
"+sandbox/linux/seccomp-bpf",
- "+sandbox/linux/services", # for bpf_dsl_more_unittest.cc
- "+sandbox/linux/syscall_broker", # for bpf_dsl_more_unittest.cc
+ "+sandbox/linux/system_headers",
]
diff --git a/sandbox/linux/bpf_dsl/dump_bpf.cc b/sandbox/linux/bpf_dsl/dump_bpf.cc
index 5cf53ff..82c9852 100644
--- a/sandbox/linux/bpf_dsl/dump_bpf.cc
+++ b/sandbox/linux/bpf_dsl/dump_bpf.cc
@@ -8,7 +8,7 @@
#include "sandbox/linux/bpf_dsl/codegen.h"
#include "sandbox/linux/bpf_dsl/trap_registry.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
+#include "sandbox/linux/system_headers/linux_seccomp.h"
namespace sandbox {
namespace bpf_dsl {
diff --git a/sandbox/linux/bpf_dsl/linux_syscall_ranges.h b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
new file mode 100644
index 0000000..a26a166
--- /dev/null
+++ b/sandbox/linux/bpf_dsl/linux_syscall_ranges.h
@@ -0,0 +1,55 @@
+// 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 SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_
+#define SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_
+
+#include <asm/unistd.h> // For __NR_SYSCALL_BASE
+
+#if defined(__x86_64__)
+
+#define MIN_SYSCALL 0u
+#define MAX_PUBLIC_SYSCALL 1024u
+#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
+
+#elif defined(__i386__)
+
+#define MIN_SYSCALL 0u
+#define MAX_PUBLIC_SYSCALL 1024u
+#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
+
+#elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))
+
+// ARM EABI includes "ARM private" system calls starting at |__ARM_NR_BASE|,
+// and a "ghost syscall private to the kernel", cmpxchg,
+// at |__ARM_NR_BASE+0x00fff0|.
+// See </arch/arm/include/asm/unistd.h> in the Linux kernel.
+#define MIN_SYSCALL ((unsigned int)__NR_SYSCALL_BASE)
+#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u)
+#define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE)
+#define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u)
+#define MIN_GHOST_SYSCALL ((unsigned int)__ARM_NR_BASE + 0xfff0u)
+#define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u)
+
+#elif defined(__mips__) && (_MIPS_SIM == _ABIO32)
+
+#define MIN_SYSCALL __NR_O32_Linux
+#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + __NR_Linux_syscalls)
+#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
+
+#elif defined(__mips__) && (_MIPS_SIM == _ABI64)
+
+#error "Add support to header file"
+
+#elif defined(__aarch64__)
+
+#define MIN_SYSCALL 0u
+#define MAX_PUBLIC_SYSCALL 279u
+#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
+
+#else
+#error "Unsupported architecture"
+#endif
+
+#endif // SANDBOX_LINUX_BPF_DSL_LINUX_SYSCALL_RANGES_H_
diff --git a/sandbox/linux/bpf_dsl/policy_compiler.cc b/sandbox/linux/bpf_dsl/policy_compiler.cc
index 2b72f3b..18ed7be 100644
--- a/sandbox/linux/bpf_dsl/policy_compiler.cc
+++ b/sandbox/linux/bpf_dsl/policy_compiler.cc
@@ -16,11 +16,12 @@
#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/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/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
+#include "sandbox/linux/system_headers/linux_seccomp.h"
namespace sandbox {
namespace bpf_dsl {
diff --git a/sandbox/linux/seccomp-bpf/linux_seccomp.h b/sandbox/linux/bpf_dsl/seccomp_macros.h
similarity index 73%
rename from sandbox/linux/seccomp-bpf/linux_seccomp.h
rename to sandbox/linux/bpf_dsl/seccomp_macros.h
index c13ef20..b72357a 100644
--- a/sandbox/linux/seccomp-bpf/linux_seccomp.h
+++ b/sandbox/linux/bpf_dsl/seccomp_macros.h
@@ -2,16 +2,8 @@
// 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_LINUX_SECCOMP_H__
-#define SANDBOX_LINUX_SECCOMP_BPF_LINUX_SECCOMP_H__
-
-// The Seccomp2 kernel ABI is not part of older versions of glibc.
-// As we can't break compilation with these versions of the library,
-// we explicitly define all missing symbols.
-// If we ever decide that we can now rely on system headers, the following
-// include files should be enabled:
-// #include <linux/audit.h>
-// #include <linux/seccomp.h>
+#ifndef SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_
+#define SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_
#include <asm/unistd.h>
#include <linux/filter.h>
@@ -29,113 +21,12 @@
#endif
#endif
-// For audit.h
-#ifndef EM_ARM
-#define EM_ARM 40
-#endif
-#ifndef EM_386
-#define EM_386 3
-#endif
-#ifndef EM_X86_64
-#define EM_X86_64 62
-#endif
-#ifndef EM_MIPS
-#define EM_MIPS 8
-#endif
-#ifndef EM_AARCH64
-#define EM_AARCH64 183
-#endif
-
-#ifndef __AUDIT_ARCH_64BIT
-#define __AUDIT_ARCH_64BIT 0x80000000
-#endif
-#ifndef __AUDIT_ARCH_LE
-#define __AUDIT_ARCH_LE 0x40000000
-#endif
-#ifndef AUDIT_ARCH_ARM
-#define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE)
-#endif
-#ifndef AUDIT_ARCH_I386
-#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
-#endif
-#ifndef AUDIT_ARCH_X86_64
-#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
-#endif
-#ifndef AUDIT_ARCH_MIPSEL
-#define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE)
-#endif
-#ifndef AUDIT_ARCH_AARCH64
-#define AUDIT_ARCH_AARCH64 (EM_AARCH64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
-#endif
-
-// For prctl.h
-#ifndef PR_SET_SECCOMP
-#define PR_SET_SECCOMP 22
-#define PR_GET_SECCOMP 21
-#endif
-#ifndef PR_SET_NO_NEW_PRIVS
-#define PR_SET_NO_NEW_PRIVS 38
-#define PR_GET_NO_NEW_PRIVS 39
-#endif
-#ifndef IPC_64
-#define IPC_64 0x0100
-#endif
-
-#ifndef BPF_MOD
-#define BPF_MOD 0x90
-#endif
-#ifndef BPF_XOR
-#define BPF_XOR 0xA0
-#endif
-
-// In order to build will older tool chains, we currently have to avoid
-// including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on
-// our own definitions of the seccomp kernel ABI.
-#ifndef SECCOMP_MODE_FILTER
-#define SECCOMP_MODE_DISABLED 0
-#define SECCOMP_MODE_STRICT 1
-#define SECCOMP_MODE_FILTER 2 // User user-supplied filter
-#endif
-
-#ifndef SECCOMP_SET_MODE_STRICT
-#define SECCOMP_SET_MODE_STRICT 0
-#endif
-#ifndef SECCOMP_SET_MODE_FILTER
-#define SECCOMP_SET_MODE_FILTER 1
-#endif
-#ifndef SECCOMP_FILTER_FLAG_TSYNC
-#define SECCOMP_FILTER_FLAG_TSYNC 1
-#endif
-
-#ifndef SECCOMP_RET_KILL
-// Return values supported for BPF filter programs. Please note that the
-// "illegal" SECCOMP_RET_INVALID is not supported by the kernel, should only
-// ever be used internally, and would result in the kernel killing our process.
-#define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately
-#define SECCOMP_RET_INVALID 0x00010000U // Illegal return value
-#define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS
-#define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno
-#define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow
-#define SECCOMP_RET_ALLOW 0x7fff0000U // Allow
-#define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value
-#define SECCOMP_RET_DATA 0x0000ffffU // sections
-#else
-#define SECCOMP_RET_INVALID 0x00010000U // Illegal return value
-#endif
-
-#ifndef SYS_SECCOMP
-#define SYS_SECCOMP 1
-#endif
-
// 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.
#define SECCOMP_MAX_PROGRAM_SIZE (1<<30)
#if defined(__i386__)
-#define MIN_SYSCALL 0u
-#define MAX_PUBLIC_SYSCALL 1024u
-#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
#define SECCOMP_ARCH AUDIT_ARCH_I386
#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)])
@@ -198,9 +89,6 @@
#define SECCOMP_PT_PARM6(_regs) (_regs).ebp
#elif defined(__x86_64__)
-#define MIN_SYSCALL 0u
-#define MAX_PUBLIC_SYSCALL 1024u
-#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
#define SECCOMP_ARCH AUDIT_ARCH_X86_64
#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.gregs[(_reg)])
@@ -236,17 +124,6 @@
#define SECCOMP_PT_PARM6(_regs) (_regs).r9
#elif defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))
-// ARM EABI includes "ARM private" system calls starting at |__ARM_NR_BASE|,
-// and a "ghost syscall private to the kernel", cmpxchg,
-// at |__ARM_NR_BASE+0x00fff0|.
-// See </arch/arm/include/asm/unistd.h> in the Linux kernel.
-#define MIN_SYSCALL ((unsigned int)__NR_SYSCALL_BASE)
-#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + 1024u)
-#define MIN_PRIVATE_SYSCALL ((unsigned int)__ARM_NR_BASE)
-#define MAX_PRIVATE_SYSCALL (MIN_PRIVATE_SYSCALL + 16u)
-#define MIN_GHOST_SYSCALL ((unsigned int)__ARM_NR_BASE + 0xfff0u)
-#define MAX_SYSCALL (MIN_GHOST_SYSCALL + 4u)
-
#define SECCOMP_ARCH AUDIT_ARCH_ARM
// ARM sigcontext_t is different from i386/x86_64.
@@ -314,9 +191,6 @@
#define SECCOMP_PT_PARM6(_regs) (_regs).REG_r5
#elif defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)
-#define MIN_SYSCALL __NR_O32_Linux
-#define MAX_PUBLIC_SYSCALL (MIN_SYSCALL + __NR_Linux_syscalls)
-#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
#define SECCOMP_ARCH AUDIT_ARCH_MIPSEL
#define SYSCALL_EIGHT_ARGS
// MIPS sigcontext_t is different from i386/x86_64 and ARM.
@@ -378,9 +252,6 @@
unsigned long long pstate;
};
-#define MIN_SYSCALL 0u
-#define MAX_PUBLIC_SYSCALL 279u
-#define MAX_SYSCALL MAX_PUBLIC_SYSCALL
#define SECCOMP_ARCH AUDIT_ARCH_AARCH64
#define SECCOMP_REG(_ctx, _reg) ((_ctx)->uc_mcontext.regs[_reg])
@@ -420,4 +291,4 @@
#endif
-#endif // SANDBOX_LINUX_SECCOMP_BPF_LINUX_SECCOMP_H__
+#endif // SANDBOX_LINUX_BPF_DSL_SECCOMP_MACROS_H_
diff --git a/sandbox/linux/bpf_dsl/syscall_set.cc b/sandbox/linux/bpf_dsl/syscall_set.cc
index 22d6046..47810e9 100644
--- a/sandbox/linux/bpf_dsl/syscall_set.cc
+++ b/sandbox/linux/bpf_dsl/syscall_set.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
+#include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h"
namespace sandbox {
diff --git a/sandbox/linux/bpf_dsl/syscall_set_unittest.cc b/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
index 5730dc4..fafb6f6 100644
--- a/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
+++ b/sandbox/linux/bpf_dsl/syscall_set_unittest.cc
@@ -6,7 +6,7 @@
#include <stdint.h>
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
+#include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h"
#include "sandbox/linux/tests/unit_tests.h"
namespace sandbox {
diff --git a/sandbox/linux/integration_tests/DEPS b/sandbox/linux/integration_tests/DEPS
new file mode 100644
index 0000000..d50729c
--- /dev/null
+++ b/sandbox/linux/integration_tests/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ "+sandbox/linux/bpf_dsl",
+ "+sandbox/linux/seccomp-bpf",
+ "+sandbox/linux/services",
+ "+sandbox/linux/syscall_broker",
+ "+sandbox/linux/system_headers",
+]
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
similarity index 93%
rename from sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
rename to sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
index 40a99e4..2d337c6 100644
--- a/sandbox/linux/bpf_dsl/bpf_dsl_more_unittest.cc
+++ b/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
@@ -1,9 +1,7 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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 "sandbox/linux/bpf_dsl/bpf_dsl.h"
-
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
@@ -33,18 +31,19 @@
#include "base/sys_info.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+#include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h"
#include "sandbox/linux/bpf_dsl/policy.h"
+#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/die.h"
#include "sandbox/linux/seccomp-bpf/errorcode.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
#include "sandbox/linux/seccomp-bpf/trap.h"
-#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/syscall_wrappers.h"
-#include "sandbox/linux/syscall_broker/broker_file_permission.h"
-#include "sandbox/linux/syscall_broker/broker_process.h"
+#include "sandbox/linux/services/thread_helpers.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/tests/scoped_temporary_file.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -733,149 +732,6 @@
BPF_ASSERT(errno == 0);
}
-bool NoOpCallback() {
- return true;
-}
-
-// Test a trap handler that makes use of a broker process to open().
-
-class InitializedOpenBroker {
- public:
- InitializedOpenBroker() : initialized_(false) {
- std::vector<syscall_broker::BrokerFilePermission> permissions;
- permissions.push_back(
- syscall_broker::BrokerFilePermission::ReadOnly("/proc/allowed"));
- permissions.push_back(
- syscall_broker::BrokerFilePermission::ReadOnly("/proc/cpuinfo"));
-
- broker_process_.reset(
- new syscall_broker::BrokerProcess(EPERM, permissions));
- BPF_ASSERT(broker_process() != NULL);
- BPF_ASSERT(broker_process_->Init(base::Bind(&NoOpCallback)));
-
- initialized_ = true;
- }
- bool initialized() { return initialized_; }
- class syscall_broker::BrokerProcess* broker_process() {
- return broker_process_.get();
- }
-
- private:
- bool initialized_;
- scoped_ptr<class syscall_broker::BrokerProcess> broker_process_;
- DISALLOW_COPY_AND_ASSIGN(InitializedOpenBroker);
-};
-
-intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args,
- void* aux) {
- BPF_ASSERT(aux);
- syscall_broker::BrokerProcess* broker_process =
- static_cast<syscall_broker::BrokerProcess*>(aux);
- switch (args.nr) {
- case __NR_faccessat: // access is a wrapper of faccessat in android
- BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD);
- return broker_process->Access(reinterpret_cast<const char*>(args.args[1]),
- static_cast<int>(args.args[2]));
-#if defined(__NR_access)
- case __NR_access:
- return broker_process->Access(reinterpret_cast<const char*>(args.args[0]),
- static_cast<int>(args.args[1]));
-#endif
-#if defined(__NR_open)
- case __NR_open:
- return broker_process->Open(reinterpret_cast<const char*>(args.args[0]),
- static_cast<int>(args.args[1]));
-#endif
- case __NR_openat:
- // We only call open() so if we arrive here, it's because glibc uses
- // the openat() system call.
- BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD);
- return broker_process->Open(reinterpret_cast<const char*>(args.args[1]),
- static_cast<int>(args.args[2]));
- default:
- BPF_ASSERT(false);
- return -ENOSYS;
- }
-}
-
-class DenyOpenPolicy : public Policy {
- public:
- explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {}
- ~DenyOpenPolicy() override {}
-
- ResultExpr EvaluateSyscall(int sysno) const override {
- DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
-
- switch (sysno) {
- case __NR_faccessat:
-#if defined(__NR_access)
- case __NR_access:
-#endif
-#if defined(__NR_open)
- case __NR_open:
-#endif
- case __NR_openat:
- // We get a InitializedOpenBroker class, but our trap handler wants
- // the syscall_broker::BrokerProcess object.
- return Trap(BrokerOpenTrapHandler, iob_->broker_process());
- default:
- return Allow();
- }
- }
-
- private:
- InitializedOpenBroker* iob_;
-
- DISALLOW_COPY_AND_ASSIGN(DenyOpenPolicy);
-};
-
-// We use a InitializedOpenBroker class, so that we can run unsandboxed
-// code in its constructor, which is the only way to do so in a BPF_TEST.
-BPF_TEST(SandboxBPF,
- UseOpenBroker,
- DenyOpenPolicy,
- InitializedOpenBroker /* (*BPF_AUX) */) {
- BPF_ASSERT(BPF_AUX->initialized());
- syscall_broker::BrokerProcess* broker_process = BPF_AUX->broker_process();
- BPF_ASSERT(broker_process != NULL);
-
- // First, use the broker "manually"
- BPF_ASSERT(broker_process->Open("/proc/denied", O_RDONLY) == -EPERM);
- BPF_ASSERT(broker_process->Access("/proc/denied", R_OK) == -EPERM);
- BPF_ASSERT(broker_process->Open("/proc/allowed", O_RDONLY) == -ENOENT);
- BPF_ASSERT(broker_process->Access("/proc/allowed", R_OK) == -ENOENT);
-
- // Now use glibc's open() as an external library would.
- BPF_ASSERT(open("/proc/denied", O_RDONLY) == -1);
- BPF_ASSERT(errno == EPERM);
-
- BPF_ASSERT(open("/proc/allowed", O_RDONLY) == -1);
- BPF_ASSERT(errno == ENOENT);
-
- // Also test glibc's openat(), some versions of libc use it transparently
- // instead of open().
- BPF_ASSERT(openat(AT_FDCWD, "/proc/denied", O_RDONLY) == -1);
- BPF_ASSERT(errno == EPERM);
-
- BPF_ASSERT(openat(AT_FDCWD, "/proc/allowed", O_RDONLY) == -1);
- BPF_ASSERT(errno == ENOENT);
-
- // And test glibc's access().
- BPF_ASSERT(access("/proc/denied", R_OK) == -1);
- BPF_ASSERT(errno == EPERM);
-
- BPF_ASSERT(access("/proc/allowed", R_OK) == -1);
- BPF_ASSERT(errno == ENOENT);
-
- // This is also white listed and does exist.
- int cpu_info_access = access("/proc/cpuinfo", R_OK);
- BPF_ASSERT(cpu_info_access == 0);
- int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY);
- BPF_ASSERT(cpu_info_fd >= 0);
- char buf[1024];
- BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0);
-}
-
// Simple test demonstrating how to use SandboxBPF::Cond()
class SimpleCondTestPolicy : public Policy {
@@ -2308,7 +2164,8 @@
SANDBOX_DEATH_TEST(
SandboxBPF,
StartMultiThreadedAsSingleThreaded,
- DEATH_MESSAGE("Cannot start sandbox; process is already multi-threaded")) {
+ DEATH_MESSAGE(
+ ThreadHelpers::GetAssertSingleThreadedErrorMessageForTests())) {
base::Thread thread("sandbox.linux.StartMultiThreadedAsSingleThreaded");
BPF_ASSERT(thread.Start());
diff --git a/sandbox/linux/services/unix_domain_socket_unittest.cc b/sandbox/linux/integration_tests/namespace_unix_domain_socket_unittest.cc
similarity index 100%
rename from sandbox/linux/services/unix_domain_socket_unittest.cc
rename to sandbox/linux/integration_tests/namespace_unix_domain_socket_unittest.cc
diff --git a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
new file mode 100644
index 0000000..9aa3209
--- /dev/null
+++ b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
@@ -0,0 +1,180 @@
+// 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/posix/eintr_wrapper.h"
+#include "build/build_config.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+#include "sandbox/linux/bpf_dsl/policy.h"
+#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
+#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
+#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/syscall_broker/broker_file_permission.h"
+#include "sandbox/linux/syscall_broker/broker_process.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
+#include "sandbox/linux/tests/unit_tests.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+namespace {
+
+using bpf_dsl::Allow;
+using bpf_dsl::ResultExpr;
+using bpf_dsl::Trap;
+
+bool NoOpCallback() {
+ return true;
+}
+
+// Test a trap handler that makes use of a broker process to open().
+
+class InitializedOpenBroker {
+ public:
+ InitializedOpenBroker() : initialized_(false) {
+ std::vector<syscall_broker::BrokerFilePermission> permissions;
+ permissions.push_back(
+ syscall_broker::BrokerFilePermission::ReadOnly("/proc/allowed"));
+ permissions.push_back(
+ syscall_broker::BrokerFilePermission::ReadOnly("/proc/cpuinfo"));
+
+ broker_process_.reset(
+ new syscall_broker::BrokerProcess(EPERM, permissions));
+ BPF_ASSERT(broker_process() != NULL);
+ BPF_ASSERT(broker_process_->Init(base::Bind(&NoOpCallback)));
+
+ initialized_ = true;
+ }
+ bool initialized() { return initialized_; }
+ class syscall_broker::BrokerProcess* broker_process() {
+ return broker_process_.get();
+ }
+
+ private:
+ bool initialized_;
+ scoped_ptr<class syscall_broker::BrokerProcess> broker_process_;
+ DISALLOW_COPY_AND_ASSIGN(InitializedOpenBroker);
+};
+
+intptr_t BrokerOpenTrapHandler(const struct arch_seccomp_data& args,
+ void* aux) {
+ BPF_ASSERT(aux);
+ syscall_broker::BrokerProcess* broker_process =
+ static_cast<syscall_broker::BrokerProcess*>(aux);
+ switch (args.nr) {
+ case __NR_faccessat: // access is a wrapper of faccessat in android
+ BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD);
+ return broker_process->Access(reinterpret_cast<const char*>(args.args[1]),
+ static_cast<int>(args.args[2]));
+#if defined(__NR_access)
+ case __NR_access:
+ return broker_process->Access(reinterpret_cast<const char*>(args.args[0]),
+ static_cast<int>(args.args[1]));
+#endif
+#if defined(__NR_open)
+ case __NR_open:
+ return broker_process->Open(reinterpret_cast<const char*>(args.args[0]),
+ static_cast<int>(args.args[1]));
+#endif
+ case __NR_openat:
+ // We only call open() so if we arrive here, it's because glibc uses
+ // the openat() system call.
+ BPF_ASSERT(static_cast<int>(args.args[0]) == AT_FDCWD);
+ return broker_process->Open(reinterpret_cast<const char*>(args.args[1]),
+ static_cast<int>(args.args[2]));
+ default:
+ BPF_ASSERT(false);
+ return -ENOSYS;
+ }
+}
+
+class DenyOpenPolicy : public bpf_dsl::Policy {
+ public:
+ explicit DenyOpenPolicy(InitializedOpenBroker* iob) : iob_(iob) {}
+ ~DenyOpenPolicy() override {}
+
+ ResultExpr EvaluateSyscall(int sysno) const override {
+ DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
+
+ switch (sysno) {
+ case __NR_faccessat:
+#if defined(__NR_access)
+ case __NR_access:
+#endif
+#if defined(__NR_open)
+ case __NR_open:
+#endif
+ case __NR_openat:
+ // We get a InitializedOpenBroker class, but our trap handler wants
+ // the syscall_broker::BrokerProcess object.
+ return Trap(BrokerOpenTrapHandler, iob_->broker_process());
+ default:
+ return Allow();
+ }
+ }
+
+ private:
+ InitializedOpenBroker* iob_;
+
+ DISALLOW_COPY_AND_ASSIGN(DenyOpenPolicy);
+};
+
+// We use a InitializedOpenBroker class, so that we can run unsandboxed
+// code in its constructor, which is the only way to do so in a BPF_TEST.
+BPF_TEST(SandboxBPF,
+ UseOpenBroker,
+ DenyOpenPolicy,
+ InitializedOpenBroker /* (*BPF_AUX) */) {
+ BPF_ASSERT(BPF_AUX->initialized());
+ syscall_broker::BrokerProcess* broker_process = BPF_AUX->broker_process();
+ BPF_ASSERT(broker_process != NULL);
+
+ // First, use the broker "manually"
+ BPF_ASSERT(broker_process->Open("/proc/denied", O_RDONLY) == -EPERM);
+ BPF_ASSERT(broker_process->Access("/proc/denied", R_OK) == -EPERM);
+ BPF_ASSERT(broker_process->Open("/proc/allowed", O_RDONLY) == -ENOENT);
+ BPF_ASSERT(broker_process->Access("/proc/allowed", R_OK) == -ENOENT);
+
+ // Now use glibc's open() as an external library would.
+ BPF_ASSERT(open("/proc/denied", O_RDONLY) == -1);
+ BPF_ASSERT(errno == EPERM);
+
+ BPF_ASSERT(open("/proc/allowed", O_RDONLY) == -1);
+ BPF_ASSERT(errno == ENOENT);
+
+ // Also test glibc's openat(), some versions of libc use it transparently
+ // instead of open().
+ BPF_ASSERT(openat(AT_FDCWD, "/proc/denied", O_RDONLY) == -1);
+ BPF_ASSERT(errno == EPERM);
+
+ BPF_ASSERT(openat(AT_FDCWD, "/proc/allowed", O_RDONLY) == -1);
+ BPF_ASSERT(errno == ENOENT);
+
+ // And test glibc's access().
+ BPF_ASSERT(access("/proc/denied", R_OK) == -1);
+ BPF_ASSERT(errno == EPERM);
+
+ BPF_ASSERT(access("/proc/allowed", R_OK) == -1);
+ BPF_ASSERT(errno == ENOENT);
+
+ // This is also white listed and does exist.
+ int cpu_info_access = access("/proc/cpuinfo", R_OK);
+ BPF_ASSERT(cpu_info_access == 0);
+ int cpu_info_fd = open("/proc/cpuinfo", O_RDONLY);
+ BPF_ASSERT(cpu_info_fd >= 0);
+ char buf[1024];
+ BPF_ASSERT(read(cpu_info_fd, buf, sizeof(buf)) > 0);
+}
+
+} // namespace
+
+} // namespace sandbox
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi
index c03b024..a623971 100644
--- a/sandbox/linux/sandbox_linux.gypi
+++ b/sandbox/linux/sandbox_linux.gypi
@@ -127,10 +127,13 @@
'bpf_dsl/cons.h',
'bpf_dsl/dump_bpf.cc',
'bpf_dsl/dump_bpf.h',
+ 'bpf_dsl/linux_syscall_ranges.h',
'bpf_dsl/policy.cc',
'bpf_dsl/policy.h',
'bpf_dsl/policy_compiler.cc',
'bpf_dsl/policy_compiler.h',
+ 'bpf_dsl/seccomp_macros.h',
+ 'bpf_dsl/seccomp_macros.h',
'bpf_dsl/syscall_set.cc',
'bpf_dsl/syscall_set.h',
'bpf_dsl/trap_registry.h',
@@ -138,7 +141,6 @@
'seccomp-bpf/die.h',
'seccomp-bpf/errorcode.cc',
'seccomp-bpf/errorcode.h',
- 'seccomp-bpf/linux_seccomp.h',
'seccomp-bpf/sandbox_bpf.cc',
'seccomp-bpf/sandbox_bpf.h',
'seccomp-bpf/syscall.cc',
@@ -221,6 +223,10 @@
'sources': [
'services/init_process_reaper.cc',
'services/init_process_reaper.h',
+ 'services/proc_util.cc',
+ 'services/proc_util.h',
+ 'services/resource_limits.cc',
+ 'services/resource_limits.h',
'services/scoped_process.cc',
'services/scoped_process.h',
'services/syscall_wrappers.cc',
@@ -258,8 +264,6 @@
'services/namespace_sandbox.h',
'services/namespace_utils.cc',
'services/namespace_utils.h',
- 'services/proc_util.cc',
- 'services/proc_util.h',
],
'dependencies': [
# for capabilities.cc.
@@ -274,18 +278,19 @@
{ 'target_name': 'sandbox_services_headers',
'type': 'none',
'sources': [
- 'services/android_arm_ucontext.h',
- 'services/android_arm64_ucontext.h',
- 'services/android_futex.h',
- 'services/android_ucontext.h',
- 'services/android_i386_ucontext.h',
- 'services/android_mips_ucontext.h',
- 'services/arm_linux_syscalls.h',
- 'services/arm64_linux_syscalls.h',
- 'services/mips_linux_syscalls.h',
- 'services/linux_syscalls.h',
- 'services/x86_32_linux_syscalls.h',
- 'services/x86_64_linux_syscalls.h',
+ 'system_headers/android_arm64_ucontext.h',
+ 'system_headers/android_arm_ucontext.h',
+ 'system_headers/android_futex.h',
+ 'system_headers/android_i386_ucontext.h',
+ 'system_headers/android_mips_ucontext.h',
+ 'system_headers/android_ucontext.h',
+ 'system_headers/arm64_linux_syscalls.h',
+ 'system_headers/arm_linux_syscalls.h',
+ 'system_headers/linux_seccomp.h',
+ 'system_headers/linux_syscalls.h',
+ 'system_headers/mips_linux_syscalls.h',
+ 'system_headers/x86_32_linux_syscalls.h',
+ 'system_headers/x86_64_linux_syscalls.h',
],
'include_dirs': [
'..',
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi
index eef29db..db039ed 100644
--- a/sandbox/linux/sandbox_linux_test_sources.gypi
+++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -17,7 +17,9 @@
'../..',
],
'sources': [
+ 'services/proc_util_unittest.cc',
'services/scoped_process_unittest.cc',
+ 'services/resource_limits_unittests.cc',
'services/syscall_wrappers_unittest.cc',
'services/thread_helpers_unittests.cc',
'services/yama_unittests.cc',
@@ -39,11 +41,12 @@
}],
[ 'use_seccomp_bpf==1', {
'sources': [
- 'bpf_dsl/bpf_dsl_more_unittest.cc',
'bpf_dsl/bpf_dsl_unittest.cc',
'bpf_dsl/codegen_unittest.cc',
'bpf_dsl/cons_unittest.cc',
'bpf_dsl/syscall_set_unittest.cc',
+ 'integration_tests/bpf_dsl_seccomp_unittest.cc',
+ 'integration_tests/seccomp_broker_process_unittest.cc',
'seccomp-bpf-helpers/baseline_policy_unittest.cc',
'seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc',
'seccomp-bpf/bpf_tests_unittest.cc',
@@ -54,11 +57,10 @@
}],
[ 'compile_credentials==1', {
'sources': [
+ 'integration_tests/namespace_unix_domain_socket_unittest.cc',
'services/credentials_unittest.cc',
'services/namespace_sandbox_unittest.cc',
'services/namespace_utils_unittest.cc',
- 'services/proc_util_unittest.cc',
- 'services/unix_domain_socket_unittest.cc',
],
}],
],
diff --git a/sandbox/linux/seccomp-bpf-helpers/DEPS b/sandbox/linux/seccomp-bpf-helpers/DEPS
index 01e1fe2..4419fd1 100644
--- a/sandbox/linux/seccomp-bpf-helpers/DEPS
+++ b/sandbox/linux/seccomp-bpf-helpers/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+sandbox/linux/bpf_dsl",
- "+sandbox/linux/services",
"+sandbox/linux/seccomp-bpf",
+ "+sandbox/linux/services",
+ "+sandbox/linux/system_headers",
"+third_party/lss/linux_syscall_support.h",
]
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index afa74cb..8c679a3 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -18,8 +18,8 @@
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/syscall_wrappers.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
// Changing this implementation will have an effect on *all* policies.
// Currently this means: Renderer/Worker, GPU, Flash and NaCl.
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index 4955dfb..e6e8934 100644
--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -30,10 +30,10 @@
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
-#include "sandbox/linux/services/android_futex.h"
-#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/services/thread_helpers.h"
+#include "sandbox/linux/system_headers/android_futex.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/tests/test_utils.h"
#include "sandbox/linux/tests/unit_tests.h"
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
index 42be00b..21fd4d7 100644
--- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc
@@ -16,8 +16,8 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
-#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/syscall_wrappers.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
#if defined(__mips__)
// __NR_Linux, is defined in <asm/unistd.h>.
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 64a6bb0..c081b29 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -27,14 +27,14 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
#if defined(OS_ANDROID)
-#include "sandbox/linux/services/android_futex.h"
+#include "sandbox/linux/system_headers/android_futex.h"
#if !defined(F_DUPFD_CLOEXEC)
#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
index e374ed2..e653b8a 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
@@ -24,8 +24,8 @@
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
-#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/syscall_wrappers.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/tests/unit_tests.h"
#if !defined(OS_ANDROID)
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
index 640be69..c217d47 100644
--- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
@@ -5,7 +5,7 @@
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "build/build_config.h"
-#include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/DEPS b/sandbox/linux/seccomp-bpf/DEPS
index 7fef15f..149c463 100644
--- a/sandbox/linux/seccomp-bpf/DEPS
+++ b/sandbox/linux/seccomp-bpf/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+sandbox/linux/bpf_dsl",
"+sandbox/linux/services",
+ "+sandbox/linux/system_headers",
]
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
index 9727d28..63e1814 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/bpf_tests_unittest.cc
@@ -16,8 +16,8 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/syscall_wrappers.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/sandbox/linux/seccomp-bpf/errorcode.cc b/sandbox/linux/seccomp-bpf/errorcode.cc
index ebae130..9bb3ddb 100644
--- a/sandbox/linux/seccomp-bpf/errorcode.cc
+++ b/sandbox/linux/seccomp-bpf/errorcode.cc
@@ -5,7 +5,7 @@
#include "sandbox/linux/seccomp-bpf/errorcode.h"
#include "sandbox/linux/seccomp-bpf/die.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
+#include "sandbox/linux/system_headers/linux_seccomp.h"
namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/errorcode_unittest.cc b/sandbox/linux/seccomp-bpf/errorcode_unittest.cc
index 5b62051..6b5491e 100644
--- a/sandbox/linux/seccomp-bpf/errorcode_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/errorcode_unittest.cc
@@ -10,8 +10,8 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/bpf_dsl/policy_compiler.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/trap.h"
+#include "sandbox/linux/system_headers/linux_seccomp.h"
#include "sandbox/linux/tests/unit_tests.h"
namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index d51fa78..31975a1 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -27,16 +27,18 @@
#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/linux_seccomp.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/linux_syscalls.h"
+#include "sandbox/linux/services/proc_util.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "sandbox/linux/services/thread_helpers.h"
+#include "sandbox/linux/system_headers/linux_seccomp.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
namespace sandbox {
@@ -116,13 +118,16 @@
return false;
}
+ if (!proc_task_fd_.is_valid()) {
+ SetProcTaskFd(ProcUtil::OpenProcSelfTask());
+ }
+
const bool supports_tsync = KernelSupportsSeccompTsync();
if (seccomp_level == SeccompLevel::SINGLE_THREADED) {
- if (!IsSingleThreaded(proc_task_fd_.get())) {
- SANDBOX_DIE("Cannot start sandbox; process is already multi-threaded");
- return false;
- }
+ // Wait for /proc/self/task/ to update if needed and assert the
+ // process is single threaded.
+ ThreadHelpers::AssertSingleThreaded(proc_task_fd_.get());
} else if (seccomp_level == SeccompLevel::MULTI_THREADED) {
if (IsSingleThreaded(proc_task_fd_.get())) {
SANDBOX_DIE("Cannot start sandbox; "
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
index 7e478b5..710f176 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
@@ -18,7 +18,7 @@
namespace {
// NOTE: most tests for the SandboxBPF class are currently in
-// bpf_dsl_more_unittest.cc.
+// integration_tests/.
TEST(SandboxBPF, CreateDestroy) {
// Give an opportunity to dynamic tools to perform some simple testing.
diff --git a/sandbox/linux/seccomp-bpf/syscall.cc b/sandbox/linux/seccomp-bpf/syscall.cc
index 4839f63..9fce1da 100644
--- a/sandbox/linux/seccomp-bpf/syscall.cc
+++ b/sandbox/linux/seccomp-bpf/syscall.cc
@@ -9,7 +9,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
+#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h
index 3686df5..dfb44eb 100644
--- a/sandbox/linux/seccomp-bpf/syscall.h
+++ b/sandbox/linux/seccomp-bpf/syscall.h
@@ -13,7 +13,7 @@
// Android's signal.h doesn't define ucontext etc.
#if defined(OS_ANDROID)
-#include "sandbox/linux/services/android_ucontext.h"
+#include "sandbox/linux/system_headers/android_ucontext.h"
#endif
namespace sandbox {
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index dce6b7b..c87bb00 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -14,13 +14,14 @@
#include "base/logging.h"
#include "build/build_config.h"
+#include "sandbox/linux/bpf_dsl/seccomp_macros.h"
#include "sandbox/linux/seccomp-bpf/die.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
+#include "sandbox/linux/system_headers/linux_seccomp.h"
// Android's signal.h doesn't define ucontext etc.
#if defined(OS_ANDROID)
-#include "sandbox/linux/services/android_ucontext.h"
+#include "sandbox/linux/system_headers/android_ucontext.h"
#endif
namespace {
diff --git a/sandbox/linux/seccomp-bpf/verifier.cc b/sandbox/linux/seccomp-bpf/verifier.cc
index 68fca88..e533b2d 100644
--- a/sandbox/linux/seccomp-bpf/verifier.cc
+++ b/sandbox/linux/seccomp-bpf/verifier.cc
@@ -12,10 +12,11 @@
#include "sandbox/linux/bpf_dsl/bpf_dsl_impl.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/errorcode.h"
-#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/system_headers/linux_seccomp.h"
namespace sandbox {
diff --git a/sandbox/linux/services/DEPS b/sandbox/linux/services/DEPS
new file mode 100644
index 0000000..70d9b18
--- /dev/null
+++ b/sandbox/linux/services/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+sandbox/linux/system_headers",
+]
diff --git a/sandbox/linux/services/android_ucontext.h b/sandbox/linux/services/android_ucontext.h
deleted file mode 100644
index 2814710..0000000
--- a/sandbox/linux/services/android_ucontext.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_LINUX_SERVICES_ANDROID_UCONTEXT_H_
-#define SANDBOX_LINUX_SERVICES_ANDROID_UCONTEXT_H_
-
-#if defined(__ANDROID__)
-
-#if defined(__arm__)
-#include "sandbox/linux/services/android_arm_ucontext.h"
-#elif defined(__i386__)
-#include "sandbox/linux/services/android_i386_ucontext.h"
-#elif defined(__x86_64__)
-#include "sandbox/linux/services/android_x86_64_ucontext.h"
-#elif defined(__mips__)
-#include "sandbox/linux/services/android_mips_ucontext.h"
-#elif defined(__aarch64__)
-#include "sandbox/linux/services/android_arm64_ucontext.h"
-#else
-#error "No support for your architecture in Android header"
-#endif
-
-#else // __ANDROID__
-#error "Android header file included on non Android."
-#endif // __ANDROID__
-
-#endif // SANDBOX_LINUX_SERVICES_ANDROID_UCONTEXT_H_
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index ce5eeda..e571dde 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -203,13 +203,17 @@
return false;
}
+ if (NamespaceUtils::KernelSupportsDenySetgroups()) {
+ PCHECK(NamespaceUtils::DenySetgroups());
+ }
+
// The current {r,e,s}{u,g}id is now an overflow id (c.f.
// /proc/sys/kernel/overflowuid). Setup the uid and gid maps.
DCHECK(GetRESIds(NULL, NULL));
const char kGidMapFile[] = "/proc/self/gid_map";
const char kUidMapFile[] = "/proc/self/uid_map";
- CHECK(NamespaceUtils::WriteToIdMapFile(kGidMapFile, gid));
- CHECK(NamespaceUtils::WriteToIdMapFile(kUidMapFile, uid));
+ PCHECK(NamespaceUtils::WriteToIdMapFile(kGidMapFile, gid));
+ PCHECK(NamespaceUtils::WriteToIdMapFile(kUidMapFile, uid));
DCHECK(GetRESIds(NULL, NULL));
return true;
}
diff --git a/sandbox/linux/services/credentials.h b/sandbox/linux/services/credentials.h
index a526176..2b761b6 100644
--- a/sandbox/linux/services/credentials.h
+++ b/sandbox/linux/services/credentials.h
@@ -26,7 +26,9 @@
class SANDBOX_EXPORT Credentials {
public:
// Drop all capabilities in the effective, inheritable and permitted sets for
- // the current process.
+ // the current process. For security reasons, since capabilities are
+ // per-thread, the caller is responsible for ensuring it is single-threaded
+ // when calling this API.
static bool DropAllCapabilities() WARN_UNUSED_RESULT;
// Return true iff there is any capability in any of the capabilities sets
// of the current process.
diff --git a/sandbox/linux/services/linux_syscalls.h b/sandbox/linux/services/linux_syscalls.h
deleted file mode 100644
index 73d9f40..0000000
--- a/sandbox/linux/services/linux_syscalls.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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.
-
-// This header will be kept up to date so that we can compile system-call
-// policies even when system headers are old.
-// System call numbers are accessible through __NR_syscall_name.
-
-#ifndef SANDBOX_LINUX_SERVICES_LINUX_SYSCALLS_H_
-#define SANDBOX_LINUX_SERVICES_LINUX_SYSCALLS_H_
-
-#if defined(__x86_64__)
-#include "sandbox/linux/services/x86_64_linux_syscalls.h"
-#endif
-
-#if defined(__i386__)
-#include "sandbox/linux/services/x86_32_linux_syscalls.h"
-#endif
-
-#if defined(__arm__) && defined(__ARM_EABI__)
-#include "sandbox/linux/services/arm_linux_syscalls.h"
-#endif
-
-#if defined(__mips__) && (_MIPS_SIM == _ABIO32)
-#include "sandbox/linux/services/mips_linux_syscalls.h"
-#endif
-
-#if defined(__mips__) && (_MIPS_SIM == _ABI64)
-#include "sandbox/linux/services/mips64_linux_syscalls.h"
-#endif
-
-#if defined(__aarch64__)
-#include "sandbox/linux/services/arm64_linux_syscalls.h"
-#endif
-
-#endif // SANDBOX_LINUX_SERVICES_LINUX_SYSCALLS_H_
-
diff --git a/sandbox/linux/services/namespace_sandbox.cc b/sandbox/linux/services/namespace_sandbox.cc
index 559b93c..0f371eb 100644
--- a/sandbox/linux/services/namespace_sandbox.cc
+++ b/sandbox/linux/services/namespace_sandbox.cc
@@ -11,6 +11,7 @@
#include <string>
#include <utility>
+#include <vector>
#include "base/command_line.h"
#include "base/environment.h"
@@ -27,18 +28,26 @@
class WriteUidGidMapDelegate : public base::LaunchOptions::PreExecDelegate {
public:
- WriteUidGidMapDelegate() : uid_(getuid()), gid_(getgid()) {}
+ WriteUidGidMapDelegate()
+ : uid_(getuid()),
+ gid_(getgid()),
+ supports_deny_setgroups_(
+ NamespaceUtils::KernelSupportsDenySetgroups()) {}
~WriteUidGidMapDelegate() override {}
void RunAsyncSafe() override {
+ if (supports_deny_setgroups_) {
+ RAW_CHECK(NamespaceUtils::DenySetgroups());
+ }
RAW_CHECK(NamespaceUtils::WriteToIdMapFile("/proc/self/uid_map", uid_));
RAW_CHECK(NamespaceUtils::WriteToIdMapFile("/proc/self/gid_map", gid_));
}
private:
- uid_t uid_;
- gid_t gid_;
+ const uid_t uid_;
+ const gid_t gid_;
+ const bool supports_deny_setgroups_;
DISALLOW_COPY_AND_ASSIGN(WriteUidGidMapDelegate);
};
@@ -59,6 +68,13 @@
base::Process NamespaceSandbox::LaunchProcess(
const base::CommandLine& cmdline,
const base::LaunchOptions& options) {
+ return LaunchProcess(cmdline.argv(), options);
+}
+
+// static
+base::Process NamespaceSandbox::LaunchProcess(
+ const std::vector<std::string>& argv,
+ const base::LaunchOptions& options) {
int clone_flags = 0;
int ns_types[] = {CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET};
for (const int ns_type : ns_types) {
@@ -91,7 +107,7 @@
SetEnvironForNamespaceType(environ, environ_name, clone_flags & flag);
}
- return base::LaunchProcess(cmdline, launch_options);
+ return base::LaunchProcess(argv, launch_options);
}
// static
diff --git a/sandbox/linux/services/namespace_sandbox.h b/sandbox/linux/services/namespace_sandbox.h
index ddc4dee..b92f581 100644
--- a/sandbox/linux/services/namespace_sandbox.h
+++ b/sandbox/linux/services/namespace_sandbox.h
@@ -5,6 +5,9 @@
#ifndef SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_
#define SANDBOX_LINUX_SERVICES_NAMESPACE_SANDBOX_H_
+#include <string>
+#include <vector>
+
#include "base/command_line.h"
#include "base/macros.h"
#include "base/process/launch.h"
@@ -41,6 +44,8 @@
// overrides them.
static base::Process LaunchProcess(const base::CommandLine& cmdline,
const base::LaunchOptions& options);
+ static base::Process LaunchProcess(const std::vector<std::string>& argv,
+ const base::LaunchOptions& options);
// Returns whether the namespace sandbox created a new user, PID, and network
// namespace. In particular, InNewUserNamespace should return true iff the
diff --git a/sandbox/linux/services/namespace_utils.cc b/sandbox/linux/services/namespace_utils.cc
index cf4c37a..82a5444 100644
--- a/sandbox/linux/services/namespace_utils.cc
+++ b/sandbox/linux/services/namespace_utils.cc
@@ -27,6 +27,8 @@
bool IsRunningOnValgrind() {
return RUNNING_ON_VALGRIND;
}
+
+const char kProcSelfSetgroups[] = "/proc/self/setgroups";
} // namespace
// static
@@ -43,7 +45,7 @@
const generic_id_t outside_id = id;
char mapping[64];
- ssize_t len =
+ const ssize_t len =
base::strings::SafeSPrintf(mapping, "%d %d 1\n", inside_id, outside_id);
const ssize_t rc = HANDLE_EINTR(write(fd, mapping, len));
RAW_CHECK(IGNORE_EINTR(close(fd)) == 0);
@@ -92,4 +94,24 @@
return base::PathExists(base::FilePath(path));
}
+// static
+bool NamespaceUtils::KernelSupportsDenySetgroups() {
+ return base::PathExists(base::FilePath(kProcSelfSetgroups));
+}
+
+// static
+bool NamespaceUtils::DenySetgroups() {
+ // This function needs to be async-signal-safe.
+ int fd = HANDLE_EINTR(open(kProcSelfSetgroups, O_WRONLY));
+ if (fd == -1) {
+ return false;
+ }
+
+ static const char kDeny[] = "deny";
+ const ssize_t len = sizeof(kDeny) - 1;
+ const ssize_t rc = HANDLE_EINTR(write(fd, kDeny, len));
+ RAW_CHECK(IGNORE_EINTR(close(fd)) == 0);
+ return rc == len;
+}
+
} // namespace sandbox
diff --git a/sandbox/linux/services/namespace_utils.h b/sandbox/linux/services/namespace_utils.h
index 6f3a2a8..f3c88a9 100644
--- a/sandbox/linux/services/namespace_utils.h
+++ b/sandbox/linux/services/namespace_utils.h
@@ -33,6 +33,17 @@
// not work from within a sandbox.
static bool KernelSupportsUnprivilegedNamespace(int type);
+ // Returns true if the kernel supports denying setgroups in a user namespace.
+ // On kernels where this is supported, DenySetgroups must be called before a
+ // gid mapping can be added.
+ static bool KernelSupportsDenySetgroups();
+
+ // Disables setgroups() within the current user namespace. On Linux 3.18.2 and
+ // later, this is required in order to write to /proc/self/gid_map without
+ // having CAP_SETGID. Callers can determine whether is this needed with
+ // KernelSupportsDenySetgroups. This function is async-signal-safe.
+ static bool DenySetgroups() WARN_UNUSED_RESULT;
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceUtils);
};
diff --git a/sandbox/linux/services/namespace_utils_unittest.cc b/sandbox/linux/services/namespace_utils_unittest.cc
index 42b469d..41ed7e8 100644
--- a/sandbox/linux/services/namespace_utils_unittest.cc
+++ b/sandbox/linux/services/namespace_utils_unittest.cc
@@ -40,10 +40,17 @@
const uid_t uid = getuid();
const gid_t gid = getgid();
+ const bool supports_deny_setgroups =
+ NamespaceUtils::KernelSupportsDenySetgroups();
+
const pid_t pid =
base::ForkWithFlags(CLONE_NEWUSER | SIGCHLD, nullptr, nullptr);
ASSERT_NE(-1, pid);
if (pid == 0) {
+ if (supports_deny_setgroups) {
+ RAW_CHECK(NamespaceUtils::DenySetgroups());
+ }
+
RAW_CHECK(getuid() != uid);
RAW_CHECK(NamespaceUtils::WriteToIdMapFile("/proc/self/uid_map", uid));
RAW_CHECK(getuid() == uid);
diff --git a/sandbox/linux/services/proc_util.cc b/sandbox/linux/services/proc_util.cc
index fd0e348..13d8842 100644
--- a/sandbox/linux/services/proc_util.cc
+++ b/sandbox/linux/services/proc_util.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
namespace sandbox {
@@ -31,7 +32,8 @@
int ProcUtil::CountOpenFds(int proc_fd) {
DCHECK_LE(0, proc_fd);
- int proc_self_fd = openat(proc_fd, "self/fd", O_DIRECTORY | O_RDONLY);
+ int proc_self_fd = HANDLE_EINTR(
+ openat(proc_fd, "self/fd", O_DIRECTORY | O_RDONLY | O_CLOEXEC));
PCHECK(0 <= proc_self_fd);
// Ownership of proc_self_fd is transferred here, it must not be closed
@@ -109,4 +111,13 @@
return false;
}
+//static
+base::ScopedFD ProcUtil::OpenProcSelfTask() {
+ base::ScopedFD proc_self_task(
+ HANDLE_EINTR(
+ open("/proc/self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC)));
+ PCHECK(proc_self_task.is_valid());
+ return proc_self_task.Pass();
+}
+
} // namespace sandbox
diff --git a/sandbox/linux/services/proc_util.h b/sandbox/linux/services/proc_util.h
index 9d9bb2e..74388f8 100644
--- a/sandbox/linux/services/proc_util.h
+++ b/sandbox/linux/services/proc_util.h
@@ -5,6 +5,7 @@
#ifndef SANDBOX_LINUX_SERVICES_PROC_UTIL_H_
#define SANDBOX_LINUX_SERVICES_PROC_UTIL_H_
+#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "sandbox/sandbox_export.h"
@@ -31,6 +32,9 @@
// false.
static bool HasOpenDirectory(int proc_fd);
+ // Open /proc/self/task/ or crash if it cannot.
+ static base::ScopedFD OpenProcSelfTask();
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProcUtil);
};
diff --git a/sandbox/linux/services/resource_limits.cc b/sandbox/linux/services/resource_limits.cc
new file mode 100644
index 0000000..1ec1129
--- /dev/null
+++ b/sandbox/linux/services/resource_limits.cc
@@ -0,0 +1,26 @@
+// 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 "sandbox/linux/services/resource_limits.h"
+
+#include <sys/resource.h>
+#include <sys/time.h>
+
+#include <algorithm>
+
+namespace sandbox {
+
+// static
+bool ResourceLimits::Lower(int resource, rlim_t limit) {
+ struct rlimit old_rlimit;
+ if (getrlimit(resource, &old_rlimit))
+ return false;
+ // Make sure we don't raise the existing limit.
+ const struct rlimit new_rlimit = {std::min(old_rlimit.rlim_cur, limit),
+ std::min(old_rlimit.rlim_max, limit)};
+ int rc = setrlimit(resource, &new_rlimit);
+ return rc == 0;
+}
+
+} // namespace sandbox
diff --git a/sandbox/linux/services/resource_limits.h b/sandbox/linux/services/resource_limits.h
new file mode 100644
index 0000000..488a5c5
--- /dev/null
+++ b/sandbox/linux/services/resource_limits.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 SANDBOX_LINUX_SERVICES_RESOURCE_LIMITS_H_
+#define SANDBOX_LINUX_SERVICES_RESOURCE_LIMITS_H_
+
+#include <sys/resource.h>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "sandbox/sandbox_export.h"
+
+namespace sandbox {
+
+// This class provides a small wrapper around setrlimit().
+class SANDBOX_EXPORT ResourceLimits {
+ public:
+ // Lower the soft and hard limit of |resource| to |limit|. If the current
+ // limit is lower than |limit|, keep it.
+ static bool Lower(int resource, rlim_t limit) WARN_UNUSED_RESULT;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ResourceLimits);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_LINUX_SERVICES_RESOURCE_LIMITS_H_
diff --git a/sandbox/linux/services/resource_limits_unittests.cc b/sandbox/linux/services/resource_limits_unittests.cc
new file mode 100644
index 0000000..910c740
--- /dev/null
+++ b/sandbox/linux/services/resource_limits_unittests.cc
@@ -0,0 +1,43 @@
+// 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 "sandbox/linux/services/resource_limits.h"
+
+#include <errno.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "sandbox/linux/tests/test_utils.h"
+#include "sandbox/linux/tests/unit_tests.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+namespace {
+
+// Fails on Android: crbug.com/459158
+#if !defined(OS_ANDROID)
+#define MAYBE_NoFork DISABLE_ON_ASAN(NoFork)
+#else
+#define MAYBE_NoFork DISABLED_NoFork
+#endif // OS_ANDROID
+
+// Not being able to fork breaks LeakSanitizer, so disable on
+// all ASAN builds.
+SANDBOX_TEST(ResourceLimits, MAYBE_NoFork) {
+ // Make sure that fork will fail with EAGAIN.
+ SANDBOX_ASSERT(ResourceLimits::Lower(RLIMIT_NPROC, 0));
+ errno = 0;
+ pid_t pid = fork();
+ // Reap any child if fork succeeded.
+ TestUtils::HandlePostForkReturn(pid);
+ SANDBOX_ASSERT_EQ(-1, pid);
+ CHECK_EQ(EAGAIN, errno);
+}
+
+} // namespace
+
+} // namespace sandbox
diff --git a/sandbox/linux/services/scoped_process.cc b/sandbox/linux/services/scoped_process.cc
index bdeaee9..4433201 100644
--- a/sandbox/linux/services/scoped_process.cc
+++ b/sandbox/linux/services/scoped_process.cc
@@ -39,7 +39,7 @@
PCHECK(0 == pipe(pipe_fds_));
#if !defined(THREAD_SANITIZER)
// Make sure that we can safely fork().
- CHECK(ThreadHelpers::IsSingleThreaded(-1));
+ CHECK(ThreadHelpers::IsSingleThreaded());
#endif
child_process_id_ = fork();
PCHECK(0 <= child_process_id_);
diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc
index efadbaf..af9dc46 100644
--- a/sandbox/linux/services/syscall_wrappers.cc
+++ b/sandbox/linux/services/syscall_wrappers.cc
@@ -17,7 +17,7 @@
#include "base/logging.h"
#include "base/third_party/valgrind/valgrind.h"
#include "build/build_config.h"
-#include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
namespace sandbox {
diff --git a/sandbox/linux/services/thread_helpers.cc b/sandbox/linux/services/thread_helpers.cc
index dbadbd4..51feb98 100644
--- a/sandbox/linux/services/thread_helpers.cc
+++ b/sandbox/linux/services/thread_helpers.cc
@@ -14,16 +14,23 @@
#include <string>
#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
+#include "sandbox/linux/services/proc_util.h"
namespace sandbox {
namespace {
+const char kAssertSingleThreadedError[] =
+ "Current process is not mono-threaded!";
+
bool IsSingleThreadedImpl(int proc_self_task) {
CHECK_LE(0, proc_self_task);
struct stat task_stat;
@@ -38,22 +45,91 @@
return task_stat.st_nlink == 3;
}
-} // namespace
-
-bool ThreadHelpers::IsSingleThreaded(int proc_self_task) {
- DCHECK_LE(-1, proc_self_task);
- if (-1 == proc_self_task) {
- const int task_fd =
- open("/proc/self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
- PCHECK(0 <= task_fd);
- const bool result = IsSingleThreadedImpl(task_fd);
- PCHECK(0 == IGNORE_EINTR(close(task_fd)));
- return result;
- } else {
- return IsSingleThreadedImpl(proc_self_task);
+bool IsThreadPresentInProcFS(int proc_self_task,
+ const std::string& thread_id_dir_str) {
+ struct stat task_stat;
+ const int fstat_ret =
+ fstatat(proc_self_task, thread_id_dir_str.c_str(), &task_stat, 0);
+ if (fstat_ret < 0) {
+ PCHECK(ENOENT == errno);
+ return false;
}
+ return true;
}
+// Run |cb| in a loop until it returns false. Every time |cb| runs, sleep
+// for an exponentially increasing amount of time. |cb| is expected to return
+// false very quickly and this will crash if it doesn't happen within ~64ms on
+// Debug builds (2s on Release builds).
+// This is guaranteed to not sleep more than twice as much as the bare minimum
+// amount of time.
+void RunWhileTrue(const base::Callback<bool(void)>& cb) {
+#if defined(NDEBUG)
+ // In Release mode, crash after 30 iterations, which means having spent
+ // roughly 2s in
+ // nanosleep(2) cumulatively.
+ const unsigned int kMaxIterations = 30U;
+#else
+ // In practice, this never goes through more than a couple iterations. In
+ // debug mode, crash after 64ms (+ eventually 25 times the granularity of
+ // the clock) in nanosleep(2). This ensures that this is not becoming too
+ // slow.
+ const unsigned int kMaxIterations = 25U;
+#endif
+
+ // Run |cb| with an exponential back-off, sleeping 2^iterations nanoseconds
+ // in nanosleep(2).
+ // Note: the clock may not allow for nanosecond granularity, in this case the
+ // first iterations would sleep a tiny bit more instead, which would not
+ // change the calculations significantly.
+ for (unsigned int i = 0; i < kMaxIterations; ++i) {
+ if (!cb.Run()) {
+ return;
+ }
+
+ // Increase the waiting time exponentially.
+ struct timespec ts = {0, 1L << i /* nanoseconds */};
+ PCHECK(0 == HANDLE_EINTR(nanosleep(&ts, &ts)));
+ }
+
+ LOG(FATAL) << kAssertSingleThreadedError << " (iterations: " << kMaxIterations
+ << ")";
+
+ NOTREACHED();
+}
+
+bool IsMultiThreaded(int proc_self_task) {
+ return !ThreadHelpers::IsSingleThreaded(proc_self_task);
+}
+
+} // namespace
+
+// static
+bool ThreadHelpers::IsSingleThreaded(int proc_self_task) {
+ DCHECK_LE(0, proc_self_task);
+ return IsSingleThreadedImpl(proc_self_task);
+}
+
+// static
+bool ThreadHelpers::IsSingleThreaded() {
+ base::ScopedFD task_fd(ProcUtil::OpenProcSelfTask());
+ return IsSingleThreaded(task_fd.get());
+}
+
+// static
+void ThreadHelpers::AssertSingleThreaded(int proc_self_task) {
+ DCHECK_LE(0, proc_self_task);
+ const base::Callback<bool(void)> cb =
+ base::Bind(&IsMultiThreaded, proc_self_task);
+ RunWhileTrue(cb);
+}
+
+void ThreadHelpers::AssertSingleThreaded() {
+ base::ScopedFD task_fd(ProcUtil::OpenProcSelfTask());
+ AssertSingleThreaded(task_fd.get());
+}
+
+// static
bool ThreadHelpers::StopThreadAndWatchProcFS(int proc_self_task,
base::Thread* thread) {
DCHECK_LE(0, proc_self_task);
@@ -66,38 +142,17 @@
// not have been updated.
thread->Stop();
- unsigned int iterations = 0;
- bool thread_present_in_procfs = true;
- // Poll /proc with an exponential back-off, sleeping 2^iterations nanoseconds
- // in nanosleep(2).
- // Note: the clock may not allow for nanosecond granularity, in this case the
- // first iterations would sleep a tiny bit more instead, which would not
- // change the calculations significantly.
- while (thread_present_in_procfs) {
- struct stat task_stat;
- const int fstat_ret =
- fstatat(proc_self_task, thread_id_dir_str.c_str(), &task_stat, 0);
- if (fstat_ret < 0) {
- PCHECK(ENOENT == errno);
- // The thread disappeared from /proc, we're done.
- thread_present_in_procfs = false;
- break;
- }
- // Increase the waiting time exponentially.
- struct timespec ts = {0, 1L << iterations /* nanoseconds */};
- PCHECK(0 == HANDLE_EINTR(nanosleep(&ts, &ts)));
- ++iterations;
+ const base::Callback<bool(void)> cb =
+ base::Bind(&IsThreadPresentInProcFS, proc_self_task, thread_id_dir_str);
- // Crash after 30 iterations, which means having spent roughly 2s in
- // nanosleep(2) cumulatively.
- CHECK_GT(30U, iterations);
- // In practice, this never goes through more than a couple iterations. In
- // debug mode, crash after 64ms (+ eventually 25 times the granularity of
- // the clock) in nanosleep(2).
- DCHECK_GT(25U, iterations);
- }
+ RunWhileTrue(cb);
return true;
}
+// static
+const char* ThreadHelpers::GetAssertSingleThreadedErrorMessageForTests() {
+ return kAssertSingleThreadedError;
+}
+
} // namespace sandbox
diff --git a/sandbox/linux/services/thread_helpers.h b/sandbox/linux/services/thread_helpers.h
index 377742a..efc2458 100644
--- a/sandbox/linux/services/thread_helpers.h
+++ b/sandbox/linux/services/thread_helpers.h
@@ -15,18 +15,26 @@
class SANDBOX_EXPORT ThreadHelpers {
public:
// Check whether the current process is single threaded. |proc_self_tasks|
- // can be a file descriptor to /proc/self/task/ and remains owned by the
- // caller or -1.
- // If |proc_self_tasks| is -1, this method will open /proc/self/task/ and
- // crash if it cannot.
+ // must be a file descriptor to /proc/self/task/ and remains owned by the
+ // caller.
static bool IsSingleThreaded(int proc_self_task);
+ static bool IsSingleThreaded();
+
+ // Crash if the current process is not single threaded. This will wait
+ // on /proc to be updated. In the case where this doesn't crash, this will
+ // return promptly. In the case where this does crash, this will first wait
+ // for a few ms in Debug mode, a few seconds in Release mode.
+ static void AssertSingleThreaded(int proc_self_task);
+ static void AssertSingleThreaded();
// Stop |thread| and ensure that it does not have an entry in
// /proc/self/task/ from the point of view of the current thread. This is
// the way to stop threads before calling IsSingleThreaded().
- static bool StopThreadAndWatchProcFS(int proc_self_tasks,
+ static bool StopThreadAndWatchProcFS(int proc_self_task,
base::Thread* thread);
+ static const char* GetAssertSingleThreadedErrorMessageForTests();
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadHelpers);
};
diff --git a/sandbox/linux/services/thread_helpers_unittests.cc b/sandbox/linux/services/thread_helpers_unittests.cc
index a36fd29..7f99aaf 100644
--- a/sandbox/linux/services/thread_helpers_unittests.cc
+++ b/sandbox/linux/services/thread_helpers_unittests.cc
@@ -27,6 +27,9 @@
namespace {
+// These tests fail under ThreadSanitizer, see http://crbug.com/342305
+#if !defined(THREAD_SANITIZER)
+
int GetRaceTestIterations() {
if (IsRunningOnValgrind()) {
return 2;
@@ -51,31 +54,29 @@
DISALLOW_COPY_AND_ASSIGN(ScopedProcSelfTask);
};
-#if defined(THREAD_SANITIZER)
-// These tests fail under ThreadSanitizer, see http://crbug.com/342305
-#define MAYBE_IsSingleThreadedBasic DISABLED_IsSingleThreadedBasic
-#define MAYBE_IsSingleThreadedIterated DISABLED_IsSingleThreadedIterated
-#define MAYBE_IsSingleThreadedStartAndStop DISABLED_IsSingleThreadedStartAndStop
-#else
-#define MAYBE_IsSingleThreadedBasic IsSingleThreadedBasic
-#define MAYBE_IsSingleThreadedIterated IsSingleThreadedIterated
-#define MAYBE_IsSingleThreadedStartAndStop IsSingleThreadedStartAndStop
-#endif
-
-TEST(ThreadHelpers, MAYBE_IsSingleThreadedBasic) {
+TEST(ThreadHelpers, IsSingleThreadedBasic) {
ScopedProcSelfTask task;
ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(task.fd()));
- ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(-1));
+ ASSERT_TRUE(ThreadHelpers::IsSingleThreaded());
base::Thread thread("sandbox_tests");
ASSERT_TRUE(thread.Start());
ASSERT_FALSE(ThreadHelpers::IsSingleThreaded(task.fd()));
- ASSERT_FALSE(ThreadHelpers::IsSingleThreaded(-1));
+ ASSERT_FALSE(ThreadHelpers::IsSingleThreaded());
// Explicitly stop the thread here to not pollute the next test.
ASSERT_TRUE(ThreadHelpers::StopThreadAndWatchProcFS(task.fd(), &thread));
}
-TEST(ThreadHelpers, MAYBE_IsSingleThreadedIterated) {
+SANDBOX_TEST(ThreadHelpers, AssertSingleThreaded) {
+ ScopedProcSelfTask task;
+ SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded(task.fd()));
+ SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded());
+
+ ThreadHelpers::AssertSingleThreaded(task.fd());
+ ThreadHelpers::AssertSingleThreaded();
+}
+
+TEST(ThreadHelpers, IsSingleThreadedIterated) {
ScopedProcSelfTask task;
ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(task.fd()));
@@ -89,7 +90,7 @@
}
}
-TEST(ThreadHelpers, MAYBE_IsSingleThreadedStartAndStop) {
+TEST(ThreadHelpers, IsSingleThreadedStartAndStop) {
ScopedProcSelfTask task;
ASSERT_TRUE(ThreadHelpers::IsSingleThreaded(task.fd()));
@@ -106,6 +107,42 @@
}
}
+SANDBOX_TEST(ThreadHelpers, AssertSingleThreadedAfterThreadStopped) {
+ SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded());
+
+ base::Thread thread1("sandbox_tests");
+ base::Thread thread2("sandbox_tests");
+
+ for (int i = 0; i < GetRaceTestIterations(); ++i) {
+ SANDBOX_ASSERT(thread1.Start());
+ SANDBOX_ASSERT(thread2.Start());
+ SANDBOX_ASSERT(!ThreadHelpers::IsSingleThreaded());
+
+ thread1.Stop();
+ thread2.Stop();
+ // This will wait on /proc/ to reflect the state of threads in the
+ // process.
+ ThreadHelpers::AssertSingleThreaded();
+ SANDBOX_ASSERT(ThreadHelpers::IsSingleThreaded());
+ }
+}
+
+// Only run this test in Debug mode, where AssertSingleThreaded() will return
+// in less than 64ms.
+#if !defined(NDEBUG)
+SANDBOX_DEATH_TEST(
+ ThreadHelpers,
+ AssertSingleThreadedDies,
+ DEATH_MESSAGE(
+ ThreadHelpers::GetAssertSingleThreadedErrorMessageForTests())) {
+ base::Thread thread1("sandbox_tests");
+ SANDBOX_ASSERT(thread1.Start());
+ ThreadHelpers::AssertSingleThreaded();
+}
+#endif // !defined(NDEBUG)
+
+#endif // !defined(THREAD_SANITIZER)
+
} // namespace
} // namespace sandbox
diff --git a/sandbox/linux/syscall_broker/DEPS b/sandbox/linux/syscall_broker/DEPS
index 99a337d..70d9b18 100644
--- a/sandbox/linux/syscall_broker/DEPS
+++ b/sandbox/linux/syscall_broker/DEPS
@@ -1,3 +1,3 @@
include_rules = [
- "+sandbox/linux/services",
+ "+sandbox/linux/system_headers",
]
diff --git a/sandbox/linux/syscall_broker/broker_host.cc b/sandbox/linux/syscall_broker/broker_host.cc
index ca55f21..fe28b47 100644
--- a/sandbox/linux/syscall_broker/broker_host.cc
+++ b/sandbox/linux/syscall_broker/broker_host.cc
@@ -20,9 +20,9 @@
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "base/third_party/valgrind/valgrind.h"
-#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/syscall_broker/broker_common.h"
#include "sandbox/linux/syscall_broker/broker_policy.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
namespace sandbox {
diff --git a/sandbox/linux/services/android_arm64_ucontext.h b/sandbox/linux/system_headers/android_arm64_ucontext.h
similarity index 78%
rename from sandbox/linux/services/android_arm64_ucontext.h
rename to sandbox/linux/system_headers/android_arm64_ucontext.h
index 3df0399..df2b66a 100644
--- a/sandbox/linux/services/android_arm64_ucontext.h
+++ b/sandbox/linux/system_headers/android_arm64_ucontext.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 SANDBOX_LINUX_SERVICES_ANDROID_ARM64_UCONTEXT_H_
-#define SANDBOX_LINUX_SERVICES_ANDROID_ARM64_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
#if !defined(__BIONIC_HAVE_UCONTEXT_T)
#include <asm/sigcontext.h>
@@ -26,4 +26,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SERVICES_ANDROID_ARM64_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
diff --git a/sandbox/linux/services/android_arm_ucontext.h b/sandbox/linux/system_headers/android_arm_ucontext.h
similarity index 83%
rename from sandbox/linux/services/android_arm_ucontext.h
rename to sandbox/linux/system_headers/android_arm_ucontext.h
index d1446c6..a380499 100644
--- a/sandbox/linux/services/android_arm_ucontext.h
+++ b/sandbox/linux/system_headers/android_arm_ucontext.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 SANDBOX_LINUX_SERVICES_ANDROID_ARM_UCONTEXT_H_
-#define SANDBOX_LINUX_SERVICES_ANDROID_ARM_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
#if !defined(__BIONIC_HAVE_UCONTEXT_T)
#include <asm/sigcontext.h>
@@ -29,4 +29,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SERVICES_ANDROID_ARM_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
diff --git a/sandbox/linux/services/android_futex.h b/sandbox/linux/system_headers/android_futex.h
similarity index 89%
rename from sandbox/linux/services/android_futex.h
rename to sandbox/linux/system_headers/android_futex.h
index 571f5d2..11b766f 100644
--- a/sandbox/linux/services/android_futex.h
+++ b/sandbox/linux/system_headers/android_futex.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 SANDBOX_LINUX_SERVICES_ANDROID_FUTEX_H_
-#define SANDBOX_LINUX_SERVICES_ANDROID_FUTEX_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
#if !defined(FUTEX_WAIT)
#define FUTEX_WAIT 0
@@ -77,4 +77,4 @@
#define FUTEX_UNLOCK_PI_PRIVATE (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
#endif
-#endif // SANDBOX_LINUX_SERVICES_ANDROID_FUTEX_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_FUTEX_H_
diff --git a/sandbox/linux/services/android_i386_ucontext.h b/sandbox/linux/system_headers/android_i386_ucontext.h
similarity index 89%
rename from sandbox/linux/services/android_i386_ucontext.h
rename to sandbox/linux/system_headers/android_i386_ucontext.h
index 580ac70..868016b 100644
--- a/sandbox/linux/services/android_i386_ucontext.h
+++ b/sandbox/linux/system_headers/android_i386_ucontext.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 SANDBOX_LINUX_SERVICES_ANDROID_I386_UCONTEXT_H_
-#define SANDBOX_LINUX_SERVICES_ANDROID_I386_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_
// We do something compatible with glibc. Hopefully, at some point Android will
// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined.
@@ -76,4 +76,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SERVICES_ANDROID_I386_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_
diff --git a/sandbox/linux/services/android_mips_ucontext.h b/sandbox/linux/system_headers/android_mips_ucontext.h
similarity index 85%
rename from sandbox/linux/services/android_mips_ucontext.h
rename to sandbox/linux/system_headers/android_mips_ucontext.h
index e23f1a7..ec3aa63 100644
--- a/sandbox/linux/services/android_mips_ucontext.h
+++ b/sandbox/linux/system_headers/android_mips_ucontext.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 SANDBOX_LINUX_SERVICES_ANDROID_MIPS_UCONTEXT_H_
-#define SANDBOX_LINUX_SERVICES_ANDROID_MIPS_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
// This is mostly copied from breakpad (common/android/include/sys/ucontext.h),
// except we do use sigset_t for uc_sigmask instead of a custom type.
@@ -48,4 +48,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SERVICES_ANDROID_MIPS_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_ucontext.h b/sandbox/linux/system_headers/android_ucontext.h
new file mode 100644
index 0000000..8e873be
--- /dev/null
+++ b/sandbox/linux/system_headers/android_ucontext.h
@@ -0,0 +1,28 @@
+// 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.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
+
+#if defined(__ANDROID__)
+
+#if defined(__arm__)
+#include "sandbox/linux/system_headers/android_arm_ucontext.h"
+#elif defined(__i386__)
+#include "sandbox/linux/system_headers/android_i386_ucontext.h"
+#elif defined(__x86_64__)
+#include "sandbox/linux/system_headers/android_x86_64_ucontext.h"
+#elif defined(__mips__)
+#include "sandbox/linux/system_headers/android_mips_ucontext.h"
+#elif defined(__aarch64__)
+#include "sandbox/linux/system_headers/android_arm64_ucontext.h"
+#else
+#error "No support for your architecture in Android header"
+#endif
+
+#else // __ANDROID__
+#error "Android header file included on non Android."
+#endif // __ANDROID__
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
diff --git a/sandbox/linux/services/android_x86_64_ucontext.h b/sandbox/linux/system_headers/android_x86_64_ucontext.h
similarity index 88%
rename from sandbox/linux/services/android_x86_64_ucontext.h
rename to sandbox/linux/system_headers/android_x86_64_ucontext.h
index ef328e5..778e6d0 100644
--- a/sandbox/linux/services/android_x86_64_ucontext.h
+++ b/sandbox/linux/system_headers/android_x86_64_ucontext.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 SANDBOX_LINUX_SERVICES_ANDROID_X86_64_UCONTEXT_H_
-#define SANDBOX_LINUX_SERVICES_ANDROID_X86_64_UCONTEXT_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
// We do something compatible with glibc. Hopefully, at some point Android will
// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined.
@@ -85,4 +85,4 @@
#include <sys/ucontext.h>
#endif // __BIONIC_HAVE_UCONTEXT_T
-#endif // SANDBOX_LINUX_SERVICES_ANDROID_X86_64_UCONTEXT_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
diff --git a/sandbox/linux/services/arm64_linux_syscalls.h b/sandbox/linux/system_headers/arm64_linux_syscalls.h
similarity index 98%
rename from sandbox/linux/services/arm64_linux_syscalls.h
rename to sandbox/linux/system_headers/arm64_linux_syscalls.h
index 4443059..8acb2d1 100644
--- a/sandbox/linux/services/arm64_linux_syscalls.h
+++ b/sandbox/linux/system_headers/arm64_linux_syscalls.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 SANDBOX_LINUX_SERVICES_ARM64_LINUX_SYSCALLS_H_
-#define SANDBOX_LINUX_SERVICES_ARM64_LINUX_SYSCALLS_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_SYSCALLS_H_
#include <asm-generic/unistd.h>
@@ -1059,4 +1059,4 @@
#define __NR_getrandom 278
#endif
-#endif // SANDBOX_LINUX_SERVICES_ARM64_LINUX_SYSCALLS_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/services/arm_linux_syscalls.h b/sandbox/linux/system_headers/arm_linux_syscalls.h
similarity index 99%
rename from sandbox/linux/services/arm_linux_syscalls.h
rename to sandbox/linux/system_headers/arm_linux_syscalls.h
index 5fa140d..b11041d 100644
--- a/sandbox/linux/services/arm_linux_syscalls.h
+++ b/sandbox/linux/system_headers/arm_linux_syscalls.h
@@ -3,8 +3,8 @@
// found in the LICENSE file.
// Generated from the Linux kernel's calls.S.
-#ifndef SANDBOX_LINUX_SERVICES_ARM_LINUX_SYSCALLS_H_
-#define SANDBOX_LINUX_SERVICES_ARM_LINUX_SYSCALLS_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_
#if !defined(__arm__) || !defined(__ARM_EABI__)
#error "Including header on wrong architecture"
@@ -1405,5 +1405,5 @@
#define __ARM_NR_cmpxchg (__ARM_NR_BASE+0x00fff0)
#endif
-#endif // SANDBOX_LINUX_SERVICES_ARM_LINUX_SYSCALLS_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/system_headers/linux_seccomp.h b/sandbox/linux/system_headers/linux_seccomp.h
new file mode 100644
index 0000000..40029c8
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_seccomp.h
@@ -0,0 +1,116 @@
+// 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 SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_
+
+#include <linux/filter.h>
+
+// The Seccomp2 kernel ABI is not part of older versions of glibc.
+// As we can't break compilation with these versions of the library,
+// we explicitly define all missing symbols.
+// If we ever decide that we can now rely on system headers, the following
+// include files should be enabled:
+// #include <linux/audit.h>
+// #include <linux/seccomp.h>
+
+// For audit.h
+#ifndef EM_ARM
+#define EM_ARM 40
+#endif
+#ifndef EM_386
+#define EM_386 3
+#endif
+#ifndef EM_X86_64
+#define EM_X86_64 62
+#endif
+#ifndef EM_MIPS
+#define EM_MIPS 8
+#endif
+#ifndef EM_AARCH64
+#define EM_AARCH64 183
+#endif
+
+#ifndef __AUDIT_ARCH_64BIT
+#define __AUDIT_ARCH_64BIT 0x80000000
+#endif
+#ifndef __AUDIT_ARCH_LE
+#define __AUDIT_ARCH_LE 0x40000000
+#endif
+#ifndef AUDIT_ARCH_ARM
+#define AUDIT_ARCH_ARM (EM_ARM|__AUDIT_ARCH_LE)
+#endif
+#ifndef AUDIT_ARCH_I386
+#define AUDIT_ARCH_I386 (EM_386|__AUDIT_ARCH_LE)
+#endif
+#ifndef AUDIT_ARCH_X86_64
+#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#endif
+#ifndef AUDIT_ARCH_MIPSEL
+#define AUDIT_ARCH_MIPSEL (EM_MIPS|__AUDIT_ARCH_LE)
+#endif
+#ifndef AUDIT_ARCH_AARCH64
+#define AUDIT_ARCH_AARCH64 (EM_AARCH64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
+#endif
+
+// For prctl.h
+#ifndef PR_SET_SECCOMP
+#define PR_SET_SECCOMP 22
+#define PR_GET_SECCOMP 21
+#endif
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#define PR_GET_NO_NEW_PRIVS 39
+#endif
+#ifndef IPC_64
+#define IPC_64 0x0100
+#endif
+
+#ifndef BPF_MOD
+#define BPF_MOD 0x90
+#endif
+#ifndef BPF_XOR
+#define BPF_XOR 0xA0
+#endif
+
+// In order to build will older tool chains, we currently have to avoid
+// including <linux/seccomp.h>. Until that can be fixed (if ever). Rely on
+// our own definitions of the seccomp kernel ABI.
+#ifndef SECCOMP_MODE_FILTER
+#define SECCOMP_MODE_DISABLED 0
+#define SECCOMP_MODE_STRICT 1
+#define SECCOMP_MODE_FILTER 2 // User user-supplied filter
+#endif
+
+#ifndef SECCOMP_SET_MODE_STRICT
+#define SECCOMP_SET_MODE_STRICT 0
+#endif
+#ifndef SECCOMP_SET_MODE_FILTER
+#define SECCOMP_SET_MODE_FILTER 1
+#endif
+#ifndef SECCOMP_FILTER_FLAG_TSYNC
+#define SECCOMP_FILTER_FLAG_TSYNC 1
+#endif
+
+#ifndef SECCOMP_RET_KILL
+// Return values supported for BPF filter programs. Please note that the
+// "illegal" SECCOMP_RET_INVALID is not supported by the kernel, should only
+// ever be used internally, and would result in the kernel killing our process.
+#define SECCOMP_RET_KILL 0x00000000U // Kill the task immediately
+#define SECCOMP_RET_INVALID 0x00010000U // Illegal return value
+#define SECCOMP_RET_TRAP 0x00030000U // Disallow and force a SIGSYS
+#define SECCOMP_RET_ERRNO 0x00050000U // Returns an errno
+#define SECCOMP_RET_TRACE 0x7ff00000U // Pass to a tracer or disallow
+#define SECCOMP_RET_ALLOW 0x7fff0000U // Allow
+#define SECCOMP_RET_ACTION 0xffff0000U // Masks for the return value
+#define SECCOMP_RET_DATA 0x0000ffffU // sections
+#else
+#define SECCOMP_RET_INVALID 0x00010000U // Illegal return value
+#endif
+
+#ifndef SYS_SECCOMP
+#define SYS_SECCOMP 1
+#endif
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_
diff --git a/sandbox/linux/system_headers/linux_syscalls.h b/sandbox/linux/system_headers/linux_syscalls.h
new file mode 100644
index 0000000..2b441e4
--- /dev/null
+++ b/sandbox/linux/system_headers/linux_syscalls.h
@@ -0,0 +1,37 @@
+// 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.
+
+// This header will be kept up to date so that we can compile system-call
+// policies even when system headers are old.
+// System call numbers are accessible through __NR_syscall_name.
+
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SYSCALLS_H_
+
+#if defined(__x86_64__)
+#include "sandbox/linux/system_headers/x86_64_linux_syscalls.h"
+#endif
+
+#if defined(__i386__)
+#include "sandbox/linux/system_headers/x86_32_linux_syscalls.h"
+#endif
+
+#if defined(__arm__) && defined(__ARM_EABI__)
+#include "sandbox/linux/system_headers/arm_linux_syscalls.h"
+#endif
+
+#if defined(__mips__) && (_MIPS_SIM == _ABIO32)
+#include "sandbox/linux/system_headers/mips_linux_syscalls.h"
+#endif
+
+#if defined(__mips__) && (_MIPS_SIM == _ABI64)
+#include "sandbox/linux/system_headers/mips64_linux_syscalls.h"
+#endif
+
+#if defined(__aarch64__)
+#include "sandbox/linux/system_headers/arm64_linux_syscalls.h"
+#endif
+
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SYSCALLS_H_
+
diff --git a/sandbox/linux/services/mips64_linux_syscalls.h b/sandbox/linux/system_headers/mips64_linux_syscalls.h
similarity index 98%
rename from sandbox/linux/services/mips64_linux_syscalls.h
rename to sandbox/linux/system_headers/mips64_linux_syscalls.h
index e6ef391..d003124 100644
--- a/sandbox/linux/services/mips64_linux_syscalls.h
+++ b/sandbox/linux/system_headers/mips64_linux_syscalls.h
@@ -3,8 +3,8 @@
// found in the LICENSE file.
// Generated from the Linux kernel's calls.S.
-#ifndef SANDBOX_LINUX_SERVICES_MIPS64_LINUX_SYSCALLS_H_
-#define SANDBOX_LINUX_SERVICES_MIPS64_LINUX_SYSCALLS_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_SYSCALLS_H_
#if !defined(__mips__) || (_MIPS_SIM != _ABI64)
#error "Including header on wrong architecture"
@@ -1263,4 +1263,4 @@
#define __NR_seccomp (__NR_Linux + 312)
#endif
-#endif // SANDBOX_LINUX_SERVICES_MIPS64_LINUX_SYSCALLS_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS64_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/services/mips_linux_syscalls.h b/sandbox/linux/system_headers/mips_linux_syscalls.h
similarity index 98%
rename from sandbox/linux/services/mips_linux_syscalls.h
rename to sandbox/linux/system_headers/mips_linux_syscalls.h
index 3a7d3d9..eb1717a 100644
--- a/sandbox/linux/services/mips_linux_syscalls.h
+++ b/sandbox/linux/system_headers/mips_linux_syscalls.h
@@ -3,8 +3,8 @@
// found in the LICENSE file.
// Generated from the Linux kernel's calls.S.
-#ifndef SANDBOX_LINUX_SERVICES_MIPS_LINUX_SYSCALLS_H_
-#define SANDBOX_LINUX_SERVICES_MIPS_LINUX_SYSCALLS_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_SYSCALLS_H_
#if !defined(__mips__) || (_MIPS_SIM != _ABIO32)
#error "Including header on wrong architecture"
@@ -1425,4 +1425,4 @@
#define __NR_seccomp (__NR_Linux + 352)
#endif
-#endif // SANDBOX_LINUX_SERVICES_MIPS_LINUX_SYSCALLS_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/services/x86_32_linux_syscalls.h b/sandbox/linux/system_headers/x86_32_linux_syscalls.h
similarity index 98%
rename from sandbox/linux/services/x86_32_linux_syscalls.h
rename to sandbox/linux/system_headers/x86_32_linux_syscalls.h
index 0fc2183..a6afc62 100644
--- a/sandbox/linux/services/x86_32_linux_syscalls.h
+++ b/sandbox/linux/system_headers/x86_32_linux_syscalls.h
@@ -3,8 +3,8 @@
// found in the LICENSE file.
// Generated from the Linux kernel's syscall_32.tbl.
-#ifndef SANDBOX_LINUX_SERVICES_X86_32_LINUX_SYSCALLS_H_
-#define SANDBOX_LINUX_SERVICES_X86_32_LINUX_SYSCALLS_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_
#if !defined(__i386__)
#error "Including header on wrong architecture"
@@ -1422,5 +1422,5 @@
#define __NR_memfd_create 356
#endif
-#endif // SANDBOX_LINUX_SERVICES_X86_32_LINUX_SYSCALLS_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/services/x86_64_linux_syscalls.h b/sandbox/linux/system_headers/x86_64_linux_syscalls.h
similarity index 98%
rename from sandbox/linux/services/x86_64_linux_syscalls.h
rename to sandbox/linux/system_headers/x86_64_linux_syscalls.h
index ea6c555..349504a 100644
--- a/sandbox/linux/services/x86_64_linux_syscalls.h
+++ b/sandbox/linux/system_headers/x86_64_linux_syscalls.h
@@ -3,8 +3,8 @@
// found in the LICENSE file.
// Generated from the Linux kernel's syscall_64.tbl.
-#ifndef SANDBOX_LINUX_SERVICES_X86_64_LINUX_SYSCALLS_H_
-#define SANDBOX_LINUX_SERVICES_X86_64_LINUX_SYSCALLS_H_
+#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_
+#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_
#if !defined(__x86_64__)
#error "Including header on wrong architecture"
@@ -1290,5 +1290,5 @@
#define __NR_memfd_create 319
#endif
-#endif // SANDBOX_LINUX_SERVICES_X86_64_LINUX_SYSCALLS_H_
+#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_
diff --git a/sandbox/linux/tests/main.cc b/sandbox/linux/tests/main.cc
index 17b4fe7..687c8bb 100644
--- a/sandbox/linux/tests/main.cc
+++ b/sandbox/linux/tests/main.cc
@@ -5,8 +5,11 @@
#include "base/at_exit.h"
#include "base/base_switches.h"
#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/test/test_suite.h"
+#include "build/build_config.h"
#include "sandbox/linux/tests/test_utils.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -16,10 +19,17 @@
namespace {
// Check for leaks in our tests.
-void RunPostTestsChecks() {
+void RunPostTestsChecks(const base::FilePath& orig_cwd) {
if (TestUtils::CurrentProcessHasChildren()) {
- LOG(ERROR) << "One of the tests created a child that was not waited for. "
- << "Please, clean-up after your tests!";
+ LOG(FATAL) << "One of the tests created a child that was not waited for. "
+ << "Please, clean up after your tests!";
+ }
+
+ base::FilePath cwd;
+ CHECK(GetCurrentDirectory(&cwd));
+ if (orig_cwd != cwd) {
+ LOG(FATAL) << "One of the tests changed the current working directory. "
+ << "Please, clean up after your tests!";
}
}
@@ -42,6 +52,9 @@
return multi_process_function_list::InvokeChildProcessTest(client_func);
}
+ base::FilePath orig_cwd;
+ CHECK(GetCurrentDirectory(&orig_cwd));
+
#if defined(OS_ANDROID)
// The use of Callbacks requires an AtExitManager.
base::AtExitManager exit_manager;
@@ -62,6 +75,6 @@
int tests_result = base::RunUnitTestsUsingBaseTestSuite(argc, argv);
#endif
- sandbox::RunPostTestsChecks();
+ sandbox::RunPostTestsChecks(orig_cwd);
return tests_result;
}
diff --git a/services/gles2/gpu_impl.cc b/services/gles2/gpu_impl.cc
index 52d3191..f3e351e 100644
--- a/services/gles2/gpu_impl.cc
+++ b/services/gles2/gpu_impl.cc
@@ -17,7 +17,7 @@
GpuImpl::State::State()
: control_thread_("gpu_command_buffer_control"),
- sync_point_manager_(new gpu::SyncPointManager),
+ sync_point_manager_(gpu::SyncPointManager::Create(true)),
share_group_(new gfx::GLShareGroup),
mailbox_manager_(new gpu::gles2::MailboxManagerImpl) {
control_thread_.Start();
diff --git a/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java b/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
index 1beac9c..f160260 100644
--- a/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
+++ b/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
@@ -9,6 +9,7 @@
import org.chromium.base.BaseChromiumApplication;
import org.chromium.base.PathUtils;
import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException;
/**
@@ -47,7 +48,7 @@
*/
private void initializeNative() {
try {
- LibraryLoader.ensureInitialized();
+ LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
} catch (ProcessInitException e) {
Log.e(TAG, "libmojo_shell initialization failed.", e);
throw new RuntimeException(e);
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index fb7da07..85ccce7 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -116,27 +116,14 @@
"//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",
- "//third_party/skia/src/image",
- "//third_party/skia/src/opts",
- "//third_party/skia/src/pdf",
- "//third_party/skia/src/ports",
- "//third_party/skia/src/sfnt",
- "//third_party/skia/src/utils",
- "//third_party/skia/src/lazy",
]
defines = gypi_skia_defines.skia_for_chromium_defines
- defines += [
- "SK_ENABLE_INST_COUNT=0",
- "GR_GL_CUSTOM_SETUP_HEADER=\"GrGLConfig_chrome.h\"",
- "SK_ENABLE_LEGACY_API_ALIASING=1",
- "SK_ATTR_DEPRECATED=SK_NOTHING_ARG1",
- "GR_GL_IGNORE_ES3_MSAA=0",
- "SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT",
- "SK_SUPPORT_LEGACY_GETTOTALCLIP",
- ]
+ defines += []
if (component_mode == "shared_library") {
defines += [ "SKIA_DLL" ]
@@ -152,12 +139,6 @@
defines += [ "SK_SUPPORT_GPU=0" ]
}
- # For POSIX platforms, prefer the Mutex implementation provided by Skia
- # since it does not generate static initializers.
- if (is_posix) {
- defines += [ "SK_USE_POSIX_THREADS" ]
- }
-
if (is_android) {
defines += [
"SK_BUILD_FOR_ANDROID",
@@ -175,7 +156,15 @@
# These include directories are only included for Skia code and are not
# exported to dependents. It's not clear if this is on purpose, but this
# matches the GYP build.
- include_dirs = []
+ include_dirs = [
+ "//third_party/skia/src/image",
+ "//third_party/skia/src/opts",
+ "//third_party/skia/src/pdf",
+ "//third_party/skia/src/ports",
+ "//third_party/skia/src/sfnt",
+ "//third_party/skia/src/utils",
+ "//third_party/skia/src/lazy",
+ ]
if (is_mac || is_ios) {
include_dirs += [ "//third_party/skia/include/utils/mac" ]
}
@@ -183,25 +172,7 @@
include_dirs += [ "//third_party/skia/include/utils/ios" ]
}
- defines = [
- #skia_export_defines ???) TODO
-
- # skia uses static initializers to initialize the serialization logic
- # of its "pictures" library. This is currently not used in chrome; if
- # it ever gets used the processes that use it need to call
- # SkGraphics::Init().
- "SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0",
-
- # Forcing the unoptimized path for the offset image filter in skia until
- # all filters used in Blink support the optimized path properly
- "SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION",
- "IGNORE_ROT_AA_RECT_OPT",
- "SK_IGNORE_BLURRED_RRECT_OPT",
-
- # this flag forces Skia not to use typographic metrics with GDI.
- "SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS",
- "SK_USE_DISCARDABLE_SCALEDIMAGECACHE",
- ]
+ defines = []
if (component_mode == "shared_library") {
defines += [ "SKIA_IMPLEMENTATION=1" ]
@@ -255,7 +226,7 @@
}
if (is_win) {
- include_dirs = [
+ include_dirs += [
"//third_party/skia/include/utils/win",
"//third_party/skia/src/utils/win",
]
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 63131ad..84a02d7 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -257,18 +257,38 @@
# define SK_IGNORE_GPU_DITHER
#endif
+#ifndef SK_SUPPORT_LEGACY_ARCTO_QUADS
+# define SK_SUPPORT_LEGACY_ARCTO_QUADS
+#endif
+
#ifndef SK_SUPPORT_LEGACY_ADDOVAL
# define SK_SUPPORT_LEGACY_ADDOVAL
#endif
-#ifndef SK_SUPPORT_LEGACY_ADDRRECT
-# define SK_SUPPORT_LEGACY_ADDRRECT
-#endif
+///////////////////////// Imported from BUILD.gn and skia_common.gypi
-// If this goes well, we can have Skia respect DYNAMIC_ANNOTATIONS_ENABLED directly.
-#if DYNAMIC_ANNOTATIONS_ENABLED
-# define SK_DYNAMIC_ANNOTATIONS_ENABLED 1
-#endif
+/* In some places Skia can use static initializers for global initialization,
+ * or fall back to lazy runtime initialization. Chrome always wants the latter.
+ */
+#define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
+
+/* Forcing the unoptimized path for the offset image filter in skia until
+ * all filters used in Blink support the optimized path properly
+ */
+#define SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
+
+/* This flag forces Skia not to use typographic metrics with GDI.
+ */
+#define SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
+
+#define IGNORE_ROT_AA_RECT_OPT
+#define SK_IGNORE_BLURRED_RRECT_OPT
+#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE
+#define SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
+
+#define SK_ATTR_DEPRECATED SK_NOTHING_ARG1
+#define SK_ENABLE_INST_COUNT 0
+#define GR_GL_CUSTOM_SETUP_HEADER "GrGLConfig_chrome.h"
// ===== End Chrome-specific definitions =====
diff --git a/skia/ext/event_tracer_impl.cc b/skia/ext/event_tracer_impl.cc
index e283814..f6e12f0 100644
--- a/skia/ext/event_tracer_impl.cc
+++ b/skia/ext/event_tracer_impl.cc
@@ -32,8 +32,7 @@
const char* SkChromiumEventTracer::getCategoryGroupName(
const uint8_t* categoryEnabledFlag) {
- return base::debug::TraceLog::GetCategoryGroupName(
- categoryEnabledFlag);
+ return base::trace_event::TraceLog::GetCategoryGroupName(categoryEnabledFlag);
}
SkEventTracer::Handle
@@ -46,9 +45,9 @@
const uint8_t* argTypes,
const uint64_t* argValues,
uint8_t flags) {
- base::debug::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT(
- phase, categoryEnabledFlag, name, id, numArgs, argNames,
- argTypes, (const long long unsigned int*) argValues, NULL, flags);
+ base::trace_event::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, categoryEnabledFlag, name, id, numArgs, argNames, argTypes,
+ (const long long unsigned int*)argValues, NULL, flags);
SkEventTracer::Handle result;
memcpy(&result, &handle, sizeof(result));
return result;
@@ -59,7 +58,7 @@
const uint8_t* categoryEnabledFlag,
const char *name,
SkEventTracer::Handle handle) {
- base::debug::TraceEventHandle traceEventHandle;
+ base::trace_event::TraceEventHandle traceEventHandle;
memcpy(&traceEventHandle, &handle, sizeof(handle));
TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
categoryEnabledFlag, name, traceEventHandle);
diff --git a/skia/skia_common.gypi b/skia/skia_common.gypi
index 13a4974..babb5cd 100644
--- a/skia/skia_common.gypi
+++ b/skia/skia_common.gypi
@@ -93,19 +93,6 @@
],
}],
- # For POSIX platforms, prefer the Mutex implementation provided by Skia
- # since it does not generate static initializers.
- [ 'os_posix == 1', {
- 'defines+': [
- 'SK_USE_POSIX_THREADS',
- ],
- 'direct_dependent_settings': {
- 'defines': [
- 'SK_USE_POSIX_THREADS',
- ],
- },
- }],
-
# Neon support.
[ 'target_arch == "arm" and arm_version >= 7 and arm_neon == 1', {
'defines': [
@@ -151,13 +138,7 @@
# This list will contain all defines that also need to be exported to
# dependent components.
'skia_export_defines': [
- 'SK_ENABLE_INST_COUNT=0',
'SK_SUPPORT_GPU=<(skia_support_gpu)',
- 'GR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"',
- 'SK_ENABLE_LEGACY_API_ALIASING=1',
- 'SK_ATTR_DEPRECATED=SK_NOTHING_ARG1',
- 'GR_GL_IGNORE_ES3_MSAA=0',
- 'SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT',
# This variable contains additional defines, specified in blink's
# blink_skia_config.gypi file.
@@ -186,26 +167,7 @@
'defines': [
'<@(skia_export_defines)',
- # skia uses static initializers to initialize the serialization logic
- # of its "pictures" library. This is currently not used in chrome; if
- # it ever gets used the processes that use it need to call
- # SkGraphics::Init().
- 'SK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0',
-
- # Forcing the unoptimized path for the offset image filter in skia until
- # all filters used in Blink support the optimized path properly
- 'SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION',
-
- 'IGNORE_ROT_AA_RECT_OPT',
-
- 'SK_IGNORE_BLURRED_RRECT_OPT',
-
- # this flag forces Skia not to use typographic metrics with GDI.
- 'SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS',
-
'SK_DEFAULT_FONT_CACHE_LIMIT=<(default_font_cache_limit)',
-
- 'SK_USE_DISCARDABLE_SCALEDIMAGECACHE',
],
'direct_dependent_settings': {
diff --git a/skia/skia_test_expectations.txt b/skia/skia_test_expectations.txt
index 0d92ff3..4327f6e 100644
--- a/skia/skia_test_expectations.txt
+++ b/skia/skia_test_expectations.txt
@@ -48,16 +48,4 @@
#
# START OVERRIDES HERE
-# https://codereview.chromium.org/776673002/
-crbug.com/452219 css3/filters/effect-combined.html [ ImageOnlyFailure Pass ]
-crbug.com/452219 css3/filters/effect-reference-subregion-hw.html [ ImageOnlyFailure Pass ]
-crbug.com/452219 svg/W3C-SVG-1.1/filters-comptran-01-b.svg [ ImageOnlyFailure Pass ]
-crbug.com/452219 svg/custom/feComponentTransfer-Discrete.svg [ ImageOnlyFailure Pass ]
-crbug.com/452219 svg/custom/feComponentTransfer-Gamma.svg [ ImageOnlyFailure Pass ]
-crbug.com/452219 svg/custom/feComponentTransfer-Linear.svg [ ImageOnlyFailure Pass ]
-crbug.com/452219 svg/custom/feComponentTransfer-Table.svg [ ImageOnlyFailure Pass ]
-crbug.com/452219 svg/dynamic-updates/SVGFEComponentTransferElement-dom-tableValues-attr.html [ ImageOnlyFailure Pass ]
-crbug.com/452219 svg/dynamic-updates/SVGFEComponentTransferElement-svgdom-tableValues-prop.html [ ImageOnlyFailure Pass ]
-
-
# END OVERRIDES HERE (this line ensures that the file is newline-terminated)
diff --git a/sky/engine/core/dom/Node.cpp b/sky/engine/core/dom/Node.cpp
index 60f5fe9..473ae8e 100644
--- a/sky/engine/core/dom/Node.cpp
+++ b/sky/engine/core/dom/Node.cpp
@@ -533,7 +533,7 @@
namespace {
-class JSONTraceValue : public base::debug::ConvertableToTraceFormat {
+class JSONTraceValue : public base::trace_event::ConvertableToTraceFormat {
public:
explicit JSONTraceValue(RefPtr<JSONValue> value)
: m_value(value.release()) { }
diff --git a/sky/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java b/sky/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java
index efb12dd..d60ce5f 100644
--- a/sky/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java
+++ b/sky/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java
@@ -10,6 +10,7 @@
import org.chromium.base.PathUtils;
import org.chromium.base.ResourceExtractor;
import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.library_loader.ProcessInitException;
/**
@@ -43,7 +44,7 @@
*/
private void initializeNative() {
try {
- LibraryLoader.ensureInitialized();
+ LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
} catch (ProcessInitException e) {
Log.e(TAG, "sky_shell initialization failed.", e);
throw new RuntimeException(e);
diff --git a/testing/buildbot/OWNERS b/testing/buildbot/OWNERS
index c70be62..8b86544 100644
--- a/testing/buildbot/OWNERS
+++ b/testing/buildbot/OWNERS
@@ -11,3 +11,4 @@
machenbach@chromium.org
phajdan.jr@chromium.org
sky@chromium.org
+thakis@chromium.org
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 8f106b7..64f2cd5 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -30,7 +30,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"display_unittests",
"extensions_unittests",
@@ -117,7 +122,12 @@
}
},
"content_unittests",
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"device_unittests",
"display_unittests",
@@ -187,7 +197,12 @@
"cacheinvalidation_unittests",
"chromeos_unittests",
"components_unittests",
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"extensions_unittests",
"google_apis_unittests",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index b5fc002..1d15ec1 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.*"] }
+ { "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.*"] }
]
},
"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.*"] }
+ { "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.*"] }
]
},
"Browser Side Navigation Linux": {
@@ -372,17 +372,32 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
"gpu_unittests",
"url_unittests",
"jingle_unittests",
- "content_unittests",
+ {
+ "test": "content_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"media_unittests",
- "net_unittests",
+ {
+ "test": "net_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
@@ -392,11 +407,22 @@
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
- "unit_tests",
+ {
+ "test": "unit_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"sql_unittests",
"ui_base_unittests",
"views_unittests",
- "browser_tests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ }
+ },
{
"test": "content_browsertests",
"swarming": {
@@ -423,17 +449,32 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
"gpu_unittests",
"url_unittests",
"jingle_unittests",
- "content_unittests",
+ {
+ "test": "content_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"media_unittests",
- "net_unittests",
+ {
+ "test": "net_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
@@ -443,11 +484,22 @@
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
- "unit_tests",
+ {
+ "test": "unit_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"sql_unittests",
"ui_base_unittests",
"views_unittests",
- "browser_tests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ }
+ },
{
"test": "content_browsertests",
"swarming": {
@@ -474,17 +526,32 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
"gpu_unittests",
"url_unittests",
"jingle_unittests",
- "content_unittests",
+ {
+ "test": "content_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"media_unittests",
- "net_unittests",
+ {
+ "test": "net_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
@@ -494,11 +561,22 @@
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
- "unit_tests",
+ {
+ "test": "unit_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"sql_unittests",
"ui_base_unittests",
"views_unittests",
- "browser_tests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ }
+ },
{
"test": "content_browsertests",
"swarming": {
@@ -525,17 +603,32 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
"gpu_unittests",
"url_unittests",
"jingle_unittests",
- "content_unittests",
+ {
+ "test": "content_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"media_unittests",
- "net_unittests",
+ {
+ "test": "net_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
@@ -545,11 +638,22 @@
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
- "unit_tests",
+ {
+ "test": "unit_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"sql_unittests",
"ui_base_unittests",
"views_unittests",
- "browser_tests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ }
+ },
{
"test": "content_browsertests",
"swarming": {
@@ -576,17 +680,32 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
"gpu_unittests",
"url_unittests",
"jingle_unittests",
- "content_unittests",
+ {
+ "test": "content_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"media_unittests",
- "net_unittests",
+ {
+ "test": "net_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
@@ -596,11 +715,22 @@
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
- "unit_tests",
+ {
+ "test": "unit_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"sql_unittests",
"ui_base_unittests",
"views_unittests",
- "browser_tests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ }
+ },
{
"test": "content_browsertests",
"swarming": {
@@ -627,17 +757,32 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
"gpu_unittests",
"url_unittests",
"jingle_unittests",
- "content_unittests",
+ {
+ "test": "content_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"media_unittests",
- "net_unittests",
+ {
+ "test": "net_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"ppapi_unittests",
"printing_unittests",
"remoting_unittests",
@@ -647,11 +792,22 @@
"ipc_tests",
"sync_unit_tests",
"skia_unittests",
- "unit_tests",
+ {
+ "test": "unit_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"sql_unittests",
"ui_base_unittests",
"views_unittests",
- "browser_tests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 10
+ }
+ },
{
"test": "content_browsertests",
"swarming": {
@@ -678,7 +834,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
@@ -729,7 +890,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
@@ -780,7 +946,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
"google_apis_unittests",
@@ -813,5 +984,69 @@
},
"installer_util_unittests"
]
+ },
+ "ClangToTLinux tester": {
+ "gtest_tests": [
+ "accessibility_unittests",
+ "app_list_unittests",
+ "app_shell_unittests",
+ "aura_unittests",
+ "interactive_ui_tests",
+ "base_unittests",
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "cc_unittests",
+ "chromedriver_unittests",
+ "components_unittests",
+ "compositor_unittests",
+ "crypto_unittests",
+ "dbus_unittests",
+ "display_unittests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "url_unittests",
+ "jingle_unittests",
+ "content_unittests",
+ "device_unittests",
+ "events_unittests",
+ "media_unittests",
+ "net_unittests",
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ "ipc_tests",
+ "sync_unit_tests",
+ "unit_tests",
+ "views_unittests",
+ "wm_unittests",
+ "sql_unittests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
+ "content_browsertests",
+ "mojo_common_unittests",
+ "mojo_public_bindings_unittests",
+ "mojo_public_environment_unittests",
+ "mojo_public_system_unittests",
+ "mojo_public_utility_unittests",
+ "mojo_system_unittests",
+ "nacl_loader_unittests"
+ ],
+ "scripts": [
+ {
+ "name": "nacl_integration",
+ "script": "nacl_integration.py"
+ }
+ ]
}
}
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 15fa1a6..f6e8c97 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -62,7 +62,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"device_unittests",
"display_unittests",
@@ -240,7 +245,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"device_unittests",
"display_unittests",
@@ -398,7 +408,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"device_unittests",
"display_unittests",
@@ -539,5 +554,21 @@
"unit_tests",
"skia_unittests"
]
+ },
+ "Android Tests (dbg)": {
+ "scripts": [
+ {
+ "name": "check_licenses",
+ "script": "webview_licenses.py"
+ }
+ ]
+ },
+ "Android Tests": {
+ "scripts": [
+ {
+ "name": "check_licenses",
+ "script": "webview_licenses.py"
+ }
+ ]
}
}
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 55e5481..d7f39bb 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -59,7 +59,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
{
@@ -204,7 +209,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
{
@@ -349,7 +359,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
{
@@ -494,7 +509,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"extensions_unittests",
"gcm_unit_tests",
{
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json
index 3d5b728..644bd9e 100644
--- a/testing/buildbot/chromium.memory.fyi.json
+++ b/testing/buildbot/chromium.memory.fyi.json
@@ -4,10 +4,12 @@
"accessibility_unittests",
"app_list_unittests",
"aura_unittests",
+ "base_unittests",
{
- "test": "base_unittests",
+ "test": "browser_tests",
"swarming": {
- "can_use_on_swarming_builders": true
+ "can_use_on_swarming_builders": true,
+ "shards": 5
}
},
"cacheinvalidation_unittests",
@@ -15,6 +17,7 @@
"cc_unittests",
"chromedriver_unittests",
"components_unittests",
+ "compositor_unittests",
"content_browsertests",
"content_unittests",
"crypto_unittests",
@@ -28,7 +31,12 @@
"gfx_unittests",
"google_apis_unittests",
"gpu_unittests",
- "interactive_ui_tests",
+ {
+ "test": "interactive_ui_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"ipc_mojo_unittests",
"ipc_tests",
"jingle_unittests",
@@ -56,32 +64,25 @@
"wm_unittests"
]
},
- "Linux MSan Browser (1)": {
- "gtest_tests": [
- {"test": "browser_tests", "shard_index": 0, "total_shards": 3}
- ]
- },
- "Linux MSan Browser (2)": {
- "gtest_tests": [
- {"test": "browser_tests", "shard_index": 1, "total_shards": 3}
- ]
- },
- "Linux MSan Browser (3)": {
- "gtest_tests": [
- {"test": "browser_tests", "shard_index": 2, "total_shards": 3}
- ]
- },
"Linux ChromeOS MSan Tests": {
"gtest_tests": [
"accessibility_unittests",
"app_list_unittests",
"aura_unittests",
"base_unittests",
+ {
+ "test": "browser_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 5
+ }
+ },
"cacheinvalidation_unittests",
"cast_unittests",
"cc_unittests",
"chromedriver_unittests",
"components_unittests",
+ "compositor_unittests",
"content_browsertests",
"content_unittests",
"crypto_unittests",
@@ -95,7 +96,13 @@
"gfx_unittests",
"google_apis_unittests",
"gpu_unittests",
- "interactive_ui_tests",
+ {
+ "test": "interactive_ui_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ }
+ },
"ipc_mojo_unittests",
"ipc_tests",
"jingle_unittests",
@@ -122,19 +129,81 @@
"wm_unittests"
]
},
- "Linux ChromeOS MSan Browser (1)": {
+ "Linux TSan Tests": {
"gtest_tests": [
- {"test": "browser_tests", "shard_index": 0, "total_shards": 3}
- ]
- },
- "Linux ChromeOS MSan Browser (2)": {
- "gtest_tests": [
- {"test": "browser_tests", "shard_index": 1, "total_shards": 3}
- ]
- },
- "Linux ChromeOS MSan Browser (3)": {
- "gtest_tests": [
- {"test": "browser_tests", "shard_index": 2, "total_shards": 3}
- ]
+ "accessibility_unittests",
+ "app_list_unittests",
+ "aura_unittests",
+ {
+ "test": "base_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
+ "cacheinvalidation_unittests",
+ "cast_unittests",
+ "chromedriver_unittests",
+ "components_unittests",
+ {
+ "test": "content_browsertests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
+ {
+ "test": "content_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
+ "crypto_unittests",
+ "dbus_unittests",
+ "device_unittests",
+ "display_unittests",
+ "events_unittests",
+ "extensions_unittests",
+ "gcm_unit_tests",
+ "gfx_unittests",
+ "google_apis_unittests",
+ "gpu_unittests",
+ "ipc_mojo_unittests",
+ "ipc_tests",
+ "jingle_unittests",
+ "media_unittests",
+ "mojo_common_unittests",
+ {
+ "test": "net_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 4
+ }
+ },
+ "ppapi_unittests",
+ "printing_unittests",
+ "remoting_unittests",
+ "sandbox_linux_unittests",
+ "skia_unittests",
+ "sql_unittests",
+ "sync_unit_tests",
+ "ui_base_unittests",
+ "ui_touch_selection_unittests",
+ {
+ "test": "unit_tests",
+ "swarming": {
+ "can_use_on_swarming_builders": true,
+ "shards": 2
+ }
+ },
+ "url_unittests",
+ "views_unittests",
+ "wm_unittests"
+ ],
+ "disabled_tests": {
+ "app_shell_browsertests": "http://crbug.com/455633",
+ "cc_unittests": "http://crbug.com/437454",
+ "browser_tests":
+ "Too many errors, clean content_browsertests first. http://crbug.com/368525",
+ "interactive_ui_tests": "http://crbug.com/455679"
+ }
}
}
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index f1e3c95..87a67e4 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -32,7 +32,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"display_unittests",
"extensions_unittests",
@@ -128,7 +133,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"gcm_unit_tests",
"gpu_unittests",
{
@@ -188,7 +198,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"gcm_unit_tests",
"gpu_unittests",
{
@@ -264,7 +279,12 @@
}
},
"components_unittests",
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"display_unittests",
"events_unittests",
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json
index 17cc5e9..ae8f0b4 100644
--- a/testing/buildbot/chromium.webkit.json
+++ b/testing/buildbot/chromium.webkit.json
@@ -30,7 +30,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"display_unittests",
"extensions_unittests",
@@ -110,7 +115,12 @@
"cacheinvalidation_unittests",
"chromeos_unittests",
"components_unittests",
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"dbus_unittests",
"extensions_unittests",
"google_apis_unittests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index c462aaf..c90ec05 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -58,7 +58,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"events_unittests",
{
"test": "extensions_browsertests",
@@ -194,7 +199,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
{
"test": "extensions_browsertests",
"swarming": {
@@ -341,7 +351,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"events_unittests",
{
@@ -495,7 +510,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
"events_unittests",
{
@@ -647,7 +667,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"events_unittests",
{
"test": "extensions_browsertests",
diff --git a/testing/buildbot/chromium_memory_trybot.json b/testing/buildbot/chromium_memory_trybot.json
index c8f0388..c794785 100644
--- a/testing/buildbot/chromium_memory_trybot.json
+++ b/testing/buildbot/chromium_memory_trybot.json
@@ -45,7 +45,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
"device_unittests",
{
"test": "display_unittests",
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json
index c2d7e72..3b3905b 100644
--- a/testing/buildbot/chromium_trybot.json
+++ b/testing/buildbot/chromium_trybot.json
@@ -104,7 +104,12 @@
"can_use_on_swarming_builders": true
}
},
- "crypto_unittests",
+ {
+ "test": "crypto_unittests",
+ "swarming": {
+ "can_use_on_swarming_builders": true
+ }
+ },
{
"test": "dbus_unittests",
"platforms": ["linux"]
diff --git a/testing/buildbot/chromium_win8_trybot.json b/testing/buildbot/chromium_win8_trybot.json
index b4bddd4..c7c32d3 100644
--- a/testing/buildbot/chromium_win8_trybot.json
+++ b/testing/buildbot/chromium_win8_trybot.json
@@ -10,6 +10,9 @@
"compositor_unittests",
"content_browsertests",
"events_unittests",
- "ui_touch_selection_unittests"
+ "ui_touch_selection_unittests",
+ "sbox_integration_tests",
+ "sbox_validation_tests",
+ "sbox_unittests"
]
}
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json
index 4563928..1b05f1c 100644
--- a/testing/commit_queue/config.json
+++ b/testing/commit_queue/config.json
@@ -5,6 +5,9 @@
"trybots": {
"launched": {
"tryserver.chromium.linux": {
+ "cast_shell": ["defaulttests"],
+ "cast_shell_apk": ["defaulttests"],
+ "linux_android_rel_ng": ["defaulttests"],
"linux_chromium_asan_rel_ng": ["defaulttests"]
},
"tryserver.chromium.mac": {
@@ -59,7 +62,7 @@
"linux_chromium_gn_dbg": ["defaulttests"],
"linux_chromium_gn_rel": ["defaulttests"],
"linux_chromium_rel_ng": ["defaulttests"],
- "android_dbg_tests_recipe": ["defaulttests"],
+ "android_rel_tests_recipe": ["defaulttests"],
"android_arm64_dbg_recipe": ["defaulttests"],
"android_clang_dbg_recipe": ["defaulttests"],
"android_aosp": ["compile"],
@@ -89,15 +92,9 @@
"win_chromium_compile_dbg_ng": ["defaulttests"],
"win_chromium_rel_ng": ["defaulttests"],
"win_chromium_x64_rel_ng": ["defaulttests"]
- },
- "tryserver.chromium.gpu": {
- "win_gpu": ["defaulttests"]
}
},
"triggered": {
- "tryserver.chromium.gpu": {
- "win_gpu_triggered_tests": "win_gpu"
- }
}
}
}
diff --git a/testing/iossim/iossim.gyp b/testing/iossim/iossim.gyp
index a8ad603..6a1fb02 100644
--- a/testing/iossim/iossim.gyp
+++ b/testing/iossim/iossim.gyp
@@ -136,6 +136,7 @@
{
'target_name': 'iossim',
'type': 'none',
+ 'toolsets': ['host'],
'variables': {
# Gyp to rerun
're_run_targets': [
diff --git a/testing/legion/client_lib.py b/testing/legion/client_lib.py
index 4d6a633..4656cac 100644
--- a/testing/legion/client_lib.py
+++ b/testing/legion/client_lib.py
@@ -18,10 +18,8 @@
#pylint: disable=relative-import
import common_lib
-THIS_DIR = os.path.dirname(os.path.abspath(__file__))
-SWARMING_DIR = os.path.join(THIS_DIR, '..', '..', 'tools/swarming_client')
-ISOLATE_PY = os.path.join(SWARMING_DIR, 'isolate.py')
-SWARMING_PY = os.path.join(SWARMING_DIR, 'swarming.py')
+ISOLATE_PY = os.path.join(common_lib.SWARMING_DIR, 'isolate.py')
+SWARMING_PY = os.path.join(common_lib.SWARMING_DIR, 'swarming.py')
class Error(Exception):
@@ -202,7 +200,6 @@
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
_, stderr = p.communicate()
if p.returncode != 0:
- stderr.seek(0)
raise Error(stderr)
def OnConnect(self, ip_address):
diff --git a/testing/legion/client_rpc_methods.py b/testing/legion/client_rpc_methods.py
index 24a552e..e43a7d8 100644
--- a/testing/legion/client_rpc_methods.py
+++ b/testing/legion/client_rpc_methods.py
@@ -4,39 +4,148 @@
"""Defines the client RPC methods."""
+import os
+import sys
import logging
-import subprocess
import threading
+#pylint: disable=relative-import
+import common_lib
+
+# Map swarming_client to use subprocess42
+sys.path.append(common_lib.SWARMING_DIR)
+
+from utils import subprocess42
+
class RPCMethods(object):
"""Class exposing RPC methods."""
+ _dotted_whitelist = ['subprocess']
+
def __init__(self, server):
- self.server = server
+ self._server = server
+ self.subprocess = Subprocess
+
+ def _dispatch(self, method, params):
+ obj = self
+ if '.' in method:
+ # Allow only white listed dotted names
+ name, method = method.split('.')
+ assert name in self._dotted_whitelist
+ obj = getattr(self, name)
+ return getattr(obj, method)(*params)
def Echo(self, message):
"""Simple RPC method to print and return a message."""
logging.info('Echoing %s', message)
return 'echo %s' % str(message)
- def Subprocess(self, cmd):
- """Run the commands in a subprocess.
-
- Returns:
- (returncode, stdout, stderr).
- """
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- stdout, stderr = p.communicate()
- return (p.returncode, stdout, stderr)
-
def Quit(self):
- """Call server.shutdown in another thread.
+ """Call _server.shutdown in another thread.
This is needed because server.shutdown waits for the server to actually
quit. However the server cannot shutdown until it completes handling this
call. Calling this in the same thread results in a deadlock.
"""
- t = threading.Thread(target=self.server.shutdown)
+ t = threading.Thread(target=self._server.shutdown)
t.start()
+
+
+class Subprocess(object):
+ """Implements a server-based non-blocking subprocess.
+
+ 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.
+ """
+
+ _processes = {}
+ _process_next_id = 0
+ _creation_lock = threading.Lock()
+
+ def __init__(self, cmd):
+ self.proc = subprocess42.Popen(cmd, stdout=subprocess42.PIPE,
+ stderr=subprocess42.PIPE)
+ self.stdout = ''
+ self.stderr = ''
+ self.data_lock = threading.Lock()
+ threading.Thread(target=self._run).start()
+
+ def _run(self):
+ for pipe, data in self.proc.yield_any():
+ with self.data_lock:
+ if pipe == 'stdout':
+ self.stdout += data
+ else:
+ self.stderr += data
+
+ @classmethod
+ def Popen(cls, cmd):
+ with cls._creation_lock:
+ key = 'Process%d' % cls._process_next_id
+ cls._process_next_id += 1
+ logging.debug('Creating process %s', key)
+ process = cls(cmd)
+ cls._processes[key] = process
+ return key
+
+ @classmethod
+ def Terminate(cls, key):
+ logging.debug('Terminating and deleting process %s', key)
+ return cls._processes.pop(key).proc.terminate()
+
+ @classmethod
+ def Kill(cls, key):
+ logging.debug('Killing and deleting process %s', key)
+ return cls._processes.pop(key).proc.kill()
+
+ @classmethod
+ def Delete(cls, key):
+ logging.debug('Deleting process %s', key)
+ cls._processes.pop(key)
+
+ @classmethod
+ def GetReturncode(cls, key):
+ return cls._processes[key].proc.returncode
+
+ @classmethod
+ def ReadStdout(cls, key):
+ """Returns all stdout since the last call to ReadStdout.
+
+ This call allows the user to read stdout while the process is running.
+ However each call will flush the local stdout buffer. In order to make
+ multiple calls to ReadStdout and to retain the entire output the results
+ of this call will need to be buffered in the calling code.
+ """
+ proc = cls._processes[key]
+ with proc.data_lock:
+ # Perform a "read" on the stdout data
+ stdout = proc.stdout
+ proc.stdout = ''
+ return stdout
+
+ @classmethod
+ def ReadStderr(cls, key):
+ """Returns all stderr read since the last call to ReadStderr.
+
+ See ReadStdout for additional details.
+ """
+ proc = cls._processes[key]
+ with proc.data_lock:
+ # Perform a "read" on the stderr data
+ stderr = proc.stderr
+ proc.stderr = ''
+ return stderr
+
+ @classmethod
+ def Wait(cls, key):
+ return cls._processes[key].proc.wait()
+
+ @classmethod
+ def Poll(cls, key):
+ return cls._processes[key].proc.poll()
+
+ @classmethod
+ def GetPid(cls, key):
+ return cls._processes[key].proc.pid
diff --git a/testing/legion/common_lib.py b/testing/legion/common_lib.py
index b66481e..2f527ea 100644
--- a/testing/legion/common_lib.py
+++ b/testing/legion/common_lib.py
@@ -6,6 +6,7 @@
import argparse
import logging
+import os
import socket
import xmlrpclib
@@ -14,6 +15,8 @@
SERVER_ADDRESS = ''
SERVER_PORT = 31710
DEFAULT_TIMEOUT_SECS = 20 * 60 # 30 minutes
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+SWARMING_DIR = os.path.join(THIS_DIR, '..', '..', 'tools', 'swarming_client')
def InitLogging():
diff --git a/testing/legion/examples/hello_world/host_test.py b/testing/legion/examples/hello_world/host_test.py
index 77eca06..7a7875b 100755
--- a/testing/legion/examples/hello_world/host_test.py
+++ b/testing/legion/examples/hello_world/host_test.py
@@ -32,7 +32,7 @@
client = self.NewClient(
isolate_file='client_test.isolate',
config_vars={'multi_machine': '1'},
- dimensions={'os': 'Linux', 'pool': 'legion'}, priority=200,
+ dimensions={'os': 'legion-linux'}, priority=200,
idle_timeout_secs=90, connection_timeout_secs=90,
verbosity=logging.INFO)
client.Create()
@@ -60,13 +60,16 @@
def CallEcho(self, client):
"""Call rpc.Echo on a client."""
logging.info('Calling Echo on %s', client.name)
- logging.info(self.client1.rpc.Echo(client.name))
+ logging.info(client.rpc.Echo(client.name))
def CallClientTest(self, client):
"""Call client_test.py name on a client."""
logging.info('Calling Subprocess to run "./client_test.py %s"', client.name)
- retcode, stdout, stderr = client.rpc.Subprocess(
- ['./client_test.py', client.name])
+ proc = client.rpc.subprocess.Popen(['./client_test.py', client.name])
+ client.rpc.subprocess.Wait(proc)
+ retcode = client.rpc.subprocess.GetReturncode(proc)
+ stdout = client.rpc.subprocess.ReadStdout(proc)
+ stderr = client.rpc.subprocess.ReadStderr(proc)
logging.info('retcode: %s, stdout: %s, stderr: %s', retcode, stdout, stderr)
diff --git a/testing/legion/examples/subprocess/client.isolate b/testing/legion/examples/subprocess/client.isolate
new file mode 100644
index 0000000..611562c
--- /dev/null
+++ b/testing/legion/examples/subprocess/client.isolate
@@ -0,0 +1,22 @@
+# 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.
+
+{
+ 'includes': [
+ '../../legion.isolate'
+ ],
+ 'conditions': [
+ ['multi_machine == 1', {
+ 'variables': {
+ 'command': [
+ 'python',
+ '../../client_controller.py',
+ ],
+ 'files': [
+ 'client.isolate'
+ ],
+ },
+ }],
+ ],
+}
diff --git a/testing/legion/examples/subprocess/subprocess_test.isolate b/testing/legion/examples/subprocess/subprocess_test.isolate
new file mode 100644
index 0000000..5b20167
--- /dev/null
+++ b/testing/legion/examples/subprocess/subprocess_test.isolate
@@ -0,0 +1,22 @@
+# 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.
+
+{
+ 'includes': [
+ '../../legion.isolate',
+ 'client.isolate'
+ ],
+ 'conditions': [
+ ['multi_machine == 1', {
+ 'variables': {
+ 'command': [
+ 'subprocess_test.py',
+ ],
+ 'files': [
+ 'subprocess_test.py',
+ ],
+ },
+ }],
+ ]
+}
diff --git a/testing/legion/examples/subprocess/subprocess_test.py b/testing/legion/examples/subprocess/subprocess_test.py
new file mode 100755
index 0000000..6d8ce87
--- /dev/null
+++ b/testing/legion/examples/subprocess/subprocess_test.py
@@ -0,0 +1,79 @@
+#!/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.
+
+"""A host test module demonstrating interacting with remote subprocesses."""
+
+# Map the legion directory so we can import the host controller.
+import sys
+sys.path.append('../../')
+
+import logging
+import time
+import xmlrpclib
+
+import host_controller
+
+
+class ExampleController(host_controller.HostController):
+ """An example controller using the remote subprocess functions."""
+
+ def __init__(self):
+ super(ExampleController, self).__init__()
+ self.client = None
+
+ def SetUp(self):
+ """Creates the client machine and waits until it connects."""
+ self.client = self.NewClient(
+ isolate_file='client.isolate',
+ config_vars={'multi_machine': '1'},
+ dimensions={'os': 'legion-linux'},
+ idle_timeout_secs=90, connection_timeout_secs=90,
+ verbosity=logging.DEBUG)
+ self.client.Create()
+ self.client.WaitForConnection()
+
+ def Task(self):
+ """Main method to run the task code."""
+ self.TestLs()
+ self.TestTerminate()
+ self.TestMultipleProcesses()
+
+ def TestMultipleProcesses(self):
+ start = time.time()
+
+ sleep20 = self.client.rpc.subprocess.Popen(['sleep', '20'])
+ sleep10 = self.client.rpc.subprocess.Popen(['sleep', '10'])
+
+ self.client.rpc.subprocess.Wait(sleep10)
+ elapsed = time.time() - start
+ assert elapsed >= 10 and elapsed < 11
+
+ self.client.rpc.subprocess.Wait(sleep20)
+ elapsed = time.time() - start
+ assert elapsed >= 20
+
+ self.client.rpc.subprocess.Delete(sleep20)
+ self.client.rpc.subprocess.Delete(sleep10)
+
+ def TestTerminate(self):
+ start = time.time()
+ proc = self.client.rpc.subprocess.Popen(['sleep', '20'])
+ self.client.rpc.subprocess.Terminate(proc) # Implicitly deleted
+ try:
+ self.client.rpc.subprocess.Wait(proc)
+ except xmlrpclib.Fault:
+ pass
+ assert time.time() - start < 20
+
+ def TestLs(self):
+ proc = self.client.rpc.subprocess.Popen(['ls'])
+ self.client.rpc.subprocess.Wait(proc)
+ assert self.client.rpc.subprocess.GetReturncode(proc) == 0
+ assert 'client.isolate' in self.client.rpc.subprocess.ReadStdout(proc)
+ self.client.rpc.subprocess.Delete(proc)
+
+
+if __name__ == '__main__':
+ ExampleController().RunController()
diff --git a/testing/scripts/host_info.py b/testing/scripts/host_info.py
new file mode 100755
index 0000000..b3131d8
--- /dev/null
+++ b/testing/scripts/host_info.py
@@ -0,0 +1,136 @@
+#!/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.
+
+import json
+import multiprocessing
+import os
+import platform
+import subprocess
+import sys
+
+
+import common
+
+
+def is_linux():
+ return sys.platform.startswith('linux')
+
+
+def get_free_disk_space(failures):
+ """Returns the amount of free space on the current disk, in GiB.
+
+ Returns:
+ The amount of free space on the current disk, measured in GiB.
+ """
+ if os.name == 'posix':
+ # Stat the current path for info on the current disk.
+ stat_result = os.statvfs('.')
+ # Multiply block size by number of free blocks, express in GiB.
+ return stat_result.f_frsize * stat_result.f_bavail / (
+ 1024.0 / 1024.0 / 1024.0)
+
+ failures.append('get_free_disk_space: OS %s not supported.' % os.name)
+ return 0
+
+
+def get_num_cpus(failures):
+ """Returns the number of logical CPUs on this machine.
+
+ Returns:
+ The number of logical CPUs on this machine, or 'unknown' if indeterminate.
+ """
+ try:
+ return multiprocessing.cpu_count()
+ except NotImplementedError:
+ failures.append('get_num_cpus')
+ return 'unknown'
+
+
+def get_device_info(args, failures):
+ """Parses the device info for each attached device, and returns a summary
+ of the device info and any mismatches.
+
+ Returns:
+ A dict indicating the result.
+ """
+ if not is_linux():
+ return {}
+
+ with common.temporary_file() as tempfile_path:
+ rc = common.run_command([
+ sys.executable,
+ os.path.join(args.paths['checkout'],
+ 'build',
+ 'android',
+ 'buildbot',
+ 'bb_device_status_check.py'),
+ '--json-output', tempfile_path])
+
+ if rc:
+ failures.append('bb_device_status_check')
+ return {}
+
+ with open(tempfile_path, 'r') as src:
+ device_info = json.load(src)
+
+ results = {}
+ results['devices'] = sorted(v['serial'] for v in device_info)
+
+ details = [v['build_detail'] for v in device_info]
+
+ def unique_build_details(index):
+ return sorted(list(set([v.split(':')[index] for v in details])))
+
+ parsed_details = {
+ 'device_names': unique_build_details(0),
+ 'build_versions': unique_build_details(1),
+ 'build_types': unique_build_details(2),
+ }
+
+ for k, v in parsed_details.iteritems():
+ if len(v) == 1:
+ results[k] = v[0]
+ else:
+ results[k] = 'MISMATCH'
+ results['%s_list' % k] = v
+ failures.append(k)
+
+ return results
+
+
+def main_run(args):
+ failures = []
+ host_info = {}
+ host_info['os_system'] = platform.system()
+ host_info['os_release'] = platform.release()
+
+ host_info['processor'] = platform.processor()
+ host_info['num_cpus'] = get_num_cpus(failures)
+ host_info['free_disk_space'] = get_free_disk_space(failures)
+
+ host_info['python_version'] = platform.python_version()
+ host_info['python_path'] = sys.executable
+
+ host_info['devices'] = get_device_info(args, failures)
+
+ json.dump({
+ 'valid': True,
+ 'failures': failures,
+ '_host_info': host_info,
+ }, args.output)
+
+ return len(failures) != 0
+
+
+def main_compile_targets(args):
+ json.dump([], args.output)
+
+
+if __name__ == '__main__':
+ funcs = {
+ 'run': main_run,
+ 'compile_targets': main_compile_targets,
+ }
+ sys.exit(common.run_script(sys.argv[1:], funcs))
diff --git a/testing/scripts/webview_licenses.py b/testing/scripts/webview_licenses.py
new file mode 100755
index 0000000..255c62e
--- /dev/null
+++ b/testing/scripts/webview_licenses.py
@@ -0,0 +1,43 @@
+#!/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.
+
+import json
+import os
+import sys
+
+
+import common
+
+
+def main_run(args):
+ with common.temporary_file() as tempfile_path:
+ rc = common.run_command([
+ os.path.join(common.SRC_DIR, 'android_webview', 'tools',
+ 'webview_licenses.py'),
+ 'scan',
+ '--json', tempfile_path
+ ])
+
+ with open(tempfile_path) as f:
+ results = json.load(f)
+
+ json.dump({
+ 'valid': True,
+ 'failures': results,
+ }, args.output)
+
+ return rc
+
+
+def main_compile_targets(args):
+ json.dump([], args.output)
+
+
+if __name__ == '__main__':
+ funcs = {
+ 'run': main_run,
+ 'compile_targets': main_compile_targets,
+ }
+ sys.exit(common.run_script(sys.argv[1:], funcs))
diff --git a/testing/test_env.py b/testing/test_env.py
index 66a3721..d19f74f 100755
--- a/testing/test_env.py
+++ b/testing/test_env.py
@@ -73,20 +73,23 @@
# fact, it needs symbolization to be able to apply suppressions.
symbolization_options = ['symbolize=1',
'external_symbolizer_path=%s' % symbolizer_path]
- elif asan or msan:
- # ASan uses a script for offline symbolization.
+ elif (asan or msan) and sys.platform not in ['win32', 'cygwin']:
+ # ASan uses a script for offline symbolization, except on Windows.
# Important note: when running ASan with leak detection enabled, we must use
# the LSan symbolization options above.
symbolization_options = ['symbolize=0']
# Set the path to llvm-symbolizer to be used by asan_symbolize.py
extra_env['LLVM_SYMBOLIZER_PATH'] = symbolizer_path
+ else:
+ symbolization_options = []
if asan:
asan_options = symbolization_options[:]
if lsan:
asan_options.append('detect_leaks=1')
- extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
+ if asan_options:
+ extra_env['ASAN_OPTIONS'] = ' '.join(asan_options)
if sys.platform == 'darwin':
isolate_output_dir = os.path.abspath(os.path.dirname(cmd[0]))
@@ -183,7 +186,13 @@
lsan = '--lsan=1' in cmd
msan = '--msan=1' in cmd
tsan = '--tsan=1' in cmd
- use_symbolization_script = (asan or msan) and not lsan
+ if sys.platform in ['win32', 'cygwin']:
+ # Symbolization works in-process on Windows even when sandboxed.
+ use_symbolization_script = False
+ else:
+ # LSan doesn't support sandboxing yet, so we use the in-process symbolizer.
+ # Note that ASan and MSan can work together with LSan.
+ use_symbolization_script = (asan or msan) and not lsan
if asan or lsan or msan or tsan:
extra_env.update(get_sanitizer_env(cmd, asan, lsan, msan, tsan))
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi
index 0750678..d44071e 100644
--- a/third_party/boringssl/boringssl.gypi
+++ b/third_party/boringssl/boringssl.gypi
@@ -27,7 +27,6 @@
'src/crypto/asn1/a_type.c',
'src/crypto/asn1/a_utctm.c',
'src/crypto/asn1/a_utf8.c',
- 'src/crypto/asn1/asn1_error.c',
'src/crypto/asn1/asn1_lib.c',
'src/crypto/asn1/asn1_par.c',
'src/crypto/asn1/asn_pack.c',
@@ -49,7 +48,6 @@
'src/crypto/asn1/x_long.c',
'src/crypto/base64/base64.c',
'src/crypto/bio/bio.c',
- 'src/crypto/bio/bio_error.c',
'src/crypto/bio/bio_mem.c',
'src/crypto/bio/buffer.c',
'src/crypto/bio/connect.c',
@@ -63,7 +61,6 @@
'src/crypto/bn/add.c',
'src/crypto/bn/asm/x86_64-gcc.c',
'src/crypto/bn/bn.c',
- 'src/crypto/bn/bn_error.c',
'src/crypto/bn/cmp.c',
'src/crypto/bn/convert.c',
'src/crypto/bn/ctx.c',
@@ -80,7 +77,6 @@
'src/crypto/bn/shift.c',
'src/crypto/bn/sqrt.c',
'src/crypto/buf/buf.c',
- 'src/crypto/buf/buf_error.c',
'src/crypto/bytestring/ber.c',
'src/crypto/bytestring/cbb.c',
'src/crypto/bytestring/cbs.c',
@@ -88,7 +84,6 @@
'src/crypto/chacha/chacha_vec.c',
'src/crypto/cipher/aead.c',
'src/crypto/cipher/cipher.c',
- 'src/crypto/cipher/cipher_error.c',
'src/crypto/cipher/derive_key.c',
'src/crypto/cipher/e_aes.c',
'src/crypto/cipher/e_chacha20poly1305.c',
@@ -100,42 +95,33 @@
'src/crypto/cipher/e_tls.c',
'src/crypto/cipher/tls_cbc.c',
'src/crypto/conf/conf.c',
- 'src/crypto/conf/conf_error.c',
'src/crypto/cpu-arm.c',
'src/crypto/cpu-intel.c',
'src/crypto/crypto.c',
- 'src/crypto/crypto_error.c',
'src/crypto/des/des.c',
'src/crypto/dh/check.c',
'src/crypto/dh/dh.c',
'src/crypto/dh/dh_asn1.c',
- 'src/crypto/dh/dh_error.c',
'src/crypto/dh/dh_impl.c',
'src/crypto/dh/params.c',
'src/crypto/digest/digest.c',
- 'src/crypto/digest/digest_error.c',
'src/crypto/digest/digests.c',
'src/crypto/directory_posix.c',
'src/crypto/directory_win.c',
'src/crypto/dsa/dsa.c',
'src/crypto/dsa/dsa_asn1.c',
- 'src/crypto/dsa/dsa_error.c',
'src/crypto/dsa/dsa_impl.c',
'src/crypto/ec/ec.c',
'src/crypto/ec/ec_asn1.c',
- 'src/crypto/ec/ec_error.c',
'src/crypto/ec/ec_key.c',
'src/crypto/ec/ec_montgomery.c',
'src/crypto/ec/oct.c',
'src/crypto/ec/simple.c',
'src/crypto/ec/wnaf.c',
'src/crypto/ecdh/ecdh.c',
- 'src/crypto/ecdh/ecdh_error.c',
'src/crypto/ecdsa/ecdsa.c',
'src/crypto/ecdsa/ecdsa_asn1.c',
- 'src/crypto/ecdsa/ecdsa_error.c',
'src/crypto/engine/engine.c',
- 'src/crypto/engine/engine_error.c',
'src/crypto/err/err.c',
'src/crypto/err/err_impl.c',
'src/crypto/evp/algorithm.c',
@@ -143,7 +129,6 @@
'src/crypto/evp/digestsign.c',
'src/crypto/evp/evp.c',
'src/crypto/evp/evp_ctx.c',
- 'src/crypto/evp/evp_error.c',
'src/crypto/evp/p_ec.c',
'src/crypto/evp/p_ec_asn1.c',
'src/crypto/evp/p_hmac.c',
@@ -155,7 +140,6 @@
'src/crypto/ex_data.c',
'src/crypto/ex_data_impl.c',
'src/crypto/hkdf/hkdf.c',
- 'src/crypto/hkdf/hkdf_error.c',
'src/crypto/hmac/hmac.c',
'src/crypto/lhash/lhash.c',
'src/crypto/md4/md4.c',
@@ -167,10 +151,8 @@
'src/crypto/modes/gcm.c',
'src/crypto/modes/ofb.c',
'src/crypto/obj/obj.c',
- 'src/crypto/obj/obj_error.c',
'src/crypto/obj/obj_xref.c',
'src/crypto/pem/pem_all.c',
- 'src/crypto/pem/pem_error.c',
'src/crypto/pem/pem_info.c',
'src/crypto/pem/pem_lib.c',
'src/crypto/pem/pem_oth.c',
@@ -182,7 +164,6 @@
'src/crypto/pkcs8/p5_pbev2.c',
'src/crypto/pkcs8/p8_pkey.c',
'src/crypto/pkcs8/pkcs8.c',
- 'src/crypto/pkcs8/pkcs8_error.c',
'src/crypto/poly1305/poly1305.c',
'src/crypto/poly1305/poly1305_arm.c',
'src/crypto/poly1305/poly1305_vec.c',
@@ -194,7 +175,6 @@
'src/crypto/rsa/padding.c',
'src/crypto/rsa/rsa.c',
'src/crypto/rsa/rsa_asn1.c',
- 'src/crypto/rsa/rsa_error.c',
'src/crypto/rsa/rsa_impl.c',
'src/crypto/sha/sha1.c',
'src/crypto/sha/sha256.c',
@@ -219,7 +199,6 @@
'src/crypto/x509/x509_cmp.c',
'src/crypto/x509/x509_d2.c',
'src/crypto/x509/x509_def.c',
- 'src/crypto/x509/x509_error.c',
'src/crypto/x509/x509_ext.c',
'src/crypto/x509/x509_lu.c',
'src/crypto/x509/x509_obj.c',
@@ -283,7 +262,6 @@
'src/crypto/x509v3/v3_skey.c',
'src/crypto/x509v3/v3_sxnet.c',
'src/crypto/x509v3/v3_utl.c',
- 'src/crypto/x509v3/x509v3_error.c',
'src/ssl/d1_both.c',
'src/ssl/d1_clnt.c',
'src/ssl/d1_lib.c',
@@ -303,7 +281,6 @@
'src/ssl/ssl_asn1.c',
'src/ssl/ssl_cert.c',
'src/ssl/ssl_ciph.c',
- 'src/ssl/ssl_error.c',
'src/ssl/ssl_lib.c',
'src/ssl/ssl_rsa.c',
'src/ssl/ssl_sess.c',
diff --git a/third_party/fontconfig/OWNERS b/third_party/fontconfig/OWNERS
index 7e5af1d..82160d5 100644
--- a/third_party/fontconfig/OWNERS
+++ b/third_party/fontconfig/OWNERS
@@ -1,3 +1,2 @@
spang@chromium.org
-rjkroege@chromium.org
-spang@chromium.org
+dnicoara@chromium.org
diff --git a/cc/layers/video_frame_provider_client_impl.cc b/third_party/fontconfig/chromium/empty.cc
similarity index 100%
rename from cc/layers/video_frame_provider_client_impl.cc
rename to third_party/fontconfig/chromium/empty.cc
diff --git a/third_party/fontconfig/fontconfig.gyp b/third_party/fontconfig/fontconfig.gyp
index c3b350c..3565a7f 100644
--- a/third_party/fontconfig/fontconfig.gyp
+++ b/third_party/fontconfig/fontconfig.gyp
@@ -26,6 +26,7 @@
}],
],
'sources': [
+ 'chromium/empty.cc',
'src/src/fcarch.h',
'src/src/fcatomic.c',
'src/src/fcblanks.c',
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium
index e365af4..5c70ed1 100644
--- a/third_party/harfbuzz-ng/README.chromium
+++ b/third_party/harfbuzz-ng/README.chromium
@@ -1,8 +1,8 @@
Name: harfbuzz-ng
Short Name: harfbuzz-ng
URL: http://harfbuzz.org
-Version: 0.9.37
-Date: 20141217
+Version: 0.9.38
+Date: 20150212
Security Critical: yes
License: MIT
License File: COPYING
diff --git a/third_party/harfbuzz-ng/src/hb-blob.cc b/third_party/harfbuzz-ng/src/hb-blob.cc
index b82b4b2..8759a25 100644
--- a/third_party/harfbuzz-ng/src/hb-blob.cc
+++ b/third_party/harfbuzz-ng/src/hb-blob.cc
@@ -78,8 +78,8 @@
}
/**
- * hb_blob_create: (Xconstructor)
- * @data: (array length=length) (closure user_data) (destroy destroy) (scope notified) (transfer none): Pointer to blob data.
+ * hb_blob_create: (skip)
+ * @data: Pointer to blob data.
* @length: Length of @data in bytes.
* @mode: Memory mode for @data.
* @user_data: Data parameter to pass to @destroy.
@@ -102,7 +102,10 @@
{
hb_blob_t *blob;
- if (!length || !(blob = hb_object_create<hb_blob_t> ())) {
+ if (!length ||
+ length >= 1u << 31 ||
+ data + length < data /* overflows */ ||
+ !(blob = hb_object_create<hb_blob_t> ())) {
if (destroy)
destroy (user_data);
return hb_blob_get_empty ();
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.cc b/third_party/harfbuzz-ng/src/hb-buffer.cc
index 74ae273..0500aa2 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.cc
+++ b/third_party/harfbuzz-ng/src/hb-buffer.cc
@@ -1328,15 +1328,15 @@
buffer->guess_segment_properties ();
}
-template <bool validate, typename T>
+template <typename utf_t>
static inline void
hb_buffer_add_utf (hb_buffer_t *buffer,
- const T *text,
+ const typename utf_t::codepoint_t *text,
int text_length,
unsigned int item_offset,
int item_length)
{
- typedef hb_utf_t<T, true> utf_t;
+ typedef typename utf_t::codepoint_t T;
const hb_codepoint_t replacement = buffer->replacement;
assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
@@ -1400,7 +1400,7 @@
/**
* hb_buffer_add_utf8:
* @buffer: a buffer.
- * @text: (array length=text_length):
+ * @text: (array length=text_length) (element-type uint8_t):
* @text_length:
* @item_offset:
* @item_length:
@@ -1416,7 +1416,7 @@
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf<true> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
+ hb_buffer_add_utf<hb_utf8_t> (buffer, (const uint8_t *) text, text_length, item_offset, item_length);
}
/**
@@ -1438,7 +1438,7 @@
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
+ hb_buffer_add_utf<hb_utf16_t> (buffer, text, text_length, item_offset, item_length);
}
/**
@@ -1460,7 +1460,29 @@
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf<true> (buffer, text, text_length, item_offset, item_length);
+ hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
+}
+
+/**
+ * hb_buffer_add_latin1:
+ * @buffer: a buffer.
+ * @text: (array length=text_length) (element-type uint8_t):
+ * @text_length:
+ * @item_offset:
+ * @item_length:
+ *
+ *
+ *
+ * Since: 1.0
+ **/
+void
+hb_buffer_add_latin1 (hb_buffer_t *buffer,
+ const uint8_t *text,
+ int text_length,
+ unsigned int item_offset,
+ int item_length)
+{
+ hb_buffer_add_utf<hb_latin1_t> (buffer, text, text_length, item_offset, item_length);
}
/**
@@ -1482,7 +1504,7 @@
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf<false> (buffer, text, text_length, item_offset, item_length);
+ hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
}
diff --git a/third_party/harfbuzz-ng/src/hb-buffer.h b/third_party/harfbuzz-ng/src/hb-buffer.h
index 7b0c920..e5b46d8 100644
--- a/third_party/harfbuzz-ng/src/hb-buffer.h
+++ b/third_party/harfbuzz-ng/src/hb-buffer.h
@@ -253,6 +253,14 @@
unsigned int item_offset,
int item_length);
+/* Allows only access to first 256 Unicode codepoints. */
+void
+hb_buffer_add_latin1 (hb_buffer_t *buffer,
+ const uint8_t *text,
+ int text_length,
+ unsigned int item_offset,
+ int item_length);
+
/* Like add_utf32 but does NOT check for invalid Unicode codepoints. */
void
hb_buffer_add_codepoints (hb_buffer_t *buffer,
diff --git a/third_party/harfbuzz-ng/src/hb-common.cc b/third_party/harfbuzz-ng/src/hb-common.cc
index a6a5144..05a1f9c 100644
--- a/third_party/harfbuzz-ng/src/hb-common.cc
+++ b/third_party/harfbuzz-ng/src/hb-common.cc
@@ -235,7 +235,7 @@
static hb_language_item_t *langs;
#ifdef HB_USE_ATEXIT
-static inline
+static
void free_langs (void)
{
while (langs) {
@@ -265,6 +265,7 @@
*lang = key;
if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
+ lang->finish ();
free (lang);
goto retry;
}
@@ -345,7 +346,7 @@
hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
if (unlikely (language == HB_LANGUAGE_INVALID)) {
language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1);
- hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
+ (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
}
return default_language;
diff --git a/third_party/harfbuzz-ng/src/hb-coretext.cc b/third_party/harfbuzz-ng/src/hb-coretext.cc
index 11629cc..4a45175 100644
--- a/third_party/harfbuzz-ng/src/hb-coretext.cc
+++ b/third_party/harfbuzz-ng/src/hb-coretext.cc
@@ -140,6 +140,7 @@
struct hb_coretext_shaper_font_data_t {
CTFontRef ct_font;
+ CGFloat x_mult, y_mult; /* From CT space to HB space. */
};
hb_coretext_shaper_font_data_t *
@@ -154,7 +155,17 @@
hb_face_t *face = font->face;
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
- data->ct_font = CTFontCreateWithGraphicsFont (face_data, font->y_scale, NULL, NULL);
+ /* Choose a CoreText font size and calculate multipliers to convert to HarfBuzz space. */
+ CGFloat font_size = 36.; /* Default... */
+ /* No idea if the following is even a good idea. */
+ if (font->y_ppem)
+ font_size = font->y_ppem;
+
+ if (font_size < 0)
+ font_size = -font_size;
+ data->x_mult = (CGFloat) font->x_scale / font_size;
+ data->y_mult = (CGFloat) font->y_scale / font_size;
+ data->ct_font = CTFontCreateWithGraphicsFont (face_data, font_size, NULL, NULL);
if (unlikely (!data->ct_font)) {
DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
free (data);
@@ -776,6 +787,7 @@
buffer->len = 0;
uint32_t status_and = ~0, status_or = 0;
+ double advances_so_far = 0;
const CFRange range_all = CFRangeMake (0, 0);
@@ -786,6 +798,10 @@
status_or |= run_status;
status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
+ double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL);
+ if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
+ run_advance = -run_advance;
+ DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
/* CoreText does automatic font fallback (AKA "cascading") for characters
* not supported by the requested font, and provides no way to turn it off,
@@ -860,8 +876,14 @@
goto resize_and_retry;
hb_glyph_info_t *info = buffer->info + buffer->len;
- CGGlyph notdef = 0;
- double advance = CTFontGetAdvancesForGlyphs (font_data->ct_font, kCTFontHorizontalOrientation, ¬def, NULL, 1);
+ hb_codepoint_t notdef = 0;
+ hb_direction_t dir = buffer->props.direction;
+ hb_position_t x_advance, y_advance, x_offset, y_offset;
+ hb_font_get_glyph_advance_for_direction (font, notdef, dir, &x_advance, &y_advance);
+ hb_font_get_glyph_origin_for_direction (font, notdef, dir, &x_offset, &y_offset);
+ hb_position_t advance = x_advance + y_advance;
+ x_offset = -x_offset;
+ y_offset = -y_offset;
unsigned int old_len = buffer->len;
for (CFIndex j = range.location; j < range.location + range.length; j++)
@@ -875,19 +897,22 @@
* for this one. */
continue;
}
+ if (buffer->unicode->is_default_ignorable (ch))
+ continue;
info->codepoint = notdef;
info->cluster = log_clusters[j];
info->mask = advance;
- info->var1.u32 = 0;
- info->var2.u32 = 0;
+ info->var1.u32 = x_offset;
+ info->var2.u32 = y_offset;
info++;
buffer->len++;
}
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
buffer->reverse_range (old_len, buffer->len);
+ advances_so_far += run_advance;
continue;
}
}
@@ -917,7 +942,7 @@
scratch_size = scratch_size_saved; \
scratch = scratch_saved;
- {
+ { /* Setup glyphs */
SCRATCH_SAVE();
const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL;
if (!glyphs) {
@@ -941,6 +966,11 @@
SCRATCH_RESTORE();
}
{
+ /* Setup positions.
+ * Note that CoreText does not return advances for glyphs. As such,
+ * for all but last glyph, we use the delta position to next glyph as
+ * advance (in the advance direction only), and for last glyph we set
+ * whatever is needed to make the whole run's advance add up. */
SCRATCH_SAVE();
const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL;
if (!positions) {
@@ -948,33 +978,42 @@
CTRunGetPositions (run, range_all, position_buf);
positions = position_buf;
}
- double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL);
- DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance);
hb_glyph_info_t *info = run_info;
+ CGFloat x_mult = font_data->x_mult, y_mult = font_data->y_mult;
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
{
+ hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult;
for (unsigned int j = 0; j < num_glyphs; j++)
{
- double advance = (j + 1 < num_glyphs ? positions[j + 1].x : positions[0].x + run_advance) - positions[j].x;
- info->mask = advance;
- info->var1.u32 = positions[0].x; /* Yes, zero. */
- info->var2.u32 = positions[j].y;
+ double advance;
+ if (likely (j + 1 < num_glyphs))
+ advance = positions[j + 1].x - positions[j].x;
+ else /* last glyph */
+ advance = run_advance - (positions[j].x - positions[0].x);
+ info->mask = advance * x_mult;
+ info->var1.u32 = x_offset;
+ info->var2.u32 = positions[j].y * y_mult;
info++;
}
}
else
{
- run_advance = -run_advance;
+ hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult;
for (unsigned int j = 0; j < num_glyphs; j++)
{
- double advance = (j + 1 < num_glyphs ? positions[j + 1].y : positions[0].y + run_advance) - positions[j].y;
- info->mask = advance;
- info->var1.u32 = positions[j].x;
- info->var2.u32 = positions[0].y; /* Yes, zero. */
+ double advance;
+ if (likely (j + 1 < num_glyphs))
+ advance = positions[j + 1].y - positions[j].y;
+ else /* last glyph */
+ advance = run_advance - (positions[j].y - positions[0].y);
+ info->mask = advance * y_mult;
+ info->var1.u32 = positions[j].x * x_mult;
+ info->var2.u32 = y_offset;
info++;
}
}
SCRATCH_RESTORE();
+ advances_so_far += run_advance;
}
#undef SCRATCH_RESTORE
#undef SCRATCH_SAVE
diff --git a/third_party/harfbuzz-ng/src/hb-ft.cc b/third_party/harfbuzz-ng/src/hb-ft.cc
index c42d484..f57f566 100644
--- a/third_party/harfbuzz-ng/src/hb-ft.cc
+++ b/third_party/harfbuzz-ng/src/hb-ft.cc
@@ -51,6 +51,13 @@
* In particular, FT_Get_Advance() without the NO_HINTING flag seems to be
* buggy.
*
+ * FreeType works in 26.6 mode. Clients can decide to use that mode, and everything
+ * would work fine. However, we also abuse this API for performing in font-space,
+ * but don't pass the correct flags to FreeType. We just abuse the no-hinting mode
+ * for that, such that no rounding etc happens. As such, we don't set ppem, and
+ * pass NO_HINTING around. This seems to work best, until we go ahead and add a full
+ * load_flags API.
+ *
* - We don't handle / allow for emboldening / obliqueing.
*
* - In the future, we should add constructors to create fonts in font space?
@@ -70,12 +77,10 @@
{
FT_Face ft_face = (FT_Face) font_data;
-#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
if (unlikely (variation_selector)) {
*glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
return *glyph != 0;
}
-#endif
*glyph = FT_Get_Char_Index (ft_face, unicode);
return *glyph != 0;
@@ -94,6 +99,9 @@
if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v)))
return 0;
+ if (font->x_scale < 0)
+ v = -v;
+
return (v + (1<<9)) >> 10;
}
@@ -340,11 +348,7 @@
blob = hb_blob_create ((const char *) ft_face->stream->base,
(unsigned int) ft_face->stream->size,
- /* TODO: We assume that it's mmap()'ed, but FreeType code
- * suggests that there are cases we reach here but font is
- * not mmapped. For example, when mmap() fails. No idea
- * how to deal with it better here. */
- HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
+ HB_MEMORY_MODE_READONLY,
ft_face, destroy);
face = hb_face_create (blob, ft_face->face_index);
hb_blob_destroy (blob);
@@ -358,6 +362,22 @@
return face;
}
+/**
+ * hb_ft_face_create_referenced:
+ * @ft_face:
+ *
+ *
+ *
+ * Return value: (transfer full):
+ * Since: 1.0
+ **/
+hb_face_t *
+hb_ft_face_create_referenced (FT_Face ft_face)
+{
+ FT_Reference_Face (ft_face);
+ return hb_ft_face_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
+}
+
static void
hb_ft_face_finalize (FT_Face ft_face)
{
@@ -420,23 +440,43 @@
hb_font_set_scale (font,
(int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16),
(int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16));
+#if 0 /* hb-ft works in no-hinting model */
hb_font_set_ppem (font,
ft_face->size->metrics.x_ppem,
ft_face->size->metrics.y_ppem);
+#endif
return font;
}
+/**
+ * hb_ft_font_create_referenced:
+ * @ft_face:
+ *
+ *
+ *
+ * Return value: (transfer full):
+ * Since: 1.0
+ **/
+hb_font_t *
+hb_ft_font_create_referenced (FT_Face ft_face)
+{
+ FT_Reference_Face (ft_face);
+ return hb_ft_font_create (ft_face, (hb_destroy_func_t) FT_Done_Face);
+}
+
/* Thread-safe, lock-free, FT_Library */
static FT_Library ft_library;
-static inline
+#ifdef HB_USE_ATEXIT
+static
void free_ft_library (void)
{
FT_Done_FreeType (ft_library);
}
+#endif
static FT_Library
get_ft_library (void)
@@ -493,14 +533,19 @@
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
- assert (font->y_scale >= 0);
FT_Set_Char_Size (ft_face,
- font->x_scale, font->y_scale,
+ abs (font->x_scale), abs (font->y_scale),
0, 0);
#if 0
font->x_ppem * 72 * 64 / font->x_scale,
font->y_ppem * 72 * 64 / font->y_scale);
#endif
+ if (font->x_scale < 0 || font->y_scale < 0)
+ {
+ FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
+ 0, font->y_scale < 0 ? -1 : +1};
+ FT_Set_Transform (ft_face, &matrix, NULL);
+ }
ft_face->generic.data = blob;
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
diff --git a/third_party/harfbuzz-ng/src/hb-ft.h b/third_party/harfbuzz-ng/src/hb-ft.h
index 696251e..92f4b36 100644
--- a/third_party/harfbuzz-ng/src/hb-ft.h
+++ b/third_party/harfbuzz-ng/src/hb-ft.h
@@ -34,19 +34,76 @@
HB_BEGIN_DECLS
-/* Note: FreeType is not thread-safe. Hence, these functions are not either. */
+/*
+ * Note: FreeType is not thread-safe.
+ * Hence, these functions are not either.
+ */
+/*
+ * hb-face from ft-face.
+ */
+
+/* This one creates a new hb-face for given ft-face.
+ * When the returned hb-face is destroyed, the destroy
+ * callback is called (if not NULL), with the ft-face passed
+ * to it.
+ *
+ * The client is responsible to make sure that ft-face is
+ * destroyed after hb-face is destroyed.
+ *
+ * Most often you don't want this function. You should use either
+ * hb_ft_face_create_cached(), or hb_ft_face_create_referenced().
+ * In particular, if you are going to pass NULL as destroy, you
+ * probably should use (the more recent) hb_ft_face_create_referenced()
+ * instead.
+ */
hb_face_t *
hb_ft_face_create (FT_Face ft_face,
hb_destroy_func_t destroy);
+/* This version is like hb_ft_face_create(), except that it caches
+ * the hb-face using the generic pointer of the ft-face. This means
+ * that subsequent calls to this function with the same ft-face will
+ * return the same hb-face (correctly referenced).
+ *
+ * Client is still responsible for making sure that ft-face is destroyed
+ * after hb-face is.
+ */
hb_face_t *
hb_ft_face_create_cached (FT_Face ft_face);
+/* This version is like hb_ft_face_create(), except that it calls
+ * FT_Reference_Face() on ft-face, as such keeping ft-face alive
+ * as long as the hb-face is.
+ *
+ * This is the most convenient version to use. Use it unless you have
+ * very good reasons not to.
+ */
+hb_face_t *
+hb_ft_face_create_referenced (FT_Face ft_face);
+
+
+/*
+ * hb-font from ft-face.
+ */
+
+/*
+ * Note:
+ *
+ * Set face size on ft-face before creating hb-font from it.
+ * Otherwise hb-ft would NOT pick up the font size correctly.
+ */
+
+/* See notes on hb_ft_face_create(). Same issues re lifecycle-management
+ * apply here. Use hb_ft_font_create_referenced() if you can. */
hb_font_t *
hb_ft_font_create (FT_Face ft_face,
hb_destroy_func_t destroy);
+/* See notes on hb_ft_face_create_referenced() re lifecycle-management
+ * issues. */
+hb_font_t *
+hb_ft_font_create_referenced (FT_Face ft_face);
/* Makes an hb_font_t use FreeType internally to implement font functions. */
diff --git a/third_party/harfbuzz-ng/src/hb-glib.cc b/third_party/harfbuzz-ng/src/hb-glib.cc
index af43cab..61dff5e 100644
--- a/third_party/harfbuzz-ng/src/hb-glib.cc
+++ b/third_party/harfbuzz-ng/src/hb-glib.cc
@@ -382,3 +382,14 @@
return const_cast<hb_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
}
+hb_blob_t *
+hb_glib_blob_create (GBytes *gbytes)
+{
+ gsize size = 0;
+ gconstpointer data = g_bytes_get_data (gbytes, &size);
+ return hb_blob_create ((const char *) data,
+ size,
+ HB_MEMORY_MODE_READONLY,
+ g_bytes_ref (gbytes),
+ (hb_destroy_func_t) g_bytes_unref);
+}
diff --git a/third_party/harfbuzz-ng/src/hb-glib.h b/third_party/harfbuzz-ng/src/hb-glib.h
index 63a9d33..1a8f42e 100644
--- a/third_party/harfbuzz-ng/src/hb-glib.h
+++ b/third_party/harfbuzz-ng/src/hb-glib.h
@@ -46,6 +46,9 @@
hb_unicode_funcs_t *
hb_glib_get_unicode_funcs (void);
+hb_blob_t *
+hb_glib_blob_create (GBytes *gbytes);
+
HB_END_DECLS
diff --git a/third_party/harfbuzz-ng/src/hb-icu.cc b/third_party/harfbuzz-ng/src/hb-icu.cc
index 86c8b5c..24cec9d 100644
--- a/third_party/harfbuzz-ng/src/hb-icu.cc
+++ b/third_party/harfbuzz-ng/src/hb-icu.cc
@@ -363,10 +363,8 @@
if (!hb_atomic_ptr_get (&normalizer)) {
UErrorCode icu_err = U_ZERO_ERROR;
/* We ignore failure in getNFCInstace(). */
- hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err));
+ (void) hb_atomic_ptr_cmpexch (&normalizer, NULL, unorm2_getNFCInstance (&icu_err));
}
#endif
return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs);
}
-
-
diff --git a/third_party/harfbuzz-ng/src/hb-mutex-private.hh b/third_party/harfbuzz-ng/src/hb-mutex-private.hh
index 6281201..a8ea39c 100644
--- a/third_party/harfbuzz-ng/src/hb-mutex-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-mutex-private.hh
@@ -47,7 +47,11 @@
#include <windows.h>
typedef CRITICAL_SECTION hb_mutex_impl_t;
#define HB_MUTEX_IMPL_INIT {0}
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
+#else
#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
+#endif
#define hb_mutex_impl_lock(M) EnterCriticalSection (M)
#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
diff --git a/third_party/harfbuzz-ng/src/hb-open-type-private.hh b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
index 5616f04..477d9e2 100644
--- a/third_party/harfbuzz-ng/src/hb-open-type-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-open-type-private.hh
@@ -194,6 +194,7 @@
{
this->start = hb_blob_get_data (this->blob, NULL);
this->end = this->start + hb_blob_get_length (this->blob);
+ assert (this->start <= this->end); /* Must not overflow. */
this->edit_count = 0;
this->debug_depth = 0;
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
index 4255f5a..f7fef52 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh
@@ -602,12 +602,24 @@
unsigned int len2 = valueFormats[1].get_len ();
unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
- const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+ const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
unsigned int count = len;
- for (unsigned int i = 0; i < count; i++)
+
+ /* Hand-coded bsearch. */
+ if (unlikely (!count))
+ return TRACE_RETURN (false);
+ hb_codepoint_t x = buffer->info[pos].codepoint;
+ int min = 0, max = (int) count - 1;
+ while (min <= max)
{
- /* TODO bsearch */
- if (buffer->info[pos].codepoint == record->secondGlyph)
+ int mid = (min + max) / 2;
+ const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
+ hb_codepoint_t mid_x = record->secondGlyph;
+ if (x < mid_x)
+ max = mid - 1;
+ else if (x > mid_x)
+ min = mid + 1;
+ else
{
valueFormats[0].apply_value (c->font, c->direction, this,
&record->values[0], buffer->cur_pos());
@@ -618,7 +630,6 @@
buffer->idx = pos;
return TRACE_RETURN (true);
}
- record = &StructAtOffset<PairValueRecord> (record, record_size);
}
return TRACE_RETURN (false);
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
index ae7daa6..3f7c858 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout-private.hh
@@ -126,8 +126,7 @@
lookup.add_coverage (&digest);
}
- template <typename TLookup>
- inline void fini (const TLookup &lookup HB_UNUSED)
+ inline void fini (void)
{
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-layout.cc b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
index 661d90e..602b94e 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-layout.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-layout.cc
@@ -84,9 +84,9 @@
_hb_ot_layout_destroy (hb_ot_layout_t *layout)
{
for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
- layout->gsub_accels[i].fini (layout->gsub->get_lookup (i));
+ layout->gsub_accels[i].fini ();
for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
- layout->gpos_accels[i].fini (layout->gpos->get_lookup (i));
+ layout->gpos_accels[i].fini ();
free (layout->gsub_accels);
free (layout->gpos_accels);
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
index dc659e0..a77f24e 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -327,7 +327,7 @@
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
if (fallback_plan->lookup_array[i])
{
- fallback_plan->accel_array[i].fini (fallback_plan->lookup_array[i]);
+ fallback_plan->accel_array[i].fini ();
if (fallback_plan->free_lookups)
free (fallback_plan->lookup_array[i]);
}
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
index f58380e..2e159a1 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc
@@ -861,41 +861,41 @@
switch (u >> 12)
{
case 0x0u:
- if (hb_in_range (u, 0x0028u, 0x0040u)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
- if (hb_in_range (u, 0x00D0u, 0x00D8u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
- if (hb_in_range (u, 0x0900u, 0x0DF8u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
+ if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
+ if (hb_in_range (u, 0x00D0u, 0x00D7u)) return indic_table[u - 0x00D0u + indic_offset_0x00d0u];
+ if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
if (unlikely (u == 0x00A0u)) return _(CP,x);
break;
case 0x1u:
- if (hb_in_range (u, 0x1000u, 0x10A0u)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
- if (hb_in_range (u, 0x1700u, 0x17F0u)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
- if (hb_in_range (u, 0x1900u, 0x1AA0u)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
- if (hb_in_range (u, 0x1B00u, 0x1C50u)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
- if (hb_in_range (u, 0x1CD0u, 0x1CF8u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+ if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
+ if (hb_in_range (u, 0x1700u, 0x17EFu)) return indic_table[u - 0x1700u + indic_offset_0x1700u];
+ if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return indic_table[u - 0x1900u + indic_offset_0x1900u];
+ if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return indic_table[u - 0x1B00u + indic_offset_0x1b00u];
+ if (hb_in_range (u, 0x1CD0u, 0x1CF7u)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
break;
case 0x2u:
- if (hb_in_range (u, 0x2008u, 0x2018u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
+ if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
if (unlikely (u == 0x25CCu)) return _(CP,x);
break;
case 0xAu:
- if (hb_in_range (u, 0xA800u, 0xAAF8u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
- if (hb_in_range (u, 0xABC0u, 0xAC00u)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
+ if (hb_in_range (u, 0xA800u, 0xAAF7u)) return indic_table[u - 0xA800u + indic_offset_0xa800u];
+ if (hb_in_range (u, 0xABC0u, 0xABFFu)) return indic_table[u - 0xABC0u + indic_offset_0xabc0u];
break;
case 0x10u:
- if (hb_in_range (u, 0x10A00u, 0x10A48u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
+ if (hb_in_range (u, 0x10A00u, 0x10A47u)) return indic_table[u - 0x10A00u + indic_offset_0x10a00u];
break;
case 0x11u:
- if (hb_in_range (u, 0x11000u, 0x110C0u)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
- if (hb_in_range (u, 0x11100u, 0x11238u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
- if (hb_in_range (u, 0x112B0u, 0x11378u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
- if (hb_in_range (u, 0x11480u, 0x114E0u)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
- if (hb_in_range (u, 0x11580u, 0x115C8u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
- if (hb_in_range (u, 0x11600u, 0x116D0u)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
+ if (hb_in_range (u, 0x11000u, 0x110BFu)) return indic_table[u - 0x11000u + indic_offset_0x11000u];
+ if (hb_in_range (u, 0x11100u, 0x11237u)) return indic_table[u - 0x11100u + indic_offset_0x11100u];
+ if (hb_in_range (u, 0x112B0u, 0x11377u)) return indic_table[u - 0x112B0u + indic_offset_0x112b0u];
+ if (hb_in_range (u, 0x11480u, 0x114DFu)) return indic_table[u - 0x11480u + indic_offset_0x11480u];
+ if (hb_in_range (u, 0x11580u, 0x115C7u)) return indic_table[u - 0x11580u + indic_offset_0x11580u];
+ if (hb_in_range (u, 0x11600u, 0x116CFu)) return indic_table[u - 0x11600u + indic_offset_0x11600u];
break;
default:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
index 9a7afcb..e268933 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-complex-private.hh
@@ -259,6 +259,7 @@
/* Unicode-4.1 additions */
case HB_SCRIPT_KHAROSHTHI:
+ case HB_SCRIPT_NEW_TAI_LUE:
case HB_SCRIPT_SYLOTI_NAGRI:
/* Unicode-5.1 additions */
@@ -339,7 +340,6 @@
/* Unicode-4.1 additions */
case HB_SCRIPT_BUGINESE:
- case HB_SCRIPT_NEW_TAI_LUE:
/* Unicode-5.1 additions */
case HB_SCRIPT_CHAM:
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
index 4287253..8cc64af 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc
@@ -197,16 +197,17 @@
decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shortest)
{
hb_buffer_t * const buffer = c->buffer;
+ hb_codepoint_t u = buffer->cur().codepoint;
hb_codepoint_t glyph;
/* Kind of a cute waterfall here... */
- if (shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph))
+ if (shortest && c->font->get_glyph (u, 0, &glyph))
next_char (buffer, glyph);
- else if (decompose (c, shortest, buffer->cur().codepoint))
+ else if (decompose (c, shortest, u))
skip_char (buffer);
- else if (!shortest && c->font->get_glyph (buffer->cur().codepoint, 0, &glyph))
+ else if (!shortest && c->font->get_glyph (u, 0, &glyph))
next_char (buffer, glyph);
- else if (decompose_compatibility (c, buffer->cur().codepoint))
+ else if (decompose_compatibility (c, u))
skip_char (buffer);
else
next_char (buffer, glyph); /* glyph is initialized in earlier branches. */
diff --git a/third_party/harfbuzz-ng/src/hb-ot-shape.cc b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
index a0b503a..07adb04 100644
--- a/third_party/harfbuzz-ng/src/hb-ot-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-ot-shape.cc
@@ -676,7 +676,7 @@
pos[i].y_advance = 0;
}
else
- continue; /* Delete it. */
+ continue; /* Delete it. XXX Merge clusters? */
}
if (j != i)
{
diff --git a/third_party/harfbuzz-ng/src/hb-private.hh b/third_party/harfbuzz-ng/src/hb-private.hh
index c92cdec..45b7712 100644
--- a/third_party/harfbuzz-ng/src/hb-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-private.hh
@@ -94,12 +94,6 @@
# endif
#endif
-#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
-#define snprintf _snprintf
-/* Windows CE only has _strdup, while rest of Windows has both. */
-#define strdup _strdup
-#endif
-
#ifdef _MSC_VER
#undef inline
#define inline __inline
@@ -134,14 +128,20 @@
# ifndef STRICT
# define STRICT 1
# endif
-#endif
-#ifdef _WIN32_WCE
-/* Some things not defined on Windows CE. */
-#define MemoryBarrier()
-#define getenv(Name) NULL
-#define setlocale(Category, Locale) "C"
+# if defined(_WIN32_WCE)
+ /* Some things not defined on Windows CE. */
+# define getenv(Name) NULL
+# define setlocale(Category, Locale) "C"
static int errno = 0; /* Use something better? */
+# elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+# define getenv(Name) NULL
+# endif
+# if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
+# define snprintf _snprintf
+ /* Windows CE only has _strdup, while rest of Windows has both. */
+# define strdup _strdup
+# endif
#endif
#if HAVE_ATEXIT
diff --git a/third_party/harfbuzz-ng/src/hb-shape.cc b/third_party/harfbuzz-ng/src/hb-shape.cc
index 74747f8..9a59c08 100644
--- a/third_party/harfbuzz-ng/src/hb-shape.cc
+++ b/third_party/harfbuzz-ng/src/hb-shape.cc
@@ -200,7 +200,7 @@
* hb_feature_from_string:
* @str: (array length=len):
* @len:
- * @feature: (out) (allow-none):
+ * @feature: (out) (optional):
*
*
*
@@ -279,11 +279,13 @@
static const char **static_shaper_list;
-static inline
+#ifdef HB_USE_ATEXIT
+static
void free_static_shaper_list (void)
{
free (static_shaper_list);
}
+#endif
/**
* hb_shape_list_shapers:
diff --git a/third_party/harfbuzz-ng/src/hb-shaper-private.hh b/third_party/harfbuzz-ng/src/hb-shaper-private.hh
index 29c4493..d1d1146 100644
--- a/third_party/harfbuzz-ng/src/hb-shaper-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-shaper-private.hh
@@ -79,10 +79,9 @@
HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data)
#define HB_SHAPER_DATA_DESTROY(shaper, object) \
- if (object->shaper_data.shaper && \
- object->shaper_data.shaper != HB_SHAPER_DATA_INVALID && \
- object->shaper_data.shaper != HB_SHAPER_DATA_SUCCEEDED) \
- HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA (shaper, object));
+ if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
+ if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
+ HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
#define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \
static inline bool \
diff --git a/third_party/harfbuzz-ng/src/hb-shaper.cc b/third_party/harfbuzz-ng/src/hb-shaper.cc
index 6ae2601..580b95c 100644
--- a/third_party/harfbuzz-ng/src/hb-shaper.cc
+++ b/third_party/harfbuzz-ng/src/hb-shaper.cc
@@ -40,12 +40,14 @@
static const hb_shaper_pair_t *static_shapers;
-static inline
+#ifdef HB_USE_ATEXIT
+static
void free_static_shapers (void)
{
if (unlikely (static_shapers != all_shapers))
free ((void *) static_shapers);
}
+#endif
const hb_shaper_pair_t *
_hb_shapers_get (void)
diff --git a/third_party/harfbuzz-ng/src/hb-unicode.cc b/third_party/harfbuzz-ng/src/hb-unicode.cc
index d59dfb2..fc19006 100644
--- a/third_party/harfbuzz-ng/src/hb-unicode.cc
+++ b/third_party/harfbuzz-ng/src/hb-unicode.cc
@@ -157,7 +157,7 @@
/**
* hb_unicode_funcs_create: (Xconstructor)
- * @parent: (allow-none):
+ * @parent: (nullable):
*
*
*
diff --git a/third_party/harfbuzz-ng/src/hb-utf-private.hh b/third_party/harfbuzz-ng/src/hb-utf-private.hh
index 0b798a0..14d3c2e 100644
--- a/third_party/harfbuzz-ng/src/hb-utf-private.hh
+++ b/third_party/harfbuzz-ng/src/hb-utf-private.hh
@@ -29,14 +29,11 @@
#include "hb-private.hh"
-template <typename T, bool validate=true> struct hb_utf_t;
-
-/* UTF-8 */
-
-template <>
-struct hb_utf_t<uint8_t, true>
+struct hb_utf8_t
{
+ typedef uint8_t codepoint_t;
+
static inline const uint8_t *
next (const uint8_t *text,
const uint8_t *end,
@@ -131,11 +128,10 @@
};
-/* UTF-16 */
-
-template <>
-struct hb_utf_t<uint16_t, true>
+struct hb_utf16_t
{
+ typedef uint16_t codepoint_t;
+
static inline const uint16_t *
next (const uint16_t *text,
const uint16_t *end,
@@ -204,11 +200,11 @@
};
-/* UTF-32 */
-
-template <bool validate>
-struct hb_utf_t<uint32_t, validate>
+template <bool validate=true>
+struct hb_utf32_t
{
+ typedef uint32_t codepoint_t;
+
static inline const uint32_t *
next (const uint32_t *text,
const uint32_t *end HB_UNUSED,
@@ -246,4 +242,37 @@
};
+struct hb_latin1_t
+{
+ typedef uint8_t codepoint_t;
+
+ static inline const uint8_t *
+ next (const uint8_t *text,
+ const uint8_t *end HB_UNUSED,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement HB_UNUSED)
+ {
+ *unicode = *text++;
+ return text;
+ }
+
+ static inline const uint8_t *
+ prev (const uint8_t *text,
+ const uint8_t *start HB_UNUSED,
+ hb_codepoint_t *unicode,
+ hb_codepoint_t replacement)
+ {
+ *unicode = *--text;
+ return text;
+ }
+
+ static inline unsigned int
+ strlen (const uint8_t *text)
+ {
+ unsigned int l = 0;
+ while (*text++) l++;
+ return l;
+ }
+};
+
#endif /* HB_UTF_PRIVATE_HH */
diff --git a/third_party/khronos/EGL/eglext.h b/third_party/khronos/EGL/eglext.h
index 3b26a79..0acc280 100644
--- a/third_party/khronos/EGL/eglext.h
+++ b/third_party/khronos/EGL/eglext.h
@@ -563,6 +563,11 @@
#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
#endif
+#ifndef EGL_ARM_implicit_external_sync
+#define EGL_ARM_implicit_external_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#endif /* EGL_ARM_implicit_external_sync */
+
#ifdef __cplusplus
}
#endif
diff --git a/third_party/khronos/README.chromium b/third_party/khronos/README.chromium
index 052e9d9..2ee108e 100644
--- a/third_party/khronos/README.chromium
+++ b/third_party/khronos/README.chromium
@@ -33,6 +33,8 @@
EGL/eglplatform.h
- Added EGLNative*Type for Mac.
- Added EGLNative*Type for native linux framebuffers.
+EGL/eglext.h
+ - Added EGL_ARM_implicit_external_sync extension tokens
KHR/khrplatform.h
- Modified KHRONOS_APICALL and KHRONOS_APIENTRY
DEPS
diff --git a/third_party/mesa/mesa.gyp b/third_party/mesa/mesa.gyp
index 220bc17..bf2afcd 100644
--- a/third_party/mesa/mesa.gyp
+++ b/third_party/mesa/mesa.gyp
@@ -46,7 +46,13 @@
"_GLAPI_NO_EXPORTS",
],
'conditions': [
- ['OS == "linux" or OS == "android"', {
+ ['OS=="android"', {
+ 'defines': [
+ '__GLIBC__',
+ '_GNU_SOURCE',
+ ],
+ }],
+ ['OS=="linux"', {
'defines': [
'_GNU_SOURCE',
],
diff --git a/third_party/protobuf/protobuf.gyp b/third_party/protobuf/protobuf.gyp
index 4e1610e..25ddbae 100644
--- a/third_party/protobuf/protobuf.gyp
+++ b/third_party/protobuf/protobuf.gyp
@@ -53,6 +53,7 @@
# normal protoc target under the condition that "OS==iOS".
'target_name': 'compile_protoc',
'type': 'none',
+ 'toolsets': ['host'],
'includes': ['../../build/ios/mac_build.gypi'],
'actions': [
{
@@ -239,6 +240,7 @@
],
}, { # else, OS=="ios" and "<(GENERATOR)"!="ninja"
'type': 'none',
+ 'toolsets': ['host'],
'dependencies': [
'compile_protoc',
],
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium
index 8fb3768..368d604 100644
--- a/third_party/qcms/README.chromium
+++ b/third_party/qcms/README.chromium
@@ -53,5 +53,7 @@
- https://code.google.com/p/chromium/issues/detail?id=401971
- Avoid divisions creating sample points in the float cube LUT builder
- 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
To regenerate google.patch:
git diff b8456f38 src > google.patch
diff --git a/third_party/qcms/src/qcms.h b/third_party/qcms/src/qcms.h
index c69a772..e9c0b09 100644
--- a/third_party/qcms/src/qcms.h
+++ b/third_party/qcms/src/qcms.h
@@ -158,11 +158,15 @@
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();
#ifdef __cplusplus
diff --git a/third_party/qcms/src/transform.c b/third_party/qcms/src/transform.c
index 9fd8238..f669a6b 100644
--- a/third_party/qcms/src/transform.c
+++ b/third_party/qcms/src/transform.c
@@ -1167,6 +1167,71 @@
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(
diff --git a/third_party/re2/patches/re2-libcxx.patch b/third_party/re2/patches/re2-libcxx.patch
index 3ef6eb5..fc4dd1c 100644
--- a/third_party/re2/patches/re2-libcxx.patch
+++ b/third_party/re2/patches/re2-libcxx.patch
@@ -12,12 +12,3 @@
#include <tr1/unordered_set>
using std::tr1::unordered_set;
-@@ -54,7 +55,7 @@ using std::tr1::unordered_set;
- #else
-
- #include <unordered_set>
--#if defined(WIN32) || defined(OS_ANDROID)
-+#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
- using std::tr1::unordered_set;
- #else
- using std::unordered_set;
diff --git a/third_party/re2/util/util.h b/third_party/re2/util/util.h
index 4f0fdb8..8350445 100644
--- a/third_party/re2/util/util.h
+++ b/third_party/re2/util/util.h
@@ -55,7 +55,7 @@
#else
#include <unordered_set>
-#if defined(WIN32) || (defined(OS_ANDROID) && !defined(_LIBCPP_ABI_VERSION))
+#if defined(WIN32) || defined(OS_ANDROID)
using std::tr1::unordered_set;
#else
using std::unordered_set;
diff --git a/tools/android/mempressure.py b/tools/android/mempressure.py
index fa3daba..5c81f3e 100755
--- a/tools/android/mempressure.py
+++ b/tools/android/mempressure.py
@@ -20,6 +20,7 @@
from pylib import flag_changer
from pylib.device import device_errors
from pylib.device import device_utils
+from pylib.device import intent
# Browser Constants
DEFAULT_BROWSER = 'chrome'
diff --git a/tools/android/run_pie/run_pie.gyp b/tools/android/run_pie/run_pie.gyp
index 75850f4..b713dc4 100644
--- a/tools/android/run_pie/run_pie.gyp
+++ b/tools/android/run_pie/run_pie.gyp
@@ -18,10 +18,10 @@
'ldflags!': [
'-pie',
],
- # Don't inherit unneeded dependencies on libc++, so the binary remains
+ # Don't inherit unneeded dependencies on stlport.so, so the binary remains
# self-contained also in component=shared_library builds.
'libraries!': [
- '-l<(android_libcpp_library)',
+ '-l<(android_stlport_library)',
],
},
{
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index dd73f23..473ad20 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -384,6 +384,8 @@
CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl();
if (decl)
CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg);
+ if (expr->getMemberName().getAsString() == kTraceImplName)
+ delegates_to_traceimpl_ = true;
return true;
}
diff --git a/tools/clang/blink_gc_plugin/OWNERS b/tools/clang/blink_gc_plugin/OWNERS
index 4fce218..9c24a96 100644
--- a/tools/clang/blink_gc_plugin/OWNERS
+++ b/tools/clang/blink_gc_plugin/OWNERS
@@ -1,4 +1,5 @@
ager@chromium.org
haraken@chromium.org
+kouhei@chromium.org
tkent@chromium.org
zerny@chromium.org
diff --git a/tools/clang/blink_gc_plugin/tests/.gitignore b/tools/clang/blink_gc_plugin/tests/.gitignore
new file mode 100644
index 0000000..8f660fe
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/.gitignore
@@ -0,0 +1,2 @@
+/*.o
+/*.graph.json
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.cpp b/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.cpp
new file mode 100644
index 0000000..9636fca
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.cpp
@@ -0,0 +1,7 @@
+// 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 "traceimpl_derived_from_templated_base.h"
+
+// Nothing to define.
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.h b/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.h
new file mode 100644
index 0000000..21b9978
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.h
@@ -0,0 +1,37 @@
+// 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 TRACEIMPL_DERIVED_FROM_TEMPLATED_BASE_H_
+#define TRACEIMPL_DERIVED_FROM_TEMPLATED_BASE_H_
+
+#include "heap/stubs.h"
+
+namespace blink {
+
+class X : public GarbageCollected<X> {
+ public:
+ virtual void trace(Visitor*) {}
+};
+
+template <int Y>
+class TraceImplTemplatedBase
+ : public GarbageCollected<TraceImplTemplatedBase<Y> > {
+ public:
+ void trace(Visitor* visitor) { traceImpl(visitor); }
+
+ template <typename VisitorDispatcher>
+ void traceImpl(VisitorDispatcher visitor) {
+ visitor->trace(x_);
+ }
+
+ private:
+ Member<X> x_;
+};
+
+class TraceImplDerivedFromTemplatedBase : public TraceImplTemplatedBase<0> {
+};
+
+}
+
+#endif // TRACEIMPL_DERIVED_FROM_TEMPLATED_BASE_H_
diff --git a/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.txt b/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/traceimpl_derived_from_templated_base.txt
@@ -0,0 +1 @@
+
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 8ea4bc1..6e55d0c 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 = '226810'
+ LLVM_WIN_REVISION = '228702'
# 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 a2b7b19..7c60472 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -31,13 +31,6 @@
ABS_LLVM_BUILD_DIR="${PWD}/${LLVM_BUILD_DIR}"
ABS_COMPILER_RT_DIR="${PWD}/${COMPILER_RT_DIR}"
-
-# Use both the clang revision and the plugin revisions to test for updates.
-BLINKGCPLUGIN_REVISION=\
-$(grep 'set(LIBRARYNAME' "$THIS_DIR"/../blink_gc_plugin/CMakeLists.txt \
- | cut -d ' ' -f 2 | tr -cd '[0-9]')
-CLANG_AND_PLUGINS_REVISION="${CLANG_REVISION}-${BLINKGCPLUGIN_REVISION}"
-
# ${A:-a} returns $A if it's set, a else.
LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
@@ -52,6 +45,21 @@
# Die if any command dies, error on undefined variable expansions.
set -eu
+
+if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+ # Use a real version number rather than HEAD to make sure that
+ # --print-revision, stamp file logic, etc. all works naturally.
+ CLANG_REVISION=$(svn info "$LLVM_REPO_URL" \
+ | grep 'Last Changed Rev' | awk '{ printf $4; }')
+fi
+
+# Use both the clang revision and the plugin revisions to test for updates.
+BLINKGCPLUGIN_REVISION=\
+$(grep 'set(LIBRARYNAME' "$THIS_DIR"/../blink_gc_plugin/CMakeLists.txt \
+ | cut -d ' ' -f 2 | tr -cd '[0-9]')
+CLANG_AND_PLUGINS_REVISION="${CLANG_REVISION}-${BLINKGCPLUGIN_REVISION}"
+
+
OS="$(uname -s)"
# Parse command line options.
@@ -62,6 +70,7 @@
with_android=yes
chrome_tools="plugins;blink_gc_plugin"
gcc_toolchain=
+with_patches=yes
if [[ "${OS}" = "Darwin" ]]; then
with_android=
@@ -88,6 +97,9 @@
--without-android)
with_android=
;;
+ --without-patches)
+ with_patches=
+ ;;
--with-chrome-tools)
shift
if [[ $# == 0 ]]; then
@@ -125,6 +137,7 @@
echo "--gcc-toolchain: Set the prefix for which GCC version should"
echo " be used for building. For example, to use gcc in"
echo " /opt/foo/bin/gcc, use '--gcc-toolchain '/opt/foo"
+ echo "--without-patches: Don't apply local patches."
echo
exit 1
;;
@@ -137,6 +150,20 @@
shift
done
+if [[ -n ${LLVM_FORCE_HEAD_REVISION:-''} ]]; then
+ force_local_build=yes
+
+ # Skip local patches when using HEAD: they probably don't apply anymore.
+ with_patches=
+
+ if ! [[ "$GYP_DEFINES" =~ .*OS=android.* ]]; then
+ # Only build the Android ASan rt when targetting Android.
+ with_android=
+ fi
+
+ echo "LLVM_FORCE_HEAD_REVISION was set; using r${CLANG_REVISION}"
+fi
+
if [[ -n "$if_needed" ]]; then
if [[ "${OS}" == "Darwin" ]]; then
# clang is used on Mac.
@@ -296,9 +323,11 @@
"${LIBCXXABI_DIR}"
fi
-# Apply patch for tests failing with --disable-pthreads (llvm.org/PR11974)
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+if [[ -n "$with_patches" ]]; then
+
+ # Apply patch for tests failing with --disable-pthreads (llvm.org/PR11974)
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- third_party/llvm/tools/clang/test/Index/crash-recovery-modules.m (revision 202554)
+++ third_party/llvm/tools/clang/test/Index/crash-recovery-modules.m (working copy)
@@ -12,6 +12,8 @@
@@ -327,12 +356,12 @@
const char *HeaderBottom = "\n};\n#endif\n";
const char *MFile = "#include \"HeaderFile.h\"\nint main() {"
EOF
-patch -p0
-popd
+ patch -p0
+ popd
-# Apply r223211: "Revert r222997."
-pushd "${LLVM_DIR}"
-cat << 'EOF' |
+ # Apply r223211: "Revert r222997."
+ pushd "${LLVM_DIR}"
+ cat << 'EOF' |
--- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -921,8 +921,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
@@ -376,12 +405,12 @@
void visitAtomicRMWInst(AtomicRMWInst &I) {
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-# Apply r223219: "Preserve LD_LIBRARY_PATH when using the 'env' command"
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+ # Apply r223219: "Preserve LD_LIBRARY_PATH when using the 'env' command"
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- a/test/Driver/env.c
+++ b/test/Driver/env.c
@@ -5,12 +5,14 @@
@@ -402,12 +431,12 @@
// RUN: --sysroot=%S/Inputs/basic_linux_tree \
// RUN: | FileCheck --check-prefix=CHECK-LD-32 %s
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-# Revert r220714: "Frontend: Define __EXCEPTIONS if -fexceptions is passed"
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+ # Revert r220714: "Frontend: Define __EXCEPTIONS if -fexceptions is passed"
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -566,7 +566,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
@@ -448,12 +477,12 @@
// RUN: %clang_cc1 -x objective-c++ -fobjc-exceptions -fexceptions -fcxx-exceptions -E -dM %s | FileCheck -check-prefix=CHECK-OBJC-CXX %s
// CHECK-OBJC-CXX: #define OBJC_ZEROCOST_EXCEPTIONS 1
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-# Apply r223177: "Ensure typos in the default values of template parameters get diagnosed."
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+ # Apply r223177: "Ensure typos in the default values of template parameters get diagnosed."
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -676,7 +676,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
@@ -492,12 +521,12 @@
+template <int I = defaultArg> struct S {}; // expected-error {{use of undeclared identifier 'defaultArg'; did you mean 'DefaultArg'?}}
+S<1> s;
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-# Apply r223209: "Handle delayed corrections in a couple more error paths in ParsePostfixExpressionSuffix."
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+ # Apply r223209: "Handle delayed corrections in a couple more error paths in ParsePostfixExpressionSuffix."
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1390,6 +1390,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
@@ -531,12 +560,12 @@
+ // expected-error {{expected expression}}
+}
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-# Apply r223705: "Handle possible TypoExprs in member initializers."
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+ # Apply r223705: "Handle possible TypoExprs in member initializers."
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2813,6 +2813,11 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
@@ -567,12 +596,12 @@
+ explicit SomeClass() : Kind(kSum) {} // expected-error {{use of undeclared identifier 'kSum'; did you mean 'kNum'?}}
+};
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-# Apply r224172: "Typo correction: Ignore temporary binding exprs after overload resolution"
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+ # Apply r224172: "Typo correction: Ignore temporary binding exprs after overload resolution"
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -6105,8 +6105,13 @@ public:
@@ -620,12 +649,12 @@
+ printf("ar: %d\n", ar.val);
+}
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-# Apply r224173: "Implement feedback on r224172 in PR21899"
-pushd "${CLANG_DIR}"
-cat << 'EOF' |
+ # Apply r224173: "Implement feedback on r224172 in PR21899"
+ pushd "${CLANG_DIR}"
+ cat << 'EOF' |
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -6105,7 +6105,7 @@ public:
@@ -670,13 +699,12 @@
+ Overload(resulta);
}
EOF
-patch -p1
-popd
+ patch -p1
+ popd
-
-# This Go bindings test doesn't work after the bootstrap build on Linux. (PR21552)
-pushd "${LLVM_DIR}"
-cat << 'EOF' |
+ # This Go bindings test doesn't work after the bootstrap build on Linux. (PR21552)
+ pushd "${LLVM_DIR}"
+ cat << 'EOF' |
Index: test/Bindings/Go/go.test
===================================================================
--- test/Bindings/Go/go.test (revision 223109)
@@ -687,9 +715,10 @@
; REQUIRES: shell
EOF
-patch -p0
-popd
+ patch -p0
+ popd
+fi
# Echo all commands.
set -x
@@ -904,7 +933,7 @@
--platform=android-14 \
--install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
--system=linux-x86_64 \
- --stl=libcxx \
+ --stl=stlport \
--toolchain=arm-linux-androideabi-4.9
# Android NDK r9d copies a broken unwind.h into the toolchain, see
diff --git a/tools/git/for-all-touched-files.py b/tools/git/for-all-touched-files.py
index a7e784a..633fd07 100755
--- a/tools/git/for-all-touched-files.py
+++ b/tools/git/for-all-touched-files.py
@@ -13,11 +13,12 @@
Deleted files are not included. Neither are untracked files.
Synopsis:
- %prog [-b BRANCH] [-d] [-x EXTENSIONS|-c] [-t TOKEN] QUOTED_COMMAND
+ %prog [-b BRANCH] [-d] [-x EXTENSIONS|-c|-g] [-t TOKEN] QUOTED_COMMAND
Examples:
%prog -x gyp,gypi "tools/format_xml.py [[FILENAME]]"
%prog -c "tools/sort-headers.py [[FILENAME]]"
+ %prog -g "tools/sort_sources.py [[FILENAME]]"
%prog -t "~~BINGO~~" "echo I modified ~~BINGO~~"
"""
@@ -29,6 +30,8 @@
# List of C++-like source file extensions.
_CPP_EXTENSIONS = ('h', 'hh', 'hpp', 'c', 'cc', 'cpp', 'cxx', 'mm',)
+# List of build file extensions.
+_BUILD_EXTENSIONS = ('gyp', 'gypi', 'gn',)
def GitShell(args, ignore_return=False):
@@ -91,6 +94,10 @@
parser.add_option('-c', '--cpp', default=False, action='store_true',
dest='cpp_only',
help='Runs your command only on C++-like source files.')
+ # -g stands for GYP and GN.
+ parser.add_option('-g', '--build', default=False, action='store_true',
+ dest='build_only',
+ help='Runs your command only on build files.')
parser.add_option('-t', '--token', default='[[FILENAME]]', dest='token',
help='Sets the token to be replaced for each file '
'in your command (default [[FILENAME]]).')
@@ -103,9 +110,14 @@
parser.print_help()
sys.exit(1)
+ if opts.cpp_only and opts.build_only:
+ parser.error("--cpp and --build are mutually exclusive")
+
extensions = opts.extensions
if opts.cpp_only:
extensions = _CPP_EXTENSIONS
+ if opts.build_only:
+ extensions = _BUILD_EXTENSIONS
ForAllTouchedFiles(opts.branch, extensions, opts.token, args[0])
diff --git a/tools/git/move_source_file.py b/tools/git/move_source_file.py
index b5496fd..1a25e44 100755
--- a/tools/git/move_source_file.py
+++ b/tools/git/move_source_file.py
@@ -106,36 +106,27 @@
r'\1%s' % to_path,
['*.cc', '*.h', '*.m', '*.mm', '*.cpp'])
- # Update references in .gyp(i) files.
- def PathMinusFirstComponent(path):
- """foo/bar/baz -> bar/baz"""
- parts = re.split(r"[/\\]", path, 1)
- if len(parts) == 2:
- return parts[1]
- else:
- return parts[0]
- mffr.MultiFileFindReplace(
- r'([\'"])%s([\'"])' % re.escape(PathMinusFirstComponent(from_path)),
- r'\1%s\2' % PathMinusFirstComponent(to_path),
- ['*.gyp*'])
-
- # Update references in BUILD.gn files.
+ # Update references in GYP and BUILD.gn files.
#
- # Unlike .gyp(i) files, BUILD.gn files can be placed in any directories,
- # and paths in a BUILD.gn file are relative to the directory where the
- # BUILD.gn file is placed.
+ # GYP files are mostly located under the first level directory (ex.
+ # chrome/chrome_browser.gypi), but sometimes they are located in
+ # directories at a deeper level (ex. extensions/shell/app_shell.gypi). On
+ # the other hand, BUILD.gn files can be placed in any directories.
+ #
+ # Paths in a GYP or BUILD.gn file are relative to the directory where the
+ # file is placed.
#
# For instance, "chrome/browser/chromeos/device_uma.h" is listed as
# "browser/chromeos/device_uma.h" in "chrome/chrome_browser_chromeos.gypi",
# but it's listed as "device_uma.h" in "chrome/browser/chromeos/BUILD.gn".
#
# To handle this, the code here will visit directories from the top level
- # src directory to the directory of |from_path| and try to update BUILD.gn
- # in each directory.
+ # src directory to the directory of |from_path| and try to update GYP and
+ # BUILD.gn files in each directory.
#
- # The code only handles files moved/renamed within the same BUILD.gn
- # file. If files are moved beyond the same BUILD.gn file, the affected
- # BUILD.gn files should be fixed manually.
+ # The code only handles files moved/renamed within the same build file. If
+ # files are moved beyond the same build file, the affected build files
+ # should be fixed manually.
def SplitByFirstComponent(path):
"""'foo/bar/baz' -> ('foo', 'bar/baz')
'bar' -> ('bar', '')
@@ -154,7 +145,8 @@
mffr.MultiFileFindReplace(
r'([\'"])%s([\'"])' % from_rest,
r'\1%s\2' % to_rest,
- [os.path.join(visiting_directory, 'BUILD.gn')])
+ [os.path.join(visiting_directory, 'BUILD.gn'),
+ os.path.join(visiting_directory, '*.gyp*')])
from_first, from_rest = SplitByFirstComponent(from_rest)
to_first, to_rest = SplitByFirstComponent(to_rest)
visiting_directory = os.path.join(visiting_directory, from_first)
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py
index 0fa9b61..bfe6698 100755
--- a/tools/idl_parser/idl_parser.py
+++ b/tools/idl_parser/idl_parser.py
@@ -229,6 +229,11 @@
"""Interface : INTERFACE identifier Inheritance '{' InterfaceMembers '}' ';'"""
p[0] = self.BuildNamed('Interface', p, 2, ListFromConcat(p[3], p[5]))
+ # [5.1] Error recovery for interface.
+ def p_InterfaceError(self, p):
+ """Interface : INTERFACE identifier Inheritance '{' error"""
+ p[0] = self.BuildError(p, 'Interface')
+
# [6]
def p_Partial(self, p):
"""Partial : PARTIAL PartialDefinition"""
diff --git a/tools/idl_parser/test_parser/interface_web.idl b/tools/idl_parser/test_parser/interface_web.idl
index cff2cd0..9e69e9f 100644
--- a/tools/idl_parser/test_parser/interface_web.idl
+++ b/tools/idl_parser/test_parser/interface_web.idl
@@ -65,6 +65,13 @@
};
/* TREE
+ *Error(Unexpected keyword "double" after keyword "readonly".)
+ */
+interface MyIFaceMissingAttribute {
+ readonly double foo;
+};
+
+/* TREE
*Interface(MyIFaceBig)
* Const(setString)
* PrimitiveType(DOMString)
diff --git a/tools/lsan/suppressions.txt b/tools/lsan/suppressions.txt
index 41f8679..afa832e 100644
--- a/tools/lsan/suppressions.txt
+++ b/tools/lsan/suppressions.txt
@@ -1,91 +1 @@
-# HeapCheck sanity test
-leak:base::ToolsSanityTest_MemoryLeak_Test::TestBody
-
-#### Third-party leaks ####
-
-# False positives in libfontconfig. http://crbug.com/39050
-leak:libfontconfig
-
-# Leaks in Nvidia's libGL.
-leak:libGL.so
-
-# A small string is leaked here (57 bytes per process). http://crbug.com/46571#c9
-leak:blink::V8GCController::collectGarbage
-
-# http://crbug.com/270180
-leak:net::ProxyResolverV8::Context::ResolveProxy
-
-# NSS leaks in CertDatabaseNSSTest tests. http://crbug.com/51988
-leak:net::NSSCertDatabase::ImportFromPKCS12
-leak:net::NSSCertDatabase::ListCerts
-leak:net::NSSCertDatabase::DeleteCertAndKey
-leak:crypto::ScopedTestNSSDB::ScopedTestNSSDB
-# Another leak due to not shutting down NSS properly. http://crbug.com/124445
-leak:error_get_my_stack
-
-# XRandR has several one time leaks.
-leak:libxrandr
-
-# The NSS suppressions above will not fire when the fast stack unwinder is used,
-# because it can't unwind through NSS libraries. Apply blanket suppressions for
-# now.
-leak:libnssutil3
-leak:libnspr4
-leak:libnss3
-leak:libplds4
-leak:libnssckbi
-
-# Skia leaks GrGpuGL::ProgramCache::Entry. http://crbug.com/262934
-leak:GrGpuGL::flushGraphicsState
-
-# xrandr leak. http://crbug.com/119677
-leak:XRRFindDisplay
-
-# V8 may leak this by design in unit tests. http://crbug.com/323149
-leak:v8::internal::Genesis::Genesis
-
-# Suppressions for objects which can be owned by the V8 heap. This is a
-# temporary workaround until LeakSanitizer supports the V8 heap.
-# Those should only fire in (browser)tests. If you see one of them in Chrome,
-# then it's a real leak.
-# http://crbug.com/328552
-leak:WTF::StringImpl::createUninitialized
-leak:WTF::StringImpl::create8BitIfPossible
-leak:blink::MouseEvent::create
-leak:blink::WindowProxy::initializeIfNeeded
-leak:blink::*::*GetterCallback
-leak:blink::CSSComputedStyleDeclaration::create
-leak:blink::V8PerIsolateData::ensureDomInJSContext
-leak:gin/object_template_builder.h
-leak:gin::internal::Dispatcher
-leak:blink::LocalDOMWindow::getComputedStyle
-
-# http://crbug.com/356785
-leak:content::RenderViewImplTest_DecideNavigationPolicyForWebUI_Test::TestBody
-
-#### Actual bugs in Chromium code ####
-# PLEASE DO NOT ADD SUPPRESSIONS FOR NEW LEAKS.
-# Instead, commits that introduce memory leaks should be reverted. Suppressing
-# the leak is acceptable in some cases when reverting is impossible, i.e. when
-# enabling leak detection for the first time for a test target with pre-existing
-# leaks.
-
-# Small test-only leak in ppapi_unittests. http://crbug.com/258113
-leak:ppapi::proxy::PPP_Instance_Private_ProxyTest_PPPInstancePrivate_Test
-
-# http://crbug.com/318221
-leak:base::EnsureProcessTerminated
-
-# http://crbug.com/322671
-leak:content::SpeechRecognitionBrowserTest::SetUpOnMainThread
-
-# http://crbug.com/355641
-leak:TrayAccessibilityTest
-
-# http://crbug.com/354644
-leak:CertificateViewerUITest::ShowModalCertificateViewer
-
-# http://crbug.com/356306
-leak:content::SetProcessTitleFromCommandLine
-
-# PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS.
+# Moved to build/sanitizers/lsan_suppressions.cc
diff --git a/tools/relocation_packer/src/debug.h b/tools/relocation_packer/src/debug.h
index 48be6c1..99db948 100644
--- a/tools/relocation_packer/src/debug.h
+++ b/tools/relocation_packer/src/debug.h
@@ -81,10 +81,10 @@
// Make logging severities visible globally.
typedef relocation_packer::Logger::Severity LogSeverity;
-using LogSeverity::INFO;
-using LogSeverity::WARNING;
-using LogSeverity::ERROR;
-using LogSeverity::FATAL;
+static const LogSeverity INFO = LogSeverity::INFO;
+static const LogSeverity WARNING = LogSeverity::WARNING;
+static const LogSeverity ERROR = LogSeverity::ERROR;
+static const LogSeverity FATAL = LogSeverity::FATAL;
// LOG(severity) prints a message with the given severity, and aborts if
// severity is FATAL. LOG_IF(severity, predicate) does the same but only if
diff --git a/tools/relocation_packer/src/elf_file.cc b/tools/relocation_packer/src/elf_file.cc
index 3ffccec..5853c9d 100644
--- a/tools/relocation_packer/src/elf_file.cc
+++ b/tools/relocation_packer/src/elf_file.cc
@@ -56,6 +56,14 @@
// page. See http://www.airs.com/blog/archives/189.
static const size_t kPreserveAlignment = 4096;
+// Alignment values used by ld and gold for the GNU_STACK segment. Different
+// linkers write different values; the actual value is immaterial on Android
+// because it ignores GNU_STACK segments. However, it is useful for binary
+// comparison and unit test purposes if packing and unpacking can preserve
+// them through a round-trip.
+static const size_t kLdGnuStackSegmentAlignment = 16;
+static const size_t kGoldGnuStackSegmentAlignment = 0;
+
namespace {
// Get section data. Checks that the section has exactly one data entry,
@@ -363,11 +371,36 @@
return first_loadable_segment;
}
+// Helper for ResizeSection(). Deduce the alignment that the PT_GNU_STACK
+// segment will use. Determined by sensing the linker that was used to
+// create the shared library.
+size_t DeduceGnuStackSegmentAlignment(Elf* elf) {
+ size_t string_index;
+ elf_getshdrstrndx(elf, &string_index);
+
+ Elf_Scn* section = NULL;
+ size_t gnu_stack_segment_alignment = kLdGnuStackSegmentAlignment;
+
+ while ((section = elf_nextscn(elf, section)) != NULL) {
+ const ELF::Shdr* section_header = ELF::getshdr(section);
+ std::string name = elf_strptr(elf, string_index, section_header->sh_name);
+
+ if (name == ".note.gnu.gold-version") {
+ gnu_stack_segment_alignment = kGoldGnuStackSegmentAlignment;
+ break;
+ }
+ }
+
+ return gnu_stack_segment_alignment;
+}
+
// Helper for ResizeSection(). Find the PT_GNU_STACK segment, and check
// that it contains what we expect so we can restore it on unpack if needed.
-ELF::Phdr* FindUnusedGnuStackSegment(ELF::Phdr* program_headers,
+ELF::Phdr* FindUnusedGnuStackSegment(Elf* elf,
+ ELF::Phdr* program_headers,
size_t count) {
ELF::Phdr* unused_segment = NULL;
+ const size_t stack_alignment = DeduceGnuStackSegmentAlignment(elf);
for (size_t i = 0; i < count; ++i) {
ELF::Phdr* program_header = &program_headers[i];
@@ -379,7 +412,7 @@
program_header->p_filesz == 0 &&
program_header->p_memsz == 0 &&
program_header->p_flags == (PF_R | PF_W) &&
- program_header->p_align == ELF::kGnuStackSegmentAlignment) {
+ program_header->p_align == stack_alignment) {
unused_segment = program_header;
}
}
@@ -558,7 +591,7 @@
// Locate the segment that we can overwrite to form the new LOAD entry,
// and the segment that we are going to split into two parts.
ELF::Phdr* spliced_header =
- FindUnusedGnuStackSegment(elf_program_header, program_header_count);
+ FindUnusedGnuStackSegment(elf, elf_program_header, program_header_count);
ELF::Phdr* split_header =
FindFirstLoadSegment(elf_program_header, program_header_count);
@@ -680,6 +713,7 @@
last_section_header->sh_offset + last_section_header->sh_size;
// Reconstruct the original GNU_STACK segment into spliced_header.
+ const size_t stack_alignment = DeduceGnuStackSegmentAlignment(elf);
spliced_header->p_type = PT_GNU_STACK;
spliced_header->p_offset = 0;
spliced_header->p_vaddr = 0;
@@ -687,7 +721,7 @@
spliced_header->p_filesz = 0;
spliced_header->p_memsz = 0;
spliced_header->p_flags = PF_R | PF_W;
- spliced_header->p_align = ELF::kGnuStackSegmentAlignment;
+ spliced_header->p_align = stack_alignment;
// Adjust the offsets of all program headers that are not one of the pair
// we just coalesced.
diff --git a/tools/relocation_packer/src/elf_traits.h b/tools/relocation_packer/src/elf_traits.h
index f099bab..1004767 100644
--- a/tools/relocation_packer/src/elf_traits.h
+++ b/tools/relocation_packer/src/elf_traits.h
@@ -57,7 +57,6 @@
enum { kFileClass = ELFCLASS32 };
enum { kRelativeRelocationCode = R_ARM_RELATIVE };
enum { kNoRelocationCode = R_ARM_NONE };
- enum { kGnuStackSegmentAlignment = 0 };
static inline const char* Machine() { return "ARM"; }
@@ -91,7 +90,6 @@
enum { kFileClass = ELFCLASS64 };
enum { kRelativeRelocationCode = R_AARCH64_RELATIVE };
enum { kNoRelocationCode = R_AARCH64_NONE };
- enum { kGnuStackSegmentAlignment = 16 };
static inline const char* Machine() { return "ARM64"; }
diff --git a/tools/valgrind/asan/asan_symbolize.py b/tools/valgrind/asan/asan_symbolize.py
index 9280d7a..0107406 100755
--- a/tools/valgrind/asan/asan_symbolize.py
+++ b/tools/valgrind/asan/asan_symbolize.py
@@ -10,6 +10,7 @@
import base64
import json
import os
+import platform
import re
import subprocess
import sys
@@ -247,8 +248,11 @@
set_symbolizer_path()
asan_symbolize.demangle = True
asan_symbolize.fix_filename_patterns = args.strip_path_prefix
+ # Most source paths for Chromium binaries start with
+ # /path/to/src/out/Release/../../
+ asan_symbolize.fix_filename_patterns.append('Release/../../')
binary_name_filter = None
- if os.uname()[0] == 'Darwin':
+ if platform.uname()[0] == 'Darwin':
binary_name_filter = make_chrome_osx_binary_name_filter(
chrome_product_dir_path(args.executable_path))
loop = asan_symbolize.SymbolizationLoop(
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt
index 1a9b9ee..d6f6096 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -722,14 +722,6 @@
...
*!content::RenderWidgetHostViewAura::Destroy
-UNADDRESSABLE ACCESS
-name=http://crbug.com/455066
-system call NtReadFile parameter #4
-KERNELBASE.dll!ReadFile
-KERNEL32.dll!ReadFile
-*!net::FileStream::Context::ReadAsync
-*!base::internal::RunnableAdapter<>::Run
-
INVALID HEAP ARGUMENT
name=http://crbug.com/455994
drmemorylib.dll!replace_operator_delete
@@ -750,24 +742,3 @@
*!content::ContentMainRunnerImpl::Run
*!content::ContentMain
*!content::LaunchTests
-
-UNADDRESSABLE ACCESS
-name=http://crbug.com/456131
-...
-*!content::NavigateToURL
-*!content::BrowserSideNavigationBrowserTest_BrowserInitiatedNavigations_Test::RunTestOnMainThread
-*!content::ContentBrowserTest::RunTestOnMainThreadLoop
-*!content::BrowserTestBase::ProxyRunTestOnMainThreadLoop
-*!content::ShellBrowserMainParts::PreMainMessageLoopRun
-*!content::BrowserMainLoop::PreMainMessageLoopRun
-*!base::internal::Invoker<>::Run
-*!content::StartupTaskRunner::RunAllTasksNow
-*!content::BrowserMainLoop::CreateStartupTasks
-*!content::BrowserMainRunnerImpl::Initialize
-*!ShellBrowserMain
-*!content::ShellMainDelegate::RunProcess
-*!content::RunNamedProcessTypeMain
-*!content::ContentMainRunnerImpl::Run
-*!content::ContentMain
-*!content::BrowserTestBase::SetUp
-*!content::ContentBrowserTest::SetUp
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt
index d823d49..d2db1bf 100644
--- a/tools/valgrind/drmemory/suppressions_full.txt
+++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -32,7 +32,11 @@
# so we just look for randomByte.
UNINITIALIZED READ
name=sqlite3_randomness UNINIT
-*!randomByte
+sql.dll!sqlite3_randomness
+
+UNINITIALIZED READ
+name=blink_web_dll_sqlite3_randomness UNINIT
+blink_web.dll!sqlite3_randomness
# Intentional leak in WebKit Template Framework for ThreadData.
LEAK
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
index faf853d..371b4bf 100644
--- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -26,3 +26,7 @@
# http://crbug.com/451992
ExtensionLoadingTest.UpgradeAfterNavigatingFromOverriddenNewTabPage
+
+# http://crbug.com/459000
+ClipboardApiTest.HostedAppNoPermission
+
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
index d283375..2030624 100644
--- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
+++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -22,3 +22,6 @@
# http://crbug.com/293125
WebRtcBrowserTest.CanMakeEmptyCallThenAddStreamsAndRenegotiate
+
+# http://crbug.com/456131
+BrowserSideNavigationBrowserTest.BrowserInitiatedNavigations
diff --git a/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt b/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt
index c322014..6491f45 100644
--- a/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt
@@ -1,2 +1,5 @@
# http://crbug.com/241856
VideoSchedulerTest.StartAndStop
+
+# crbug.com/458691
+ClientSessionTest.ClipboardStubFilter
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 10849ae..67243d1 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -3016,11 +3016,10 @@
Memcheck:Uninitialized
fun:_ZNK8SkStroke10strokePathERK6SkPathPS0_
fun:_ZNK11SkStrokeRec11applyToPathEP6SkPathRKS0_
- fun:_ZNK7SkPaint11getFillPathERK6SkPathPS0_PK6SkRect
- fun:_ZNK6SkDraw8drawPathERK6SkPathRK7SkPaintPK8SkMatrixbb
+ fun:_ZNK7SkPaint11getFillPathERK6SkPathPS0_PK6SkRectf
+ fun:_ZNK6SkDraw8drawPathERK6SkPathRK7SkPaintPK8SkMatrixbbP9SkBlitter
fun:_ZNK6SkDraw8drawPathERK6SkPathRK7SkPaintPK8SkMatrixb
fun:_ZN14SkBitmapDevice8drawPathERK6SkDrawRK6SkPathRK7SkPaintPK8SkMatrixb
- fun:_ZN8SkCanvas8drawPathERK6SkPathRK7SkPaint
}
{
bug_392936
@@ -3398,7 +3397,7 @@
fun:_ZN8remoting13ClipboardAura4Core20InjectClipboardEventERKNS_8protocol14ClipboardEventE
}
{
- bug_431213
+ bug_431213_a
Memcheck:Leak
fun:_Znw*
fun:_ZN3gin22CreateFunctionTemplateIF*LocalINS6_16FunctionTemplateEEEPNS6_7IsolateEN4base8CallbackIT_EEi
@@ -3407,6 +3406,33 @@
fun:_ZN*24GetObjectTemplateBuilderEPN2v87IsolateE
}
{
+ bug_431213_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3gin22CreateFunctionTemplateIF*IsolateEN4base8CallbackIT_EEi
+ fun:_ZN3gin12_GLOBAL__N_114CallbackTraitsIF*
+ fun:_ZN3gin21ObjectTemplateBuilder9SetMethod*RKN4base16BasicStringPieceISsEERKT_
+ fun:_ZN4mojo2js*GetModuleEPN2v87IsolateE
+}
+{
+ bug_431213_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3gin22CreateFunctionTemplateIF*IsolateEN4base8CallbackIT_EEi
+ fun:_ZN3gin12_GLOBAL__N_114CallbackTraitsI*
+ fun:_ZN3gin21ObjectTemplateBuilder9SetMethod*RKN4base16BasicStringPieceISsEERKT_
+ fun:_ZN10extensions19TestServiceProvider24GetObjectTemplateBuilderEPN2v87IsolateE
+}
+{
+ bug_431213_d
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3gin22CreateFunctionTemplateIF*IsolateEN4base8CallbackIT_EEi
+ fun:_ZN3gin12_GLOBAL__N_114CallbackTraitsI*
+ fun:_ZN3gin21ObjectTemplateBuilder9SetMethod*RKN4base16BasicStringPieceISsEERKT_
+ fun:_ZN10extensions12_GLOBAL__N_111TestNatives24GetObjectTemplateBuilderEPN2v87IsolateE
+}
+{
bug_436110
Memcheck:Param
socketcall.sendto(msg)
@@ -3616,3 +3642,14 @@
fun:_ZN4mojo8internal9Connector17CallOnHandleReadyEPvi
fun:_ZN4mojo8internal12_GLOBAL__N_113OnHandleReadyEPNS_6common13HandleWatcherEPFvPviES5_i
}
+{
+ bug_457557
+ Memcheck:Leak
+ fun:calloc
+ fun:pthread_setspecific
+ fun:_ZN4base8internal19ThreadLocalPlatform14SetValueInSlotEjPv
+ fun:_ZN4base18ThreadLocalPointerIvE3SetEPv
+ fun:_ZN4base18ThreadLocalBoolean3SetEb
+ fun:_ZN4base12_GLOBAL__N_112WorkerThread10ThreadMainEv
+ fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
+}
diff --git a/tools/valgrind/memcheck/suppressions_mac.txt b/tools/valgrind/memcheck/suppressions_mac.txt
index c817091..f0e9d32 100644
--- a/tools/valgrind/memcheck/suppressions_mac.txt
+++ b/tools/valgrind/memcheck/suppressions_mac.txt
@@ -209,6 +209,18 @@
fun:_ZN11CUIRenderer4DrawE6CGRectP9CGContextPK14__CFDictionaryPS5_
}
{
+ bug_173779_b
+ Memcheck:Uninitialized
+ ...
+ fun:img_data_lock
+ fun:CGSImageDataLock
+ fun:ripc_AcquireImage
+ fun:ripc_DrawImage*
+ fun:CGContextDrawImage*
+ ...
+ fun:-[NSImage hitTestRect:withImageDestinationRect:context:hints:flipped:]
+}
+{
bug_340726
Memcheck:Leak
fun:_Znw*
diff --git a/ui/events/latency_info.cc b/ui/events/latency_info.cc
index 145b77a..9d16b29 100644
--- a/ui/events/latency_info.cc
+++ b/ui/events/latency_info.cc
@@ -71,7 +71,7 @@
}
// This class is for converting latency info to trace buffer friendly format.
-class LatencyInfoTracedValue : public base::debug::ConvertableToTraceFormat {
+class LatencyInfoTracedValue : public base::trace_event::ConvertableToTraceFormat {
public:
static scoped_refptr<ConvertableToTraceFormat> FromValue(
scoped_ptr<base::Value> value);
@@ -87,9 +87,9 @@
DISALLOW_COPY_AND_ASSIGN(LatencyInfoTracedValue);
};
-scoped_refptr<base::debug::ConvertableToTraceFormat>
+scoped_refptr<base::trace_event::ConvertableToTraceFormat>
LatencyInfoTracedValue::FromValue(scoped_ptr<base::Value> value) {
- return scoped_refptr<base::debug::ConvertableToTraceFormat>(
+ return scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
new LatencyInfoTracedValue(value.release()));
}
@@ -107,7 +107,7 @@
}
// Converts latencyinfo into format that can be dumped into trace buffer.
-scoped_refptr<base::debug::ConvertableToTraceFormat> AsTraceableData(
+scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsTraceableData(
const ui::LatencyInfo& latency) {
scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
for (ui::LatencyInfo::LatencyMap::const_iterator it =
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc
index 7fe5174..c13ae1d 100644
--- a/ui/gfx/transform.cc
+++ b/ui/gfx/transform.cc
@@ -40,6 +40,12 @@
return std::abs(x - SkDoubleToMScalar(1.0)) <= tolerance;
}
+static float Round(float f) {
+ if (f == 0.f)
+ return f;
+ return (f > 0.f) ? std::floor(f + 0.5f) : std::ceil(f - 0.5f);
+}
+
} // namespace
Transform::Transform(SkMScalar col1row1,
@@ -493,6 +499,12 @@
return true;
}
+void Transform::RoundTranslationComponents() {
+ matrix_.set(0, 3, Round(matrix_.get(0, 3)));
+ matrix_.set(1, 3, Round(matrix_.get(1, 3)));
+}
+
+
void Transform::TransformPointInternal(const SkMatrix44& xform,
Point3F* point) const {
if (xform.isIdentity())
diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h
index 8156b72..68a734e 100644
--- a/ui/gfx/transform.h
+++ b/ui/gfx/transform.h
@@ -238,6 +238,8 @@
// DecomposedTransform.
bool Blend(const Transform& from, double progress);
+ void RoundTranslationComponents();
+
// Returns |this| * |other|.
Transform operator*(const Transform& other) const {
return Transform(*this, other);
diff --git a/ui/gfx/transform_util.cc b/ui/gfx/transform_util.cc
index 655ce57..e96d96e 100644
--- a/ui/gfx/transform_util.cc
+++ b/ui/gfx/transform_util.cc
@@ -498,4 +498,21 @@
quaternion[3]);
}
+float MatrixDistance(const Transform& a, const Transform& b) {
+ double sum = 0.0;
+
+ const SkMatrix44& a_data = a.matrix();
+ const SkMatrix44& b_data = b.matrix();
+
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ double diff = a_data.get(row, col) - b_data.get(row, col);
+ sum += diff * diff;
+ }
+ }
+
+ return static_cast<float>(std::sqrt(sum));
+}
+
+
} // namespace ui
diff --git a/ui/gfx/transform_util.h b/ui/gfx/transform_util.h
index a77ded2..6b091a2 100644
--- a/ui/gfx/transform_util.h
+++ b/ui/gfx/transform_util.h
@@ -58,6 +58,9 @@
const Transform& transform,
const Rect& viewport);
+// Computes the Frobenius norm of (a - b).
+GFX_EXPORT float MatrixDistance(const Transform& a, const Transform& b);
+
} // namespace gfx
#endif // UI_GFX_TRANSFORM_UTIL_H_
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index bbd9363..c596f53 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -81,11 +81,11 @@
"gl_surface.h",
"gl_surface_android.cc",
"gl_surface_mac.cc",
+ "gl_surface_osmesa.cc",
+ "gl_surface_osmesa.h",
"gl_surface_stub.cc",
"gl_surface_stub.h",
"gl_surface_win.cc",
- "gl_surface_osmesa.cc",
- "gl_surface_osmesa.h",
"gl_switches.cc",
"gl_switches.h",
"gl_version_info.cc",
@@ -159,6 +159,8 @@
"gl_context_glx.cc",
"gl_context_glx.h",
"gl_context_x11.cc",
+ "gl_egl_api_implementation.cc",
+ "gl_egl_api_implementation.h",
"gl_glx_api_implementation.cc",
"gl_glx_api_implementation.h",
"gl_image_glx.cc",
@@ -167,8 +169,6 @@
"gl_surface_glx.cc",
"gl_surface_glx.h",
"gl_surface_x11.cc",
- "gl_egl_api_implementation.cc",
- "gl_egl_api_implementation.h",
]
configs += [
@@ -254,9 +254,9 @@
sources = [
"gl_bindings_autogen_mock.cc",
"gl_bindings_autogen_mock.h",
- "gl_mock_autogen_gl.h",
- "gl_mock.h",
"gl_mock.cc",
+ "gl_mock.h",
+ "gl_mock_autogen_gl.h",
]
configs += [ "//third_party/khronos:khronos_headers" ]
diff --git a/ui/gl/egl_util.h b/ui/gl/egl_util.h
index c0fe4ce..0ef9095 100644
--- a/ui/gl/egl_util.h
+++ b/ui/gl/egl_util.h
@@ -5,10 +5,12 @@
#ifndef UI_GL_EGL_UTIL_H_
#define UI_GL_EGL_UTIL_H_
+#include "ui/gl/gl_export.h"
+
namespace ui {
// Returns the last EGL error as a string.
-const char* GetLastEGLErrorString();
+GL_EXPORT const char* GetLastEGLErrorString();
} // namespace ui
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 52daf1c..639ec7e 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -642,7 +642,7 @@
{ 'return_type': 'void',
'versions': [{ 'name': 'glGetTransformFeedbackVarying' }],
'arguments': 'GLuint program, GLuint index, GLsizei bufSize, '
- 'GLsizei* length, GLenum* type, char* name', },
+ 'GLsizei* length, GLsizei* size, GLenum* type, char* name', },
{ 'return_type': 'void',
'names': ['glGetTranslatedShaderSourceANGLE'],
'arguments':
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp
index 7d97c66..6b173f4 100644
--- a/ui/gl/gl.gyp
+++ b/ui/gl/gl.gyp
@@ -52,9 +52,9 @@
'gl_context.h',
'gl_context_android.cc',
'gl_context_mac.mm',
- 'gl_context_ozone.cc',
'gl_context_osmesa.cc',
'gl_context_osmesa.h',
+ 'gl_context_ozone.cc',
'gl_context_stub.cc',
'gl_context_stub.h',
'gl_context_stub_with_extensions.cc',
@@ -85,8 +85,8 @@
'gl_implementation.cc',
'gl_implementation.h',
'gl_implementation_android.cc',
- 'gl_implementation_ozone.cc',
'gl_implementation_mac.cc',
+ 'gl_implementation_ozone.cc',
'gl_implementation_win.cc',
'gl_implementation_x11.cc',
'gl_osmesa_api_implementation.cc',
@@ -99,13 +99,13 @@
'gl_surface.h',
'gl_surface_android.cc',
'gl_surface_mac.cc',
+ 'gl_surface_osmesa.cc',
+ 'gl_surface_osmesa.h',
+ 'gl_surface_ozone.cc',
'gl_surface_stub.cc',
'gl_surface_stub.h',
'gl_surface_win.cc',
'gl_surface_x11.cc',
- 'gl_surface_osmesa.cc',
- 'gl_surface_osmesa.h',
- 'gl_surface_ozone.cc',
'gl_switches.cc',
'gl_switches.h',
'gl_version_info.cc',
@@ -129,14 +129,14 @@
'gl_bindings_autogen_egl.h',
'gl_context_egl.cc',
'gl_context_egl.h',
+ 'gl_egl_api_implementation.cc',
+ 'gl_egl_api_implementation.h',
'gl_fence_egl.cc',
'gl_fence_egl.h',
'gl_image_egl.cc',
'gl_image_egl.h',
'gl_surface_egl.cc',
'gl_surface_egl.h',
- 'gl_egl_api_implementation.cc',
- 'gl_egl_api_implementation.h',
],
'include_dirs': [
'<(DEPTH)/third_party/khronos',
@@ -160,14 +160,14 @@
'gl_bindings_autogen_glx.h',
'gl_context_glx.cc',
'gl_context_glx.h',
+ 'gl_egl_api_implementation.cc',
+ 'gl_egl_api_implementation.h',
'gl_glx_api_implementation.cc',
'gl_glx_api_implementation.h',
'gl_image_glx.cc',
'gl_image_glx.h',
'gl_surface_glx.cc',
'gl_surface_glx.h',
- 'gl_egl_api_implementation.cc',
- 'gl_egl_api_implementation.h',
],
'all_dependent_settings': {
'defines': [
@@ -280,9 +280,9 @@
'sources': [
'gl_bindings_autogen_mock.cc',
'gl_bindings_autogen_mock.h',
- 'gl_mock_autogen_gl.h',
- 'gl_mock.h',
'gl_mock.cc',
+ 'gl_mock.h',
+ 'gl_mock_autogen_gl.h',
],
},
],
diff --git a/ui/gl/gl_bindings_api_autogen_gl.h b/ui/gl/gl_bindings_api_autogen_gl.h
index 5aac77c..c886a23 100644
--- a/ui/gl/gl_bindings_api_autogen_gl.h
+++ b/ui/gl/gl_bindings_api_autogen_gl.h
@@ -397,6 +397,7 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name) override;
void glGetTranslatedShaderSourceANGLEFn(GLuint shader,
diff --git a/ui/gl/gl_bindings_autogen_gl.cc b/ui/gl/gl_bindings_autogen_gl.cc
index 11383b1..f1100e8 100644
--- a/ui/gl/gl_bindings_autogen_gl.cc
+++ b/ui/gl/gl_bindings_autogen_gl.cc
@@ -3447,15 +3447,17 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name) {
GL_SERVICE_LOG("glGetTransformFeedbackVarying"
<< "(" << program << ", " << index << ", " << bufSize << ", "
<< static_cast<const void*>(length) << ", "
+ << static_cast<const void*>(size) << ", "
<< static_cast<const void*>(type) << ", "
<< static_cast<const void*>(name) << ")");
- g_driver_gl.debug_fn.glGetTransformFeedbackVaryingFn(program, index, bufSize,
- length, type, name);
+ g_driver_gl.debug_fn.glGetTransformFeedbackVaryingFn(
+ program, index, bufSize, length, size, type, name);
}
static void GL_BINDING_CALL
@@ -6776,10 +6778,11 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name) {
driver_->fn.glGetTransformFeedbackVaryingFn(program, index, bufSize, length,
- type, name);
+ size, type, name);
}
void GLApiBase::glGetTranslatedShaderSourceANGLEFn(GLuint shader,
@@ -8599,12 +8602,13 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu",
"TraceGLAPI::glGetTransformFeedbackVarying")
gl_api_->glGetTransformFeedbackVaryingFn(program, index, bufSize, length,
- type, name);
+ size, type, name);
}
void TraceGLApi::glGetTranslatedShaderSourceANGLEFn(GLuint shader,
@@ -10723,6 +10727,7 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name) {
NOTREACHED() << "Trying to call glGetTransformFeedbackVarying() without "
diff --git a/ui/gl/gl_bindings_autogen_gl.h b/ui/gl/gl_bindings_autogen_gl.h
index b38ba3f..b930484 100644
--- a/ui/gl/gl_bindings_autogen_gl.h
+++ b/ui/gl/gl_bindings_autogen_gl.h
@@ -481,6 +481,7 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name);
typedef void(GL_BINDING_CALL* glGetTranslatedShaderSourceANGLEProc)(
@@ -1644,6 +1645,7 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name) = 0;
virtual void glGetTranslatedShaderSourceANGLEFn(GLuint shader,
diff --git a/ui/gl/gl_bindings_autogen_mock.cc b/ui/gl/gl_bindings_autogen_mock.cc
index 8e84aa3..8d3614b 100644
--- a/ui/gl/gl_bindings_autogen_mock.cc
+++ b/ui/gl/gl_bindings_autogen_mock.cc
@@ -1445,11 +1445,12 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name) {
MakeFunctionUnique("glGetTransformFeedbackVarying");
- interface_->GetTransformFeedbackVarying(program, index, bufSize, length, type,
- name);
+ interface_->GetTransformFeedbackVarying(program, index, bufSize, length, size,
+ type, name);
}
void GL_BINDING_CALL
diff --git a/ui/gl/gl_bindings_autogen_mock.h b/ui/gl/gl_bindings_autogen_mock.h
index 4b1ff4b..52abdae 100644
--- a/ui/gl/gl_bindings_autogen_mock.h
+++ b/ui/gl/gl_bindings_autogen_mock.h
@@ -515,6 +515,7 @@
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name);
static void GL_BINDING_CALL
diff --git a/ui/gl/gl_bindings_skia_in_process.cc b/ui/gl/gl_bindings_skia_in_process.cc
index 5ce7821..91d0b0f 100644
--- a/ui/gl/gl_bindings_skia_in_process.cc
+++ b/ui/gl/gl_bindings_skia_in_process.cc
@@ -277,6 +277,10 @@
glGenVertexArraysOES(n, arrays);
}
+GLvoid StubGLGenerateMipmap(GLenum target){
+ glGenerateMipmapEXT(target);
+}
+
GLvoid StubGLGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
glGetBufferParameteriv(target, pname, params);
}
@@ -668,6 +672,7 @@
functions->fGenQueries = StubGLGenQueries;
functions->fGenTextures = StubGLGenTextures;
functions->fGenVertexArrays = StubGLGenVertexArrays;
+ functions->fGenerateMipmap = StubGLGenerateMipmap;
functions->fGetBufferParameteriv = StubGLGetBufferParameteriv;
functions->fGetError = StubGLGetError;
functions->fGetIntegerv = StubGLGetIntegerv;
diff --git a/ui/gl/gl_fence_egl.cc b/ui/gl/gl_fence_egl.cc
index 74f0a01..641b8c2 100644
--- a/ui/gl/gl_fence_egl.cc
+++ b/ui/gl/gl_fence_egl.cc
@@ -45,7 +45,7 @@
EGLTimeKHR time = EGL_FOREVER_KHR;
EGLint result = eglClientWaitSyncKHR(display_, sync_, flags, time);
DCHECK_IMPLIES(!g_ignore_egl_sync_failures,
- EGL_TIMEOUT_EXPIRED_KHR == result);
+ EGL_TIMEOUT_EXPIRED_KHR != result);
if (result == EGL_FALSE) {
LOG(ERROR) << "Failed to wait for EGLSync. error:"
<< ui::GetLastEGLErrorString();
diff --git a/ui/gl/gl_mock_autogen_gl.h b/ui/gl/gl_mock_autogen_gl.h
index 470de01..5b47058 100644
--- a/ui/gl/gl_mock_autogen_gl.h
+++ b/ui/gl/gl_mock_autogen_gl.h
@@ -390,11 +390,12 @@
void(GLenum target, GLenum pname, GLfloat* params));
MOCK_METHOD3(GetTexParameteriv,
void(GLenum target, GLenum pname, GLint* params));
-MOCK_METHOD6(GetTransformFeedbackVarying,
+MOCK_METHOD7(GetTransformFeedbackVarying,
void(GLuint program,
GLuint index,
GLsizei bufSize,
GLsizei* length,
+ GLsizei* size,
GLenum* type,
char* name));
MOCK_METHOD4(
diff --git a/ui/gl/gl_surface_osmesa.cc b/ui/gl/gl_surface_osmesa.cc
index 4c49166..7f1b1ad 100644
--- a/ui/gl/gl_surface_osmesa.cc
+++ b/ui/gl/gl_surface_osmesa.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/logging.h"
+#include "base/numerics/safe_math.h"
#include "third_party/mesa/src/include/GL/osmesa.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
@@ -50,8 +51,17 @@
// Preserve the old buffer.
scoped_ptr<int32[]> old_buffer(buffer_.release());
+ base::CheckedNumeric<int> checked_size = sizeof(buffer_[0]);
+ checked_size *= new_size.width();
+ checked_size *= new_size.height();
+ if (!checked_size.IsValid())
+ return false;
+
// Allocate a new one.
buffer_.reset(new int32[new_size.GetArea()]);
+ if (!buffer_.get())
+ return false;
+
memset(buffer_.get(), 0, new_size.GetArea() * sizeof(buffer_[0]));
// Copy the old back buffer into the new buffer.
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc
index eecd064..cba706b 100644
--- a/ui/gl/gl_surface_ozone.cc
+++ b/ui/gl/gl_surface_ozone.cc
@@ -105,7 +105,9 @@
AcceleratedWidget widget)
: SurfacelessEGL(gfx::Size()),
ozone_surface_(ozone_surface.Pass()),
- widget_(widget) {}
+ widget_(widget),
+ has_implicit_external_sync_(
+ HasEGLExtension("EGL_ARM_implicit_external_sync")) {}
bool Initialize() override {
if (!SurfacelessEGL::Initialize())
@@ -122,8 +124,8 @@
return SurfacelessEGL::Resize(size);
}
bool SwapBuffers() override {
- // TODO: this should be replaced by a fence when supported by the driver.
- glFlush();
+ if (!Flush())
+ return false;
return ozone_surface_->OnSwapBuffers();
}
bool ScheduleOverlayPlane(int z_order,
@@ -143,8 +145,8 @@
return true;
}
bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
- // TODO: this should be replaced by a fence when supported by the driver.
- glFlush();
+ if (!Flush())
+ return false;
return ozone_surface_->OnSwapBuffersAsync(callback);
}
bool PostSubBufferAsync(int x,
@@ -160,11 +162,35 @@
Destroy(); // EGL surface must be destroyed before SurfaceOzone
}
+ bool Flush() {
+ glFlush();
+ // TODO: 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;
+ }
+ }
+ return true;
+ }
+
// The native surface. Deleting this is allowed to free the EGLNativeWindow.
scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
AcceleratedWidget widget_;
scoped_ptr<VSyncProvider> vsync_provider_;
-
+ bool has_implicit_external_sync_;
DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
};
diff --git a/url/url_canon_relative.cc b/url/url_canon_relative.cc
index 9436245..06ca99c 100644
--- a/url/url_canon_relative.cc
+++ b/url/url_canon_relative.cc
@@ -170,8 +170,8 @@
// up until and including the last slash. There should be a slash in the
// range, if not, nothing will be copied.
//
-// The input is assumed to be canonical, so we search only for exact slashes
-// and not backslashes as well. We also know that it's ASCII.
+// For stardard URLs the input should be canonical, but when resolving relative
+// URLs on a non-standard base (like "data:") the input can be anything.
void CopyToLastSlash(const char* spec,
int begin,
int end,
@@ -179,7 +179,7 @@
// Find the last slash.
int last_slash = -1;
for (int i = end - 1; i >= begin; i--) {
- if (spec[i] == '/') {
+ if (spec[i] == '/' || spec[i] == '\\') {
last_slash = i;
break;
}
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc
index 17c1b0f..73ff93b 100644
--- a/url/url_util_unittest.cc
+++ b/url/url_util_unittest.cc
@@ -273,6 +273,15 @@
// any URL scheme is we might break javascript: URLs by doing so...
{"javascript:alert('foo#bar')", "#badfrag", true,
"javascript:alert('foo#badfrag" },
+ // In this case, the backslashes will not be canonicalized because it's a
+ // non-standard URL, but they will be treated as a path separators,
+ // giving the base URL here a path of "\".
+ //
+ // The result here is somewhat arbitrary. One could argue it should be
+ // either "aaa://a\" or "aaa://a/" since the path is being replaced with
+ // the "current directory". But in the context of resolving on data URLs,
+ // adding the requested dot doesn't seem wrong either.
+ {"aaa://a\\", "aaa:.", true, "aaa://a\\." }
};
for (size_t i = 0; i < arraysize(resolve_non_standard_cases); i++) {