Update from https://crrev.com/308331 Fix ui/compositor/compositor.(h|cpp) based on http://crrev.com/738983002 Fix sky/engine based on current Blink code R=qsr@chromium.org Review URL: https://codereview.chromium.org/812543002
diff --git a/DEPS b/DEPS index b65d15f..79ed2f1 100644 --- a/DEPS +++ b/DEPS
@@ -22,19 +22,19 @@ 'libcxx_revision': '48198f9110397fff47fe7c37cbfa296be7d44d3d', 'libcxxabi_revision': '4ad1009ab3a59fa7a6896d74d5e4de5885697f95', 'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac', - 'skia_revision': '3054be16dfdb0d06233770cbfc338958edef44ea', + 'skia_revision': '912ed6ebb8e2813e72ed7a3dec3b6710ba7e7405', # 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': 'a2359f44508afdb9abe8cb89cdfb02a7b48095b2', + 'v8_revision': '74869d9a9122e26952e517bcc7ad990078644047', # 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": "16545669136028420f67ac496c45c2e9a32ed5a9", + "angle_revision": "797ff4c0ecf1b4950f6948175ea38ccbe888de7f", # 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': '05dd6a24723170d7c6ff35b537ee02947f619891', + 'buildtools_revision': '4995faa4a7ad968f1fa1917c26edd5cea295582f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -78,7 +78,7 @@ Var('chromium_git') + '/angle/angle.git' + '@' + Var('angle_revision'), 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '53ecf0f68b27a004bef5526553b8e5f6c235b80b', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'b0932a04c79198b0fd44282304eb48a5c1850ea3', 'src/third_party/libc++/trunk': Var('chromium_git') + '/chromium/llvm-project/libcxx.git' + '@' + Var('libcxx_revision'), @@ -152,7 +152,7 @@ Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919', 'src/third_party/android_tools': - Var('chromium_git') + '/android_tools.git' + '@' + '4f723e2a5fa5b7b8a198072ac19b92344be2b271', + Var('chromium_git') + '/android_tools.git' + '@' + '8fe116f93f350dcf73c6fe70db893985bf1b91d5', 'src/third_party/freetype': Var('chromium_git') + '/chromium/src/third_party/freetype.git' + '@' + 'a2b9955b49034a51dfbc8bf9f4e9d312149cecac',
diff --git a/base/BUILD.gn b/base/BUILD.gn index fe03aac..de464f9 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -121,6 +121,8 @@ "cancelable_callback.h", "command_line.cc", "command_line.h", + "chromeos/memory_pressure_observer_chromeos.cc", + "chromeos/memory_pressure_observer_chromeos.h", "compiler_specific.h", "containers/adapters.h", "containers/hash_tables.h", @@ -249,6 +251,8 @@ "ios/ios_util.mm", "ios/scoped_critical_action.h", "ios/scoped_critical_action.mm", + "ios/weak_nsobject.h", + "ios/weak_nsobject.mm", "json/json_file_value_serializer.cc", "json/json_file_value_serializer.h", "json/json_parser.cc", @@ -771,6 +775,12 @@ "//third_party/modp_b64", ] + # Allow more direct string conversions on platforms with native utf8 + # strings + if (is_mac || is_ios || is_chromeos) { + defines += [ "SYSTEM_NATIVE_UTF8" ] + } + if (is_android) { sources += [ "memory/discardable_memory_ashmem_allocator.cc", @@ -1187,6 +1197,7 @@ "i18n/time_formatting_unittest.cc", "i18n/timezone_unittest.cc", "ios/device_util_unittest.mm", + "ios/weak_nsobject_unittest.mm", "json/json_parser_unittest.cc", "json/json_reader_unittest.cc", "json/json_value_converter_unittest.cc",
diff --git a/base/base.gyp b/base/base.gyp index ec5444a..d3a55b8 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -519,6 +519,7 @@ 'i18n/time_formatting_unittest.cc', 'i18n/timezone_unittest.cc', 'ios/device_util_unittest.mm', + 'ios/weak_nsobject_unittest.mm', 'json/json_parser_unittest.cc', 'json/json_reader_unittest.cc', 'json/json_value_converter_unittest.cc',
diff --git a/base/base.gypi b/base/base.gypi index f945166..5ec4142 100644 --- a/base/base.gypi +++ b/base/base.gypi
@@ -122,6 +122,8 @@ 'callback_internal.h', 'callback_list.h', 'cancelable_callback.h', + 'chromeos/memory_pressure_observer_chromeos.cc', + 'chromeos/memory_pressure_observer_chromeos.h', 'command_line.cc', 'command_line.h', 'compiler_specific.h', @@ -251,6 +253,8 @@ 'ios/ios_util.mm', 'ios/scoped_critical_action.h', 'ios/scoped_critical_action.mm', + 'ios/weak_nsobject.h', + 'ios/weak_nsobject.mm', 'json/json_file_value_serializer.cc', 'json/json_file_value_serializer.h', 'json/json_parser.cc', @@ -979,6 +983,11 @@ ['OS == "win" and >(nacl_untrusted_build)==1', { 'sources/': [ ['exclude', '\\.h$'] ], }], + # Enable more direct string conversions on platforms with native utf8 + # strings + ['OS=="mac" or OS=="ios" or <(chromeos)==1 or <(chromecast)==1', { + 'defines': ['SYSTEM_NATIVE_UTF8'], + }], ], }], ['base_i18n_target==1', {
diff --git a/base/chromeos/OWNERS b/base/chromeos/OWNERS new file mode 100644 index 0000000..8fda46a --- /dev/null +++ b/base/chromeos/OWNERS
@@ -0,0 +1,3 @@ +skuhne@chromium.org +oshima@chromium.org +
diff --git a/base/chromeos/memory_pressure_observer_chromeos.cc b/base/chromeos/memory_pressure_observer_chromeos.cc new file mode 100644 index 0000000..d991e3f --- /dev/null +++ b/base/chromeos/memory_pressure_observer_chromeos.cc
@@ -0,0 +1,116 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/chromeos/memory_pressure_observer_chromeos.h" + +#include "base/process/process_metrics.h" +#include "base/time/time.h" + +namespace base { + +namespace { + +// The time between memory pressure checks. +const int kMemoryPressureIntervalInMS = 1000; + +// Converts free percent of memory into a memory pressure value. +MemoryPressureObserverChromeOS::MemoryPressureLevel +GetMemoryPressureLevelFromFillLevel( + int memory_fill_level) { + if (memory_fill_level < 50) + return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_LOW; + if (memory_fill_level < 75) + return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_MODERATE; + if (memory_fill_level < 90) + return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_HIGH; + return MemoryPressureObserverChromeOS::MEMORY_PRESSURE_LEVEL_CRITICAL; +} + +// Gets the used ChromeOS memory in percent. +int GetUsedMemoryInPercent() { + base::SystemMemoryInfoKB info; + if (!base::GetSystemMemoryInfo(&info)) { + VLOG(1) << "Cannot determine the free memory of the system."; + return 0; + } + // TODO(skuhne): Instead of adding the kernel memory pressure calculation + // logic here, we should have a kernel mechanism similar to the low memory + // notifier in ChromeOS which offers multiple pressure states. + // To track this, we have crbug.com/381196. + + // The available memory consists of "real" and virtual (z)ram memory. + // Since swappable memory uses a non pre-deterministic compression and + // the compression creates its own "dynamic" in the system, it gets + // de-emphasized by the |kSwapWeight| factor. + const int kSwapWeight = 4; + + // The total memory we have is the "real memory" plus the virtual (z)ram. + int total_memory = info.total + info.swap_total / kSwapWeight; + + // The kernel internally uses 50MB. + const int kMinFileMemory = 50 * 1024; + + // Most file memory can be easily reclaimed. + int file_memory = info.active_file + info.inactive_file; + // unless it is dirty or it's a minimal portion which is required. + file_memory -= info.dirty + kMinFileMemory; + + // Available memory is the sum of free, swap and easy reclaimable memory. + int available_memory = + info.free + info.swap_free / kSwapWeight + file_memory; + + DCHECK(available_memory < total_memory); + int percentage = ((total_memory - available_memory) * 100) / total_memory; + return percentage; +} + +} // namespace + +MemoryPressureObserverChromeOS::MemoryPressureObserverChromeOS() + : current_memory_pressure_level_(MEMORY_PRESSURE_LEVEL_LOW) { + StartObserving(); +} + +MemoryPressureObserverChromeOS::~MemoryPressureObserverChromeOS() { + StopObserving(); +} + +void MemoryPressureObserverChromeOS::StartObserving() { + timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(kMemoryPressureIntervalInMS), + base::Bind(&MemoryPressureObserverChromeOS::CheckMemoryPressure, + base::Unretained(this))); +} + +void MemoryPressureObserverChromeOS::StopObserving() { + // If StartObserving failed, StopObserving will still get called. + timer_.Stop(); +} + +void MemoryPressureObserverChromeOS::CheckMemoryPressure() { + MemoryPressureLevel old_pressure = current_memory_pressure_level_; + MemoryPressureLevel new_pressure = + GetMemoryPressureLevelFromFillLevel(GetUsedMemoryInPercent()); + if (old_pressure != new_pressure) { + current_memory_pressure_level_ = new_pressure; + switch (new_pressure) { + case MEMORY_PRESSURE_LEVEL_LOW: + // The |MemoryPressureListener| does currently not support this. + break; + case MEMORY_PRESSURE_LEVEL_MODERATE: + MemoryPressureListener::NotifyMemoryPressure( + MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); + break; + case MEMORY_PRESSURE_LEVEL_HIGH: + // The |MemoryPressureListener| does currently not support this. + break; + case MEMORY_PRESSURE_LEVEL_CRITICAL: + MemoryPressureListener::NotifyMemoryPressure( + MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL); + break; + } + } +} + +} // namespace base
diff --git a/base/chromeos/memory_pressure_observer_chromeos.h b/base/chromeos/memory_pressure_observer_chromeos.h new file mode 100644 index 0000000..92b1c48 --- /dev/null +++ b/base/chromeos/memory_pressure_observer_chromeos.h
@@ -0,0 +1,81 @@ +// 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_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_ +#define BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_ + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/memory/memory_pressure_listener.h" +#include "base/timer/timer.h" + +namespace base { + +//////////////////////////////////////////////////////////////////////////////// +// MemoryPressureObserverChromeOS +// +// A class to handle the observation of our free memory. It notifies the +// MemoryPressureListener of memory fill level changes, so that it can take +// action to reduce memory resources accordingly. +// +class BASE_EXPORT MemoryPressureObserverChromeOS { + public: + // This is like the |MemoryPressureListener::MemoryPressureLevel| but it has + // more states to allow for a finer grained control as well as a request for + // the current status. + // TODO(skuhne): If the |MemoryPressureListener| will get extended to support + // all these levels, this can be removed. + enum MemoryPressureLevel { + // There is enough memory available to use. + MEMORY_PRESSURE_LEVEL_LOW = 0, + + // Modules are advised to free buffers that are cheap to re-allocate and not + // immediately needed. + MEMORY_PRESSURE_LEVEL_MODERATE = 1, + + // Modules are advised that they might get unloaded dependent on the OS. + // As such they should start to release more memory if possible. + MEMORY_PRESSURE_LEVEL_HIGH = 2, + + // At this level, modules are advised to free all possible memory. The + // alternative is to be killed by the system, which means all memory will + // have to be re-created, plus the cost of a cold start. + MEMORY_PRESSURE_LEVEL_CRITICAL = 3, + }; + + MemoryPressureObserverChromeOS(); + ~MemoryPressureObserverChromeOS(); + + // Get the current memory pressure level. + MemoryPressureLevel GetCurrentPressureLevel() { + return current_memory_pressure_level_; + } + + private: + // Starts observing the memory fill level. + // Calls to StartObserving should always be matched with calls to + // StopObserving. + void StartObserving(); + + // Stop observing the memory fill level. + // May be safely called if StartObserving has not been called. + void StopObserving(); + + // The function which gets periodically be called to check any changes in the + // memory pressure. + void CheckMemoryPressure(); + + // The current memory pressure. + MemoryPressureLevel current_memory_pressure_level_; + + // A periodic timer to check for resource pressure changes. This will get + // replaced by a kernel triggered event system (see crbug.com/381196). + base::RepeatingTimer<MemoryPressureObserverChromeOS> timer_; + + DISALLOW_COPY_AND_ASSIGN(MemoryPressureObserverChromeOS); +}; + +} // namespace base + +#endif // BASE_CHROMEOS_MEMORY_PRESSURE_OBSERVER_CHROMEOS_H_
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc index 1a64eb0..4591286 100644 --- a/base/debug/trace_event_impl.cc +++ b/base/debug/trace_event_impl.cc
@@ -2358,24 +2358,6 @@ str.at(str.length() - 1) == ' '; } -bool CategoryFilter::DoesCategoryGroupContainCategory( - const char* category_group, - const char* category) const { - DCHECK(category); - CStringTokenizer category_group_tokens(category_group, - category_group + strlen(category_group), ","); - while (category_group_tokens.GetNext()) { - std::string category_group_token = category_group_tokens.token(); - // Don't allow empty tokens, nor tokens with leading or trailing space. - DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( - category_group_token)) - << "Disallowed category string"; - if (MatchPattern(category_group_token.c_str(), category)) - return true; - } - return false; -} - CategoryFilter::CategoryFilter(const std::string& filter_string) { if (!filter_string.empty()) Initialize(filter_string); @@ -2483,30 +2465,61 @@ const char* category_group_name) const { // TraceLog should call this method only as part of enabling/disabling // categories. + + bool had_enabled_by_default = false; + DCHECK(category_group_name); + CStringTokenizer category_group_tokens( + category_group_name, category_group_name + strlen(category_group_name), + ","); + while (category_group_tokens.GetNext()) { + std::string category_group_token = category_group_tokens.token(); + // Don't allow empty tokens, nor tokens with leading or trailing space. + DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace( + category_group_token)) + << "Disallowed category string"; + if (IsCategoryEnabled(category_group_token.c_str())) { + return true; + } + if (!MatchPattern(category_group_token.c_str(), + TRACE_DISABLED_BY_DEFAULT("*"))) + had_enabled_by_default = true; + } + // Do a second pass to check for explicitly disabled categories + // (those explicitly enabled have priority due to first pass). + category_group_tokens.Reset(); + while (category_group_tokens.GetNext()) { + std::string category_group_token = category_group_tokens.token(); + for (StringList::const_iterator ci = excluded_.begin(); + ci != excluded_.end(); ++ci) { + if (MatchPattern(category_group_token.c_str(), ci->c_str())) + return false; + } + } + // If the category group is not excluded, and there are no included patterns + // we consider this category group enabled, as long as it had categories + // other than disabled-by-default. + return included_.empty() && had_enabled_by_default; +} + +bool CategoryFilter::IsCategoryEnabled(const char* category_name) const { StringList::const_iterator ci; // Check the disabled- filters and the disabled-* wildcard first so that a // "*" filter does not include the disabled. for (ci = disabled_.begin(); ci != disabled_.end(); ++ci) { - if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) + if (MatchPattern(category_name, ci->c_str())) return true; } - if (DoesCategoryGroupContainCategory(category_group_name, - TRACE_DISABLED_BY_DEFAULT("*"))) + + if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) return false; for (ci = included_.begin(); ci != included_.end(); ++ci) { - if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) + if (MatchPattern(category_name, ci->c_str())) return true; } - for (ci = excluded_.begin(); ci != excluded_.end(); ++ci) { - if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str())) - return false; - } - // If the category group is not excluded, and there are no included patterns - // we consider this pattern enabled. - return included_.empty(); + return false; } bool CategoryFilter::HasIncludedPatterns() const {
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h index ce2e017..c80826c 100644 --- a/base/debug/trace_event_impl.h +++ b/base/debug/trace_event_impl.h
@@ -320,8 +320,8 @@ // categories are distinguished from included categories by the prefix '-'. std::string ToString() const; - // Determines whether category group would be enabled or - // disabled by this category filter. + // Returns true if at least one category in the list is enabled by this + // category filter. bool IsCategoryGroupEnabled(const char* category_group) const; // Return a list of the synthetic delays specified in this category filter. @@ -341,6 +341,9 @@ private: FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, CategoryFilter); + // Returns true if category is enable according to this filter. + bool IsCategoryEnabled(const char* category_name) const; + static bool IsEmptyOrContainsLeadingOrTrailingWhitespace( const std::string& str); @@ -351,9 +354,6 @@ void WriteString(const StringList& delays, std::string* out) const; bool HasIncludedPatterns() const; - bool DoesCategoryGroupContainCategory(const char* category_group, - const char* category) const; - StringList included_; StringList disabled_; StringList excluded_;
diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc index 0904954..85cf4eb 100644 --- a/base/debug/trace_event_unittest.cc +++ b/base/debug/trace_event_unittest.cc
@@ -1615,6 +1615,22 @@ EXPECT_FIND_("disabled-by-default-cc"); EXPECT_FIND_("other_included"); } + + Clear(); + + BeginSpecificTrace("other_included"); + TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("cc") ",other_included", + "first", TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_INSTANT0("other_included," TRACE_DISABLED_BY_DEFAULT("cc"), + "second", TRACE_EVENT_SCOPE_THREAD); + EndTraceAndFlush(); + + { + const DictionaryValue* item = NULL; + ListValue& trace_parsed = trace_parsed_; + EXPECT_FIND_("disabled-by-default-cc,other_included"); + EXPECT_FIND_("other_included,disabled-by-default-cc"); + } } TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
diff --git a/base/files/file_path.cc b/base/files/file_path.cc index bf37be6..33d5ca1 100644 --- a/base/files/file_path.cc +++ b/base/files/file_path.cc
@@ -593,7 +593,7 @@ } std::string FilePath::AsUTF8Unsafe() const { -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) +#if defined(SYSTEM_NATIVE_UTF8) return value(); #else return WideToUTF8(SysNativeMBToWide(value())); @@ -601,7 +601,7 @@ } string16 FilePath::AsUTF16Unsafe() const { -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) +#if defined(SYSTEM_NATIVE_UTF8) return UTF8ToUTF16(value()); #else return WideToUTF16(SysNativeMBToWide(value())); @@ -610,7 +610,7 @@ // static FilePath FilePath::FromUTF8Unsafe(const std::string& utf8) { -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) +#if defined(SYSTEM_NATIVE_UTF8) return FilePath(utf8); #else return FilePath(SysWideToNativeMB(UTF8ToWide(utf8))); @@ -619,7 +619,7 @@ // static FilePath FilePath::FromUTF16Unsafe(const string16& utf16) { -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) +#if defined(SYSTEM_NATIVE_UTF8) return FilePath(UTF16ToUTF8(utf16)); #else return FilePath(SysWideToNativeMB(UTF16ToWide(utf16)));
diff --git a/base/ios/weak_nsobject.h b/base/ios/weak_nsobject.h new file mode 100644 index 0000000..46aecb5 --- /dev/null +++ b/base/ios/weak_nsobject.h
@@ -0,0 +1,166 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_IOS_WEAK_NSOBJECT_H_ +#define BASE_IOS_WEAK_NSOBJECT_H_ + +#import <Foundation/Foundation.h> +#import <objc/runtime.h> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/threading/non_thread_safe.h" +#include "base/threading/thread_checker.h" + +// WeakNSObject<> is patterned after scoped_nsobject<>, but instead of +// maintaining ownership of an NSObject subclass object, it will nil itself out +// when the object is deallocated. +// +// WeakNSProtocol<> has the same behavior as WeakNSObject, but can be used +// with protocols. +// +// Example usage (base::WeakNSObject<T>): +// scoped_nsobject<Foo> foo([[Foo alloc] init]); +// WeakNSObject<Foo> weak_foo; // No pointer +// weak_foo.reset(foo) // Now a weak reference is kept. +// [weak_foo description]; // Returns [foo description]. +// foo.reset(); // The reference is released. +// [weak_foo description]; // Returns nil, as weak_foo is pointing to nil. +// +// +// Implementation wise a WeakNSObject keeps a reference to a refcounted +// WeakContainer. There is one unique instance of a WeakContainer per watched +// NSObject, this relationship is maintained via the ObjectiveC associated +// object API, indirectly via an ObjectiveC CRBWeakNSProtocolSentinel class. +// +// The implementation assumes that the tracked object will be released on the +// same thread that the WeakNSObject is created on. +// +namespace base { + +// WeakContainer keeps a weak pointer to an object and clears it when it +// receives nullify() from the object's sentinel. +class WeakContainer : public base::RefCountedThreadSafe<WeakContainer> { + public: + WeakContainer(id object) : object_(object) {} + id object() { return object_; } + void nullify() { + DCHECK(checker_.CalledOnValidThread()); + object_ = nil; + } + + private: + friend base::RefCountedThreadSafe<WeakContainer>; + ~WeakContainer() {} + base::ThreadChecker checker_; + id object_; +}; + +} // namespace base + +// Sentinel for observing the object contained in the weak pointer. The object +// will be deleted when the weak object is deleted and will notify its +// container. +@interface CRBWeakNSProtocolSentinel : NSObject +// Return the only associated container for this object. There can be only one. +// Will return null if object is nil . ++ (scoped_refptr<base::WeakContainer>)containerForObject:(id)object; +@end + +namespace base { + +// Base class for all WeakNSObject derivatives. +template <typename NST> +class WeakNSProtocol : public base::NonThreadSafe { + public: + explicit WeakNSProtocol(NST object = nil) { + container_ = [CRBWeakNSProtocolSentinel containerForObject:object]; + } + + WeakNSProtocol(const WeakNSProtocol<NST>& that) { + container_ = that.container_; + } + + ~WeakNSProtocol() { + // A WeakNSProtocol object can be allocated on one thread and released on + // another. This is not the case for the contained object. + DetachFromThread(); + } + + void reset(NST object = nil) { + DCHECK(CalledOnValidThread()); + container_ = [CRBWeakNSProtocolSentinel containerForObject:object]; + } + + NST get() const { + DCHECK(CalledOnValidThread()); + if (!container_.get()) + return nil; + return container_->object(); + } + + WeakNSProtocol& operator=(const WeakNSProtocol<NST>& that) { + DCHECK(CalledOnValidThread()); + container_ = that.container_; + return *this; + } + + bool operator==(NST that) const { + DCHECK(CalledOnValidThread()); + return get() == that; + } + + bool operator!=(NST that) const { return get() != that; } + + operator NST() const { return get(); } + + private: + // Refecounted reference to the container tracking the ObjectiveC object this + // class encapsulates. + scoped_refptr<base::WeakContainer> container_; +}; + +// Free functions +template <class NST> +bool operator==(NST p1, const WeakNSProtocol<NST>& p2) { + return p1 == p2.get(); +} + +template <class NST> +bool operator!=(NST p1, const WeakNSProtocol<NST>& p2) { + return p1 != p2.get(); +} + +template <typename NST> +class WeakNSObject : public WeakNSProtocol<NST*> { + public: + explicit WeakNSObject(NST* object = nil) : WeakNSProtocol<NST*>(object) {} + + WeakNSObject(const WeakNSObject<NST>& that) : WeakNSProtocol<NST*>(that) {} + + WeakNSObject& operator=(const WeakNSObject<NST>& that) { + WeakNSProtocol<NST*>::operator=(that); + return *this; + } +}; + +// Specialization to make WeakNSObject<id> work. +template <> +class WeakNSObject<id> : public WeakNSProtocol<id> { + public: + explicit WeakNSObject(id object = nil) : WeakNSProtocol<id>(object) {} + + WeakNSObject(const WeakNSObject<id>& that) : WeakNSProtocol<id>(that) {} + + WeakNSObject& operator=(const WeakNSObject<id>& that) { + WeakNSProtocol<id>::operator=(that); + return *this; + } +}; + +} // namespace base + +#endif // BASE_IOS_WEAK_NSOBJECT_H_
diff --git a/base/ios/weak_nsobject.mm b/base/ios/weak_nsobject.mm new file mode 100644 index 0000000..36f9d3e --- /dev/null +++ b/base/ios/weak_nsobject.mm
@@ -0,0 +1,61 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/ios/weak_nsobject.h" + +#include "base/mac/scoped_nsautorelease_pool.h" +#include "base/mac/scoped_nsobject.h" + +namespace { +// The key needed by objc_setAssociatedObject. +char sentinelObserverKey_; +} + +@interface CRBWeakNSProtocolSentinel () +// Container to notify on dealloc. +@property(readonly, assign) scoped_refptr<base::WeakContainer> container; +// Designed initializer. +- (id)initWithContainer:(scoped_refptr<base::WeakContainer>)container; +@end + +@implementation CRBWeakNSProtocolSentinel + +@synthesize container = container_; + ++ (scoped_refptr<base::WeakContainer>)containerForObject:(id)object { + if (object == nil) + return nullptr; + // The autoreleasePool is needed here as the call to objc_getAssociatedObject + // returns an autoreleased object which is better released sooner than later. + base::mac::ScopedNSAutoreleasePool pool; + CRBWeakNSProtocolSentinel* sentinel = + objc_getAssociatedObject(object, &sentinelObserverKey_); + if (!sentinel) { + base::scoped_nsobject<CRBWeakNSProtocolSentinel> newSentinel( + [[CRBWeakNSProtocolSentinel alloc] + initWithContainer:new base::WeakContainer(object)]); + sentinel = newSentinel; + objc_setAssociatedObject(object, &sentinelObserverKey_, sentinel, + OBJC_ASSOCIATION_RETAIN); + // The retain count is 2. One retain is due to the alloc, the other to the + // association with the weak object. + DCHECK_EQ(2u, [sentinel retainCount]); + } + return [sentinel container]; +} + +- (id)initWithContainer:(scoped_refptr<base::WeakContainer>)container { + DCHECK(container.get()); + self = [super init]; + if (self) + container_ = container; + return self; +} + +- (void)dealloc { + self.container->nullify(); + [super dealloc]; +} + +@end
diff --git a/base/ios/weak_nsobject_unittest.mm b/base/ios/weak_nsobject_unittest.mm new file mode 100644 index 0000000..9758aed --- /dev/null +++ b/base/ios/weak_nsobject_unittest.mm
@@ -0,0 +1,97 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/basictypes.h" +#include "base/ios/weak_nsobject.h" +#include "base/mac/scoped_nsobject.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::WeakNSObject; + +namespace { + +TEST(WeakNSObjectTest, WeakNSObject) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + WeakNSObject<NSObject> w1(p1); + EXPECT_TRUE(w1); + p1.reset(); + EXPECT_FALSE(w1); +} + +TEST(WeakNSObjectTest, MultipleWeakNSObject) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + WeakNSObject<NSObject> w1(p1); + WeakNSObject<NSObject> w2(w1); + EXPECT_TRUE(w1); + EXPECT_TRUE(w2); + EXPECT_TRUE(w1.get() == w2.get()); + p1.reset(); + EXPECT_FALSE(w1); + EXPECT_FALSE(w2); +} + +TEST(WeakNSObjectTest, WeakNSObjectDies) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + { + WeakNSObject<NSObject> w1(p1); + EXPECT_TRUE(w1); + } +} + +TEST(WeakNSObjectTest, WeakNSObjectReset) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + WeakNSObject<NSObject> w1(p1); + EXPECT_TRUE(w1); + w1.reset(); + EXPECT_FALSE(w1); + EXPECT_TRUE(p1); + EXPECT_TRUE([p1 description]); +} + +TEST(WeakNSObjectTest, WeakNSObjectResetWithObject) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + base::scoped_nsobject<NSObject> p2([[NSObject alloc] init]); + WeakNSObject<NSObject> w1(p1); + EXPECT_TRUE(w1); + w1.reset(p2); + EXPECT_TRUE(w1); + EXPECT_TRUE([p1 description]); + EXPECT_TRUE([p2 description]); +} + +TEST(WeakNSObjectTest, WeakNSObjectEmpty) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + WeakNSObject<NSObject> w1; + EXPECT_FALSE(w1); + w1.reset(p1); + EXPECT_TRUE(w1); + p1.reset(); + EXPECT_FALSE(w1); +} + +TEST(WeakNSObjectTest, WeakNSObjectCopy) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + WeakNSObject<NSObject> w1(p1); + WeakNSObject<NSObject> w2(w1); + EXPECT_TRUE(w1); + EXPECT_TRUE(w2); + p1.reset(); + EXPECT_FALSE(w1); + EXPECT_FALSE(w2); +} + +TEST(WeakNSObjectTest, WeakNSObjectAssignment) { + base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); + WeakNSObject<NSObject> w1(p1); + WeakNSObject<NSObject> w2; + EXPECT_FALSE(w2); + w2 = w1; + EXPECT_TRUE(w1); + EXPECT_TRUE(w2); + p1.reset(); + EXPECT_FALSE(w1); + EXPECT_FALSE(w2); +} + +} // namespace
diff --git a/base/mac/sdk_forward_declarations.h b/base/mac/sdk_forward_declarations.h index fa6df4d..f606dab 100644 --- a/base/mac/sdk_forward_declarations.h +++ b/base/mac/sdk_forward_declarations.h
@@ -334,6 +334,10 @@ @property (copy) NSDictionary* userInfo; @property (copy) NSURL* webpageURL; +- (instancetype)initWithActivityType:(NSString*)activityType; +- (void)becomeCurrent; +- (void)invalidate; + @end BASE_EXPORT extern "C" NSString* const NSUserActivityTypeBrowsingWeb;
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc index 6533048..851f1ad 100644 --- a/base/memory/discardable_shared_memory.cc +++ b/base/memory/discardable_shared_memory.cc
@@ -224,6 +224,7 @@ } void DiscardableSharedMemory::Close() { + shared_memory_.Unmap(); shared_memory_.Close(); }
diff --git a/base/memory/shared_memory.h b/base/memory/shared_memory.h index 7254950..d76e01c 100644 --- a/base/memory/shared_memory.h +++ b/base/memory/shared_memory.h
@@ -200,7 +200,8 @@ SharedMemoryId id() const { return inode_; } #endif - // Closes the open shared memory segment. + // Closes the open shared memory segment. The memory will remain mapped if + // it was previously mapped. // It is safe to call Close repeatedly. void Close();
diff --git a/base/memory/shared_memory_nacl.cc b/base/memory/shared_memory_nacl.cc index 39625ee..8435b2b 100644 --- a/base/memory/shared_memory_nacl.cc +++ b/base/memory/shared_memory_nacl.cc
@@ -46,6 +46,7 @@ } SharedMemory::~SharedMemory() { + Unmap(); Close(); } @@ -125,7 +126,6 @@ } void SharedMemory::Close() { - Unmap(); if (mapped_file_ > 0) { if (close(mapped_file_) < 0) DPLOG(ERROR) << "close"; @@ -159,8 +159,10 @@ new_handle->fd = new_fd; new_handle->auto_close = true; - if (close_self) + if (close_self) { + Unmap(); Close(); + } return true; }
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc index 0358e63..fd26ad1 100644 --- a/base/memory/shared_memory_posix.cc +++ b/base/memory/shared_memory_posix.cc
@@ -80,6 +80,7 @@ } SharedMemory::~SharedMemory() { + Unmap(); Close(); } @@ -331,8 +332,6 @@ } void SharedMemory::Close() { - Unmap(); - if (mapped_file_ > 0) { if (close(mapped_file_) < 0) PLOG(ERROR) << "close"; @@ -468,8 +467,10 @@ new_handle->fd = new_fd; new_handle->auto_close = true; - if (close_self) + if (close_self) { + Unmap(); Close(); + } return true; }
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc index 0b3fd7b..265179a 100644 --- a/base/memory/shared_memory_unittest.cc +++ b/base/memory/shared_memory_unittest.cc
@@ -260,6 +260,29 @@ } #endif +// Check that memory is still mapped after its closed. +TEST(SharedMemoryTest, CloseNoUnmap) { + const size_t kDataSize = 4096; + + SharedMemory memory; + ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); + char* ptr = static_cast<char*>(memory.memory()); + ASSERT_NE(ptr, static_cast<void*>(NULL)); + memset(ptr, 'G', kDataSize); + + memory.Close(); + + EXPECT_EQ(ptr, memory.memory()); + EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle()); + + for (size_t i = 0; i < kDataSize; i++) { + EXPECT_EQ('G', ptr[i]); + } + + memory.Unmap(); + EXPECT_EQ(nullptr, memory.memory()); +} + // Create a set of N threads to each open a shared memory segment and write to // it. Verify that they are always reading/writing consistent data. TEST(SharedMemoryTest, MultipleThreads) {
diff --git a/base/memory/shared_memory_win.cc b/base/memory/shared_memory_win.cc index 5d2fa2a..20659ab 100644 --- a/base/memory/shared_memory_win.cc +++ b/base/memory/shared_memory_win.cc
@@ -71,6 +71,7 @@ } SharedMemory::~SharedMemory() { + Unmap(); Close(); if (lock_ != NULL) CloseHandle(lock_); @@ -249,11 +250,6 @@ void SharedMemory::Close() { - if (memory_ != NULL) { - UnmapViewOfFile(memory_); - memory_ = NULL; - } - if (mapped_file_ != NULL) { CloseHandle(mapped_file_); mapped_file_ = NULL;
diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc index 2ca32d6..9e5b013 100644 --- a/base/message_loop/incoming_task_queue.cc +++ b/base/message_loop/incoming_task_queue.cc
@@ -6,16 +6,36 @@ #include "base/location.h" #include "base/message_loop/message_loop.h" +#include "base/metrics/histogram.h" #include "base/synchronization/waitable_event.h" #include "base/time/time.h" namespace base { namespace internal { +namespace { + +// Returns true if MessagePump::ScheduleWork() must be called one +// time for every task that is added to the MessageLoop incoming queue. +bool AlwaysNotifyPump(MessageLoop::Type type) { +#if defined(OS_ANDROID) + // The Android UI message loop needs to get notified each time a task is + // added + // to the incoming queue. + return type == MessageLoop::TYPE_UI || type == MessageLoop::TYPE_JAVA; +#else + return false; +#endif +} + +} // namespace + IncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop) : high_res_task_count_(0), message_loop_(message_loop), - next_sequence_num_(0) { + next_sequence_num_(0), + message_loop_scheduled_(false), + always_schedule_work_(AlwaysNotifyPump(message_loop_->type())) { } bool IncomingTaskQueue::AddToIncomingQueue( @@ -56,9 +76,14 @@ // Acquire all we can from the inter-thread queue with one lock acquisition. AutoLock lock(incoming_queue_lock_); - if (!incoming_queue_.empty()) + if (incoming_queue_.empty()) { + // If the loop attempts to reload but there are no tasks in the incoming + // queue, that means it will go to sleep waiting for more work. If the + // incoming queue becomes nonempty we need to schedule it again. + message_loop_scheduled_ = false; + } else { incoming_queue_.Swap(work_queue); - + } // Reset the count of high resolution tasks since our queue is now empty. int high_res_tasks = high_res_task_count_; high_res_task_count_ = 0; @@ -109,8 +134,16 @@ incoming_queue_.push(*pending_task); pending_task->task.Reset(); - // Wake up the pump. - message_loop_->ScheduleWork(was_empty); + if (always_schedule_work_ || (!message_loop_scheduled_ && was_empty)) { + // Wake up the message loop. + message_loop_->ScheduleWork(); + // After we've scheduled the message loop, we do not need to do so again + // until we know it has processed all of the work in our queue and is + // waiting for more work again. The message loop will always attempt to + // reload from the incoming queue before waiting again so we clear this flag + // in ReloadWorkQueue(). + message_loop_scheduled_ = true; + } return true; }
diff --git a/base/message_loop/incoming_task_queue.h b/base/message_loop/incoming_task_queue.h index 30f2603..72e1f30 100644 --- a/base/message_loop/incoming_task_queue.h +++ b/base/message_loop/incoming_task_queue.h
@@ -84,6 +84,14 @@ // The next sequence number to use for delayed tasks. int next_sequence_num_; + // True if our message loop has already been scheduled and does not need to be + // scheduled again until an empty reload occurs. + bool message_loop_scheduled_; + + // True if we always need to call ScheduleWork when receiving a new task, even + // if the incoming queue was not empty. + const bool always_schedule_work_; + DISALLOW_COPY_AND_ASSIGN(IncomingTaskQueue); };
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 2f4a03c..8180733 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc
@@ -86,18 +86,6 @@ MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = NULL; -// Returns true if MessagePump::ScheduleWork() must be called one -// time for every task that is added to the MessageLoop incoming queue. -bool AlwaysNotifyPump(MessageLoop::Type type) { -#if defined(OS_ANDROID) - // The Android UI message loop needs to get notified each time a task is added - // to the incoming queue. - return type == MessageLoop::TYPE_UI || type == MessageLoop::TYPE_JAVA; -#else - return false; -#endif -} - #if defined(OS_IOS) typedef MessagePumpIOSForIO MessagePumpForIO; #elif defined(OS_NACL_SFI) @@ -512,9 +500,8 @@ } } -void MessageLoop::ScheduleWork(bool was_empty) { - if (was_empty || AlwaysNotifyPump(type_)) - pump_->ScheduleWork(); +void MessageLoop::ScheduleWork() { + pump_->ScheduleWork(); } //------------------------------------------------------------------------------
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h index 47df69a..32e826d 100644 --- a/base/message_loop/message_loop.h +++ b/base/message_loop/message_loop.h
@@ -391,7 +391,7 @@ // Wakes up the message pump. Can be called on any thread. The caller is // responsible for synchronizing ScheduleWork() calls. - void ScheduleWork(bool was_empty); + void ScheduleWork(); // Returns the TaskAnnotator which is used to add debug information to posted // tasks.
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc index 9fca465..39ed5a8 100644 --- a/base/message_loop/message_pump_perftest.cc +++ b/base/message_loop/message_pump_perftest.cc
@@ -39,7 +39,7 @@ uint64_t schedule_calls = 0u; do { for (size_t i = 0; i < kBatchSize; ++i) { - target_message_loop()->ScheduleWork(true); + target_message_loop()->ScheduleWork(); schedule_calls++; } now = base::TimeTicks::HighResNow();
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc index ad89b7f..3f94c80 100644 --- a/base/message_loop/message_pump_win.cc +++ b/base/message_loop/message_pump_win.cc
@@ -10,6 +10,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/process/memory.h" +#include "base/profiler/scoped_tracker.h" #include "base/strings/stringprintf.h" #include "base/win/wrapped_window_proc.h" @@ -319,6 +320,11 @@ } bool MessagePumpForUI::ProcessNextWindowsMessage() { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "440919 <<MessagePumpForUI::ProcessNextWindowsMessage>>")); + // If there are sent messages in the queue then PeekMessage internally // dispatches the message and returns false. We return true in this // case to ensure that the message loop peeks again instead of calling
diff --git a/base/port.h b/base/port.h index 0a04d55..56c4d4e 100644 --- a/base/port.h +++ b/base/port.h
@@ -26,18 +26,6 @@ #define GG_INT64_C(x) GG_LONGLONG(x) #define GG_UINT64_C(x) GG_ULONGLONG(x) -// It's possible for functions that use a va_list, such as StringPrintf, to -// invalidate the data in it upon use. The fix is to make a copy of the -// structure before using it and use that copy instead. va_copy is provided -// for this purpose. MSVC does not provide va_copy, so define an -// implementation here. It is not guaranteed that assignment is a copy, so the -// StringUtil.VariableArgsFunc unit test tests this capability. -#if defined(COMPILER_GCC) -#define GG_VA_COPY(a, b) (va_copy(a, b)) -#elif defined(COMPILER_MSVC) -#define GG_VA_COPY(a, b) (a = b) -#endif - // Define an OS-neutral wrapper for shared library entry points #if defined(OS_WIN) #define API_CALL __stdcall
diff --git a/base/process/process.h b/base/process/process.h index 50ccf8d..ad8f8ee 100644 --- a/base/process/process.h +++ b/base/process/process.h
@@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "base/move.h" #include "base/process/process_handle.h" +#include "base/time/time.h" #include "build/build_config.h" #if defined(OS_WIN) @@ -81,6 +82,13 @@ // NOTE: On POSIX |result_code| is ignored. void Terminate(int result_code); + // Waits for the process to exit. Returns true on success. + // On POSIX, if the process has been signaled then |exit_code| is set to -1. + bool WaitForExit(int* exit_code); + + // Same as WaitForExit() but only waits for up to |timeout|. + bool WaitForExitWithTimeout(TimeDelta timeout, int* exit_code); + // A process is backgrounded when it's priority is lower than normal. // Return true if this process is backgrounded, false otherwise. bool IsProcessBackgrounded() const;
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc index 270438e..58852bc 100644 --- a/base/process/process_posix.cc +++ b/base/process/process_posix.cc
@@ -89,6 +89,18 @@ KillProcess(process_, result_code, false); } +bool Process::WaitForExit(int* exit_code) { + // TODO(rvargas) crbug.com/417532: Remove this constant. + const int kNoTimeout = -1; + return WaitForExitWithTimeout(TimeDelta::FromMilliseconds(kNoTimeout), + exit_code); +} + +bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) { + // TODO(rvargas) crbug.com/417532: Move the implementation here. + return base::WaitForExitCodeWithTimeout(Handle(), exit_code, timeout); +} + #if !defined(OS_LINUX) bool Process::IsProcessBackgrounded() const { // See SetProcessBackgrounded().
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc index a5ba834..5180f64 100644 --- a/base/process/process_unittest.cc +++ b/base/process/process_unittest.cc
@@ -135,6 +135,34 @@ #endif } +MULTIPROCESS_TEST_MAIN(FastSleepyChildProcess) { + PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 10); + return 0; +} + +TEST_F(ProcessTest, WaitForExit) { + Process process(SpawnChild("FastSleepyChildProcess")); + ASSERT_TRUE(process.IsValid()); + + const int kDummyExitCode = 42; + int exit_code = kDummyExitCode; + EXPECT_TRUE(process.WaitForExit(&exit_code)); + EXPECT_EQ(0, exit_code); +} + +TEST_F(ProcessTest, WaitForExitWithTimeout) { + Process process(SpawnChild("SleepyChildProcess")); + ASSERT_TRUE(process.IsValid()); + + const int kDummyExitCode = 42; + int exit_code = kDummyExitCode; + TimeDelta timeout = TestTimeouts::tiny_timeout(); + EXPECT_FALSE(process.WaitForExitWithTimeout(timeout, &exit_code)); + EXPECT_EQ(kDummyExitCode, exit_code); + + process.Terminate(kDummyExitCode); +} + // Ensure that the priority of a process is restored correctly after // backgrounding and restoring. // Note: a platform may not be willing or able to lower the priority of
diff --git a/base/process/process_win.cc b/base/process/process_win.cc index 3e0d79f..96556a9 100644 --- a/base/process/process_win.cc +++ b/base/process/process_win.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/process/kill.h" #include "base/win/windows_version.h" namespace base { @@ -110,6 +111,18 @@ terminate_process(Handle(), result_code); } +bool Process::WaitForExit(int* exit_code) { + return WaitForExitWithTimeout(TimeDelta::FromMilliseconds(INFINITE), + exit_code); +} + +bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) { + // TODO(rvargas) crbug.com/417532: Move the implementation here. + if (timeout > TimeDelta::FromMilliseconds(INFINITE)) + timeout = TimeDelta::FromMilliseconds(INFINITE); + return base::WaitForExitCodeWithTimeout(Handle(), exit_code, timeout); +} + bool Process::IsProcessBackgrounded() const { DCHECK(IsValid()); DWORD priority = GetPriority();
diff --git a/base/profiler/tracked_time.cc b/base/profiler/tracked_time.cc index 7791c3a..0121038 100644 --- a/base/profiler/tracked_time.cc +++ b/base/profiler/tracked_time.cc
@@ -46,7 +46,7 @@ TrackedTime::TrackedTime() : ms_(0) {} TrackedTime::TrackedTime(int32 ms) : ms_(ms) {} TrackedTime::TrackedTime(const base::TimeTicks& time) - : ms_((time - base::TimeTicks()).InMilliseconds()) { + : ms_(static_cast<int32>((time - base::TimeTicks()).InMilliseconds())) { } // static
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc index 923116d..d887c0b 100644 --- a/base/strings/string_util_unittest.cc +++ b/base/strings/string_util_unittest.cc
@@ -669,39 +669,6 @@ EXPECT_EQ(15, HexDigitToInt('f')); } -// This checks where we can use the assignment operator for a va_list. We need -// a way to do this since Visual C doesn't support va_copy, but assignment on -// va_list is not guaranteed to be a copy. See StringAppendVT which uses this -// capability. -static void VariableArgsFunc(const char* format, ...) { - va_list org; - va_start(org, format); - - va_list dup; - GG_VA_COPY(dup, org); - int i1 = va_arg(org, int); - int j1 = va_arg(org, int); - char* s1 = va_arg(org, char*); - double d1 = va_arg(org, double); - va_end(org); - - int i2 = va_arg(dup, int); - int j2 = va_arg(dup, int); - char* s2 = va_arg(dup, char*); - double d2 = va_arg(dup, double); - - EXPECT_EQ(i1, i2); - EXPECT_EQ(j1, j2); - EXPECT_STREQ(s1, s2); - EXPECT_EQ(d1, d2); - - va_end(dup); -} - -TEST(StringUtilTest, VAList) { - VariableArgsFunc("%d %d %s %lf", 45, 92, "This is interesting", 9.21); -} - // Test for Tokenize template <typename STR> void TokenizeTest() {
diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc index 3d024fa..f3a57b3 100644 --- a/base/strings/stringprintf.cc +++ b/base/strings/stringprintf.cc
@@ -48,7 +48,7 @@ typename StringType::value_type stack_buf[1024]; va_list ap_copy; - GG_VA_COPY(ap_copy, ap); + va_copy(ap_copy, ap); #if !defined(OS_WIN) ScopedClearErrno clear_errno; @@ -94,7 +94,7 @@ // NOTE: You can only use a va_list once. Since we're in a while loop, we // need to make a new copy each time so we don't use up the original. - GG_VA_COPY(ap_copy, ap); + va_copy(ap_copy, ap); result = vsnprintfT(&mem_buf[0], mem_length, format, ap_copy); va_end(ap_copy);
diff --git a/base/strings/sys_string_conversions_posix.cc b/base/strings/sys_string_conversions_posix.cc index 1e926bb..3b18456 100644 --- a/base/strings/sys_string_conversions_posix.cc +++ b/base/strings/sys_string_conversions_posix.cc
@@ -24,11 +24,10 @@ return out; } -#if defined(OS_CHROMEOS) || defined(OS_ANDROID) +#if defined(SYSTEM_NATIVE_UTF8) || defined(OS_ANDROID) // TODO(port): Consider reverting the OS_ANDROID when we have wcrtomb() // support and a better understanding of what calls these routines. -// ChromeOS always runs in UTF-8 locale. std::string SysWideToNativeMB(const std::wstring& wide) { return WideToUTF8(wide); }
diff --git a/base/supports_user_data.h b/base/supports_user_data.h index 6d515d7..711ee7d 100644 --- a/base/supports_user_data.h +++ b/base/supports_user_data.h
@@ -61,7 +61,7 @@ template <typename T> class UserDataAdapter : public base::SupportsUserData::Data { public: - static T* Get(SupportsUserData* supports_user_data, const void* key) { + static T* Get(const SupportsUserData* supports_user_data, const void* key) { UserDataAdapter* data = static_cast<UserDataAdapter*>(supports_user_data->GetUserData(key)); return data ? static_cast<T*>(data->object_.get()) : NULL;
diff --git a/build/all.gyp b/build/all.gyp index 149ac0a..5f06ae0 100644 --- a/build/all.gyp +++ b/build/all.gyp
@@ -846,6 +846,7 @@ '../tools/android/android_tools.gyp:android_tools', '../tools/android/android_tools.gyp:memconsumer', '../tools/android/findbugs_plugin/findbugs_plugin.gyp:findbugs_plugin_test', + '../ui/android/ui_android.gyp:ui_android_unittests', '../ui/base/ui_base_tests.gyp:ui_base_unittests', '../ui/events/events.gyp:events_unittests', '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_unittests', @@ -874,6 +875,7 @@ '../sql/sql.gyp:sql_unittests_apk', '../sync/sync.gyp:sync_unit_tests_apk', '../tools/android/heap_profiler/heap_profiler.gyp:heap_profiler_unittests_apk', + '../ui/android/ui_android.gyp:ui_android_unittests_apk', '../ui/base/ui_base_tests.gyp:ui_base_unittests_apk', '../ui/events/events.gyp:events_unittests_apk', '../ui/gfx/gfx_tests.gyp:gfx_unittests_apk', @@ -883,7 +885,6 @@ ['enable_webrtc==1 and "<(libpeer_target_type)"=="static_library"', { 'dependencies': [ '../components/devtools_bridge.gyp:devtools_bridge_tests_apk', - '../components/devtools_bridge.gyp:libdevtools_bridge_browsertests', ], }], ], @@ -899,7 +900,6 @@ '../tools/android/android_tools.gyp:memconsumer', # Unit test bundles packaged as an apk. '../components/devtools_bridge.gyp:devtools_bridge_tests_apk', - '../components/devtools_bridge.gyp:libdevtools_bridge_browsertests', '../content/content_shell_and_tests.gyp:content_browsertests_apk', ], }, # target_name: android_builder_chromium_webrtc
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py index a72a0c7..08bccc9 100755 --- a/build/android/buildbot/bb_device_status_check.py +++ b/build/android/buildbot/bb_device_status_check.py
@@ -46,10 +46,10 @@ """ device_adb = device_utils.DeviceUtils(serial) - device_type = device_adb.GetProp('ro.build.product') - device_build = device_adb.GetProp('ro.build.id') - device_build_type = device_adb.GetProp('ro.build.type') - device_product_name = device_adb.GetProp('ro.product.name') + device_type = device_adb.build_product + device_build = device_adb.build_id + device_build_type = device_adb.build_type + device_product_name = device_adb.product_name try: battery_info = device_adb.old_interface.GetBatteryInfo() @@ -71,7 +71,7 @@ lambda x: x[-6:]) report = ['Device %s (%s)' % (serial, device_type), ' Build: %s (%s)' % - (device_build, device_adb.GetProp('ro.build.fingerprint')), + (device_build, device_adb.build_fingerprint), ' Current Battery Service state: ', '\n'.join([' %s: %s' % (k, v) for k, v in battery_info.iteritems()]),
diff --git a/build/android/findbugs_filter/findbugs_known_bugs.txt b/build/android/findbugs_filter/findbugs_known_bugs.txt index 6ad2b3a..cbc5e30 100644 --- a/build/android/findbugs_filter/findbugs_known_bugs.txt +++ b/build/android/findbugs_filter/findbugs_known_bugs.txt
@@ -23,3 +23,10 @@ M V EI2: org.chromium.content_public.browser.LoadUrlParams.setPostData(byte[]) may expose internal representation by storing an externally mutable object into LoadUrlParams.mPostData At LoadUrlParams.java M V EI: org.chromium.content_public.browser.LoadUrlParams.getPostData() may expose internal representation by returning LoadUrlParams.mPostData At LoadUrlParams.java M V EI2: org.chromium.net.ChromiumUrlRequest.setUploadData(String, byte[]) may expose internal representation by storing an externally mutable object into ChromiumUrlRequest.mUploadData At ChromiumUrlRequest.java +M D UrF: Unread public/protected field: org.chromium.chrome.browser.tabmodel.document.DocumentTabModel$Entry.initialUrl At DocumentTabModel.java +M D UrF: Unread public/protected field: org.chromium.chrome.browser.tabmodel.document.DocumentTabModel$Entry.isTabStateReady At DocumentTabModel.java +M D UrF: Unread public/protected field: org.chromium.chrome.browser.tabmodel.document.DocumentTabModel$Entry.tabState At DocumentTabModel.java +M D UuF: Unused public or protected field: org.chromium.chrome.browser.tabmodel.document.DocumentTabModel$Entry.canGoBack In DocumentTabModel.java +M D UuF: Unused public or protected field: org.chromium.chrome.browser.tabmodel.document.DocumentTabModel$Entry.currentUrl In DocumentTabModel.java +M D UuF: Unused public or protected field: org.chromium.chrome.browser.tabmodel.document.DocumentTabModel$Entry.isDirty In DocumentTabModel.java +M D UuF: Unused public or protected field: org.chromium.chrome.browser.tabmodel.document.DocumentTabModel$Entry.placeholderTab In DocumentTabModel.java
diff --git a/build/android/pylib/base/environment_factory.py b/build/android/pylib/base/environment_factory.py index c96d199..3ad39fc 100644 --- a/build/android/pylib/base/environment_factory.py +++ b/build/android/pylib/base/environment_factory.py
@@ -2,10 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from pylib.remote.device import remote_device_environment -def CreateEnvironment(_args, error_func): +def CreateEnvironment(args, error_func): # TODO(jbudorick) Add local device environment. # TODO(jbudorick) Add local machine environment. - error_func('No environments currently supported.') + if args.environment == 'remote_device': + return remote_device_environment.RemoteDeviceEnvironment(args, + error_func) + error_func('Unable to create %s environment.' % args.environment)
diff --git a/build/android/pylib/base/test_instance_factory.py b/build/android/pylib/base/test_instance_factory.py index 5204b2e..af989ef 100644 --- a/build/android/pylib/base/test_instance_factory.py +++ b/build/android/pylib/base/test_instance_factory.py
@@ -5,6 +5,8 @@ from pylib import constants from pylib.gtest import gtest_test_instance from pylib.utils import isolator +from pylib.uirobot import uirobot_test_instance + def CreateTestInstance(args, error_func): @@ -12,7 +14,8 @@ if args.command == 'gtest': return gtest_test_instance.GtestTestInstance( args, isolator.Isolator(constants.ISOLATE_DEPS_DIR)) + if args.command == 'uirobot': + return uirobot_test_instance.UirobotTestInstance(args) # TODO(jbudorick) Add instrumentation test instance. error_func('Unable to create %s test instance.' % args.command) -
diff --git a/build/android/pylib/base/test_run.py b/build/android/pylib/base/test_run.py index 2c594fd..7380e78 100644 --- a/build/android/pylib/base/test_run.py +++ b/build/android/pylib/base/test_run.py
@@ -24,7 +24,7 @@ def SetUp(self): raise NotImplementedError - def RunTest(self): + def RunTests(self): raise NotImplementedError def TearDown(self):
diff --git a/build/android/pylib/base/test_run_factory.py b/build/android/pylib/base/test_run_factory.py index 6ccfb37..550b4cf 100644 --- a/build/android/pylib/base/test_run_factory.py +++ b/build/android/pylib/base/test_run_factory.py
@@ -2,9 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -def CreateTestRun(_args, _env, _test_instance, error_func): +from pylib.remote.device import remote_device_gtest_run +from pylib.remote.device import remote_device_uirobot_run +def CreateTestRun(args, env, test_instance, error_func): + if args.environment == 'remote_device': + if test_instance.TestType() == 'gtest': + return remote_device_gtest_run.RemoteDeviceGtestRun(env, test_instance) + if test_instance.TestType() == 'uirobot': + return remote_device_uirobot_run.RemoteDeviceUirobotRun( + env, test_instance) # TODO(jbudorick) Add local gtest test runs # TODO(jbudorick) Add local instrumentation test runs. - error_func('No test runs are currently supported.') - + error_func('Unable to create %s test run in %s environment' % ( + test_instance.TestType(), args.environment))
diff --git a/build/android/pylib/cmd_helper.py b/build/android/pylib/cmd_helper.py index e3abab7..f881553 100644 --- a/build/android/pylib/cmd_helper.py +++ b/build/android/pylib/cmd_helper.py
@@ -115,14 +115,20 @@ return output -def _LogCommand(args, cwd=None): - if not isinstance(args, basestring): +def _ValidateAndLogCommand(args, cwd, shell): + if isinstance(args, basestring): + if not shell: + raise Exception('string args must be run with shell=True') + else: + if shell: + raise Exception('array args must be run with shell=False') args = ' '.join(SingleQuote(c) for c in args) if cwd is None: cwd = '' else: cwd = ':' + cwd logging.info('[host]%s> %s', cwd, args) + return args def GetCmdStatusAndOutput(args, cwd=None, shell=False): @@ -133,18 +139,13 @@ the string or the first item in the args sequence. cwd: If not None, the subprocess's current directory will be changed to |cwd| before it's executed. - shell: Whether to execute args as a shell command. + shell: Whether to execute args as a shell command. Must be True if args + is a string and False if args is a sequence. Returns: The 2-tuple (exit code, output). """ - if isinstance(args, basestring): - if not shell: - raise Exception('string args must be run with shell=True') - elif shell: - raise Exception('array args must be run with shell=False') - - _LogCommand(args, cwd) + _ValidateAndLogCommand(args, cwd, shell) pipe = Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell, cwd=cwd) stdout, stderr = pipe.communicate() @@ -162,44 +163,16 @@ pass -def GetCmdStatusAndOutputWithTimeout(args, timeout, cwd=None, shell=False, - logfile=None): - """Executes a subprocess with a timeout. - - Args: - args: List of arguments to the program, the program to execute is the first - element. - timeout: the timeout in seconds or None to wait forever. - cwd: If not None, the subprocess's current directory will be changed to - |cwd| before it's executed. - shell: Whether to execute args as a shell command. - logfile: Optional file-like object that will receive output from the - command as it is running. - - Returns: - The 2-tuple (exit code, output). - """ +def _IterProcessStdout(process, timeout=None, buffer_size=4096, + poll_interval=1): assert fcntl, 'fcntl module is required' - if isinstance(args, basestring): - if not shell: - raise Exception('string args must be run with shell=True') - elif shell: - raise Exception('array args must be run with shell=False') - - _LogCommand(args, cwd) - process = Popen(args, cwd=cwd, shell=shell, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) try: - end_time = (time.time() + timeout) if timeout else None - poll_interval = 1 - buffer_size = 4096 - child_fd = process.stdout.fileno() - output = StringIO.StringIO() - # Enable non-blocking reads from the child's stdout. + child_fd = process.stdout.fileno() fl = fcntl.fcntl(child_fd, fcntl.F_GETFL) fcntl.fcntl(child_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + end_time = (time.time() + timeout) if timeout else None while True: if end_time and time.time() > end_time: raise TimeoutError @@ -208,9 +181,7 @@ data = os.read(child_fd, buffer_size) if not data: break - if logfile: - logfile.write(data) - output.write(data) + yield data if process.poll() is not None: break finally: @@ -221,4 +192,70 @@ except OSError: pass process.wait() + + +def GetCmdStatusAndOutputWithTimeout(args, timeout, cwd=None, shell=False, + logfile=None): + """Executes a subprocess with a timeout. + + Args: + args: List of arguments to the program, the program to execute is the first + element. + timeout: the timeout in seconds or None to wait forever. + cwd: If not None, the subprocess's current directory will be changed to + |cwd| before it's executed. + shell: Whether to execute args as a shell command. Must be True if args + is a string and False if args is a sequence. + logfile: Optional file-like object that will receive output from the + command as it is running. + + Returns: + The 2-tuple (exit code, output). + """ + _ValidateAndLogCommand(args, cwd, shell) + output = StringIO.StringIO() + process = Popen(args, cwd=cwd, shell=shell, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + for data in _IterProcessStdout(process, timeout=timeout): + if logfile: + logfile.write(data) + output.write(data) return process.returncode, output.getvalue() + + +def IterCmdOutputLines(args, timeout=None, cwd=None, shell=False, + check_status=True): + """Executes a subprocess and continuously yields lines from its output. + + Args: + args: List of arguments to the program, the program to execute is the first + element. + cwd: If not None, the subprocess's current directory will be changed to + |cwd| before it's executed. + shell: Whether to execute args as a shell command. Must be True if args + is a string and False if args is a sequence. + check_status: A boolean indicating whether to check the exit status of the + process after all output has been read. + + Yields: + The output of the subprocess, line by line. + + Raises: + CalledProcessError if check_status is True and the process exited with a + non-zero exit status. + """ + cmd = _ValidateAndLogCommand(args, cwd, shell) + process = Popen(args, cwd=cwd, shell=shell, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + buffer_output = '' + for data in _IterProcessStdout(process, timeout=timeout): + buffer_output += data + has_incomplete_line = buffer_output[-1] not in '\r\n' + lines = buffer_output.splitlines() + buffer_output = lines.pop() if has_incomplete_line else '' + for line in lines: + yield line + if buffer_output: + yield buffer_output + if check_status and process.returncode: + raise subprocess.CalledProcessError(process.returncode, cmd)
diff --git a/build/android/pylib/cmd_helper_test.py b/build/android/pylib/cmd_helper_test.py index 8b5680d..5155cea 100644 --- a/build/android/pylib/cmd_helper_test.py +++ b/build/android/pylib/cmd_helper_test.py
@@ -5,11 +5,10 @@ """Tests for the cmd_helper module.""" import unittest +import subprocess from pylib import cmd_helper -# TODO(jbudorick) Make these tests run on the bots. - class CmdHelperSingleQuoteTest(unittest.TestCase): @@ -51,3 +50,34 @@ cmd = 'TEST_VAR=world; echo %s' % cmd_helper.DoubleQuote(test_string) self.assertEquals('hello world', cmd_helper.GetCmdOutput(cmd, shell=True).rstrip()) + + +class CmdHelperIterCmdOutputLinesTest(unittest.TestCase): + """Test IterCmdOutputLines with some calls to the unix 'seq' command.""" + + def testIterCmdOutputLines_success(self): + for num, line in enumerate( + cmd_helper.IterCmdOutputLines(['seq', '10']), 1): + self.assertEquals(num, int(line)) + + def testIterCmdOutputLines_exitStatusFail(self): + with self.assertRaises(subprocess.CalledProcessError): + for num, line in enumerate( + cmd_helper.IterCmdOutputLines('seq 10 && false', shell=True), 1): + self.assertEquals(num, int(line)) + # after reading all the output we get an exit status of 1 + + def testIterCmdOutputLines_exitStatusIgnored(self): + for num, line in enumerate( + cmd_helper.IterCmdOutputLines('seq 10 && false', shell=True, + check_status=False), 1): + self.assertEquals(num, int(line)) + + def testIterCmdOutputLines_exitStatusSkipped(self): + for num, line in enumerate( + cmd_helper.IterCmdOutputLines('seq 10 && false', shell=True), 1): + self.assertEquals(num, int(line)) + # no exception will be raised because we don't attempt to read past + # the end of the output and, thus, the status never gets checked + if num == 10: + break
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py index ac57969..50dc075 100644 --- a/build/android/pylib/constants.py +++ b/build/android/pylib/constants.py
@@ -187,6 +187,7 @@ 'pylib_py_unittests': { 'path': os.path.join(DIR_SOURCE_ROOT, 'build', 'android'), 'test_modules': [ + 'pylib.cmd_helper_test', 'pylib.device.device_utils_test', 'pylib.results.json_results_test', 'pylib.utils.md5sum_test', @@ -201,9 +202,9 @@ } LOCAL_MACHINE_TESTS = ['junit', 'python'] -VALID_ENVIRONMENTS = ['local'] +VALID_ENVIRONMENTS = ['local', 'remote_device'] VALID_TEST_TYPES = ['gtest', 'instrumentation', 'junit', 'linker', 'monkey', - 'perf', 'python', 'uiautomator'] + 'perf', 'python', 'uiautomator', 'uirobot'] def GetBuildType():
diff --git a/build/android/pylib/content_settings.py b/build/android/pylib/content_settings.py index f00553f..f039c96 100644 --- a/build/android/pylib/content_settings.py +++ b/build/android/pylib/content_settings.py
@@ -14,13 +14,9 @@ def __init__(self, table, device): super(ContentSettings, self).__init__() - sdk_version_string = device.GetProp('ro.build.version.sdk') - try: - sdk_version = int(sdk_version_string) - assert sdk_version >= constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN, ( - 'ContentSettings supported only on SDK 16 and later') - except ValueError: - assert False, ('Unknown SDK version %s' % sdk_version_string) + assert (device.build_version_sdk + >= constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN), ( + 'ContentSettings supported only on SDK 16 and later') self._table = table self._device = device
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py index 39fe706..4006a21 100644 --- a/build/android/pylib/device/adb_wrapper.py +++ b/build/android/pylib/device/adb_wrapper.py
@@ -56,15 +56,22 @@ # pylint: disable=unused-argument @classmethod - @decorators.WithTimeoutAndRetries - def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None, - check_error=True): + def _BuildAdbCmd(cls, args, device_serial): cmd = [constants.GetAdbPath()] if device_serial is not None: cmd.extend(['-s', device_serial]) cmd.extend(args) + return cmd + # pylint: enable=unused-argument + + # pylint: disable=unused-argument + @classmethod + @decorators.WithTimeoutAndRetries + def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None, + check_error=True): status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( - cmd, timeout_retry.CurrentTimeoutThread().GetRemainingTime()) + cls._BuildAdbCmd(args, device_serial), + timeout_retry.CurrentTimeoutThread().GetRemainingTime()) if status != 0: raise device_errors.AdbCommandFailedError( args, output, status, device_serial) @@ -93,6 +100,19 @@ device_serial=self._device_serial, check_error=check_error) + def _IterRunDeviceAdbCmd(self, args, timeout): + """Runs an adb command and returns an iterator over its output lines. + + Args: + args: A list of arguments to adb. + timeout: Timeout in seconds. + + Yields: + The output of the command line by line. + """ + return cmd_helper.IterCmdOutputLines( + self._BuildAdbCmd(args, self._device_serial), timeout=timeout) + def __eq__(self, other): """Consider instances equal if they refer to the same device. @@ -242,22 +262,20 @@ cmd, 'path does not specify an accessible directory in the device', device_serial=self._device_serial) - def Logcat(self, filter_spec=None, timeout=_DEFAULT_TIMEOUT, - retries=_DEFAULT_RETRIES): - """Get the logcat output. + def Logcat(self, filter_spec=None, timeout=None): + """Get an iterator over the logcat output. Args: filter_spec: (optional) Spec to filter the logcat. timeout: (optional) Timeout per try in seconds. - retries: (optional) Number of retries to attempt. - Returns: - logcat output as a string. + Yields: + logcat output line by line. """ cmd = ['logcat'] if filter_spec is not None: cmd.append(filter_spec) - return self._RunDeviceAdbCmd(cmd, timeout, retries, check_error=False) + return self._IterRunDeviceAdbCmd(cmd, timeout) 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 1624ccc..f461b28 100644 --- a/build/android/pylib/device/device_utils.py +++ b/build/android/pylib/device/device_utils.py
@@ -34,6 +34,11 @@ _DEFAULT_TIMEOUT = 30 _DEFAULT_RETRIES = 3 +# A sentinel object for default values +# TODO(jbudorick,perezju): revisit how default values are handled by +# the timeout_retry decorators. +DEFAULT = object() + @decorators.WithExplicitTimeoutAndRetries( _DEFAULT_TIMEOUT, _DEFAULT_RETRIES) @@ -146,7 +151,7 @@ except device_errors.AdbCommandFailedError: return False - def NeedsSU(self, timeout=None, retries=None): + def NeedsSU(self, timeout=DEFAULT, retries=DEFAULT): """Checks whether 'su' is needed to access protected resources. Args: @@ -165,8 +170,10 @@ """ if 'needs_su' not in self._cache: try: - self.RunShellCommand('su -c ls /root && ! ls /root', check_return=True, - timeout=timeout, retries=retries) + self.RunShellCommand( + 'su -c ls /root && ! ls /root', check_return=True, + timeout=self._default_timeout if timeout is DEFAULT else timeout, + retries=self._default_retries if retries is DEFAULT else retries) self._cache['needs_su'] = True except device_errors.AdbCommandFailedError: self._cache['needs_su'] = False @@ -249,8 +256,14 @@ Returns: Path to the apk on the device if it exists, None otherwise. """ + # 'pm path' is liable to incorrectly exit with a nonzero number starting + # in Lollipop. + # TODO(jbudorick): Check if this is fixed as new Android versions are + # released to put an upper bound on this. + should_check_return = (self.build_version_sdk < + constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP) output = self.RunShellCommand(['pm', 'path', package], single_line=True, - check_return=True) + check_return=should_check_return) if not output: return None if not output.startswith('package:'): @@ -994,12 +1007,77 @@ """ return self.old_interface.SetJavaAssertsEnabled(enabled) + + @property + def build_description(self): + """Returns the build description of the system. + + For example: + nakasi-user 4.4.4 KTU84P 1227136 release-keys + """ + return self.GetProp('ro.build.description', cache=True) + + @property + def build_fingerprint(self): + """Returns the build fingerprint of the system. + + For example: + google/nakasi/grouper:4.4.4/KTU84P/1227136:user/release-keys + """ + return self.GetProp('ro.build.fingerprint', cache=True) + + @property + def build_id(self): + """Returns the build ID of the system (e.g. 'KTU84P').""" + return self.GetProp('ro.build.id', cache=True) + + @property + def build_product(self): + """Returns the build product of the system (e.g. 'grouper').""" + return self.GetProp('ro.build.product', cache=True) + @property def build_type(self): - """Returns the build type of the system (e.g. userdebug).""" + """Returns the build type of the system (e.g. 'user').""" return self.GetProp('ro.build.type', cache=True) - def GetProp(self, property_name, cache=False, timeout=None, retries=None): + @property + def build_version_sdk(self): + """Returns the build version sdk of the system as a number (e.g. 19). + + For version code numbers see: + http://developer.android.com/reference/android/os/Build.VERSION_CODES.html + + For named constants see: + pylib.constants.ANDROID_SDK_VERSION_CODES + + Raises: + CommandFailedError if the build version sdk is not a number. + """ + value = self.GetProp('ro.build.version.sdk', cache=True) + try: + return int(value) + except ValueError: + raise device_errors.CommandFailedError( + 'Invalid build version sdk: %r' % value) + + @property + def product_cpu_abi(self): + """Returns the product cpu abi of the device (e.g. 'armeabi-v7a').""" + return self.GetProp('ro.product.cpu.abi', cache=True) + + @property + def product_model(self): + """Returns the name of the product model (e.g. 'Nexus 7').""" + return self.GetProp('ro.product.model', cache=True) + + @property + def product_name(self): + """Returns the product name of the device (e.g. 'nakasi').""" + return self.GetProp('ro.product.name', cache=True) + + def GetProp(self, property_name, cache=False, timeout=DEFAULT, + retries=DEFAULT): """Gets a property from the device. Args: @@ -1024,9 +1102,10 @@ else: # timeout and retries are handled down at run shell, because we don't # want to apply them in the other branch when reading from the cache - value = self.RunShellCommand(['getprop', property_name], - single_line=True, check_return=True, - timeout=timeout, retries=retries) + value = self.RunShellCommand( + ['getprop', property_name], single_line=True, check_return=True, + timeout=self._default_timeout if timeout is DEFAULT else timeout, + retries=self._default_retries if retries is DEFAULT else retries) if cache or cache_key in self._cache: self._cache[cache_key] = value return value
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py index 2646bfb..16699ad 100755 --- a/build/android/pylib/device/device_utils_test.py +++ b/build/android/pylib/device/device_utils_test.py
@@ -370,19 +370,25 @@ class DeviceUtilsGetApplicationPathTest(DeviceUtilsNewImplTest): def testGetApplicationPath_exists(self): - with self.assertCall(self.call.adb.Shell('pm path android'), - 'package:/path/to/android.apk\n'): + with self.assertCalls( + (self.call.adb.Shell('getprop ro.build.version.sdk'), '19\n'), + (self.call.adb.Shell('pm path android'), + 'package:/path/to/android.apk\n')): self.assertEquals('/path/to/android.apk', self.device.GetApplicationPath('android')) def testGetApplicationPath_notExists(self): - with self.assertCall(self.call.adb.Shell('pm path not.installed.app'), ''): + with self.assertCalls( + (self.call.adb.Shell('getprop ro.build.version.sdk'), '19\n'), + (self.call.adb.Shell('pm path not.installed.app'), '')): self.assertEquals(None, self.device.GetApplicationPath('not.installed.app')) def testGetApplicationPath_fails(self): - with self.assertCall(self.call.adb.Shell('pm path android'), - self.CommandError('ERROR. Is package manager running?\n')): + with self.assertCalls( + (self.call.adb.Shell('getprop ro.build.version.sdk'), '19\n'), + (self.call.adb.Shell('pm path android'), + self.CommandError('ERROR. Is package manager running?\n'))): with self.assertRaises(device_errors.CommandFailedError): self.device.GetApplicationPath('android')
diff --git a/build/android/pylib/device_settings.py b/build/android/pylib/device_settings.py index 246c1d1..73ffa72 100644 --- a/build/android/pylib/device_settings.py +++ b/build/android/pylib/device_settings.py
@@ -6,6 +6,7 @@ from pylib import constants from pylib import content_settings +from pylib.device import device_errors _LOCK_SCREEN_SETTINGS_PATH = '/data/system/locksettings.db' _ALTERNATE_LOCK_SCREEN_SETTINGS_PATH = ( @@ -29,17 +30,16 @@ settings to configure. """ try: - sdk_version = int(device.GetProp('ro.build.version.sdk')) - except ValueError: - logging.error('Skipping content settings configuration, unknown sdk %s', - device.GetProp('ro.build.version.sdk')) + sdk_version = device.build_version_sdk + except device_errors.CommandFailedError as exc: + logging.error('Skipping content settings configuration: %s', str(exc)) return if sdk_version < constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN: logging.error('Skipping content settings configuration due to outdated sdk') return - if device.GetProp('ro.build.type') == 'userdebug': + if device.build_type == 'userdebug': for table, key_value in desired_settings: settings = content_settings.ContentSettings(table, device) for key, value in key_value: @@ -68,7 +68,7 @@ Raises: Exception if the setting was not properly set. """ - if device.GetProp('ro.build.type') != 'userdebug': + if device.build_type != 'userdebug': logging.warning('Unable to disable lockscreen on user builds.') return
diff --git a/build/android/pylib/gtest/filter/unit_tests_disabled b/build/android/pylib/gtest/filter/unit_tests_disabled index 6e7be1a..93defbe 100644 --- a/build/android/pylib/gtest/filter/unit_tests_disabled +++ b/build/android/pylib/gtest/filter/unit_tests_disabled
@@ -67,7 +67,6 @@ PermissionsUpdaterTest.* ImageLoaderTest.* ImageLoadingTrackerTest.* -ScriptBadgeControllerTest.* ExtensionSettingsFrontendTest.* ExtensionSettingsSyncTest.* ExtensionUpdaterTest.*
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py index 20aaf68..cf72d65 100644 --- a/build/android/pylib/gtest/gtest_config.py +++ b/build/android/pylib/gtest/gtest_config.py
@@ -35,6 +35,7 @@ 'sandbox_linux_unittests', 'sql_unittests', 'sync_unit_tests', + 'ui_android_unittests', 'ui_base_unittests', 'ui_touch_selection_unittests', 'unit_tests',
diff --git a/build/android/pylib/gtest/gtest_test_instance.py b/build/android/pylib/gtest/gtest_test_instance.py index 1e87693..f4623e4 100644 --- a/build/android/pylib/gtest/gtest_test_instance.py +++ b/build/android/pylib/gtest/gtest_test_instance.py
@@ -42,9 +42,12 @@ def __init__(self, options, isolate_delegate): super(GtestTestInstance, self).__init__() + # TODO(jbudorick): Support multiple test suites. + if len(options.suite_name) > 1: + raise ValueError('Platform mode currently supports only 1 gtest suite') self._apk_path = os.path.join( - constants.GetOutDirectory(), '%s_apk' % options.suite_name, - '%s-debug.apk' % options.suite_name) + constants.GetOutDirectory(), '%s_apk' % options.suite_name[0], + '%s-debug.apk' % options.suite_name[0]) self._data_deps = [] self._gtest_filter = options.test_filter if options.isolate_file_path:
diff --git a/build/android/pylib/instrumentation/test_jar.py b/build/android/pylib/instrumentation/test_jar.py index 4473810..c3faef3 100644 --- a/build/android/pylib/instrumentation/test_jar.py +++ b/build/android/pylib/instrumentation/test_jar.py
@@ -215,12 +215,10 @@ # Filter out any tests with SDK level requirements that don't match the set # of attached devices. - sdk_versions = [ - int(v) for v in - device_utils.DeviceUtils.parallel().GetProp( - 'ro.build.version.sdk').pGet(None)] + devices = device_utils.DeviceUtils.parallel() + min_sdk_version = min(devices.build_version_sdk.pGet(None)) tests = [t for t in tests - if self._IsTestValidForSdkRange(t, min(sdk_versions))] + if self._IsTestValidForSdkRange(t, min_sdk_version)] return tests
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py index 92d80f97..fe444e9 100644 --- a/build/android/pylib/instrumentation/test_runner.py +++ b/build/android/pylib/instrumentation/test_runner.py
@@ -299,8 +299,8 @@ if 'SmallTest' in annotations: return 1 * 60 - logging.warn(("Test size not found in annotations for test '{0}', using " + - "1 minute for timeout.").format(test)) + logging.warn(("Test size not found in annotations for test '%s', using " + + "1 minute for timeout.") % test) return 1 * 60 def _RunTest(self, test, timeout): @@ -443,7 +443,7 @@ timeout = (self._GetIndividualTestTimeoutSecs(test) * self._GetIndividualTestTimeoutScale(test) * self.tool.GetTimeoutScale()) - if (self.device.GetProp('ro.build.version.sdk') + if (self.device.build_version_sdk < constants.ANDROID_SDK_VERSION_CODES.JELLY_BEAN): timeout *= 10
diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py index 0da1bcf..97fa4a7 100644 --- a/build/android/pylib/perf/perf_control.py +++ b/build/android/pylib/perf/perf_control.py
@@ -36,7 +36,7 @@ atexit.register(logging.warning, message) return - product_model = self._device.old_interface.GetProductModel() + product_model = self._device.product_model # TODO(epenner): Enable on all devices (http://crbug.com/383566) if 'Nexus 4' == product_model: self._ForceAllCpusOnline(True) @@ -66,7 +66,7 @@ """Sets the performance mode for the device to its default mode.""" if not self._device.old_interface.IsRootEnabled(): return - product_model = self._device.old_interface.GetProductModel() + product_model = self._device.product_model if 'Nexus 5' == product_model: if self._AllCpusAreOnline(): self._SetScalingMaxFreq(2265600)
diff --git a/build/android/pylib/remote/__init__.py b/build/android/pylib/remote/__init__.py new file mode 100644 index 0000000..4d6aabb --- /dev/null +++ b/build/android/pylib/remote/__init__.py
@@ -0,0 +1,3 @@ +# 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.
diff --git a/build/android/pylib/remote/device/__init__.py b/build/android/pylib/remote/device/__init__.py new file mode 100644 index 0000000..4d6aabb --- /dev/null +++ b/build/android/pylib/remote/device/__init__.py
@@ -0,0 +1,3 @@ +# 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.
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py new file mode 100644 index 0000000..871c0a8 --- /dev/null +++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -0,0 +1,151 @@ +# 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. + +"""Environment setup and teardown for remote devices.""" + +import os +import sys + +from pylib import constants +from pylib.base import environment +from pylib.remote.device import remote_device_helper + +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'requests', 'src')) +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'appurify-python', 'src')) +import appurify.api + + +class RemoteDeviceEnvironment(environment.Environment): + """An environment for running on remote devices.""" + + def __init__(self, args, error_func): + """Constructor. + + Args: + args: Command line arguments. + error_func: error to show when using bad command line arguments. + """ + super(RemoteDeviceEnvironment, self).__init__() + + if args.api_key_file: + with open(args.api_key_file) as api_key_file: + self._api_key = api_key_file.read().strip() + elif args.api_key: + self._api_key = args.api_key + else: + error_func('Must set api key with --api-key or --api-key-file') + + if args.api_secret_file: + with open(args.api_secret_file) as api_secret_file: + self._api_secret = api_secret_file.read().strip() + elif args.api_secret: + self._api_secret = args.api_secret + else: + error_func('Must set api secret with --api-secret or --api-secret-file') + + if not args.api_protocol: + error_func('Must set api protocol with --api-protocol. Example: http') + self._api_protocol = args.api_protocol + + if not args.api_address: + error_func('Must set api address with --api-address') + self._api_address = args.api_address + + if not args.api_port: + error_func('Must set api port with --api-port.') + self._api_port = args.api_port + + self._access_token = '' + self._results_path = args.results_path + self._remote_device = args.remote_device + self._remote_device_os = args.remote_device_os + self._runner_package = args.runner_package + self._runner_type = args.runner_type + self._device = '' + if not args.trigger and not args.collect: + self._trigger = True + self._collect = True + else: + self._trigger = args.trigger + self._collect = args.collect + + def SetUp(self): + """Set up the test environment.""" + os.environ['APPURIFY_API_PROTO'] = self._api_protocol + os.environ['APPURIFY_API_HOST'] = self._api_address + os.environ['APPURIFY_API_PORT'] = self._api_port + self._GetAccessToken() + if self._trigger: + self._device = self._SelectDevice() + + def TearDown(self): + """Teardown the test environment.""" + self._RevokeAccessToken() + + def __enter__(self): + """Set up the test run when used as a context manager.""" + self.SetUp() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Tears down the test run when used as a context manager.""" + self.TearDown() + + def _GetAccessToken(self): + """Generates access token for remote device service.""" + access_token_results = appurify.api.access_token_generate( + self._api_key, self._api_secret) + remote_device_helper.TestHttpResponse(access_token_results, + 'Unable to generate access token.') + self._access_token = access_token_results.json()['response']['access_token'] + + def _RevokeAccessToken(self): + """Destroys access token for remote device service.""" + revoke_token_results = appurify.api.access_token_revoke(self._access_token) + remote_device_helper.TestHttpResponse(revoke_token_results, + 'Unable to revoke access token.') + + def _SelectDevice(self): + """Select which device to use.""" + dev_list_res = appurify.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'] + for device in device_list: + if (device['name'] == self._remote_device + and device['os_version'] == self._remote_device_os): + return device['device_type_id'] + raise remote_device_helper.RemoteDeviceError( + 'No device found: %s %s' % (self._remote_device, + self._remote_device_os)) + + @property + def device(self): + return self._device + + @property + def token(self): + return self._access_token + + @property + def results_path(self): + return self._results_path + + @property + def runner_type(self): + return self._runner_type + + @property + def runner_package(self): + return self._runner_package + + @property + def trigger(self): + return self._trigger + + @property + def collect(self): + return self._collect
diff --git a/build/android/pylib/remote/device/remote_device_gtest_run.py b/build/android/pylib/remote/device/remote_device_gtest_run.py new file mode 100644 index 0000000..fa8d5f9 --- /dev/null +++ b/build/android/pylib/remote/device/remote_device_gtest_run.py
@@ -0,0 +1,59 @@ +# 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. + +"""Run specific test on specific environment.""" + +import logging +import os +import sys + +from pylib import constants +from pylib.base import base_test_result +from pylib.remote.device import remote_device_test_run +from pylib.remote.device import remote_device_helper + +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'requests', 'src')) +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'appurify-python', 'src')) +import appurify.api +import appurify.utils + +class RemoteDeviceGtestRun(remote_device_test_run.RemoteDeviceTestRun): + """Run gtests and uirobot tests on a remote device.""" + + DEFAULT_RUNNER_TYPE = 'robotium' + DEFAULT_RUNNER_PACKAGE = ( + 'org.chromium.native_test.ChromiumNativeTestInstrumentationTestRunner') + + def TestPackage(self): + pass + + #override + def _TriggerSetUp(self): + """Set up the triggering of a test run.""" + self._app_id = self._UploadAppToDevice(self._test_instance.apk) + + if not self._env.runner_type: + runner_type = self.DEFAULT_RUNNER_TYPE + logging.info('Using default runner type: %s', self.DEFAULT_RUNNER_TYPE) + else: + runner_type = self._env.runner_type + + if not self._env.runner_package: + runner_package = self.DEFAULT_RUNNER_PACKAGE + logging.info('Using default runner package: %s', + self.DEFAULT_RUNNER_TYPE) + else: + runner_package = self._env.runner_package + + self._test_id = self._UploadTestToDevice(runner_type) + config_body = {'runner': runner_package} + self._SetTestConfig(runner_type, config_body) + + #override + def _ParseTestResults(self): + # TODO(rnephew): Populate test results object. + results = base_test_result.TestRunResults() + return results
diff --git a/build/android/pylib/remote/device/remote_device_helper.py b/build/android/pylib/remote/device/remote_device_helper.py new file mode 100644 index 0000000..a4cd488 --- /dev/null +++ b/build/android/pylib/remote/device/remote_device_helper.py
@@ -0,0 +1,21 @@ +# 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. + +"""Common functions and Exceptions for remote_device_*""" + + +class RemoteDeviceError(Exception): + """Exception to throw when problems occur with remote device service.""" + pass + + +def TestHttpResponse(response, error_msg): + """Checks the Http response from remote device service. + + Args: + response: response dict from the remote device service. + error_msg: Error message to display if bad response is seen. + """ + if response.status_code != 200: + raise RemoteDeviceError(error_msg)
diff --git a/build/android/pylib/remote/device/remote_device_test_run.py b/build/android/pylib/remote/device/remote_device_test_run.py new file mode 100644 index 0000000..97e44b0 --- /dev/null +++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -0,0 +1,176 @@ +# 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. + +"""Run specific test on specific environment.""" + +import logging +import os +import sys +import tempfile +import time + +from pylib import constants +from pylib.base import test_run +from pylib.remote.device import remote_device_helper + +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'requests', 'src')) +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'appurify-python', 'src')) +import appurify.api +import appurify.utils + +class RemoteDeviceTestRun(test_run.TestRun): + """Run gtests and uirobot tests on a remote device.""" + + WAIT_TIME = 5 + COMPLETE = 'complete' + + def __init__(self, env, test_instance): + """Constructor. + + Args: + env: Environment the tests will run in. + test_instance: The test that will be run. + """ + super(RemoteDeviceTestRun, self).__init__(env, test_instance) + self._env = env + self._test_instance = test_instance + self._app_id = '' + self._test_id = '' + self._results = '' + + def TestPackage(self): + pass + + #override + def RunTests(self): + """Run the test.""" + if self._env.trigger: + test_start_res = appurify.api.tests_run( + self._env.token, self._env.device, self._app_id, self._test_id) + remote_device_helper.TestHttpResponse( + test_start_res, 'Unable to run test.') + test_run_id = test_start_res.json()['response']['test_run_id'] + if not self._env.collect: + assert isinstance(self._env.trigger, basestring), ( + 'File for storing test_run_id must be a string.') + with open(self._env.trigger, 'w') as test_run_id_file: + test_run_id_file.write(test_run_id) + + if self._env.collect: + if not self._env.trigger: + assert isinstance(self._env.trigger, basestring), ( + 'File for storing test_run_id must be a string.') + with open(self._env.collect, 'r') as test_run_id_file: + test_run_id = test_run_id_file.read() + while self._GetTestStatus(test_run_id) != self.COMPLETE: + time.sleep(self.WAIT_TIME) + self._DownloadTestResults(self._env.results_path) + return self._ParseTestResults() + + #override + def TearDown(self): + """Tear down the test run.""" + pass + + def __enter__(self): + """Set up the test run when used as a context manager.""" + self.SetUp() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + """Tear down the test run when used as a context manager.""" + self.TearDown() + + #override + def SetUp(self): + """Set up a test run.""" + if self._env.trigger: + self._TriggerSetUp() + + def _TriggerSetUp(self): + """Set up the triggering of a test run.""" + raise NotImplementedError + + def _ParseTestResults(self): + raise NotImplementedError + + def _GetTestByName(self, test_name): + """Gets test_id for specific test. + + Args: + test_name: Test to find the ID of. + """ + test_list_res = appurify.api.tests_list(self._env.token) + remote_device_helper.TestHttpResponse(test_list_res, + 'Unable to get tests list.') + for test in test_list_res.json()['response']: + if test['test_type'] == test_name: + return test['test_id'] + raise remote_device_helper.RemoteDeviceError( + 'No test found with name %s' % (test_name)) + + def _DownloadTestResults(self, results_path): + """Download the test results from remote device service. + + Args: + results_path: path to download results to. + """ + if results_path: + if not os.path.exists(os.path.basename(results_path)): + os.makedirs(os.path.basename(results_path)) + appurify.utils.wget(self._results['results']['url'], results_path) + + def _GetTestStatus(self, test_run_id): + """Checks the state of the test, and sets self._results + + Args: + test_run_id: Id of test on on remote service. + """ + + test_check_res = appurify.api.tests_check_result(self._env.token, + test_run_id) + remote_device_helper.TestHttpResponse(test_check_res, + 'Unable to get test status.') + self._results = test_check_res.json()['response'] + return self._results['status'] + + def _UploadAppToDevice(self, apk_path): + """Upload app to device.""" + apk_name = os.path.basename(apk_path) + with open(apk_path, 'rb') as apk_src: + upload_results = appurify.api.apps_upload(self._env.token, + apk_src, 'raw', name=apk_name) + remote_device_helper.TestHttpResponse( + upload_results, 'Unable to upload %s.' %(apk_path)) + return upload_results.json()['response']['app_id'] + + def _UploadTestToDevice(self, test_type): + """Upload test to device + Args: + test_type: Type of test that is being uploaded. Ex. uirobot, gtest.. + """ + with open(self._test_instance.apk, 'rb') as test_src: + upload_results = appurify.api.tests_upload( + self._env.token, test_src, 'raw', test_type, app_id=self._app_id) + remote_device_helper.TestHttpResponse(upload_results, + 'Unable to upload %s.' %(self._test_instance.apk)) + return upload_results.json()['response']['test_id'] + + def _SetTestConfig(self, runner_type, body): + """Generates and uploads config file for test. + Args: + extras: Extra arguments to set in the config file. + """ + with tempfile.TemporaryFile() as config: + config_data = ['[appurify]', '[%s]' % runner_type] + config_data.extend('%s=%s' % (k, v) for k, v in body.iteritems()) + config.write(''.join('%s\n' % l for l in config_data)) + config.flush() + config.seek(0) + config_response = appurify.api.config_upload(self._env.token, + config, self._test_id) + remote_device_helper.TestHttpResponse(config_response, + 'Unable to upload test config.')
diff --git a/build/android/pylib/remote/device/remote_device_uirobot_run.py b/build/android/pylib/remote/device/remote_device_uirobot_run.py new file mode 100644 index 0000000..d2d6f36 --- /dev/null +++ b/build/android/pylib/remote/device/remote_device_uirobot_run.py
@@ -0,0 +1,58 @@ +# 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. + +"""Run specific test on specific environment.""" + +import logging +import os +import sys + +from pylib import constants +from pylib.base import base_test_result +from pylib.remote.device import remote_device_test_run +from pylib.remote.device import remote_device_helper + +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'requests', 'src')) +sys.path.append(os.path.join( + constants.DIR_SOURCE_ROOT, 'third_party', 'appurify-python', 'src')) +import appurify.api +import appurify.utils + +class RemoteDeviceUirobotRun(remote_device_test_run.RemoteDeviceTestRun): + """Run uirobot tests on a remote device.""" + + DEFAULT_RUNNER_TYPE = 'android_robot' + + def __init__(self, env, test_instance): + """Constructor. + + Args: + env: Environment the tests will run in. + test_instance: The test that will be run. + """ + super(RemoteDeviceUirobotRun, self).__init__(env, test_instance) + + def TestPackage(self): + pass + + #override + def _TriggerSetUp(self): + """Set up the triggering of a test run.""" + self._app_id = self._UploadAppToDevice(self._test_instance.apk_under_test) + if not self._env.runner_type: + runner_type = self.DEFAULT_RUNNER_TYPE + logging.info('Using default runner type: %s', self.DEFAULT_RUNNER_TYPE) + else: + runner_type = self._env.runner_type + self._test_id = self._GetTestByName(runner_type) + config_body = {'duration': self._test_instance.minutes} + self._SetTestConfig(runner_type, config_body) + + #override + def _ParseTestResults(self): + # TODO(rnephew): Populate test results object. + results = remote_device_test_run.TestRunResults() + return results +
diff --git a/build/android/pylib/uirobot/__init__.py b/build/android/pylib/uirobot/__init__.py new file mode 100644 index 0000000..5cac026 --- /dev/null +++ b/build/android/pylib/uirobot/__init__.py
@@ -0,0 +1,4 @@ +# 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. +
diff --git a/build/android/pylib/uirobot/uirobot_test_instance.py b/build/android/pylib/uirobot/uirobot_test_instance.py new file mode 100644 index 0000000..b129f89 --- /dev/null +++ b/build/android/pylib/uirobot/uirobot_test_instance.py
@@ -0,0 +1,51 @@ +# 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 os + +from pylib import constants +from pylib.base import test_instance + +class UirobotTestInstance(test_instance.TestInstance): + + def __init__(self, args): + """Constructor. + + Args: + args: Command line arguments. + """ + super(UirobotTestInstance, self).__init__() + self._apk_under_test = os.path.join( + constants.GetOutDirectory(), args.apk_under_test) + self._minutes = args.minutes + + #override + def TestType(self): + """Returns type of test.""" + return 'uirobot' + + #override + def SetUp(self): + """Setup for test.""" + pass + + #override + def TearDown(self): + """Teardown for test.""" + pass + + @property + def apk_under_test(self): + """Returns the app to run the test on.""" + return self._apk_under_test + + @property + def suite(self): + """Returns the test suite, none for uirobot.""" + return None + + @property + def minutes(self): + """Returns the number of minutes to run the uirobot for.""" + return self._minutes
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 68827b9..657e7c2 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -119,6 +119,45 @@ os.environ['PATH'] = adb_dir + os.pathsep + os.environ['PATH'] +def AddRemoteDeviceOptions(parser): + group = parser.add_argument_group('Remote Device Options') + + group.add_argument('--trigger', default='', + help=('Only triggers the test if set. Stores test_run_id ' + 'in given file path. ')) + group.add_argument('--collect', default='', + help=('Only collects the test results if set. ' + 'Gets test_run_id from given file path.')) + group.add_argument('--remote-device', default='Nexus 5', + help=('Device type to run test on.')) + group.add_argument('--remote-device-os', default='4.4.2', + help=('OS to have on the device.')) + group.add_argument('--results-path', default='', + help=('File path to download results to.')) + group.add_argument('--api-protocol', + help=('HTTP protocol to use. (http or https)')) + group.add_argument('--api-address', help=('Address to send HTTP requests.')) + group.add_argument('--api-port', help=('Port to send HTTP requests to.')) + group.add_argument('--runner-type', default='', + help=('Type of test to run as.')) + group.add_argument('--runner-package', default='', + help=('Package name of test.')) + group.add_argument('--apk-under-test', default='apks/Chrome.apk', + help=('APK to run tests on.')) + + api_secret_group = group.add_mutually_exclusive_group() + api_secret_group.add_argument('--api-secret', default='', + help=('API secret for remote devices.')) + api_secret_group.add_argument('--api-secret-file', default='', + help=('Path to file that contains API secret.')) + + api_key_group = group.add_mutually_exclusive_group() + api_key_group.add_argument('--api-key', default='', + help=('API key for remote devices.')) + api_key_group.add_argument('--api-key-file', default='', + help=('Path to file that contains API key.')) + + def AddDeviceOptions(parser): """Adds device options to |parser|.""" group = parser.add_argument_group(title='Device Options') @@ -166,6 +205,7 @@ 'path') AddDeviceOptions(parser) AddCommonOptions(parser) + AddRemoteDeviceOptions(parser) def AddLinkerTestOptions(parser): @@ -426,7 +466,6 @@ AddCommonOptions(parser) AddDeviceOptions(parser) - def ProcessMonkeyTestOptions(args): """Processes all monkey test options. @@ -452,6 +491,17 @@ args.seed, args.extra_args) +def AddUirobotTestOptions(parser): + """Adds uirobot test options to |option_parser|.""" + group = parser.add_argument_group('Uirobot Test Options') + + group.add_argument( + '--minutes', default=5, type=int, + help='Number of minutes to run uirobot test [default: %default].') + + AddCommonOptions(parser) + AddDeviceOptions(parser) + AddRemoteDeviceOptions(parser) def AddPerfTestOptions(parser): """Adds perf test options to |parser|.""" @@ -812,7 +862,7 @@ ProcessCommonOptions(args) if args.enable_platform_mode: - return RunTestsInPlatformMode(args, parser.error) + return RunTestsInPlatformMode(args, parser) if command in constants.LOCAL_MACHINE_TESTS: devices = [] @@ -845,7 +895,7 @@ _SUPPORTED_IN_PLATFORM_MODE = [ # TODO(jbudorick): Add support for more test types. - 'gtest', + 'gtest', 'uirobot', ] @@ -860,6 +910,9 @@ args, env, test, parser.error) as test_run: results = test_run.RunTests() + if args.trigger: + return 0 # Not returning results, only triggering. + report_results.LogFull( results=results, test_type=test.TestType(), @@ -871,7 +924,7 @@ json_results.GenerateJsonResultsFile( results, args.json_results_file) - return results + return 0 if results.DidRunPass() else 1 CommandConfigTuple = collections.namedtuple( @@ -902,6 +955,9 @@ 'linker': CommandConfigTuple( AddLinkerTestOptions, 'Linker tests'), + 'uirobot': CommandConfigTuple( + AddUirobotTestOptions, + 'Uirobot test'), }
diff --git a/build/android/tombstones.py b/build/android/tombstones.py index fd060ad..a78d89f 100755 --- a/build/android/tombstones.py +++ b/build/android/tombstones.py
@@ -173,7 +173,7 @@ device_now = _GetDeviceDateTime(device) for tombstone_file, tombstone_time in tombstones: ret += [{'serial': str(device), - 'device_abi': device.GetProp('ro.product.cpu.abi'), + 'device_abi': device.product_cpu_abi, 'device_now': device_now, 'time': tombstone_time, 'file': tombstone_file,
diff --git a/build/common.gypi b/build/common.gypi index c899e14..30239f1 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -619,7 +619,7 @@ # completion, but only actually requires them for layout tests. However, # we need to maintain all the old behaviors while the plumbing is put in # place on both sides of the repo boundary. - 'enable_load_completion_hacks%': 1, + 'enable_load_completion_hacks%': 0, # Automatically select platforms under ozone. Turn this off to # build only explicitly selected platforms. @@ -706,6 +706,13 @@ 'use_dbus%': 0, }], + # Libxkbcommon usage. + ['use_ozone==1 and embedded==0', { + 'use_xkbcommon%': 1, + }, { + 'use_xkbcommon%': 0, + }], + # We always use skia text rendering in Aura on Windows, since GDI # doesn't agree with our BackingStore. # TODO(beng): remove once skia text rendering is on by default. @@ -1087,6 +1094,7 @@ 'use_cairo%': '<(use_cairo)', 'use_ozone%': '<(use_ozone)', 'use_ozone_evdev%': '<(use_ozone_evdev)', + 'use_xkbcommon%': '<(use_xkbcommon)', 'use_clipboard_aurax11%': '<(use_clipboard_aurax11)', 'desktop_linux%': '<(desktop_linux)', 'use_x11%': '<(use_x11)', @@ -2521,6 +2529,9 @@ # code generated by flex (used in angle) contains that keyword. # http://crbug.com/255186 '-Wno-deprecated-register', + + # TODO(hans): Get this cleaned up. + '-Wno-inconsistent-missing-override', ], }, 'includes': [ 'set_clang_warning_flags.gypi', ], @@ -4185,6 +4196,13 @@ ], }], ], + 'conditions': [ + ['OS=="mac"', { + 'cflags': [ + '-mllvm -asan-globals=0', # http://crbug.com/352073 + ], + }], + ], }], ['ubsan==1', { 'target_conditions': [ @@ -4235,7 +4253,7 @@ 'target_conditions': [ ['_toolset=="target"', { 'cflags': [ - '-mllvm -asan-coverage=<(asan_coverage)', + '-fsanitize-coverage=<(asan_coverage)', ], }], ], @@ -4606,16 +4624,6 @@ # TODO(eugenis): find a way to reenable this. '-mllvm -asan-globals=0', ], - 'conditions': [ - ['target_arch=="arm"', { - 'ldflags': [ - # TODO(hans): The ASan runtime is no longer automatically - # added to the link line when using -nostdlib. Can we - # stop adding -nostdlib? (crbug.com/423429) - '<!(cd <(DEPTH) && pwd -P)/<(make_clang_dir)/lib/clang/3.6.0/lib/linux/libclang_rt.asan-arm-android.so', - ], - }], - ], }], ['android_webview_build==0', { 'defines': [ @@ -4900,6 +4908,7 @@ 'xcode_settings': { 'OTHER_CFLAGS': [ '-fsanitize=address', + '-mllvm -asan-globals=0', # http://crbug.com/352073 '-gline-tables-only', ], }, @@ -4908,7 +4917,7 @@ 'target_conditions': [ ['_toolset=="target"', { 'cflags': [ - '-mllvm -asan-coverage=<(asan_coverage)', + '-fsanitize-coverage=<(asan_coverage)', ], }], ],
diff --git a/build/config/OWNERS b/build/config/OWNERS index 9b79b9a..bd53091 100644 --- a/build/config/OWNERS +++ b/build/config/OWNERS
@@ -1,2 +1,6 @@ -set noparent brettw@chromium.org +dpranke@chromium.org +scottmg@chromium.org + +per-file BUILDCONFIG.gn=brettw@chromium.org +per-file BUILDCONFIG.gn=set noparent
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 81269d6..c221ddd 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -762,6 +762,9 @@ # TODO(thakis): Remove, http://crbug.com/263960 "-Wno-reserved-user-defined-literal", + + # TODO(hans): Get this cleaned up. + "-Wno-inconsistent-missing-override", ] } if (gcc_version >= 48) {
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index 0d9faa0..b8d3caa 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt
@@ -464,8 +464,6 @@ IDS_FLAGS_COMPOSITING_FOR_FIXED_POSITION_DESCRIPTION IDS_FLAGS_COMPOSITING_FOR_FIXED_POSITION_HIGH_DPI IDS_FLAGS_COMPOSITING_FOR_FIXED_POSITION_NAME -IDS_FLAGS_COMPOSITING_FOR_TRANSITION_DESCRIPTION -IDS_FLAGS_COMPOSITING_FOR_TRANSITION_NAME IDS_FLAGS_CONFLICTS_CHECK_DESCRIPTION IDS_FLAGS_CONFLICTS_CHECK_NAME IDS_FLAGS_DEBUG_PACKED_APP_DESCRIPTION
diff --git a/build/linux/system.gyp b/build/linux/system.gyp index cd0288b..09ee713 100644 --- a/build/linux/system.gyp +++ b/build/linux/system.gyp
@@ -465,6 +465,27 @@ }, ], }], + ['use_xkbcommon==1', { + 'targets': [ + { + 'target_name': 'xkbcommon', + 'type': 'none', + 'direct_dependent_settings': { + 'cflags': [ + '<!@(<(pkg-config) --cflags xkbcommon)' + ], + }, + 'link_settings': { + 'ldflags': [ + '<!@(<(pkg-config) --libs-only-L --libs-only-other xkbcommon)', + ], + 'libraries': [ + '<!@(<(pkg-config) --libs-only-l xkbcommon)', + ], + }, + }, + ], + }], ['ozone_platform_gbm==1', { 'targets': [ {
diff --git a/build/sanitizers/sanitizer_options.cc b/build/sanitizers/sanitizer_options.cc index 614a4a6..af78bf8 100644 --- a/build/sanitizers/sanitizer_options.cc +++ b/build/sanitizers/sanitizer_options.cc
@@ -72,7 +72,7 @@ const char *kAsanDefaultOptions = "strict_memcmp=0 replace_intrin=0 check_printf=1 use_sigaltstack=1 " "strip_path_prefix=Release/../../ fast_unwind_on_fatal=1 " - "detect_stack_use_after_return=1 "; + "detect_stack_use_after_return=1 detect_odr_violation=0 "; static const char kNaClDefaultOptions[] = "handle_segv=0"; static const char kNaClFlag[] = "--type=nacl-loader"; #endif // OS_LINUX
diff --git a/build/toolchain/OWNERS b/build/toolchain/OWNERS index 9b79b9a..c6cda3f 100644 --- a/build/toolchain/OWNERS +++ b/build/toolchain/OWNERS
@@ -1,2 +1,3 @@ -set noparent brettw@chromium.org +dpranke@chromium.org +scottmg@chromium.org
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py index 6b7ea7a..e8826b0 100644 --- a/build/toolchain/win/setup_toolchain.py +++ b/build/toolchain/win/setup_toolchain.py
@@ -67,7 +67,8 @@ # We only support x64-hosted tools. # TODO(scottmg|dpranke): Non-depot_tools toolchain: need to get Visual # Studio install location from registry. - return [os.path.normpath(os.path.join(FIND_VS_IN_REG, 'VC/vcvarsall.bat')), + return [os.path.normpath(os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'], + 'VC/vcvarsall.bat')), 'amd64_x86' if target_arch == 'x86' else 'amd64']
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py index fb7e142..5373f03 100644 --- a/build/vs_toolchain.py +++ b/build/vs_toolchain.py
@@ -202,7 +202,7 @@ os.environ['WINDOWSSDKDIR'], os.environ['GYP_MSVS_VERSION'], os.environ.get('WDK_DIR', ''), - ';'.join(runtime_dll_dirs)) + ';'.join(runtime_dll_dirs or ['None'])) def main():
diff --git a/build/whitespace_file.txt b/build/whitespace_file.txt index 526203f..192677e 100644 --- a/build/whitespace_file.txt +++ b/build/whitespace_file.txt
@@ -145,3 +145,5 @@ Oh god the bots are red! I'm blind! Mmmm, cronuts. If you stand on your head, you will get footprints in your hair. + +sigh \ No newline at end of file
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 592fd6e..13e974d 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -581,6 +581,8 @@ "test/fake_tile_manager_client.h", "test/fake_ui_resource_layer_tree_host_impl.cc", "test/fake_ui_resource_layer_tree_host_impl.h", + "test/failure_output_surface.cc", + "test/failure_output_surface.h", "test/geometry_test_utils.cc", "test/geometry_test_utils.h", "test/test_in_process_context_provider.cc",
diff --git a/cc/base/tiling_data.cc b/cc/base/tiling_data.cc index 7b39878..95fd68b 100644 --- a/cc/base/tiling_data.cc +++ b/cc/base/tiling_data.cc
@@ -293,40 +293,39 @@ max_texture_size_.height(), tiling_size_.height(), border_texels_); } -TilingData::BaseIterator::BaseIterator(const TilingData* tiling_data) - : tiling_data_(tiling_data), - index_x_(-1), - index_y_(-1) { +TilingData::BaseIterator::BaseIterator() : index_x_(-1), index_y_(-1) { } -TilingData::Iterator::Iterator() : BaseIterator(nullptr) { done(); } +TilingData::Iterator::Iterator() { + done(); +} TilingData::Iterator::Iterator(const TilingData* tiling_data, const gfx::Rect& consider_rect, bool include_borders) - : BaseIterator(tiling_data), left_(-1), right_(-1), bottom_(-1) { - if (tiling_data_->num_tiles_x() <= 0 || tiling_data_->num_tiles_y() <= 0) { + : left_(-1), right_(-1), bottom_(-1) { + if (tiling_data->num_tiles_x() <= 0 || tiling_data->num_tiles_y() <= 0) { done(); return; } - gfx::Rect tiling_bounds_rect(tiling_data_->tiling_size()); + gfx::Rect tiling_bounds_rect(tiling_data->tiling_size()); gfx::Rect rect(consider_rect); rect.Intersect(tiling_bounds_rect); gfx::Rect top_left_tile; if (include_borders) { - index_x_ = tiling_data_->FirstBorderTileXIndexFromSrcCoord(rect.x()); - index_y_ = tiling_data_->FirstBorderTileYIndexFromSrcCoord(rect.y()); - right_ = tiling_data_->LastBorderTileXIndexFromSrcCoord(rect.right() - 1); - bottom_ = tiling_data_->LastBorderTileYIndexFromSrcCoord(rect.bottom() - 1); - top_left_tile = tiling_data_->TileBoundsWithBorder(index_x_, index_y_); + index_x_ = tiling_data->FirstBorderTileXIndexFromSrcCoord(rect.x()); + index_y_ = tiling_data->FirstBorderTileYIndexFromSrcCoord(rect.y()); + right_ = tiling_data->LastBorderTileXIndexFromSrcCoord(rect.right() - 1); + bottom_ = tiling_data->LastBorderTileYIndexFromSrcCoord(rect.bottom() - 1); + top_left_tile = tiling_data->TileBoundsWithBorder(index_x_, index_y_); } else { - index_x_ = tiling_data_->TileXIndexFromSrcCoord(rect.x()); - index_y_ = tiling_data_->TileYIndexFromSrcCoord(rect.y()); - right_ = tiling_data_->TileXIndexFromSrcCoord(rect.right() - 1); - bottom_ = tiling_data_->TileYIndexFromSrcCoord(rect.bottom() - 1); - top_left_tile = tiling_data_->TileBounds(index_x_, index_y_); + index_x_ = tiling_data->TileXIndexFromSrcCoord(rect.x()); + index_y_ = tiling_data->TileYIndexFromSrcCoord(rect.y()); + right_ = tiling_data->TileXIndexFromSrcCoord(rect.right() - 1); + bottom_ = tiling_data->TileYIndexFromSrcCoord(rect.bottom() - 1); + top_left_tile = tiling_data->TileBounds(index_x_, index_y_); } left_ = index_x_; @@ -355,8 +354,7 @@ const TilingData* tiling_data, const gfx::Rect& consider_rect, const gfx::Rect& ignore_rect) - : BaseIterator(tiling_data), - consider_left_(-1), + : consider_left_(-1), consider_top_(-1), consider_right_(-1), consider_bottom_(-1), @@ -364,12 +362,12 @@ ignore_top_(-1), ignore_right_(-1), ignore_bottom_(-1) { - if (tiling_data_->num_tiles_x() <= 0 || tiling_data_->num_tiles_y() <= 0) { + if (tiling_data->num_tiles_x() <= 0 || tiling_data->num_tiles_y() <= 0) { done(); return; } - gfx::Rect tiling_bounds_rect(tiling_data_->tiling_size()); + gfx::Rect tiling_bounds_rect(tiling_data->tiling_size()); gfx::Rect consider(consider_rect); gfx::Rect ignore(ignore_rect); consider.Intersect(tiling_bounds_rect); @@ -379,17 +377,16 @@ return; } - consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x()); - consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y()); - consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1); - consider_bottom_ = - tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1); + consider_left_ = tiling_data->TileXIndexFromSrcCoord(consider.x()); + consider_top_ = tiling_data->TileYIndexFromSrcCoord(consider.y()); + consider_right_ = tiling_data->TileXIndexFromSrcCoord(consider.right() - 1); + consider_bottom_ = tiling_data->TileYIndexFromSrcCoord(consider.bottom() - 1); if (!ignore.IsEmpty()) { - ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x()); - ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y()); - ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1); - ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1); + ignore_left_ = tiling_data->TileXIndexFromSrcCoord(ignore.x()); + ignore_top_ = tiling_data->TileYIndexFromSrcCoord(ignore.y()); + ignore_right_ = tiling_data->TileXIndexFromSrcCoord(ignore.right() - 1); + ignore_bottom_ = tiling_data->TileYIndexFromSrcCoord(ignore.bottom() - 1); // Clamp ignore indices to consider indices. ignore_left_ = std::max(ignore_left_, consider_left_); @@ -440,8 +437,7 @@ return *this; } -TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator() - : BaseIterator(nullptr) { +TilingData::SpiralDifferenceIterator::SpiralDifferenceIterator() { done(); } @@ -450,8 +446,7 @@ const gfx::Rect& consider_rect, const gfx::Rect& ignore_rect, const gfx::Rect& center_rect) - : BaseIterator(tiling_data), - consider_left_(-1), + : consider_left_(-1), consider_top_(-1), consider_right_(-1), consider_bottom_(-1), @@ -465,12 +460,12 @@ current_step_(0), horizontal_step_count_(0), vertical_step_count_(0) { - if (tiling_data_->num_tiles_x() <= 0 || tiling_data_->num_tiles_y() <= 0) { + if (tiling_data->num_tiles_x() <= 0 || tiling_data->num_tiles_y() <= 0) { done(); return; } - gfx::Rect tiling_bounds_rect(tiling_data_->tiling_size()); + gfx::Rect tiling_bounds_rect(tiling_data->tiling_size()); gfx::Rect consider(consider_rect); gfx::Rect ignore(ignore_rect); gfx::Rect center(center_rect); @@ -481,17 +476,16 @@ return; } - consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x()); - consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y()); - consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1); - consider_bottom_ = - tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1); + consider_left_ = tiling_data->TileXIndexFromSrcCoord(consider.x()); + consider_top_ = tiling_data->TileYIndexFromSrcCoord(consider.y()); + consider_right_ = tiling_data->TileXIndexFromSrcCoord(consider.right() - 1); + consider_bottom_ = tiling_data->TileYIndexFromSrcCoord(consider.bottom() - 1); if (!ignore.IsEmpty()) { - ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x()); - ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y()); - ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1); - ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1); + ignore_left_ = tiling_data->TileXIndexFromSrcCoord(ignore.x()); + ignore_top_ = tiling_data->TileYIndexFromSrcCoord(ignore.y()); + ignore_right_ = tiling_data->TileXIndexFromSrcCoord(ignore.right() - 1); + ignore_bottom_ = tiling_data->TileYIndexFromSrcCoord(ignore.bottom() - 1); // Clamp ignore indices to consider indices. ignore_left_ = std::max(ignore_left_, consider_left_); @@ -666,8 +660,7 @@ } } -TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator() - : BaseIterator(nullptr) { +TilingData::ReverseSpiralDifferenceIterator::ReverseSpiralDifferenceIterator() { done(); } @@ -676,8 +669,7 @@ const gfx::Rect& consider_rect, const gfx::Rect& ignore_rect, const gfx::Rect& center_rect) - : BaseIterator(tiling_data), - consider_left_(-1), + : consider_left_(-1), consider_top_(-1), consider_right_(-1), consider_bottom_(-1), @@ -695,12 +687,12 @@ current_step_(0), horizontal_step_count_(0), vertical_step_count_(0) { - if (tiling_data_->num_tiles_x() <= 0 || tiling_data_->num_tiles_y() <= 0) { + if (tiling_data->num_tiles_x() <= 0 || tiling_data->num_tiles_y() <= 0) { done(); return; } - gfx::Rect tiling_bounds_rect(tiling_data_->tiling_size()); + gfx::Rect tiling_bounds_rect(tiling_data->tiling_size()); gfx::Rect consider(consider_rect); gfx::Rect ignore(ignore_rect); gfx::Rect center(center_rect); @@ -711,17 +703,16 @@ return; } - consider_left_ = tiling_data_->TileXIndexFromSrcCoord(consider.x()); - consider_top_ = tiling_data_->TileYIndexFromSrcCoord(consider.y()); - consider_right_ = tiling_data_->TileXIndexFromSrcCoord(consider.right() - 1); - consider_bottom_ = - tiling_data_->TileYIndexFromSrcCoord(consider.bottom() - 1); + consider_left_ = tiling_data->TileXIndexFromSrcCoord(consider.x()); + consider_top_ = tiling_data->TileYIndexFromSrcCoord(consider.y()); + consider_right_ = tiling_data->TileXIndexFromSrcCoord(consider.right() - 1); + consider_bottom_ = tiling_data->TileYIndexFromSrcCoord(consider.bottom() - 1); if (!ignore.IsEmpty()) { - ignore_left_ = tiling_data_->TileXIndexFromSrcCoord(ignore.x()); - ignore_top_ = tiling_data_->TileYIndexFromSrcCoord(ignore.y()); - ignore_right_ = tiling_data_->TileXIndexFromSrcCoord(ignore.right() - 1); - ignore_bottom_ = tiling_data_->TileYIndexFromSrcCoord(ignore.bottom() - 1); + ignore_left_ = tiling_data->TileXIndexFromSrcCoord(ignore.x()); + ignore_top_ = tiling_data->TileYIndexFromSrcCoord(ignore.y()); + ignore_right_ = tiling_data->TileXIndexFromSrcCoord(ignore.right() - 1); + ignore_bottom_ = tiling_data->TileYIndexFromSrcCoord(ignore.bottom() - 1); // Clamp ignore indices to consider indices. ignore_left_ = std::max(ignore_left_, consider_left_);
diff --git a/cc/base/tiling_data.h b/cc/base/tiling_data.h index 5e8a4d6..45b763e 100644 --- a/cc/base/tiling_data.h +++ b/cc/base/tiling_data.h
@@ -76,13 +76,12 @@ } protected: - explicit BaseIterator(const TilingData* tiling_data); + BaseIterator(); void done() { index_x_ = -1; index_y_ = -1; } - const TilingData* tiling_data_; int index_x_; int index_y_; };
diff --git a/cc/blink/web_external_bitmap_impl.cc b/cc/blink/web_external_bitmap_impl.cc index a101079..e2c67e4 100644 --- a/cc/blink/web_external_bitmap_impl.cc +++ b/cc/blink/web_external_bitmap_impl.cc
@@ -4,18 +4,18 @@ #include "cc/blink/web_external_bitmap_impl.h" -#include "base/memory/shared_memory.h" +#include "cc/resources/shared_bitmap.h" namespace cc_blink { namespace { -SharedMemoryAllocationFunction g_memory_allocator; +SharedBitmapAllocationFunction g_memory_allocator; } // namespace -void SetSharedMemoryAllocationFunction( - SharedMemoryAllocationFunction allocator) { +void SetSharedBitmapAllocationFunction( + SharedBitmapAllocationFunction allocator) { g_memory_allocator = allocator; } @@ -27,10 +27,7 @@ void WebExternalBitmapImpl::setSize(blink::WebSize size) { if (size != size_) { - size_t byte_size = size.width * size.height * 4; - shared_memory_ = g_memory_allocator(byte_size); - if (shared_memory_) - shared_memory_->Map(byte_size); + shared_bitmap_ = g_memory_allocator(gfx::Size(size)); size_ = size; } } @@ -40,7 +37,7 @@ } uint8* WebExternalBitmapImpl::pixels() { - return static_cast<uint8*>(shared_memory_->memory()); + return shared_bitmap_->pixels(); } } // namespace cc_blink
diff --git a/cc/blink/web_external_bitmap_impl.h b/cc/blink/web_external_bitmap_impl.h index 2d2d8ce..6cada7d 100644 --- a/cc/blink/web_external_bitmap_impl.h +++ b/cc/blink/web_external_bitmap_impl.h
@@ -10,17 +10,18 @@ #include "cc/blink/cc_blink_export.h" #include "third_party/WebKit/public/platform/WebExternalBitmap.h" -namespace base { -class SharedMemory; +namespace cc { +class SharedBitmap; } namespace cc_blink { -typedef scoped_ptr<base::SharedMemory>(*SharedMemoryAllocationFunction)(size_t); +typedef scoped_ptr<cc::SharedBitmap>(*SharedBitmapAllocationFunction)( + const gfx::Size& size); // Sets the function that this will use to allocate shared memory. -CC_BLINK_EXPORT void SetSharedMemoryAllocationFunction( - SharedMemoryAllocationFunction); +CC_BLINK_EXPORT void SetSharedBitmapAllocationFunction( + SharedBitmapAllocationFunction); class WebExternalBitmapImpl : public blink::WebExternalBitmap { public: @@ -32,10 +33,10 @@ void setSize(blink::WebSize size) override; uint8* pixels() override; - base::SharedMemory* shared_memory() { return shared_memory_.get(); } + cc::SharedBitmap* shared_bitmap() { return shared_bitmap_.get(); } private: - scoped_ptr<base::SharedMemory> shared_memory_; + scoped_ptr<cc::SharedBitmap> shared_bitmap_; blink::WebSize size_; DISALLOW_COPY_AND_ASSIGN(WebExternalBitmapImpl);
diff --git a/cc/blink/web_external_texture_layer_impl.cc b/cc/blink/web_external_texture_layer_impl.cc index 30e0ce6..8d29aa1 100644 --- a/cc/blink/web_external_texture_layer_impl.cc +++ b/cc/blink/web_external_texture_layer_impl.cc
@@ -84,7 +84,7 @@ gpu::Mailbox name; name.SetName(client_mailbox.name); if (bitmap) { - *mailbox = cc::TextureMailbox(bitmap->shared_memory(), bitmap->size()); + *mailbox = cc::TextureMailbox(bitmap->shared_bitmap(), bitmap->size()); } else { *mailbox = cc::TextureMailbox(name, GL_TEXTURE_2D, client_mailbox.syncPoint);
diff --git a/cc/blink/web_image_layer_impl.cc b/cc/blink/web_image_layer_impl.cc index ee80ca6..afd551a 100644 --- a/cc/blink/web_image_layer_impl.cc +++ b/cc/blink/web_image_layer_impl.cc
@@ -35,4 +35,11 @@ } } +void WebImageLayerImpl::setNearestNeighbor(bool nearest_neighbor) { + if (WebLayerImpl::UsingPictureLayer()) { + static_cast<cc::PictureImageLayer*>(layer_->layer()) + ->SetNearestNeighbor(nearest_neighbor); + } +} + } // namespace cc_blink
diff --git a/cc/blink/web_image_layer_impl.h b/cc/blink/web_image_layer_impl.h index e0591aa..48c31ea 100644 --- a/cc/blink/web_image_layer_impl.h +++ b/cc/blink/web_image_layer_impl.h
@@ -22,6 +22,7 @@ // blink::WebImageLayer implementation. virtual blink::WebLayer* layer(); virtual void setImageBitmap(const SkBitmap& bitmap); + virtual void setNearestNeighbor(bool nearest_neighbor); private: scoped_ptr<WebLayerImpl> layer_;
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index c32fcba..cbea932 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp
@@ -192,6 +192,8 @@ 'test/fake_ui_resource_layer_tree_host_impl.h', 'test/fake_video_frame_provider.cc', 'test/fake_video_frame_provider.h', + 'test/failure_output_surface.cc', + 'test/failure_output_surface.h', 'test/geometry_test_utils.cc', 'test/geometry_test_utils.h', 'test/test_in_process_context_provider.cc',
diff --git a/cc/debug/rasterize_and_record_benchmark_impl.cc b/cc/debug/rasterize_and_record_benchmark_impl.cc index c00d0b9..03267a8 100644 --- a/cc/debug/rasterize_and_record_benchmark_impl.cc +++ b/cc/debug/rasterize_and_record_benchmark_impl.cc
@@ -15,6 +15,7 @@ #include "cc/resources/tile_task_worker_pool.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_host_impl.h" +#include "cc/trees/layer_tree_impl.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -121,18 +122,6 @@ return base_client_->GetMaxTilePriorityBin(); } - size_t GetMaxTilesForInterestArea() const override { - return base_client_->GetMaxTilesForInterestArea(); - } - - float GetSkewportTargetTimeInSeconds() const override { - return base_client_->GetSkewportTargetTimeInSeconds(); - } - - int GetSkewportExtrapolationLimitInContentPixels() const override { - return base_client_->GetSkewportExtrapolationLimitInContentPixels(); - } - WhichTree GetTree() const override { return base_client_->GetTree(); } bool RequiresHighResToDraw() const override { @@ -215,7 +204,15 @@ FixedInvalidationPictureLayerTilingClient client( layer, gfx::Rect(layer->content_bounds())); - auto tiling_set = PictureLayerTilingSet::Create(&client); + + // In this benchmark, we will create a local tiling set and measure how long + // it takes to rasterize content. As such, the actual settings used here don't + // really matter. + const LayerTreeSettings& settings = layer->layer_tree_impl()->settings(); + auto tiling_set = PictureLayerTilingSet::Create( + &client, settings.max_tiles_for_interest_area, + settings.skewport_target_time_in_seconds, + settings.skewport_extrapolation_limit_in_content_pixels); PictureLayerTiling* tiling = tiling_set->AddTiling(layer->contents_scale_x(), layer->bounds());
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 066d26c..6793d12 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -1268,8 +1268,6 @@ DCHECK(this != page_scale_layer); DCHECK(scrollbar_clip_layer); - DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() || - IsContainerForFixedPositionLayers()); gfx::RectF clip_rect(gfx::PointF(), scrollbar_clip_layer->BoundsForScrolling());
diff --git a/cc/layers/picture_image_layer.cc b/cc/layers/picture_image_layer.cc index 5d76618..cebc8b7 100644 --- a/cc/layers/picture_image_layer.cc +++ b/cc/layers/picture_image_layer.cc
@@ -21,7 +21,7 @@ scoped_ptr<LayerImpl> PictureImageLayer::CreateLayerImpl( LayerTreeImpl* tree_impl) { - return PictureImageLayerImpl::Create(tree_impl, id()); + return PictureImageLayerImpl::Create(tree_impl, id(), is_mask()); } bool PictureImageLayer::HasDrawableContent() const {
diff --git a/cc/layers/picture_image_layer_impl.cc b/cc/layers/picture_image_layer_impl.cc index a72ab01..cf09654 100644 --- a/cc/layers/picture_image_layer_impl.cc +++ b/cc/layers/picture_image_layer_impl.cc
@@ -11,8 +11,10 @@ namespace cc { -PictureImageLayerImpl::PictureImageLayerImpl(LayerTreeImpl* tree_impl, int id) - : PictureLayerImpl(tree_impl, id) { +PictureImageLayerImpl::PictureImageLayerImpl(LayerTreeImpl* tree_impl, + int id, + bool is_mask) + : PictureLayerImpl(tree_impl, id, is_mask) { } PictureImageLayerImpl::~PictureImageLayerImpl() { @@ -24,7 +26,7 @@ scoped_ptr<LayerImpl> PictureImageLayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { - return PictureImageLayerImpl::Create(tree_impl, id()); + return PictureImageLayerImpl::Create(tree_impl, id(), is_mask_); } void PictureImageLayerImpl::GetDebugBorderProperties(
diff --git a/cc/layers/picture_image_layer_impl.h b/cc/layers/picture_image_layer_impl.h index 7a363a1..f478951 100644 --- a/cc/layers/picture_image_layer_impl.h +++ b/cc/layers/picture_image_layer_impl.h
@@ -12,8 +12,9 @@ class CC_EXPORT PictureImageLayerImpl : public PictureLayerImpl { public: static scoped_ptr<PictureImageLayerImpl> Create(LayerTreeImpl* tree_impl, - int id) { - return make_scoped_ptr(new PictureImageLayerImpl(tree_impl, id)); + int id, + bool is_mask) { + return make_scoped_ptr(new PictureImageLayerImpl(tree_impl, id, is_mask)); } ~PictureImageLayerImpl() override; @@ -22,7 +23,7 @@ scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; protected: - PictureImageLayerImpl(LayerTreeImpl* tree_impl, int id); + PictureImageLayerImpl(LayerTreeImpl* tree_impl, int id, bool is_mask); bool ShouldAdjustRasterScale() const override; void RecalculateRasterScales() override;
diff --git a/cc/layers/picture_image_layer_impl_unittest.cc b/cc/layers/picture_image_layer_impl_unittest.cc index 1c766ba..dbdcf6a 100644 --- a/cc/layers/picture_image_layer_impl_unittest.cc +++ b/cc/layers/picture_image_layer_impl_unittest.cc
@@ -22,8 +22,7 @@ class TestablePictureImageLayerImpl : public PictureImageLayerImpl { public: TestablePictureImageLayerImpl(LayerTreeImpl* tree_impl, int id) - : PictureImageLayerImpl(tree_impl, id) { - } + : PictureImageLayerImpl(tree_impl, id, false) {} using PictureLayerImpl::UpdateIdealScales; using PictureLayerImpl::MaximumTilingContentsScale; using PictureLayerImpl::DoPostCommitInitializationIfNeeded;
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index 55241d0..48f3f73 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc
@@ -24,7 +24,8 @@ instrumentation_object_tracker_(id()), update_source_frame_number_(-1), can_use_lcd_text_for_update_(true), - is_mask_(false) { + is_mask_(false), + nearest_neighbor_(false) { } PictureLayer::PictureLayer(ContentLayerClient* client, @@ -37,12 +38,14 @@ } scoped_ptr<LayerImpl> PictureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { - return PictureLayerImpl::Create(tree_impl, id()); + return PictureLayerImpl::Create(tree_impl, id(), is_mask_); } void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { Layer::PushPropertiesTo(base_layer); PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); + // TODO(danakj): Make is_mask_ a constructor parameter for PictureLayer. + DCHECK_EQ(layer_impl->is_mask_, is_mask_); int source_frame_number = layer_tree_host()->source_frame_number(); gfx::Size impl_bounds = layer_impl->bounds(); @@ -63,17 +66,16 @@ recording_source_->SetEmptyBounds(); } - // Unlike other properties, invalidation must always be set on layer_impl. - // See PictureLayerImpl::PushPropertiesTo for more details. - layer_impl->invalidation_.Clear(); - layer_impl->invalidation_.Swap(&recording_invalidation_); - layer_impl->set_is_mask(is_mask_); + layer_impl->SetNearestNeighbor(nearest_neighbor_); + scoped_refptr<RasterSource> raster_source = recording_source_->CreateRasterSource(); raster_source->SetBackgoundColor(SafeOpaqueBackgroundColor()); raster_source->SetRequiresClear(!contents_opaque() && !client_->FillsBoundsCompletely()); - layer_impl->UpdateRasterSource(raster_source); + layer_impl->UpdateRasterSource(raster_source, &recording_invalidation_, + nullptr); + DCHECK(recording_invalidation_.IsEmpty()); } void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { @@ -206,6 +208,14 @@ UpdateDrawsContent(HasDrawableContent()); } +void PictureLayer::SetNearestNeighbor(bool nearest_neighbor) { + if (nearest_neighbor_ == nearest_neighbor) + return; + + nearest_neighbor_ = nearest_neighbor; + SetNeedsCommit(); +} + bool PictureLayer::HasDrawableContent() const { return client_ && Layer::HasDrawableContent(); }
diff --git a/cc/layers/picture_layer.h b/cc/layers/picture_layer.h index 01a37a3..648d1c9 100644 --- a/cc/layers/picture_layer.h +++ b/cc/layers/picture_layer.h
@@ -23,6 +23,8 @@ void ClearClient(); + void SetNearestNeighbor(bool nearest_neighbor); + // Layer interface. scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override; void SetLayerTreeHost(LayerTreeHost* host) override; @@ -50,9 +52,12 @@ ~PictureLayer() override; bool HasDrawableContent() const override; - bool UpdateCanUseLCDText(); + + bool is_mask() const { return is_mask_; } private: + bool UpdateCanUseLCDText(); + ContentLayerClient* client_; scoped_ptr<RecordingSource> recording_source_; devtools_instrumentation:: @@ -66,6 +71,7 @@ int update_source_frame_number_; bool can_use_lcd_text_for_update_; bool is_mask_; + bool nearest_neighbor_; DISALLOW_COPY_AND_ASSIGN(PictureLayer); };
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 54cfac8..392450a 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -63,9 +63,13 @@ PictureLayerImpl::Pair::~Pair() { } -PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) +PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, + int id, + bool is_mask) : LayerImpl(tree_impl, id), twin_layer_(nullptr), + tilings_(CreatePictureLayerTilingSet()), + // TODO(danakj): Can this be null to start? raster_source_(PicturePileImpl::Create()), ideal_page_scale_(0.f), ideal_device_scale_(0.f), @@ -81,7 +85,8 @@ needs_post_commit_initialization_(true), should_update_tile_priorities_(false), only_used_low_res_last_append_quads_(false), - is_mask_(false) { + is_mask_(is_mask), + nearest_neighbor_(false) { layer_tree_impl()->RegisterPictureLayerImpl(this); } @@ -95,8 +100,10 @@ TreePriority tree_priority) { if (!tilings_) return make_scoped_ptr(new TilingSetEvictionQueue()); - return make_scoped_ptr( - new TilingSetEvictionQueue(tilings_.get(), tree_priority)); + bool skip_shared_out_of_order_tiles = + GetPendingOrActiveTwinLayer() != nullptr; + return make_scoped_ptr(new TilingSetEvictionQueue( + tilings_.get(), tree_priority, skip_shared_out_of_order_tiles)); } scoped_ptr<TilingSetRasterQueue> PictureLayerImpl::CreateRasterQueue( @@ -113,7 +120,7 @@ scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { - return PictureLayerImpl::Create(tree_impl, id()); + return PictureLayerImpl::Create(tree_impl, id(), is_mask_); } void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { @@ -121,6 +128,7 @@ // a descendant of an opacity 0 layer). DoPostCommitInitializationIfNeeded(); PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); + DCHECK_EQ(layer_impl->is_mask_, is_mask_); LayerImpl::PushPropertiesTo(base_layer); @@ -134,54 +142,39 @@ twin_layer_ = layer_impl; layer_impl->twin_layer_ = this; - layer_impl->set_is_mask(is_mask_); - layer_impl->UpdateRasterSource(raster_source_); + layer_impl->SetNearestNeighbor(nearest_neighbor_); + // Solid color layers have no tilings. DCHECK_IMPLIES(raster_source_->IsSolidColor(), tilings_->num_tilings() == 0); - // Tilings would be expensive to push, so we swap. - layer_impl->tilings_.swap(tilings_); - layer_impl->tilings_->SetClient(layer_impl); - if (tilings_) - tilings_->SetClient(this); + // The pending tree should only have a high res (and possibly low res) tiling. + DCHECK_LE(tilings_->num_tilings(), + layer_tree_impl()->create_low_res_tiling() ? 2u : 1u); - // Ensure that the recycle tree doesn't have any unshared tiles. - if (tilings_ && raster_source_->IsSolidColor()) - tilings_->RemoveAllTilings(); + layer_impl->UpdateRasterSource(raster_source_, &invalidation_, + tilings_.get()); + DCHECK(invalidation_.IsEmpty()); - // Remove invalidated tiles from what will become a recycle tree. - if (tilings_) - tilings_->RemoveTilesInRegion(invalidation_); + // After syncing a solid color layer, the active layer has no tilings. + DCHECK_IMPLIES(raster_source_->IsSolidColor(), + layer_impl->tilings_->num_tilings() == 0); layer_impl->raster_page_scale_ = raster_page_scale_; layer_impl->raster_device_scale_ = raster_device_scale_; layer_impl->raster_source_scale_ = raster_source_scale_; layer_impl->raster_contents_scale_ = raster_contents_scale_; layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_; - layer_impl->needs_post_commit_initialization_ = false; - // The invalidation on this soon-to-be-recycled layer must be cleared to - // mirror clearing the invalidation in PictureLayer's version of this function - // in case push properties is skipped. - layer_impl->invalidation_.Swap(&invalidation_); - invalidation_.Clear(); + layer_impl->SanityCheckTilingState(); + + layer_impl->needs_post_commit_initialization_ = false; needs_post_commit_initialization_ = true; // We always need to push properties. // See http://crbug.com/303943 + // TODO(danakj): Stop always pushing properties since we don't swap tilings. needs_push_properties_ = true; } -void PictureLayerImpl::UpdateRasterSource( - scoped_refptr<RasterSource> raster_source) { - bool could_have_tilings = CanHaveTilings(); - raster_source_.swap(raster_source); - - // Need to call UpdateTiles again if CanHaveTilings changed. - if (could_have_tilings != CanHaveTilings()) { - layer_tree_impl()->set_needs_update_draw_properties(); - } -} - void PictureLayerImpl::AppendQuads(RenderPass* render_pass, const Occlusion& occlusion_in_content_space, AppendQuadsData* append_quads_data) { @@ -251,8 +244,9 @@ PictureDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); quad->SetNew(shared_quad_state, geometry_rect, opaque_rect, - visible_geometry_rect, texture_rect, texture_size, RGBA_8888, - quad_content_rect, max_contents_scale, raster_source_); + visible_geometry_rect, texture_rect, texture_size, + nearest_neighbor_, RGBA_8888, quad_content_rect, + max_contents_scale, raster_source_); return; } @@ -364,7 +358,8 @@ draw_info.get_resource_id(), texture_rect, iter.texture_size(), - draw_info.contents_swizzled()); + draw_info.contents_swizzled(), + nearest_neighbor_); has_draw_quad = true; break; } @@ -386,8 +381,8 @@ render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); quad->SetNew(shared_quad_state, geometry_rect, opaque_rect, visible_geometry_rect, texture_rect, iter.texture_size(), - format, iter->content_rect(), iter->contents_scale(), - raster_source_); + nearest_neighbor_, format, iter->content_rect(), + iter->contents_scale(), raster_source_); has_draw_quad = true; break; } @@ -485,8 +480,6 @@ UpdateIdealScales(); - DCHECK_IMPLIES(tilings_->num_tilings() == 0, raster_contents_scale_ == 0.f) - << "A layer with no tilings shouldn't have valid raster scales"; if (!raster_contents_scale_ || ShouldAdjustRasterScale()) { RecalculateRasterScales(); AddTilingsForRasterScale(); @@ -581,6 +574,44 @@ return twin_layer_; } +void PictureLayerImpl::UpdateRasterSource( + scoped_refptr<RasterSource> raster_source, + Region* new_invalidation, + const PictureLayerTilingSet* pending_set) { + // 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. + DCHECK_IMPLIES(!raster_source->GetSize().IsEmpty(), + bounds() == raster_source->GetSize()) + << " bounds " << bounds().ToString() << " pile " + << raster_source->GetSize().ToString(); + + bool could_have_tilings = CanHaveTilings(); + raster_source_.swap(raster_source); + + // The |new_invalidation| must be cleared before updating tilings since they + // access the invalidation through the PictureLayerTilingClient interface. + invalidation_.Clear(); + invalidation_.Swap(new_invalidation); + + bool can_have_tilings = CanHaveTilings(); + + // Need to call UpdateTiles again if CanHaveTilings changed. + if (could_have_tilings != can_have_tilings) + layer_tree_impl()->set_needs_update_draw_properties(); + + if (!can_have_tilings) { + RemoveAllTilings(); + return; + } + + // We could do this after doing UpdateTiles, which would avoid doing this for + // tilings that are going to disappear on the pending tree (if scale changed). + // But that would also be more complicated, so we just do it here for now. + tilings_->UpdateTilingsToCurrentRasterSource( + raster_source_.get(), pending_set, raster_source_->GetSize(), + invalidation_, MinimumContentsScale()); +} + void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { if (layer_tree_impl()->IsActiveTree()) { gfx::RectF layer_damage_rect = @@ -600,9 +631,10 @@ } void PictureLayerImpl::ReleaseResources() { + // Recreate tilings with new settings, since some of those might change when + // we release resources. If tilings_ is null, then leave it as null. if (tilings_) - RemoveAllTilings(); - + tilings_ = CreatePictureLayerTilingSet(); ResetRasterScale(); // To avoid an edge case after lost context where the tree is up to date but @@ -637,6 +669,8 @@ const Region* PictureLayerImpl::GetPendingInvalidation() { if (layer_tree_impl()->IsPendingTree()) return &invalidation_; + if (layer_tree_impl()->IsRecycleTree()) + return nullptr; DCHECK(layer_tree_impl()->IsActiveTree()); if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer()) return &twin_layer->invalidation_; @@ -648,9 +682,6 @@ PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer(); if (!twin_layer) return nullptr; - // TODO(danakj): Remove this when no longer swapping tilings. - if (!twin_layer->tilings_) - return nullptr; return twin_layer->tilings_->FindTilingWithScale(tiling->contents_scale()); } @@ -668,22 +699,6 @@ return TilePriority::NOW; } -size_t PictureLayerImpl::GetMaxTilesForInterestArea() const { - return layer_tree_impl()->settings().max_tiles_for_interest_area; -} - -float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const { - return layer_tree_impl()->use_gpu_rasterization() - ? 0.f - : layer_tree_impl()->settings().skewport_target_time_in_seconds; -} - -int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const { - return layer_tree_impl() - ->settings() - .skewport_extrapolation_limit_in_content_pixels; -} - bool PictureLayerImpl::RequiresHighResToDraw() const { return layer_tree_impl()->RequiresHighResToDraw(); } @@ -765,69 +780,15 @@ return gfx::Size(tile_width, tile_height); } -void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { - DCHECK(!other->needs_post_commit_initialization_); - DCHECK(other->tilings_); - - if (!DrawsContent()) { - RemoveAllTilings(); - return; - } - - raster_page_scale_ = other->raster_page_scale_; - raster_device_scale_ = other->raster_device_scale_; - raster_source_scale_ = other->raster_source_scale_; - raster_contents_scale_ = other->raster_contents_scale_; - low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_; - - bool synced_high_res_tiling = false; - if (CanHaveTilings()) { - synced_high_res_tiling = tilings_->SyncTilings( - *other->tilings_, raster_source_->GetSize(), invalidation_, - MinimumContentsScale(), raster_source_.get()); - } else { - RemoveAllTilings(); - } - - // If our MinimumContentsScale has changed to prevent the twin's high res - // tiling from being synced, we should reset the raster scale and let it be - // recalculated (1) again. This can happen if our bounds shrink to the point - // where min contents scale grows. - // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we - // should refactor this code a little bit and actually recalculate this. - // However, this is a larger undertaking, so this will work for now. - if (!synced_high_res_tiling) - ResetRasterScale(); - else - SanityCheckTilingState(); -} - -void PictureLayerImpl::SyncTiling( - const PictureLayerTiling* tiling) { - if (!tilings_) - return; - if (!CanHaveTilingWithScale(tiling->contents_scale())) - return; - tilings_->AddTiling(tiling->contents_scale(), raster_source_->GetSize()); - - // If this tree needs update draw properties, then the tiling will - // get updated prior to drawing or activation. If this tree does not - // need update draw properties, then its transforms are up to date and - // we can create tiles for this tiling immediately. - if (!layer_tree_impl()->needs_update_draw_properties() && - should_update_tile_priorities_) { - // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking - // when we stop using the pending tree in the browser compositor. If we want - // to support occlusion tracking here, we need to dirty the draw properties - // or save occlusion as a draw property. - UpdateTilePriorities(Occlusion()); - } -} - void PictureLayerImpl::GetContentsResourceId( ResourceProvider::ResourceId* resource_id, gfx::Size* resource_size) const { - DCHECK_EQ(bounds().ToString(), raster_source_->GetSize().ToString()); + // 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. + DCHECK_IMPLIES(!raster_source_->GetSize().IsEmpty(), + bounds() == raster_source_->GetSize()) + << " bounds " << bounds().ToString() << " pile " + << raster_source_->GetSize().ToString(); gfx::Rect content_rect(bounds()); PictureLayerTilingSet::CoverageIterator iter( tilings_.get(), 1.f, content_rect, ideal_contents_scale_); @@ -854,21 +815,18 @@ *resource_size = iter.texture_size(); } +void PictureLayerImpl::SetNearestNeighbor(bool nearest_neighbor) { + if (nearest_neighbor_ == nearest_neighbor) + return; + + nearest_neighbor_ = nearest_neighbor; + NoteLayerPropertyChanged(); +} + void PictureLayerImpl::DoPostCommitInitialization() { + // TODO(danakj): Remove this. DCHECK(needs_post_commit_initialization_); DCHECK(layer_tree_impl()->IsPendingTree()); - - if (!tilings_) - tilings_ = PictureLayerTilingSet::Create(this); - - PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer(); - if (twin_layer) { - // If the twin has never been pushed to, do not sync from it. - // This can happen if this function is called during activation. - if (!twin_layer->needs_post_commit_initialization_) - SyncFromActiveLayer(twin_layer); - } - needs_post_commit_initialization_ = false; } @@ -881,9 +839,6 @@ DCHECK(raster_source_->HasRecordings()); - if (PictureLayerImpl* twin_layer = GetPendingOrActiveTwinLayer()) - twin_layer->SyncTiling(tiling); - return tiling; } @@ -929,6 +884,12 @@ // Make sure we always have one high-res (even if high == low). high_res->set_resolution(HIGH_RESOLUTION); + if (layer_tree_impl()->IsPendingTree()) { + // On the pending tree, drop any tilings that are non-ideal since we don't + // need them to activate anyway. + tilings_->RemoveNonIdealTilings(); + } + SanityCheckTilingState(); } @@ -1113,9 +1074,6 @@ layer_tree_impl()->create_low_res_tiling(), twin_set, recycled_twin_set); - if (twin_set && twin_set->num_tilings() == 0) - twin->ResetRasterScale(); - if (recycled_twin_set && recycled_twin_set->num_tilings() == 0) recycled_twin->ResetRasterScale(); @@ -1158,6 +1116,8 @@ return false; if (!raster_source_->HasRecordings()) return false; + // If the |raster_source_| has a recording it should have non-empty bounds. + DCHECK(!raster_source_->GetSize().IsEmpty()); return true; } @@ -1196,6 +1156,17 @@ return std::max(max_contents_scale, MinimumContentsScale()); } +scoped_ptr<PictureLayerTilingSet> +PictureLayerImpl::CreatePictureLayerTilingSet() { + const LayerTreeSettings& settings = layer_tree_impl()->settings(); + return PictureLayerTilingSet::Create( + this, settings.max_tiles_for_interest_area, + layer_tree_impl()->use_gpu_rasterization() + ? 0.f + : settings.skewport_target_time_in_seconds, + settings.skewport_extrapolation_limit_in_content_pixels); +} + void PictureLayerImpl::UpdateIdealScales() { DCHECK(CanHaveTilings());
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index ddf928b..f17743d 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h
@@ -39,8 +39,10 @@ PictureLayerImpl* pending; }; - static scoped_ptr<PictureLayerImpl> Create(LayerTreeImpl* tree_impl, int id) { - return make_scoped_ptr(new PictureLayerImpl(tree_impl, id)); + static scoped_ptr<PictureLayerImpl> Create(LayerTreeImpl* tree_impl, + int id, + bool is_mask) { + return make_scoped_ptr(new PictureLayerImpl(tree_impl, id, is_mask)); } ~PictureLayerImpl() override; @@ -73,9 +75,6 @@ PictureLayerTiling* GetRecycledTwinTiling( const PictureLayerTiling* tiling) override; TilePriority::PriorityBin GetMaxTilePriorityBin() const override; - size_t GetMaxTilesForInterestArea() const override; - float GetSkewportTargetTimeInSeconds() const override; - int GetSkewportExtrapolationLimitInContentPixels() const override; WhichTree GetTree() const override; bool RequiresHighResToDraw() const override; @@ -85,7 +84,8 @@ // Mask-related functions. void GetContentsResourceId(ResourceProvider::ResourceId* resource_id, gfx::Size* resource_size) const override; - void set_is_mask(bool is_mask) { is_mask_ = is_mask; } + + void SetNearestNeighbor(bool nearest_neighbor); size_t GPUMemoryUsageInBytes() const override; @@ -108,10 +108,9 @@ friend class LayerRasterTileIterator; using TileRequirementCheck = bool (PictureLayerTiling::*)(const Tile*) const; - PictureLayerImpl(LayerTreeImpl* tree_impl, int id); + PictureLayerImpl(LayerTreeImpl* tree_impl, int id, bool is_mask); PictureLayerTiling* AddTiling(float contents_scale); void RemoveAllTilings(); - void SyncFromActiveLayer(const PictureLayerImpl* other); void AddTilingsForRasterScale(); void UpdateTilePriorities(const Occlusion& occlusion_in_content_space); virtual bool ShouldAdjustRasterScale() const; @@ -122,7 +121,9 @@ void ResetRasterScale(); gfx::Rect GetViewportForTilePriorityInContentSpace() const; PictureLayerImpl* GetRecycledTwinLayer() const; - void UpdateRasterSource(scoped_refptr<RasterSource> raster_source); + void UpdateRasterSource(scoped_refptr<RasterSource> raster_source, + Region* new_invalidation, + const PictureLayerTilingSet* pending_set); void DoPostCommitInitializationIfNeeded() { if (needs_post_commit_initialization_) @@ -146,6 +147,7 @@ virtual void UpdateIdealScales(); float MaximumTilingContentsScale() const; + scoped_ptr<PictureLayerTilingSet> CreatePictureLayerTilingSet(); PictureLayerImpl* twin_layer_; @@ -171,7 +173,9 @@ // after a CalculateContentsScale/ManageTilings. bool should_update_tile_priorities_; bool only_used_low_res_last_append_quads_; - bool is_mask_; + const bool is_mask_; + + bool nearest_neighbor_; // Any draw properties derived from |transform|, |viewport|, and |clip| // parameters in LayerTreeHostImpl::SetExternalDrawConstraints are not valid
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index 90a36f7..7c7c899 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -34,6 +34,18 @@ namespace cc { namespace { +#define EXPECT_BOTH_EQ(expression, x) \ + do { \ + EXPECT_EQ(x, pending_layer_->expression); \ + EXPECT_EQ(x, active_layer_->expression); \ + } while (false) + +#define EXPECT_BOTH_NE(expression, x) \ + do { \ + EXPECT_NE(x, pending_layer_->expression); \ + EXPECT_NE(x, active_layer_->expression); \ + } while (false) + class MockCanvas : public SkCanvas { public: explicit MockCanvas(int w, int h) : SkCanvas(w, h) {} @@ -58,15 +70,21 @@ PictureLayerImplTest() : proxy_(base::MessageLoopProxy::current()), host_impl_(LowResTilingsSettings(), &proxy_, &shared_bitmap_manager_), + root_id_(6), id_(7), pending_layer_(nullptr), old_pending_layer_(nullptr), - active_layer_(nullptr) {} + active_layer_(nullptr) { + host_impl_.SetViewportSize(gfx::Size(10000, 10000)); + } explicit PictureLayerImplTest(const LayerTreeSettings& settings) : proxy_(base::MessageLoopProxy::current()), host_impl_(settings, &proxy_, &shared_bitmap_manager_), - id_(7) {} + root_id_(6), + id_(7) { + host_impl_.SetViewportSize(gfx::Size(10000, 10000)); + } virtual ~PictureLayerImplTest() { } @@ -88,6 +106,18 @@ SetupTrees(pending_pile, active_pile); } + void SetupDefaultTreesWithInvalidation(const gfx::Size& layer_bounds, + const Region& invalidation) { + gfx::Size tile_size(100, 100); + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + + SetupTreesWithInvalidation(pending_pile, active_pile, invalidation); + } + void ActivateTree() { host_impl_.ActivateSyncTree(); CHECK(!host_impl_.pending_tree()); @@ -96,13 +126,22 @@ pending_layer_ = nullptr; active_layer_ = static_cast<FakePictureLayerImpl*>( host_impl_.active_tree()->LayerById(id_)); + + host_impl_.active_tree()->UpdateDrawProperties(); } void SetupDefaultTreesWithFixedTileSize(const gfx::Size& layer_bounds, - const gfx::Size& tile_size) { - SetupDefaultTrees(layer_bounds); - pending_layer_->set_fixed_tile_size(tile_size); - active_layer_->set_fixed_tile_size(tile_size); + const gfx::Size& tile_size, + const Region& invalidation) { + gfx::Size pile_tile_size(100, 100); + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(pile_tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(pile_tile_size, layer_bounds); + + SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, + invalidation); } void SetupTrees( @@ -110,54 +149,80 @@ scoped_refptr<PicturePileImpl> active_pile) { SetupPendingTree(active_pile); ActivateTree(); - SetupPendingTree(pending_pile); + SetupPendingTreeInternal(pending_pile, gfx::Size(), Region()); } - void CreateHighLowResAndSetAllTilesVisible() { - // Active layer must get updated first so pending layer can share from it. - active_layer_->CreateDefaultTilingsAndTiles(); - active_layer_->SetAllTilesVisible(); - pending_layer_->CreateDefaultTilingsAndTiles(); - pending_layer_->SetAllTilesVisible(); + void SetupTreesWithInvalidation(scoped_refptr<PicturePileImpl> pending_pile, + scoped_refptr<PicturePileImpl> active_pile, + const Region& pending_invalidation) { + SetupPendingTreeInternal(active_pile, gfx::Size(), Region()); + ActivateTree(); + SetupPendingTreeInternal(pending_pile, gfx::Size(), pending_invalidation); } - void AddDefaultTilingsWithInvalidation(const Region& invalidation) { - active_layer_->AddTiling(2.3f); - active_layer_->AddTiling(1.0f); - active_layer_->AddTiling(0.5f); - for (size_t i = 0; i < active_layer_->tilings()->num_tilings(); ++i) - active_layer_->tilings()->tiling_at(i)->CreateAllTilesForTesting(); - pending_layer_->set_invalidation(invalidation); - for (size_t i = 0; i < pending_layer_->tilings()->num_tilings(); ++i) - pending_layer_->tilings()->tiling_at(i)->CreateAllTilesForTesting(); + void SetupTreesWithFixedTileSize(scoped_refptr<PicturePileImpl> pending_pile, + scoped_refptr<PicturePileImpl> active_pile, + const gfx::Size& tile_size, + const Region& pending_invalidation) { + SetupPendingTreeInternal(active_pile, tile_size, Region()); + ActivateTree(); + SetupPendingTreeInternal(pending_pile, tile_size, pending_invalidation); } void SetupPendingTree(scoped_refptr<RasterSource> raster_source) { + SetupPendingTreeInternal(raster_source, gfx::Size(), Region()); + } + + void SetupPendingTreeWithInvalidation( + scoped_refptr<RasterSource> raster_source, + const Region& invalidation) { + SetupPendingTreeInternal(raster_source, gfx::Size(), invalidation); + } + + void SetupPendingTreeWithFixedTileSize( + scoped_refptr<RasterSource> raster_source, + const gfx::Size& tile_size, + const Region& invalidation) { + SetupPendingTreeInternal(raster_source, tile_size, invalidation); + } + + void SetupPendingTreeInternal(scoped_refptr<RasterSource> raster_source, + const gfx::Size& tile_size, + const Region& invalidation) { host_impl_.CreatePendingTree(); host_impl_.pending_tree()->PushPageScaleFromMainThread(1.f, 0.25f, 100.f); LayerTreeImpl* pending_tree = host_impl_.pending_tree(); - // Steal from the recycled tree. - scoped_ptr<LayerImpl> old_pending_root = pending_tree->DetachLayerTree(); - DCHECK_IMPLIES(old_pending_root, old_pending_root->id() == id_); - + // Steal from the recycled tree if possible. + scoped_ptr<LayerImpl> pending_root = pending_tree->DetachLayerTree(); scoped_ptr<FakePictureLayerImpl> pending_layer; - if (old_pending_root) { - pending_layer.reset( - static_cast<FakePictureLayerImpl*>(old_pending_root.release())); - pending_layer->SetRasterSource(raster_source); - } else { - pending_layer = FakePictureLayerImpl::CreateWithRasterSource( - pending_tree, id_, raster_source); + DCHECK_IMPLIES(pending_root, pending_root->id() == root_id_); + if (!pending_root) { + pending_root = LayerImpl::Create(pending_tree, root_id_); + pending_layer = FakePictureLayerImpl::Create(pending_tree, id_); + if (!tile_size.IsEmpty()) + pending_layer->set_fixed_tile_size(tile_size); pending_layer->SetDrawsContent(true); + } else { + pending_layer.reset(static_cast<FakePictureLayerImpl*>( + pending_root->RemoveChild(pending_root->children()[0]).release())); + if (!tile_size.IsEmpty()) + pending_layer->set_fixed_tile_size(tile_size); } // The bounds() just mirror the pile size. - pending_layer->SetBounds(pending_layer->raster_source()->GetSize()); - pending_tree->SetRootLayer(pending_layer.Pass()); + pending_layer->SetBounds(raster_source->GetSize()); + pending_layer->SetContentBounds(raster_source->GetSize()); + pending_layer->SetRasterSourceOnPending(raster_source, invalidation); + + pending_root->AddChild(pending_layer.Pass()); + pending_tree->SetRootLayer(pending_root.Pass()); pending_layer_ = static_cast<FakePictureLayerImpl*>( host_impl_.pending_tree()->LayerById(id_)); pending_layer_->DoPostCommitInitializationIfNeeded(); + + // Add tilings/tiles for the layer. + host_impl_.pending_tree()->UpdateDrawProperties(); } void SetupDrawPropertiesAndUpdateTiles(FakePictureLayerImpl* layer, @@ -213,6 +278,10 @@ void ResetTilingsAndRasterScales() { pending_layer_->ReleaseResources(); active_layer_->ReleaseResources(); + if (pending_layer_) + EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); + if (active_layer_) + EXPECT_EQ(0u, active_layer_->tilings()->num_tilings()); } void AssertAllTilesRequired(PictureLayerTiling* tiling) { @@ -230,60 +299,12 @@ } protected: - void TestTileGridAlignmentCommon() { - // Layer to span 4 raster tiles in x and in y - ImplSidePaintingSettings settings; - gfx::Size layer_size( - settings.default_tile_size.width() * 7 / 2, - settings.default_tile_size.height() * 7 / 2); - - scoped_refptr<FakePicturePileImpl> pending_pile = - FakePicturePileImpl::CreateFilledPile(layer_size, layer_size); - scoped_refptr<FakePicturePileImpl> active_pile = - FakePicturePileImpl::CreateFilledPile(layer_size, layer_size); - - SetupTrees(pending_pile, active_pile); - - SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false); - - // Add 1x1 rects at the centers of each tile, then re-record pile contents - active_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting(); - std::vector<Tile*> tiles = - active_layer_->tilings()->tiling_at(0)->AllTilesForTesting(); - EXPECT_EQ(16u, tiles.size()); - std::vector<SkRect> rects; - std::vector<Tile*>::const_iterator tile_iter; - 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); - rects.push_back(SkRect::MakeXYWH(rect.x(), rect.y(), 1, 1)); - } - // Force re-record with newly injected content - active_pile->RemoveRecordingAt(0, 0); - active_pile->AddRecordingAt(0, 0); - - 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); - - // This test verifies that when drawing the contents of a specific tile - // at content scale 1.0, the playback canvas never receives content from - // neighboring tiles which indicates that the tile grid embedded in - // SkPicture is perfectly aligned with the compositor's tiles. - EXPECT_EQ(1u, mock_canvas.rects_.size()); - EXPECT_EQ(*rect_iter, mock_canvas.rects_[0]); - rect_iter++; - } - } - void TestQuadsForSolidColor(bool test_for_solid); FakeImplProxy proxy_; TestSharedBitmapManager shared_bitmap_manager_; FakeLayerTreeHostImpl host_impl_; + int root_id_; int id_; FakePictureLayerImpl* pending_layer_; FakePictureLayerImpl* old_pending_layer_; @@ -293,14 +314,56 @@ DISALLOW_COPY_AND_ASSIGN(PictureLayerImplTest); }; -TEST_F(PictureLayerImplTest, TileGridAlignment) { - host_impl_.SetDeviceScaleFactor(1.f); - TestTileGridAlignmentCommon(); -} +class NoLowResPictureLayerImplTest : public PictureLayerImplTest { + public: + NoLowResPictureLayerImplTest() + : PictureLayerImplTest(NoLowResTilingsSettings()) {} +}; -TEST_F(PictureLayerImplTest, TileGridAlignmentHiDPI) { - host_impl_.SetDeviceScaleFactor(2.f); - TestTileGridAlignmentCommon(); +TEST_F(PictureLayerImplTest, TileGridAlignment) { + // Layer to span 4 raster tiles in x and in y + ImplSidePaintingSettings settings; + gfx::Size layer_size(settings.default_tile_size.width() * 7 / 2, + settings.default_tile_size.height() * 7 / 2); + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(layer_size, layer_size); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(layer_size, layer_size); + + SetupTrees(pending_pile, active_pile); + + // Add 1x1 rects at the centers of each tile, then re-record pile contents + active_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting(); + std::vector<Tile*> tiles = + active_layer_->tilings()->tiling_at(0)->AllTilesForTesting(); + EXPECT_EQ(16u, tiles.size()); + std::vector<SkRect> rects; + std::vector<Tile*>::const_iterator tile_iter; + 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); + 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); + + 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); + + // This test verifies that when drawing the contents of a specific tile + // at content scale 1.0, the playback canvas never receives content from + // neighboring tiles which indicates that the tile grid embedded in + // SkPicture is perfectly aligned with the compositor's tiles. + EXPECT_EQ(1u, mock_canvas.rects_.size()); + EXPECT_EQ(*rect_iter, mock_canvas.rects_[0]); + rect_iter++; + } } TEST_F(PictureLayerImplTest, CloneNoInvalidation) { @@ -312,10 +375,7 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); - - Region invalidation; - AddDefaultTilingsWithInvalidation(invalidation); + SetupTreesWithInvalidation(pending_pile, active_pile, Region()); EXPECT_EQ(pending_layer_->tilings()->num_tilings(), active_layer_->tilings()->num_tilings()); @@ -323,7 +383,7 @@ const PictureLayerTilingSet* tilings = pending_layer_->tilings(); EXPECT_GT(tilings->num_tilings(), 0u); for (size_t i = 0; i < tilings->num_tilings(); ++i) - VerifyAllTilesExistAndHavePile(tilings->tiling_at(i), active_pile.get()); + VerifyAllTilesExistAndHavePile(tilings->tiling_at(i), pending_pile.get()); } TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) { @@ -339,10 +399,8 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); + SetupTreesWithInvalidation(pending_pile, active_pile, Region()); - Region invalidation; - AddDefaultTilingsWithInvalidation(invalidation); SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false); time_ticks += base::TimeDelta::FromMilliseconds(200); @@ -436,10 +494,8 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); + SetupTreesWithInvalidation(pending_pile, active_pile, Region()); - Region invalidation; - AddDefaultTilingsWithInvalidation(invalidation); SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false); // UpdateTiles with valid viewport. Should update tile viewport. @@ -516,11 +572,20 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> lost_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); + SetupPendingTreeWithFixedTileSize(lost_pile, gfx::Size(50, 50), Region()); + ActivateTree(); + // Add a non-shared tiling on the active tree. + PictureLayerTiling* tiling = active_layer_->AddTiling(3.f); + tiling->CreateAllTilesForTesting(); + // Then setup a new pending tree and activate it. + SetupTreesWithFixedTileSize(pending_pile, active_pile, gfx::Size(50, 50), + layer_invalidation); - Region invalidation(layer_invalidation); - AddDefaultTilingsWithInvalidation(invalidation); + EXPECT_EQ(2u, pending_layer_->num_tilings()); + EXPECT_EQ(3u, active_layer_->num_tilings()); const PictureLayerTilingSet* tilings = pending_layer_->tilings(); EXPECT_GT(tilings->num_tilings(), 0u); @@ -537,10 +602,30 @@ ++iter) { EXPECT_TRUE(*iter); EXPECT_FALSE(iter.geometry_rect().IsEmpty()); + EXPECT_EQ(pending_pile.get(), iter->raster_source()); + } + } + + tilings = active_layer_->tilings(); + EXPECT_GT(tilings->num_tilings(), 0u); + for (size_t i = 0; i < tilings->num_tilings(); ++i) { + const PictureLayerTiling* tiling = tilings->tiling_at(i); + gfx::Rect content_invalidation = + gfx::ScaleToEnclosingRect(layer_invalidation, tiling->contents_scale()); + for (PictureLayerTiling::CoverageIterator iter( + tiling, + tiling->contents_scale(), + gfx::Rect(tiling->tiling_size())); + iter; + ++iter) { + EXPECT_TRUE(*iter); + EXPECT_FALSE(iter.geometry_rect().IsEmpty()); if (iter.geometry_rect().Intersects(content_invalidation)) - EXPECT_EQ(pending_pile.get(), iter->raster_source()); - else EXPECT_EQ(active_pile.get(), iter->raster_source()); + else if (!active_layer_->GetPendingOrActiveTwinTiling(tiling)) + EXPECT_EQ(active_pile.get(), iter->raster_source()); + else + EXPECT_EQ(pending_pile.get(), iter->raster_source()); } } } @@ -554,10 +639,8 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); - - Region invalidation((gfx::Rect(layer_bounds))); - AddDefaultTilingsWithInvalidation(invalidation); + SetupTreesWithInvalidation(pending_pile, active_pile, + gfx::Rect(layer_bounds)); EXPECT_EQ(pending_layer_->tilings()->num_tilings(), active_layer_->tilings()->num_tilings()); @@ -568,125 +651,6 @@ VerifyAllTilesExistAndHavePile(tilings->tiling_at(i), pending_pile.get()); } -TEST_F(PictureLayerImplTest, NoInvalidationBoundsChange) { - gfx::Size tile_size(90, 80); - gfx::Size active_layer_bounds(300, 500); - gfx::Size pending_layer_bounds(400, 800); - - scoped_refptr<FakePicturePileImpl> pending_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, - pending_layer_bounds); - scoped_refptr<FakePicturePileImpl> active_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, active_layer_bounds); - - SetupTrees(pending_pile, active_pile); - pending_layer_->set_fixed_tile_size(gfx::Size(100, 100)); - - Region invalidation; - AddDefaultTilingsWithInvalidation(invalidation); - - const PictureLayerTilingSet* tilings = pending_layer_->tilings(); - EXPECT_GT(tilings->num_tilings(), 0u); - for (size_t i = 0; i < tilings->num_tilings(); ++i) { - const PictureLayerTiling* tiling = tilings->tiling_at(i); - gfx::Rect active_content_bounds = gfx::ScaleToEnclosingRect( - gfx::Rect(active_layer_bounds), - tiling->contents_scale()); - for (PictureLayerTiling::CoverageIterator iter( - tiling, - tiling->contents_scale(), - gfx::Rect(tiling->tiling_size())); - iter; - ++iter) { - EXPECT_TRUE(*iter); - EXPECT_FALSE(iter.geometry_rect().IsEmpty()); - std::vector<Tile*> active_tiles = - active_layer_->tilings()->tiling_at(i)->AllTilesForTesting(); - std::vector<Tile*> pending_tiles = tiling->AllTilesForTesting(); - if (iter.geometry_rect().right() >= active_content_bounds.width() || - iter.geometry_rect().bottom() >= active_content_bounds.height() || - active_tiles[0]->content_rect().size() != - pending_tiles[0]->content_rect().size()) { - EXPECT_EQ(pending_pile.get(), iter->raster_source()); - } else { - EXPECT_EQ(active_pile.get(), iter->raster_source()); - } - } - } -} - -TEST_F(PictureLayerImplTest, AddTilesFromNewRecording) { - gfx::Size tile_size(400, 400); - gfx::Size layer_bounds(1300, 1900); - - scoped_refptr<FakePicturePileImpl> pending_pile = - FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds); - scoped_refptr<FakePicturePileImpl> active_pile = - FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds); - - // Fill in some of active pile, but more of pending pile. - int hole_count = 0; - for (int x = 0; x < active_pile->tiling().num_tiles_x(); ++x) { - for (int y = 0; y < active_pile->tiling().num_tiles_y(); ++y) { - if ((x + y) % 2) { - pending_pile->AddRecordingAt(x, y); - active_pile->AddRecordingAt(x, y); - } else { - hole_count++; - if (hole_count % 2) - pending_pile->AddRecordingAt(x, y); - } - } - } - - SetupTrees(pending_pile, active_pile); - Region invalidation; - AddDefaultTilingsWithInvalidation(invalidation); - - const PictureLayerTilingSet* tilings = pending_layer_->tilings(); - EXPECT_GT(tilings->num_tilings(), 0u); - for (size_t i = 0; i < tilings->num_tilings(); ++i) { - const PictureLayerTiling* tiling = tilings->tiling_at(i); - - for (PictureLayerTiling::CoverageIterator iter( - tiling, - tiling->contents_scale(), - gfx::Rect(tiling->tiling_size())); - iter; - ++iter) { - EXPECT_FALSE(iter.full_tile_geometry_rect().IsEmpty()); - // Ensure there is a recording for this tile. - bool in_pending = pending_pile->CoversRect(iter.full_tile_geometry_rect(), - tiling->contents_scale()); - bool in_active = active_pile->CoversRect(iter.full_tile_geometry_rect(), - tiling->contents_scale()); - - if (in_pending && !in_active) - EXPECT_EQ(pending_pile.get(), iter->raster_source()); - else if (in_active) - EXPECT_EQ(active_pile.get(), iter->raster_source()); - else - EXPECT_FALSE(*iter); - } - } -} - -TEST_F(PictureLayerImplTest, ManageTilingsWithNoRecording) { - gfx::Size tile_size(400, 400); - gfx::Size layer_bounds(1300, 1900); - - scoped_refptr<FakePicturePileImpl> pending_pile = - FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds); - scoped_refptr<FakePicturePileImpl> active_pile = - FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds); - - SetupTrees(pending_pile, active_pile); - - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false); - - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); -} - TEST_F(PictureLayerImplTest, ManageTilingsCreatesTilings) { gfx::Size tile_size(400, 400); gfx::Size layer_bounds(1300, 1900); @@ -697,11 +661,83 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; EXPECT_LT(low_res_factor, 1.f); + active_layer_->ReleaseResources(); + EXPECT_EQ(0u, active_layer_->tilings()->num_tilings()); + + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 6.f, // ideal contents scale + 3.f, // device scale + 2.f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(2u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(6.f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ(6.f * low_res_factor, + active_layer_->tilings()->tiling_at(1)->contents_scale()); + + // If we change the page scale factor, then we should get new tilings. + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 6.6f, // ideal contents scale + 3.f, // device scale + 2.2f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(4u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(6.6f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ(6.6f * low_res_factor, + active_layer_->tilings()->tiling_at(2)->contents_scale()); + + // If we change the device scale factor, then we should get new tilings. + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 7.26f, // ideal contents scale + 3.3f, // device scale + 2.2f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(6u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(7.26f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ(7.26f * low_res_factor, + active_layer_->tilings()->tiling_at(3)->contents_scale()); + + // If we change the device scale factor, but end up at the same total scale + // factor somehow, then we don't get new tilings. + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 7.26f, // ideal contents scale + 2.2f, // device scale + 3.3f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(6u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(7.26f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); + EXPECT_FLOAT_EQ(7.26f * low_res_factor, + active_layer_->tilings()->tiling_at(3)->contents_scale()); +} + +TEST_F(PictureLayerImplTest, PendingLayerOnlyHasHighAndLowResTiling) { + gfx::Size tile_size(400, 400); + gfx::Size layer_bounds(1300, 1900); + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + + SetupTrees(pending_pile, active_pile); + + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + EXPECT_LT(low_res_factor, 1.f); + + pending_layer_->ReleaseResources(); + EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); + SetupDrawPropertiesAndUpdateTiles(pending_layer_, 6.f, // ideal contents scale 3.f, // device scale @@ -721,11 +757,11 @@ 2.2f, // page scale 1.f, // maximum animation scale false); - ASSERT_EQ(4u, pending_layer_->tilings()->num_tilings()); + ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(6.6f, pending_layer_->tilings()->tiling_at(0)->contents_scale()); EXPECT_FLOAT_EQ(6.6f * low_res_factor, - pending_layer_->tilings()->tiling_at(2)->contents_scale()); + pending_layer_->tilings()->tiling_at(1)->contents_scale()); // If we change the device scale factor, then we should get new tilings. SetupDrawPropertiesAndUpdateTiles(pending_layer_, @@ -734,11 +770,11 @@ 2.2f, // page scale 1.f, // maximum animation scale false); - ASSERT_EQ(6u, pending_layer_->tilings()->num_tilings()); + ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(7.26f, pending_layer_->tilings()->tiling_at(0)->contents_scale()); EXPECT_FLOAT_EQ(7.26f * low_res_factor, - pending_layer_->tilings()->tiling_at(3)->contents_scale()); + pending_layer_->tilings()->tiling_at(1)->contents_scale()); // If we change the device scale factor, but end up at the same total scale // factor somehow, then we don't get new tilings. @@ -748,11 +784,11 @@ 3.3f, // page scale 1.f, // maximum animation scale false); - ASSERT_EQ(6u, pending_layer_->tilings()->num_tilings()); + ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(7.26f, pending_layer_->tilings()->tiling_at(0)->contents_scale()); EXPECT_FLOAT_EQ(7.26f * low_res_factor, - pending_layer_->tilings()->tiling_at(3)->contents_scale()); + pending_layer_->tilings()->tiling_at(1)->contents_scale()); } TEST_F(PictureLayerImplTest, CreateTilingsEvenIfTwinHasNone) { @@ -767,63 +803,22 @@ scoped_refptr<FakePicturePileImpl> valid_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - EXPECT_LT(low_res_factor, 1.f); - - float high_res_scale = 1.3f; - float low_res_scale = high_res_scale * low_res_factor; - float device_scale = 1.7f; - float page_scale = 3.2f; - float maximum_animation_scale = 1.f; - SetupPendingTree(valid_pile); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, - high_res_scale, - device_scale, - page_scale, - maximum_animation_scale, - false); ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(high_res_scale, - pending_layer_->HighResTiling()->contents_scale()); - EXPECT_FLOAT_EQ(low_res_scale, - pending_layer_->LowResTiling()->contents_scale()); ActivateTree(); SetupPendingTree(empty_pile); EXPECT_FALSE(pending_layer_->CanHaveTilings()); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, - high_res_scale, - device_scale, - page_scale, - maximum_animation_scale, - false); ASSERT_EQ(2u, active_layer_->tilings()->num_tilings()); ASSERT_EQ(0u, pending_layer_->tilings()->num_tilings()); ActivateTree(); EXPECT_FALSE(active_layer_->CanHaveTilings()); - SetupDrawPropertiesAndUpdateTiles(active_layer_, - high_res_scale, - device_scale, - page_scale, - maximum_animation_scale, - false); ASSERT_EQ(0u, active_layer_->tilings()->num_tilings()); SetupPendingTree(valid_pile); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, - high_res_scale, - device_scale, - page_scale, - maximum_animation_scale, - false); ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); ASSERT_EQ(0u, active_layer_->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(high_res_scale, - pending_layer_->HighResTiling()->contents_scale()); - EXPECT_FLOAT_EQ(low_res_scale, - pending_layer_->LowResTiling()->contents_scale()); } TEST_F(PictureLayerImplTest, ZoomOutCrash) { @@ -837,8 +832,10 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupTrees(pending_pile, active_pile); + ResetTilingsAndRasterScales(); EXPECT_EQ(0u, active_layer_->tilings()->num_tilings()); SetContentsScaleOnBothLayers(32.0f, 1.0f, 32.0f, 1.0f, false); + EXPECT_EQ(32.f, active_layer_->HighResTiling()->contents_scale()); host_impl_.PinchGestureBegin(); SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, false); SetContentsScaleOnBothLayers(1.0f, 1.0f, 1.0f, 1.0f, false); @@ -849,6 +846,8 @@ gfx::Size tile_size(400, 400); gfx::Size layer_bounds(1300, 1900); + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); scoped_refptr<FakePicturePileImpl> active_pile = @@ -856,21 +855,20 @@ // Set up the high and low res tilings before pinch zoom. SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, active_layer_->tilings()->num_tilings()); - SetContentsScaleOnBothLayers(2.0f, 1.0f, 1.0f, 1.0f, false); - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - EXPECT_EQ(2u, active_layer_->tilings()->num_tilings()); - EXPECT_FLOAT_EQ(2.0f, - active_layer_->tilings()->tiling_at(0)->contents_scale()); - EXPECT_FLOAT_EQ(2.0f * low_res_factor, - active_layer_->tilings()->tiling_at(1)->contents_scale()); + ResetTilingsAndRasterScales(); + + SetContentsScaleOnBothLayers(2.f, 1.0f, 2.f, 1.0f, false); + EXPECT_BOTH_EQ(num_tilings(), 2u); + EXPECT_BOTH_EQ(tilings()->tiling_at(0)->contents_scale(), 2.f); + EXPECT_BOTH_EQ(tilings()->tiling_at(1)->contents_scale(), + 2.f * low_res_factor); // Start a pinch gesture. host_impl_.PinchGestureBegin(); // Zoom out by a small amount. We should create a tiling at half // the scale (2/kMaxScaleRatioDuringPinch). - SetContentsScaleOnBothLayers(1.8f, 1.0f, 0.9f, 1.0f, false); + SetContentsScaleOnBothLayers(1.8f, 1.0f, 1.8f, 1.0f, false); EXPECT_EQ(3u, active_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(2.0f, active_layer_->tilings()->tiling_at(0)->contents_scale()); @@ -887,7 +885,7 @@ // Zoom in a lot now. Since we increase by increments of // kMaxScaleRatioDuringPinch, this will create a new tiling at 4.0. - SetContentsScaleOnBothLayers(3.8f, 1.0f, 2.1f, 1.f, false); + SetContentsScaleOnBothLayers(3.8f, 1.0f, 3.8f, 1.f, false); EXPECT_EQ(4u, active_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(4.0f, active_layer_->tilings()->tiling_at(0)->contents_scale()); @@ -902,9 +900,12 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - // Set up the high and low res tilings before pinch zoom. SetupTrees(pending_pile, active_pile); + + ResetTilingsAndRasterScales(); EXPECT_EQ(0u, active_layer_->tilings()->num_tilings()); + + // Set up the high and low res tilings before pinch zoom. SetContentsScaleOnBothLayers(0.24f, 1.0f, 0.24f, 1.0f, false); EXPECT_EQ(2u, active_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(0.24f, @@ -955,31 +956,28 @@ std::vector<PictureLayerTiling*> used_tilings; - SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; EXPECT_LT(low_res_factor, 1.f); - float device_scale = 1.7f; - float page_scale = 3.2f; float scale = 1.f; + float page_scale = 1.f; - SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, false); - ASSERT_EQ(2u, active_layer_->tilings()->num_tilings()); + SetupTrees(pending_pile, active_pile); + EXPECT_EQ(2u, active_layer_->tilings()->num_tilings()); + EXPECT_EQ(1.f, active_layer_->HighResTiling()->contents_scale()); // We only have ideal tilings, so they aren't removed. used_tilings.clear(); active_layer_->CleanUpTilingsOnActiveLayer(used_tilings); - ASSERT_EQ(2u, active_layer_->tilings()->num_tilings()); + EXPECT_EQ(2u, active_layer_->tilings()->num_tilings()); host_impl_.PinchGestureBegin(); // Changing the ideal but not creating new tilings. - scale *= 1.5f; - page_scale *= 1.5f; - SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, false); - ASSERT_EQ(2u, active_layer_->tilings()->num_tilings()); + scale = 1.5f; + page_scale = 1.5f; + SetContentsScaleOnBothLayers(scale, 1.f, page_scale, 1.f, false); + EXPECT_EQ(2u, active_layer_->tilings()->num_tilings()); // The tilings are still our target scale, so they aren't removed. used_tilings.clear(); @@ -989,9 +987,9 @@ host_impl_.PinchGestureEnd(); // Create a 1.2 scale tiling. Now we have 1.0 and 1.2 tilings. Ideal = 1.2. - scale /= 4.f; - page_scale /= 4.f; - SetContentsScaleOnBothLayers(1.2f, device_scale, page_scale, 1.f, false); + scale = 1.2f; + page_scale = 1.2f; + SetContentsScaleOnBothLayers(1.2f, 1.f, page_scale, 1.f, false); ASSERT_EQ(4u, active_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ( 1.f, @@ -1008,7 +1006,7 @@ ASSERT_EQ(4u, active_layer_->tilings()->num_tilings()); // Now move the ideal scale to 0.5. Our target stays 1.2. - SetContentsScaleOnBothLayers(0.5f, device_scale, page_scale, 1.f, false); + SetContentsScaleOnBothLayers(0.5f, 1.f, page_scale, 1.f, false); // The high resolution tiling is between target and ideal, so is not // removed. The low res tiling for the old ideal=1.0 scale is removed. @@ -1017,7 +1015,7 @@ ASSERT_EQ(3u, active_layer_->tilings()->num_tilings()); // Now move the ideal scale to 1.0. Our target stays 1.2. - SetContentsScaleOnBothLayers(1.f, device_scale, page_scale, 1.f, false); + SetContentsScaleOnBothLayers(1.f, 1.f, page_scale, 1.f, false); // All the tilings are between are target and the ideal, so they are not // removed. @@ -1026,8 +1024,8 @@ ASSERT_EQ(3u, active_layer_->tilings()->num_tilings()); // Now move the ideal scale to 1.1 on the active layer. Our target stays 1.2. - SetupDrawPropertiesAndUpdateTiles( - active_layer_, 1.1f, device_scale, page_scale, 1.f, false); + SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.1f, 1.f, page_scale, 1.f, + false); // Because the pending layer's ideal scale is still 1.0, our tilings fall // in the range [1.0,1.2] and are kept. @@ -1037,8 +1035,8 @@ // Move the ideal scale on the pending layer to 1.1 as well. Our target stays // 1.2 still. - SetupDrawPropertiesAndUpdateTiles( - pending_layer_, 1.1f, device_scale, page_scale, 1.f, false); + SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.1f, 1.f, page_scale, 1.f, + false); // Our 1.0 tiling now falls outside the range between our ideal scale and our // target raster scale. But it is in our used tilings set, so nothing is @@ -1055,26 +1053,13 @@ ASSERT_EQ(2u, active_layer_->tilings()->num_tilings()); } -#define EXPECT_BOTH_EQ(expression, x) \ - do { \ - EXPECT_EQ(x, pending_layer_->expression); \ - EXPECT_EQ(x, active_layer_->expression); \ - } while (false) - -#define EXPECT_BOTH_NE(expression, x) \ - do { \ - EXPECT_NE(x, pending_layer_->expression); \ - EXPECT_NE(x, active_layer_->expression); \ - } while (false) - TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) { // Make sure this layer covers multiple tiles, since otherwise low // res won't get created because it is too small. gfx::Size tile_size(host_impl_.settings().default_tile_size); - SetupDefaultTrees(gfx::Size(tile_size.width() + 1, tile_size.height() + 1)); // Avoid max untiled layer size heuristics via fixed tile size. - pending_layer_->set_fixed_tile_size(tile_size); - active_layer_->set_fixed_tile_size(tile_size); + gfx::Size layer_bounds(tile_size.width() + 1, tile_size.height() + 1); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region()); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; float contents_scale = 1.f; @@ -1083,6 +1068,8 @@ float maximum_animation_scale = 1.f; bool animating_transform = true; + ResetTilingsAndRasterScales(); + // Animating, so don't create low res even if there isn't one already. SetContentsScaleOnBothLayers(contents_scale, device_scale, @@ -1104,7 +1091,8 @@ EXPECT_BOTH_EQ(num_tilings(), 2u); // Page scale animation, new high res, but no low res. We still have - // a tiling at the previous scale, it's just not marked as low res. + // a tiling at the previous scale, it's just not marked as low res on the + // active layer. The pending layer drops non-ideal tilings. contents_scale = 2.f; page_scale = 2.f; maximum_animation_scale = 2.f; @@ -1117,7 +1105,8 @@ EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); EXPECT_FALSE(active_layer_->LowResTiling()); EXPECT_FALSE(pending_layer_->LowResTiling()); - EXPECT_BOTH_EQ(num_tilings(), 3u); + EXPECT_EQ(3u, active_layer_->num_tilings()); + EXPECT_EQ(1u, pending_layer_->num_tilings()); // Stop animating, new low res gets created for final page scale. animating_transform = false; @@ -1128,7 +1117,8 @@ animating_transform); EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 2.f); EXPECT_BOTH_EQ(LowResTiling()->contents_scale(), 2.f * low_res_factor); - EXPECT_BOTH_EQ(num_tilings(), 4u); + EXPECT_EQ(4u, active_layer_->num_tilings()); + EXPECT_EQ(2u, pending_layer_->num_tilings()); } TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) { @@ -1185,120 +1175,187 @@ contents_scale * low_res_factor); EXPECT_BOTH_EQ(num_tilings(), 2u); - ResetTilingsAndRasterScales(); - // Mask layers dont create low res since they always fit on one tile. - pending_layer_->set_is_mask(true); - active_layer_->set_is_mask(true); - SetContentsScaleOnBothLayers(contents_scale, - device_scale, - page_scale, - maximum_animation_scale, - animating_transform); - EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), contents_scale); - EXPECT_BOTH_EQ(num_tilings(), 1u); + scoped_ptr<FakePictureLayerImpl> mask = + FakePictureLayerImpl::CreateMaskWithRasterSource( + host_impl_.pending_tree(), 3, pending_pile); + mask->SetBounds(layer_bounds); + mask->SetContentBounds(layer_bounds); + mask->SetDrawsContent(true); + + SetupDrawPropertiesAndUpdateTiles(mask.get(), contents_scale, device_scale, + page_scale, maximum_animation_scale, + animating_transform); + EXPECT_EQ(mask->HighResTiling()->contents_scale(), contents_scale); + EXPECT_EQ(mask->num_tilings(), 1u); } TEST_F(PictureLayerImplTest, HugeMasksDontGetTiles) { + base::TimeTicks time_ticks; + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(1000, 1000); scoped_refptr<FakePicturePileImpl> valid_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1000, 1000)); + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupPendingTree(valid_pile); - pending_layer_->set_is_mask(true); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false); - EXPECT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale()); - EXPECT_EQ(1u, pending_layer_->num_tilings()); + scoped_ptr<FakePictureLayerImpl> mask_ptr = + FakePictureLayerImpl::CreateMaskWithRasterSource( + host_impl_.pending_tree(), 3, valid_pile); + mask_ptr->SetBounds(layer_bounds); + mask_ptr->SetContentBounds(layer_bounds); + mask_ptr->SetDrawsContent(true); + pending_layer_->SetMaskLayer(mask_ptr.Pass()); - pending_layer_->HighResTiling()->CreateAllTilesForTesting(); + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.pending_tree()->UpdateDrawProperties(); + + FakePictureLayerImpl* pending_mask = + static_cast<FakePictureLayerImpl*>(pending_layer_->mask_layer()); + + EXPECT_EQ(1.f, pending_mask->HighResTiling()->contents_scale()); + EXPECT_EQ(1u, pending_mask->num_tilings()); + host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting( - pending_layer_->HighResTiling()->AllTilesForTesting()); + pending_mask->HighResTiling()->AllTilesForTesting()); ActivateTree(); + FakePictureLayerImpl* active_mask = + static_cast<FakePictureLayerImpl*>(active_layer_->mask_layer()); + // Mask layers have a tiling with a single tile in it. - EXPECT_EQ(1u, active_layer_->HighResTiling()->AllTilesForTesting().size()); + EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size()); // The mask resource exists. ResourceProvider::ResourceId mask_resource_id; gfx::Size mask_texture_size; - active_layer_->GetContentsResourceId(&mask_resource_id, &mask_texture_size); + active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size); + EXPECT_NE(0u, mask_resource_id); + EXPECT_EQ(mask_texture_size, active_mask->bounds()); + + // Drop resources and recreate them, still the same. + pending_mask->ReleaseResources(); + active_mask->ReleaseResources(); + SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, false); + active_mask->HighResTiling()->CreateAllTilesForTesting(); + EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size()); EXPECT_NE(0u, mask_resource_id); EXPECT_EQ(mask_texture_size, active_layer_->bounds()); // Drop resources and recreate them, still the same. - old_pending_layer_->ReleaseResources(); - active_layer_->ReleaseResources(); - SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false); - active_layer_->HighResTiling()->CreateAllTilesForTesting(); - EXPECT_EQ(1u, active_layer_->HighResTiling()->AllTilesForTesting().size()); + pending_mask->ReleaseResources(); + active_mask->ReleaseResources(); + SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, false); + active_mask->HighResTiling()->CreateAllTilesForTesting(); + EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size()); EXPECT_NE(0u, mask_resource_id); - EXPECT_EQ(mask_texture_size, active_layer_->bounds()); + EXPECT_EQ(mask_texture_size, active_mask->bounds()); // Resize larger than the max texture size. int max_texture_size = host_impl_.GetRendererCapabilities().max_texture_size; + gfx::Size huge_bounds(max_texture_size + 1, 10); scoped_refptr<FakePicturePileImpl> huge_pile = - FakePicturePileImpl::CreateFilledPile( - tile_size, gfx::Size(max_texture_size + 1, 10)); + FakePicturePileImpl::CreateFilledPile(tile_size, huge_bounds); + SetupPendingTree(huge_pile); - pending_layer_->set_is_mask(true); + pending_mask->SetBounds(huge_bounds); + pending_mask->SetContentBounds(huge_bounds); + pending_mask->SetRasterSourceOnPending(huge_pile, Region()); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false); - EXPECT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale()); - EXPECT_EQ(1u, pending_layer_->num_tilings()); + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.pending_tree()->UpdateDrawProperties(); - pending_layer_->HighResTiling()->CreateAllTilesForTesting(); + EXPECT_EQ(1.f, pending_mask->HighResTiling()->contents_scale()); + EXPECT_EQ(1u, pending_mask->num_tilings()); + host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting( - pending_layer_->HighResTiling()->AllTilesForTesting()); + pending_mask->HighResTiling()->AllTilesForTesting()); ActivateTree(); // Mask layers have a tiling, but there should be no tiles in it. - EXPECT_EQ(0u, active_layer_->HighResTiling()->AllTilesForTesting().size()); + EXPECT_EQ(0u, active_mask->HighResTiling()->AllTilesForTesting().size()); // The mask resource is empty. active_layer_->GetContentsResourceId(&mask_resource_id, &mask_texture_size); EXPECT_EQ(0u, mask_resource_id); // Drop resources and recreate them, still the same. - old_pending_layer_->ReleaseResources(); - active_layer_->ReleaseResources(); - SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false); - active_layer_->HighResTiling()->CreateAllTilesForTesting(); - EXPECT_EQ(0u, active_layer_->HighResTiling()->AllTilesForTesting().size()); + pending_mask->ReleaseResources(); + active_mask->ReleaseResources(); + SetupDrawPropertiesAndUpdateTiles(active_mask, 1.f, 1.f, 1.f, 1.f, false); + active_mask->HighResTiling()->CreateAllTilesForTesting(); + EXPECT_EQ(0u, active_mask->HighResTiling()->AllTilesForTesting().size()); + active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size); + EXPECT_EQ(0u, mask_resource_id); + + // Do another activate, the same holds. + SetupPendingTree(huge_pile); + ActivateTree(); + EXPECT_EQ(0u, active_mask->HighResTiling()->AllTilesForTesting().size()); active_layer_->GetContentsResourceId(&mask_resource_id, &mask_texture_size); EXPECT_EQ(0u, mask_resource_id); } TEST_F(PictureLayerImplTest, ScaledMaskLayer) { + base::TimeTicks time_ticks; + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(1000, 1000); + + host_impl_.SetDeviceScaleFactor(1.3f); scoped_refptr<FakePicturePileImpl> valid_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1000, 1000)); + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupPendingTree(valid_pile); - pending_layer_->set_is_mask(true); - float ideal_contents_scale = 1.3f; - SetupDrawPropertiesAndUpdateTiles( - pending_layer_, ideal_contents_scale, 1.f, 1.f, 1.f, false); - EXPECT_EQ(ideal_contents_scale, - pending_layer_->HighResTiling()->contents_scale()); - EXPECT_EQ(1u, pending_layer_->num_tilings()); + scoped_ptr<FakePictureLayerImpl> mask_ptr = + FakePictureLayerImpl::CreateMaskWithRasterSource( + host_impl_.pending_tree(), 3, valid_pile); + mask_ptr->SetBounds(layer_bounds); + mask_ptr->SetContentBounds(layer_bounds); + mask_ptr->SetDrawsContent(true); + pending_layer_->SetMaskLayer(mask_ptr.Pass()); - pending_layer_->HighResTiling()->CreateAllTilesForTesting(); + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.pending_tree()->UpdateDrawProperties(); + + FakePictureLayerImpl* pending_mask = + static_cast<FakePictureLayerImpl*>(pending_layer_->mask_layer()); + + // Masks are scaled, and do not have a low res tiling. + EXPECT_EQ(1.3f, pending_mask->HighResTiling()->contents_scale()); + EXPECT_EQ(1u, pending_mask->num_tilings()); + host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting( - pending_layer_->HighResTiling()->AllTilesForTesting()); + pending_mask->HighResTiling()->AllTilesForTesting()); ActivateTree(); + FakePictureLayerImpl* active_mask = + static_cast<FakePictureLayerImpl*>(active_layer_->mask_layer()); + // Mask layers have a tiling with a single tile in it. - EXPECT_EQ(1u, active_layer_->HighResTiling()->AllTilesForTesting().size()); + EXPECT_EQ(1u, active_mask->HighResTiling()->AllTilesForTesting().size()); // The mask resource exists. ResourceProvider::ResourceId mask_resource_id; gfx::Size mask_texture_size; - active_layer_->GetContentsResourceId(&mask_resource_id, &mask_texture_size); + active_mask->GetContentsResourceId(&mask_resource_id, &mask_texture_size); EXPECT_NE(0u, mask_resource_id); - gfx::Size expected_mask_texture_size = gfx::ToCeiledSize( - gfx::ScaleSize(active_layer_->bounds(), ideal_contents_scale)); + gfx::Size expected_mask_texture_size = + gfx::ToCeiledSize(gfx::ScaleSize(active_mask->bounds(), 1.3f)); EXPECT_EQ(mask_texture_size, expected_mask_texture_size); } @@ -1312,14 +1369,6 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); - - SetupDrawPropertiesAndUpdateTiles(pending_layer_, - 1.3f, // ideal contents scale - 2.7f, // device scale - 3.2f, // page scale - 1.f, // maximum animation scale - false); EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings()); // All tilings should be removed when losing output surface. @@ -1330,10 +1379,10 @@ // This should create new tilings. SetupDrawPropertiesAndUpdateTiles(pending_layer_, - 1.3f, // ideal contents scale - 2.7f, // device scale - 3.2f, // page scale - 1.f, // maximum animation scale + 1.f, // ideal contents scale + 1.f, // device scale + 1.f, // page scale + 1.f, // maximum animation scale false); EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings()); } @@ -1349,10 +1398,7 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); - - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false); - ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); + EXPECT_GE(pending_layer_->tilings()->num_tilings(), 1u); pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting(); @@ -1364,7 +1410,7 @@ EXPECT_EQ(gfx::Size(256, 256).ToString(), tile->content_rect().size().ToString()); - pending_layer_->ReleaseResources(); + ResetTilingsAndRasterScales(); // Change the max texture size on the output surface context. scoped_ptr<TestWebGraphicsContext3D> context = @@ -1396,10 +1442,7 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); - - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false); - ASSERT_LE(1u, pending_layer_->tilings()->num_tilings()); + EXPECT_GE(pending_layer_->tilings()->num_tilings(), 1u); pending_layer_->tilings()->tiling_at(0)->CreateAllTilesForTesting(); @@ -1411,7 +1454,7 @@ PictureLayerTiling* high_res_tiling = pending_layer_->tilings()->tiling_at(0); EXPECT_EQ(1u, high_res_tiling->AllTilesForTesting().size()); - pending_layer_->ReleaseResources(); + ResetTilingsAndRasterScales(); // Change the max texture size on the output surface context. scoped_ptr<TestWebGraphicsContext3D> context = @@ -1448,15 +1491,12 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); + gfx::Rect layer_invalidation(150, 200, 30, 180); + SetupTreesWithInvalidation(pending_pile, active_pile, layer_invalidation); active_layer_->draw_properties().visible_content_rect = gfx::Rect(layer_bounds); - gfx::Rect layer_invalidation(150, 200, 30, 180); - Region invalidation(layer_invalidation); - AddDefaultTilingsWithInvalidation(invalidation); - AppendQuadsData data; active_layer_->WillDraw(DRAW_MODE_RESOURCELESS_SOFTWARE, nullptr); active_layer_->AppendQuads(render_pass.get(), Occlusion(), &data); @@ -1514,33 +1554,20 @@ pending_pile->set_is_solid_color(false); active_pile->set_is_solid_color(true); SetupTrees(pending_pile, active_pile); - // Solid color layer should not have tilings. - ASSERT_FALSE(active_layer_->CanHaveTilings()); - - // Update properties with solid color pile should not allow tilings at any - // scale. - host_impl_.active_tree()->UpdateDrawProperties(); + // Solid color pile should not allow tilings at any scale. EXPECT_FALSE(active_layer_->CanHaveTilings()); EXPECT_EQ(0.f, active_layer_->ideal_contents_scale()); - // Push non-solid-color pending pile makes active layer can have tilings. - active_layer_->UpdateRasterSource(pending_pile); - ASSERT_TRUE(active_layer_->CanHaveTilings()); - - // Update properties with non-solid color pile should allow tilings. - host_impl_.active_tree()->UpdateDrawProperties(); + // Activate non-solid-color pending pile makes active layer can have tilings. + ActivateTree(); EXPECT_TRUE(active_layer_->CanHaveTilings()); EXPECT_GT(active_layer_->ideal_contents_scale(), 0.f); } -TEST_F(PictureLayerImplTest, MarkRequiredOffscreenTiles) { +TEST_F(NoLowResPictureLayerImplTest, MarkRequiredOffscreenTiles) { gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); - scoped_refptr<FakePicturePileImpl> pending_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); - gfx::Transform transform; gfx::Transform transform_for_tile_priority; bool resourceless_software_draw = false; @@ -1552,10 +1579,11 @@ transform, resourceless_software_draw); - pending_layer_->set_fixed_tile_size(tile_size); - ASSERT_TRUE(pending_layer_->CanHaveTilings()); - PictureLayerTiling* tiling = pending_layer_->AddTiling(1.f); - host_impl_.pending_tree()->UpdateDrawProperties(); + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); + + EXPECT_EQ(1u, pending_layer_->num_tilings()); EXPECT_EQ(viewport, pending_layer_->visible_rect_for_tile_priority()); base::TimeTicks time_ticks; @@ -1563,13 +1591,13 @@ host_impl_.SetCurrentBeginFrameArgs( CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); pending_layer_->UpdateTiles(Occlusion(), resourceless_software_draw); - EXPECT_EQ(HIGH_RESOLUTION, tiling->resolution()); int num_visible = 0; int num_offscreen = 0; - for (PictureLayerTiling::TilingRasterTileIterator iter(tiling); iter; - ++iter) { + for (PictureLayerTiling::TilingRasterTileIterator iter( + pending_layer_->HighResTiling()); + iter; ++iter) { const Tile* tile = *iter; DCHECK(tile); if (tile->priority(PENDING_TREE).distance_to_visible == 0.f) { @@ -1585,7 +1613,8 @@ EXPECT_GT(num_offscreen, 0); } -TEST_F(PictureLayerImplTest, TileOutsideOfViewportForTilePriorityNotRequired) { +TEST_F(NoLowResPictureLayerImplTest, + TileOutsideOfViewportForTilePriorityNotRequired) { base::TimeTicks time_ticks; time_ticks += base::TimeDelta::FromMilliseconds(1); host_impl_.SetCurrentBeginFrameArgs( @@ -1600,12 +1629,10 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); + SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region()); - active_layer_->set_fixed_tile_size(tile_size); - pending_layer_->set_fixed_tile_size(tile_size); - ASSERT_TRUE(pending_layer_->CanHaveTilings()); - PictureLayerTiling* tiling = pending_layer_->AddTiling(1.f); + ASSERT_EQ(1u, pending_layer_->num_tilings()); + ASSERT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale()); // Set external viewport for tile priority. gfx::Rect viewport = gfx::Rect(layer_bounds); @@ -1618,6 +1645,9 @@ external_viewport_for_tile_priority, transform_for_tile_priority, resourceless_software_draw); + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); host_impl_.pending_tree()->UpdateDrawProperties(); // Set visible content rect that is different from @@ -1637,9 +1667,8 @@ int num_inside = 0; int num_outside = 0; for (PictureLayerTiling::CoverageIterator iter( - tiling, pending_layer_->contents_scale_x(), gfx::Rect(layer_bounds)); - iter; - ++iter) { + pending_layer_->HighResTiling(), 1.f, gfx::Rect(layer_bounds)); + iter; ++iter) { if (!*iter) continue; Tile* tile = *iter; @@ -1683,16 +1712,13 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); - host_impl_.SetViewportSize(layer_bounds); - scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); + + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); ActivateTree(); // All high res tiles have resources. - active_layer_->set_fixed_tile_size(tile_size); - host_impl_.active_tree()->UpdateDrawProperties(); std::vector<Tile*> tiles = active_layer_->tilings()->tiling_at(0)->AllTilesForTesting(); host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles); @@ -1719,16 +1745,11 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); - host_impl_.SetViewportSize(layer_bounds); - scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); ActivateTree(); - active_layer_->set_fixed_tile_size(tile_size); - host_impl_.active_tree()->UpdateDrawProperties(); - scoped_ptr<RenderPass> render_pass = RenderPass::Create(); AppendQuadsData data; active_layer_->WillDraw(DRAW_MODE_SOFTWARE, nullptr); @@ -1750,15 +1771,11 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); - host_impl_.SetViewportSize(layer_bounds); - scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); ActivateTree(); - active_layer_->set_fixed_tile_size(tile_size); - host_impl_.active_tree()->UpdateDrawProperties(); std::vector<Tile*> low_tiles = active_layer_->tilings()->tiling_at(1)->AllTilesForTesting(); host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(low_tiles); @@ -1784,16 +1801,12 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); - host_impl_.SetViewportSize(layer_bounds); - scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); ActivateTree(); // All high res tiles have resources except one. - active_layer_->set_fixed_tile_size(tile_size); - host_impl_.active_tree()->UpdateDrawProperties(); std::vector<Tile*> high_tiles = active_layer_->tilings()->tiling_at(0)->AllTilesForTesting(); high_tiles.erase(high_tiles.begin()); @@ -1826,20 +1839,16 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(200, 200); + gfx::Size viewport_size(400, 400); - host_impl_.SetViewportSize(layer_bounds); + host_impl_.SetViewportSize(viewport_size); + host_impl_.SetDeviceScaleFactor(2.f); scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); - - active_layer_->set_fixed_tile_size(tile_size); - - active_layer_->draw_properties().visible_content_rect = - gfx::Rect(layer_bounds); - SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.f, 1.f, 1.f, 1.f, false); + SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region()); // One ideal tile exists, this will get used when drawing. std::vector<Tile*> ideal_tiles; @@ -1891,14 +1900,9 @@ gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - // No tiles shared. - pending_layer_->set_invalidation(gfx::Rect(layer_bounds)); - - CreateHighLowResAndSetAllTilesVisible(); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, + gfx::Rect(layer_bounds)); active_layer_->SetAllTilesReady(); @@ -1915,12 +1919,8 @@ gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - // All tiles shared (no invalidation). - CreateHighLowResAndSetAllTilesVisible(); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region()); // Verify active tree not ready. Tile* some_active_tile = @@ -1942,11 +1942,7 @@ gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - - CreateHighLowResAndSetAllTilesVisible(); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region()); Tile* some_active_tile = active_layer_->HighResTiling()->AllTilesForTesting()[0]; @@ -1964,9 +1960,8 @@ TEST_F(PictureLayerImplTest, DisallowRequiredForActivation) { gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - CreateHighLowResAndSetAllTilesVisible(); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region()); Tile* some_active_tile = active_layer_->HighResTiling()->AllTilesForTesting()[0]; @@ -1986,6 +1981,7 @@ TEST_F(PictureLayerImplTest, NothingRequiredIfActiveMissingTiles) { gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); + scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); // This pile will create tilings, but has no recordings so will not create any @@ -1995,11 +1991,8 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings( tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); - pending_layer_->set_fixed_tile_size(tile_size); - active_layer_->set_fixed_tile_size(tile_size); - CreateHighLowResAndSetAllTilesVisible(); + SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region()); // Active layer has tilings, but no tiles due to missing recordings. EXPECT_TRUE(active_layer_->CanHaveTilings()); @@ -2019,17 +2012,11 @@ gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); - host_impl_.SetViewportSize(layer_bounds); - scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateEmptyPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); - pending_layer_->set_fixed_tile_size(tile_size); - active_layer_->set_fixed_tile_size(tile_size); - - CreateHighLowResAndSetAllTilesVisible(); + SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region()); // Active layer can't have tiles. EXPECT_FALSE(active_layer_->CanHaveTilings()); @@ -2046,21 +2033,16 @@ } TEST_F(PictureLayerImplTest, HighResRequiredWhenActiveHasDifferentBounds) { - gfx::Size layer_bounds(200, 200); - gfx::Size tile_size(100, 100); - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - gfx::Size pending_layer_bounds(400, 400); - pending_layer_->SetBounds(pending_layer_bounds); + gfx::Size active_layer_bounds(200, 200); + gfx::Size tile_size(100, 100); - CreateHighLowResAndSetAllTilesVisible(); - // TODO(vmpstr): This is confusing. Rework the test to create different bounds - // on different trees instead of fudging tilings. - pending_layer_->HighResTiling()->ComputeTilePriorityRects( - gfx::Rect(pending_layer_bounds), 1.f, 1.f, Occlusion()); + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, pending_layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, active_layer_bounds); - pending_layer_->HighResTiling()->UpdateAllTilePrioritiesForTesting(); - active_layer_->SetAllTilesReady(); + SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region()); // Since the active layer has different bounds, the pending layer needs all // high res tiles in order to activate. @@ -2108,9 +2090,15 @@ } TEST_F(PictureLayerImplTest, ShareTilesOnNextFrame) { - SetupDefaultTrees(gfx::Size(1500, 1500)); + gfx::Size layer_bounds(1500, 1500); + gfx::Size tile_size(100, 100); - PictureLayerTiling* tiling = pending_layer_->AddTiling(1.f); + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + + SetupPendingTree(pending_pile); + + PictureLayerTiling* tiling = pending_layer_->HighResTiling(); gfx::Rect first_invalidate = tiling->TilingDataForTesting().TileBounds(0, 0); first_invalidate.Inset(tiling->TilingDataForTesting().border_texels(), tiling->TilingDataForTesting().border_texels()); @@ -2118,22 +2106,20 @@ second_invalidate.Inset(tiling->TilingDataForTesting().border_texels(), tiling->TilingDataForTesting().border_texels()); + ActivateTree(); + // Make a pending tree with an invalidated raster tile 0,0. - tiling->CreateAllTilesForTesting(); - pending_layer_->set_invalidation(first_invalidate); + SetupPendingTreeWithInvalidation(pending_pile, first_invalidate); // Activate and make a pending tree with an invalidated raster tile 1,1. ActivateTree(); - host_impl_.CreatePendingTree(); - pending_layer_ = static_cast<FakePictureLayerImpl*>( - host_impl_.pending_tree()->root_layer()); - pending_layer_->set_invalidation(second_invalidate); + SetupPendingTreeWithInvalidation(pending_pile, second_invalidate); PictureLayerTiling* pending_tiling = pending_layer_->tilings()->tiling_at(0); PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(0); - pending_tiling->CreateAllTilesForTesting(); + // pending_tiling->CreateAllTilesForTesting(); // Tile 0,0 should be shared, but tile 1,1 should not be. EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0)); @@ -2162,180 +2148,138 @@ EXPECT_FALSE(pending_tiling->TileAt(1, 1)->is_shared()); } -TEST_F(PictureLayerImplTest, ShareTilesOnSync) { +TEST_F(PictureLayerImplTest, ShareTilesWithNoInvalidation) { SetupDefaultTrees(gfx::Size(1500, 1500)); - AddDefaultTilingsWithInvalidation(gfx::Rect()); - host_impl_.ActivateSyncTree(); - host_impl_.CreatePendingTree(); - active_layer_ = static_cast<FakePictureLayerImpl*>( - host_impl_.active_tree()->LayerById(id_)); + EXPECT_GE(active_layer_->num_tilings(), 1u); + EXPECT_GE(pending_layer_->num_tilings(), 1u); - // Force the active tree to sync to the pending tree "post-commit". - pending_layer_->DoPostCommitInitializationIfNeeded(); + // No invalidation, so all tiles are shared. + PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(0); + PictureLayerTiling* pending_tiling = pending_layer_->tilings()->tiling_at(0); + ASSERT_TRUE(active_tiling); + ASSERT_TRUE(pending_tiling); - // Both invalidations should drop tiles from the pending tree. - EXPECT_EQ(3u, active_layer_->num_tilings()); - EXPECT_EQ(3u, pending_layer_->num_tilings()); - for (size_t i = 0; i < active_layer_->num_tilings(); ++i) { - PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i); - PictureLayerTiling* pending_tiling = - pending_layer_->tilings()->tiling_at(i); + EXPECT_TRUE(active_tiling->TileAt(0, 0)); + EXPECT_TRUE(active_tiling->TileAt(1, 0)); + EXPECT_TRUE(active_tiling->TileAt(0, 1)); + EXPECT_TRUE(active_tiling->TileAt(1, 1)); - ASSERT_TRUE(active_tiling); - ASSERT_TRUE(pending_tiling); + EXPECT_TRUE(pending_tiling->TileAt(0, 0)); + EXPECT_TRUE(pending_tiling->TileAt(1, 0)); + EXPECT_TRUE(pending_tiling->TileAt(0, 1)); + EXPECT_TRUE(pending_tiling->TileAt(1, 1)); - EXPECT_TRUE(active_tiling->TileAt(0, 0)); - EXPECT_TRUE(active_tiling->TileAt(1, 0)); - EXPECT_TRUE(active_tiling->TileAt(0, 1)); - EXPECT_TRUE(active_tiling->TileAt(1, 1)); - - EXPECT_TRUE(pending_tiling->TileAt(0, 0)); - EXPECT_TRUE(pending_tiling->TileAt(1, 0)); - EXPECT_TRUE(pending_tiling->TileAt(0, 1)); - EXPECT_TRUE(pending_tiling->TileAt(1, 1)); - - EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0)); - EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0)); - EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1)); - EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1)); - EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); - } + EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0)); + EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0)); + EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1)); + EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1)); + EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); } -TEST_F(PictureLayerImplTest, ShareInvalidActiveTreeTilesOnSync) { - SetupDefaultTrees(gfx::Size(1500, 1500)); - AddDefaultTilingsWithInvalidation(gfx::Rect(0, 0, 1, 1)); +TEST_F(PictureLayerImplTest, ShareInvalidActiveTreeTiles) { + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(1500, 1500); - // This activates the 0,0,1,1 invalidation. - host_impl_.ActivateSyncTree(); - host_impl_.CreatePendingTree(); - active_layer_ = static_cast<FakePictureLayerImpl*>( - host_impl_.active_tree()->LayerById(id_)); + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + SetupTreesWithInvalidation(pending_pile, active_pile, gfx::Rect(1, 1)); + // Activate the invalidation. + ActivateTree(); + // Make another pending tree without any invalidation in it. + scoped_refptr<FakePicturePileImpl> pending_pile2 = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + SetupPendingTree(pending_pile2); - // Force the active tree to sync to the pending tree "post-commit". - pending_layer_->DoPostCommitInitializationIfNeeded(); + EXPECT_GE(active_layer_->num_tilings(), 1u); + EXPECT_GE(pending_layer_->num_tilings(), 1u); // The active tree invalidation was handled by the active tiles, so they // can be shared with the pending tree. - EXPECT_EQ(3u, active_layer_->num_tilings()); - EXPECT_EQ(3u, pending_layer_->num_tilings()); - for (size_t i = 0; i < active_layer_->num_tilings(); ++i) { - PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i); - PictureLayerTiling* pending_tiling = - pending_layer_->tilings()->tiling_at(i); + PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(0); + PictureLayerTiling* pending_tiling = pending_layer_->tilings()->tiling_at(0); + ASSERT_TRUE(active_tiling); + ASSERT_TRUE(pending_tiling); - ASSERT_TRUE(active_tiling); - ASSERT_TRUE(pending_tiling); + EXPECT_TRUE(active_tiling->TileAt(0, 0)); + EXPECT_TRUE(active_tiling->TileAt(1, 0)); + EXPECT_TRUE(active_tiling->TileAt(0, 1)); + EXPECT_TRUE(active_tiling->TileAt(1, 1)); - EXPECT_TRUE(active_tiling->TileAt(0, 0)); - EXPECT_TRUE(active_tiling->TileAt(1, 0)); - EXPECT_TRUE(active_tiling->TileAt(0, 1)); - EXPECT_TRUE(active_tiling->TileAt(1, 1)); + EXPECT_TRUE(pending_tiling->TileAt(0, 0)); + EXPECT_TRUE(pending_tiling->TileAt(1, 0)); + EXPECT_TRUE(pending_tiling->TileAt(0, 1)); + EXPECT_TRUE(pending_tiling->TileAt(1, 1)); - EXPECT_TRUE(pending_tiling->TileAt(0, 0)); - EXPECT_TRUE(pending_tiling->TileAt(1, 0)); - EXPECT_TRUE(pending_tiling->TileAt(0, 1)); - EXPECT_TRUE(pending_tiling->TileAt(1, 1)); - - EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0)); - EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0)); - EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1)); - EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1)); - EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); - } + EXPECT_EQ(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0)); + EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0)); + EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1)); + EXPECT_TRUE(active_tiling->TileAt(0, 1)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1)); + EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); } -TEST_F(PictureLayerImplTest, RemoveInvalidPendingTreeTilesOnSync) { - SetupDefaultTrees(gfx::Size(1500, 1500)); - AddDefaultTilingsWithInvalidation(gfx::Rect()); +TEST_F(PictureLayerImplTest, RecreateInvalidPendingTreeTiles) { + // Set some invalidation on the pending tree. We should replace raster tiles + // that touch this. + SetupDefaultTreesWithInvalidation(gfx::Size(1500, 1500), gfx::Rect(1, 1)); - host_impl_.ActivateSyncTree(); - host_impl_.CreatePendingTree(); - active_layer_ = static_cast<FakePictureLayerImpl*>( - host_impl_.active_tree()->LayerById(id_)); - - // Set some invalidation on the pending tree "during commit". We should - // replace raster tiles that touch this. - pending_layer_->set_invalidation(gfx::Rect(1, 1)); - - // Force the active tree to sync to the pending tree "post-commit". - pending_layer_->DoPostCommitInitializationIfNeeded(); + EXPECT_GE(active_layer_->num_tilings(), 1u); + EXPECT_GE(pending_layer_->num_tilings(), 1u); // The pending tree invalidation means tiles can not be shared with the // active tree. - EXPECT_EQ(3u, active_layer_->num_tilings()); - EXPECT_EQ(3u, pending_layer_->num_tilings()); - for (size_t i = 0; i < active_layer_->num_tilings(); ++i) { - PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(i); - PictureLayerTiling* pending_tiling = - pending_layer_->tilings()->tiling_at(i); + PictureLayerTiling* active_tiling = active_layer_->tilings()->tiling_at(0); + PictureLayerTiling* pending_tiling = pending_layer_->tilings()->tiling_at(0); + ASSERT_TRUE(active_tiling); + ASSERT_TRUE(pending_tiling); - ASSERT_TRUE(active_tiling); - ASSERT_TRUE(pending_tiling); + EXPECT_TRUE(active_tiling->TileAt(0, 0)); + EXPECT_TRUE(active_tiling->TileAt(1, 0)); + EXPECT_TRUE(active_tiling->TileAt(0, 1)); + EXPECT_TRUE(active_tiling->TileAt(1, 1)); - EXPECT_TRUE(active_tiling->TileAt(0, 0)); - EXPECT_TRUE(active_tiling->TileAt(1, 0)); - EXPECT_TRUE(active_tiling->TileAt(0, 1)); - EXPECT_TRUE(active_tiling->TileAt(1, 1)); + EXPECT_TRUE(pending_tiling->TileAt(0, 0)); + EXPECT_TRUE(pending_tiling->TileAt(1, 0)); + EXPECT_TRUE(pending_tiling->TileAt(0, 1)); + EXPECT_TRUE(pending_tiling->TileAt(1, 1)); - EXPECT_TRUE(pending_tiling->TileAt(0, 0)); - EXPECT_TRUE(pending_tiling->TileAt(1, 0)); - EXPECT_TRUE(pending_tiling->TileAt(0, 1)); - EXPECT_TRUE(pending_tiling->TileAt(1, 1)); - - EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0)); - EXPECT_FALSE(active_tiling->TileAt(0, 0)->is_shared()); - EXPECT_FALSE(pending_tiling->TileAt(0, 0)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0)); - EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1)); - EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); - EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1)); - EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); - } -} - -TEST_F(PictureLayerImplTest, SyncTilingAfterReleaseResource) { - SetupDefaultTrees(gfx::Size(10, 10)); - host_impl_.active_tree()->UpdateDrawProperties(); - EXPECT_FALSE(host_impl_.active_tree()->needs_update_draw_properties()); - - // Contrived unit test of a real crash. A layer is transparent during a - // context loss, and later becomes opaque, causing active layer SyncTiling to - // be called. - float new_scale = 1.f; - active_layer_->ReleaseResources(); - pending_layer_->ReleaseResources(); - EXPECT_FALSE(active_layer_->tilings()->FindTilingWithScale(new_scale)); - pending_layer_->AddTiling(new_scale); - EXPECT_TRUE(active_layer_->tilings()->FindTilingWithScale(new_scale)); - - // UpdateDrawProperties early-outs if the tree doesn't need it. It is also - // responsible for calling ManageTilings. These checks verify that - // ReleaseResources has set needs update draw properties so that the - // new tiling gets the appropriate resolution set in ManageTilings. - EXPECT_TRUE(host_impl_.active_tree()->needs_update_draw_properties()); - host_impl_.active_tree()->UpdateDrawProperties(); - PictureLayerTiling* high_res = - active_layer_->tilings()->FindTilingWithScale(new_scale); - ASSERT_TRUE(!!high_res); - EXPECT_EQ(HIGH_RESOLUTION, high_res->resolution()); + EXPECT_NE(active_tiling->TileAt(0, 0), pending_tiling->TileAt(0, 0)); + EXPECT_FALSE(active_tiling->TileAt(0, 0)->is_shared()); + EXPECT_FALSE(pending_tiling->TileAt(0, 0)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(1, 0), pending_tiling->TileAt(1, 0)); + EXPECT_TRUE(active_tiling->TileAt(1, 0)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(0, 1), pending_tiling->TileAt(0, 1)); + EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); + EXPECT_EQ(active_tiling->TileAt(1, 1), pending_tiling->TileAt(1, 1)); + EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); } TEST_F(PictureLayerImplTest, SyncTilingAfterGpuRasterizationToggles) { - SetupDefaultTrees(gfx::Size(10, 10)); + base::TimeTicks time_ticks; + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); - const float kScale = 1.f; - pending_layer_->AddTiling(kScale); - EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(kScale)); - EXPECT_TRUE(active_layer_->tilings()->FindTilingWithScale(kScale)); + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(10, 10); + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + + SetupTrees(pending_pile, active_pile); + + EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.f)); + EXPECT_TRUE(active_layer_->tilings()->FindTilingWithScale(1.f)); // Gpu rasterization is disabled by default. EXPECT_FALSE(host_impl_.use_gpu_rasterization()); @@ -2346,9 +2290,17 @@ // Make sure that we can still add tiling to the pending layer, // that gets synced to the active layer. - pending_layer_->AddTiling(kScale); - EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(kScale)); - EXPECT_TRUE(active_layer_->tilings()->FindTilingWithScale(kScale)); + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.pending_tree()->UpdateDrawProperties(); + EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.f)); + + ActivateTree(); + EXPECT_TRUE(active_layer_->tilings()->FindTilingWithScale(1.f)); + + SetupPendingTree(pending_pile); + EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.f)); // Toggling the gpu rasterization clears all tilings on both trees. EXPECT_TRUE(host_impl_.use_gpu_rasterization()); @@ -2360,50 +2312,49 @@ TEST_F(PictureLayerImplTest, HighResCreatedWhenBoundsShrink) { gfx::Size tile_size(100, 100); - scoped_refptr<FakePicturePileImpl> active_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(10, 10)); - SetupPendingTree(active_pile); - ActivateTree(); - host_impl_.active_tree()->UpdateDrawProperties(); - EXPECT_FALSE(host_impl_.active_tree()->needs_update_draw_properties()); + // Put 0.5 as high res. + host_impl_.SetDeviceScaleFactor(0.5f); - SetupDrawPropertiesAndUpdateTiles( - active_layer_, 0.5f, 0.5f, 0.5f, 0.5f, false); - active_layer_->tilings()->RemoveAllTilings(); - PictureLayerTiling* tiling = active_layer_->AddTiling(0.5f); - active_layer_->AddTiling(1.5f); - active_layer_->AddTiling(0.25f); - tiling->set_resolution(HIGH_RESOLUTION); + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(10, 10)); + SetupPendingTree(pending_pile); // Sanity checks. - ASSERT_EQ(3u, active_layer_->tilings()->num_tilings()); - ASSERT_EQ(tiling, active_layer_->tilings()->FindTilingWithScale(0.5f)); + EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings()); + EXPECT_TRUE(pending_layer_->tilings()->FindTilingWithScale(0.5f)); - // Now, set the bounds to be 1x1 (so that minimum contents scale becomes - // 1.0f). Note that we should also ensure that the pending layer needs post - // commit initialization, since this is what would happen during commit. In - // other words we want the pending layer to sync from the active layer. - scoped_refptr<FakePicturePileImpl> pending_pile = + ActivateTree(); + + // Now, set the bounds to be 1x1, so that minimum contents scale becomes 1. + pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1, 1)); SetupPendingTree(pending_pile); - // Update the draw properties: sync from active tree should happen here. - host_impl_.pending_tree()->UpdateDrawProperties(); - EXPECT_FALSE(pending_layer_->needs_post_commit_initialization()); - // Another sanity check. - ASSERT_EQ(1.f, pending_layer_->MinimumContentsScale()); + EXPECT_EQ(1.f, pending_layer_->MinimumContentsScale()); - // Now we should've synced 1.5f tiling, since that's the only one that doesn't - // violate minimum contents scale. At the same time, we should've created a - // new high res tiling at scale 1.0f. + // Since the MinContentsScale is 1, the 0.5 tiling should be replaced by a 1.0 + // tiling. + SetupDrawPropertiesAndUpdateTiles(pending_layer_, 0.5f, 1.f, 1.f, 1.f, false); + + EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings()); + PictureLayerTiling* tiling = + pending_layer_->tilings()->FindTilingWithScale(1.0f); + ASSERT_TRUE(tiling); + EXPECT_EQ(HIGH_RESOLUTION, tiling->resolution()); +} + +TEST_F(PictureLayerImplTest, LowResTilingWithoutGpuRasterization) { + gfx::Size default_tile_size(host_impl_.settings().default_tile_size); + gfx::Size layer_bounds(default_tile_size.width() * 4, + default_tile_size.height() * 4); + + host_impl_.SetUseGpuRasterization(false); + + SetupDefaultTrees(layer_bounds); + EXPECT_FALSE(host_impl_.use_gpu_rasterization()); + // Should have a low-res and a high-res tiling. EXPECT_EQ(2u, pending_layer_->tilings()->num_tilings()); - ASSERT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.0f)); - EXPECT_EQ(HIGH_RESOLUTION, - pending_layer_->tilings()->FindTilingWithScale(1.0f)->resolution()); - ASSERT_TRUE(pending_layer_->tilings()->FindTilingWithScale(1.5f)); - EXPECT_EQ(NON_IDEAL_RESOLUTION, - pending_layer_->tilings()->FindTilingWithScale(1.5f)->resolution()); } TEST_F(PictureLayerImplTest, NoLowResTilingWithGpuRasterization) { @@ -2411,21 +2362,12 @@ gfx::Size layer_bounds(default_tile_size.width() * 4, default_tile_size.height() * 4); - SetupDefaultTrees(layer_bounds); - EXPECT_FALSE(host_impl_.use_gpu_rasterization()); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false); - // Should have a low-res and a high-res tiling. - ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); - - ResetTilingsAndRasterScales(); - host_impl_.SetUseGpuRasterization(true); - EXPECT_TRUE(host_impl_.use_gpu_rasterization()); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false); + SetupDefaultTrees(layer_bounds); + EXPECT_TRUE(host_impl_.use_gpu_rasterization()); // Should only have the high-res tiling. - ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings()); + EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings()); } TEST_F(PictureLayerImplTest, NoTilingIfDoesNotDrawContent) { @@ -2450,31 +2392,38 @@ TEST_F(PictureLayerImplTest, FirstTilingDuringPinch) { SetupDefaultTrees(gfx::Size(10, 10)); + + // We start with a tiling at scale 1. + EXPECT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale()); + + // When we scale up by 2.3, we get a new tiling that is a power of 2, in this + // case 4. host_impl_.PinchGestureBegin(); float high_res_scale = 2.3f; SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, 1.f, false); - - ASSERT_GE(pending_layer_->num_tilings(), 0u); - EXPECT_FLOAT_EQ(high_res_scale, - pending_layer_->HighResTiling()->contents_scale()); -} - -TEST_F(PictureLayerImplTest, FirstTilingTooSmall) { - SetupDefaultTrees(gfx::Size(10, 10)); - host_impl_.PinchGestureBegin(); - float high_res_scale = 0.0001f; - EXPECT_GT(pending_layer_->MinimumContentsScale(), high_res_scale); - - SetContentsScaleOnBothLayers(high_res_scale, 1.f, 1.f, 1.f, false); - - ASSERT_GE(pending_layer_->num_tilings(), 0u); - EXPECT_FLOAT_EQ(pending_layer_->MinimumContentsScale(), - pending_layer_->HighResTiling()->contents_scale()); + EXPECT_EQ(4.f, pending_layer_->HighResTiling()->contents_scale()); } TEST_F(PictureLayerImplTest, PinchingTooSmall) { SetupDefaultTrees(gfx::Size(10, 10)); + // We start with a tiling at scale 1. + EXPECT_EQ(1.f, pending_layer_->HighResTiling()->contents_scale()); + + host_impl_.PinchGestureBegin(); + float high_res_scale = 0.0001f; + EXPECT_LT(high_res_scale, pending_layer_->MinimumContentsScale()); + + SetContentsScaleOnBothLayers(high_res_scale, 1.f, high_res_scale, 1.f, false); + EXPECT_FLOAT_EQ(pending_layer_->MinimumContentsScale(), + pending_layer_->HighResTiling()->contents_scale()); +} + +TEST_F(PictureLayerImplTest, PinchingTooSmallWithContentsScale) { + SetupDefaultTrees(gfx::Size(10, 10)); + + ResetTilingsAndRasterScales(); + float contents_scale = 0.15f; SetContentsScaleOnBothLayers(contents_scale, 1.f, 1.f, 1.f, false); @@ -2542,22 +2491,18 @@ } TEST_F(PictureLayerImplTest, HighResTilingDuringAnimationForCpuRasterization) { - gfx::Size layer_bounds(100, 100); gfx::Size viewport_size(1000, 1000); - SetupDefaultTrees(layer_bounds); host_impl_.SetViewportSize(viewport_size); + gfx::Size layer_bounds(100, 100); + SetupDefaultTrees(layer_bounds); + float contents_scale = 1.f; - float device_scale = 1.3f; - float page_scale = 1.4f; + float device_scale = 1.f; + float page_scale = 1.f; float maximum_animation_scale = 1.f; bool animating_transform = false; - SetContentsScaleOnBothLayers(contents_scale, - device_scale, - page_scale, - maximum_animation_scale, - animating_transform); EXPECT_BOTH_EQ(HighResTiling()->contents_scale(), 1.f); // Since we're CPU-rasterizing, starting an animation should cause tiling @@ -2781,6 +2726,8 @@ host_impl_.SetCurrentBeginFrameArgs( CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + host_impl_.SetViewportSize(gfx::Size(500, 500)); + gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); @@ -2788,24 +2735,10 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupPendingTree(pending_pile); + EXPECT_EQ(2u, pending_layer_->num_tilings()); - ASSERT_TRUE(pending_layer_->CanHaveTilings()); - - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - - // No tilings. scoped_ptr<TilingSetRasterQueue> queue = pending_layer_->CreateRasterQueue(false); - EXPECT_TRUE(queue->IsEmpty()); - - pending_layer_->AddTiling(low_res_factor); - pending_layer_->AddTiling(0.3f); - pending_layer_->AddTiling(0.7f); - PictureLayerTiling* high_res_tiling = pending_layer_->AddTiling(1.0f); - pending_layer_->AddTiling(2.0f); - - host_impl_.SetViewportSize(gfx::Size(500, 500)); - host_impl_.pending_tree()->UpdateDrawProperties(); std::set<Tile*> unique_tiles; bool reached_prepaint = false; @@ -2883,7 +2816,8 @@ gfx::Rect(0, 0, 500, 500); pending_layer_->UpdateTiles(Occlusion(), resourceless_software_draw); - std::vector<Tile*> high_res_tiles = high_res_tiling->AllTilesForTesting(); + std::vector<Tile*> high_res_tiles = + pending_layer_->HighResTiling()->AllTilesForTesting(); for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin(); tile_it != high_res_tiles.end(); ++tile_it) { @@ -2916,33 +2850,23 @@ TEST_F(PictureLayerImplTest, TilingSetEvictionQueue) { gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + + host_impl_.SetViewportSize(gfx::Size(500, 500)); scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + // TODO(vmpstr): Add a test with tilings other than high/low res on the active + // tree. SetupPendingTree(pending_pile); - - ASSERT_TRUE(pending_layer_->CanHaveTilings()); - - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - - std::vector<PictureLayerTiling*> tilings; - tilings.push_back(pending_layer_->AddTiling(low_res_factor)); - tilings.push_back(pending_layer_->AddTiling(0.3f)); - tilings.push_back(pending_layer_->AddTiling(0.7f)); - tilings.push_back(pending_layer_->AddTiling(1.0f)); - tilings.push_back(pending_layer_->AddTiling(2.0f)); - - host_impl_.SetViewportSize(gfx::Size(500, 500)); - host_impl_.pending_tree()->UpdateDrawProperties(); + EXPECT_EQ(2u, pending_layer_->num_tilings()); std::vector<Tile*> all_tiles; - for (std::vector<PictureLayerTiling*>::iterator tiling_iterator = - tilings.begin(); - tiling_iterator != tilings.end(); - ++tiling_iterator) { - std::vector<Tile*> tiles = (*tiling_iterator)->AllTilesForTesting(); - std::copy(tiles.begin(), tiles.end(), std::back_inserter(all_tiles)); + for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { + PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i); + std::vector<Tile*> tiles = tiling->AllTilesForTesting(); + all_tiles.insert(all_tiles.end(), tiles.begin(), tiles.end()); } std::set<Tile*> all_tiles_set(all_tiles.begin(), all_tiles.end()); @@ -2950,8 +2874,8 @@ bool mark_required = false; size_t number_of_marked_tiles = 0u; size_t number_of_unmarked_tiles = 0u; - for (size_t i = 0; i < tilings.size(); ++i) { - PictureLayerTiling* tiling = tilings.at(i); + for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { + PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i); for (PictureLayerTiling::CoverageIterator iter( tiling, pending_layer_->contents_scale_x(), @@ -2969,8 +2893,8 @@ } // Sanity checks. - EXPECT_EQ(91u, all_tiles.size()); - EXPECT_EQ(91u, all_tiles_set.size()); + EXPECT_EQ(17u, all_tiles.size()); + EXPECT_EQ(17u, all_tiles_set.size()); EXPECT_GT(number_of_marked_tiles, 1u); EXPECT_GT(number_of_unmarked_tiles, 1u); @@ -2982,10 +2906,12 @@ host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles); std::set<Tile*> unique_tiles; - float expected_scales[] = {2.0f, 0.3f, 0.7f, low_res_factor, 1.0f}; + float expected_scales[] = {low_res_factor, 1.f}; size_t scale_index = 0; bool reached_visible = false; Tile* last_tile = nullptr; + size_t distance_decreasing = 0; + size_t distance_increasing = 0; queue = pending_layer_->CreateEvictionQueue(SAME_PRIORITY_FOR_BOTH_TREES); while (!queue->IsEmpty()) { Tile* tile = queue->Top(); @@ -3013,24 +2939,28 @@ EXPECT_FLOAT_EQ(tile->contents_scale(), expected_scales[scale_index]); unique_tiles.insert(tile); - // If the tile is the same rough bin as last tile (same activation, bin, and - // scale), then distance should be decreasing. 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()) { - EXPECT_LE(priority.distance_to_visible, - last_tile->priority(PENDING_TREE).distance_to_visible); + if (priority.distance_to_visible <= + last_tile->priority(PENDING_TREE).distance_to_visible) + ++distance_decreasing; + else + ++distance_increasing; } last_tile = tile; queue->Pop(); } + // 4 high res tiles are inside the viewport, the rest are evicted. EXPECT_TRUE(reached_visible); - EXPECT_EQ(65u, unique_tiles.size()); + EXPECT_EQ(12u, unique_tiles.size()); + EXPECT_EQ(1u, distance_increasing); + EXPECT_EQ(11u, distance_decreasing); scale_index = 0; bool reached_required = false; @@ -3069,16 +2999,12 @@ gfx::Size viewport_size(1000, 1000); LayerTestCommon::LayerImplTest impl; + host_impl_.SetViewportSize(viewport_size); scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(layer_bounds, layer_bounds); - SetupPendingTree(pending_pile); - pending_layer_->SetBounds(layer_bounds); + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); ActivateTree(); - active_layer_->set_fixed_tile_size(tile_size); - - host_impl_.SetViewportSize(viewport_size); - host_impl_.active_tree()->UpdateDrawProperties(); std::vector<Tile*> tiles = active_layer_->HighResTiling()->AllTilesForTesting(); @@ -3121,6 +3047,8 @@ gfx::Size tile_size(host_impl_.settings().default_tile_size); SetupDefaultTrees(tile_size); + ResetTilingsAndRasterScales(); + float contents_scale = 2.f; float device_scale = 1.f; float page_scale = 1.f; @@ -3161,15 +3089,9 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - // Make sure some tiles are not shared. - pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size)); - - CreateHighLowResAndSetAllTilesVisible(); - active_layer_->SetAllTilesReady(); + gfx::Rect invalidation(gfx::Point(50, 50), tile_size); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation); // All pending layer tiles required are not ready. EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); @@ -3190,15 +3112,9 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - // Make sure some tiles are not shared. - pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size)); - - CreateHighLowResAndSetAllTilesVisible(); - active_layer_->SetAllTilesReady(); + gfx::Rect invalidation(gfx::Point(50, 50), tile_size); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation); // All pending layer tiles required are not ready. EXPECT_FALSE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); @@ -3215,14 +3131,9 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - // Make sure some tiles are not shared. - pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size)); - - CreateHighLowResAndSetAllTilesVisible(); + gfx::Rect invalidation(gfx::Point(50, 50), tile_size); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation); // Initialize all high-res tiles in the active layer. active_layer_->SetAllTilesReadyInTiling(active_layer_->HighResTiling()); @@ -3241,14 +3152,9 @@ gfx::Size tile_size(100, 100); gfx::Size layer_bounds(1000, 1000); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - // Make sure some tiles are not shared. - pending_layer_->set_invalidation(gfx::Rect(gfx::Point(50, 50), tile_size)); - - CreateHighLowResAndSetAllTilesVisible(); + gfx::Rect invalidation(gfx::Point(50, 50), tile_size); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, invalidation); // Initialize all high-res tiles in the active layer. active_layer_->SetAllTilesReadyInTiling(active_layer_->HighResTiling()); @@ -3261,12 +3167,6 @@ EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); } -class NoLowResPictureLayerImplTest : public PictureLayerImplTest { - public: - NoLowResPictureLayerImplTest() - : PictureLayerImplTest(NoLowResTilingsSettings()) {} -}; - TEST_F(NoLowResPictureLayerImplTest, ManageTilingsCreatesTilings) { gfx::Size tile_size(400, 400); gfx::Size layer_bounds(1300, 1900); @@ -3277,11 +3177,73 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; EXPECT_LT(low_res_factor, 1.f); + ResetTilingsAndRasterScales(); + + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 6.f, // ideal contents scale + 3.f, // device scale + 2.f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(1u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(6.f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); + + // If we change the page scale factor, then we should get new tilings. + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 6.6f, // ideal contents scale + 3.f, // device scale + 2.2f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(2u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(6.6f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); + + // If we change the device scale factor, then we should get new tilings. + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 7.26f, // ideal contents scale + 3.3f, // device scale + 2.2f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(3u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(7.26f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); + + // If we change the device scale factor, but end up at the same total scale + // factor somehow, then we don't get new tilings. + SetupDrawPropertiesAndUpdateTiles(active_layer_, + 7.26f, // ideal contents scale + 2.2f, // device scale + 3.3f, // page scale + 1.f, // maximum animation scale + false); + ASSERT_EQ(3u, active_layer_->tilings()->num_tilings()); + EXPECT_FLOAT_EQ(7.26f, + active_layer_->tilings()->tiling_at(0)->contents_scale()); +} + +TEST_F(NoLowResPictureLayerImplTest, PendingLayerOnlyHasHighResTiling) { + gfx::Size tile_size(400, 400); + gfx::Size layer_bounds(1300, 1900); + + scoped_refptr<FakePicturePileImpl> pending_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<FakePicturePileImpl> active_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + + SetupTrees(pending_pile, active_pile); + + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + EXPECT_LT(low_res_factor, 1.f); + + ResetTilingsAndRasterScales(); + SetupDrawPropertiesAndUpdateTiles(pending_layer_, 6.f, // ideal contents scale 3.f, // device scale @@ -3299,7 +3261,7 @@ 2.2f, // page scale 1.f, // maximum animation scale false); - ASSERT_EQ(2u, pending_layer_->tilings()->num_tilings()); + ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(6.6f, pending_layer_->tilings()->tiling_at(0)->contents_scale()); @@ -3310,7 +3272,7 @@ 2.2f, // page scale 1.f, // maximum animation scale false); - ASSERT_EQ(3u, pending_layer_->tilings()->num_tilings()); + ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(7.26f, pending_layer_->tilings()->tiling_at(0)->contents_scale()); @@ -3322,7 +3284,7 @@ 3.3f, // page scale 1.f, // maximum animation scale false); - ASSERT_EQ(3u, pending_layer_->tilings()->num_tilings()); + ASSERT_EQ(1u, pending_layer_->tilings()->num_tilings()); EXPECT_FLOAT_EQ(7.26f, pending_layer_->tilings()->tiling_at(0)->contents_scale()); } @@ -3331,11 +3293,7 @@ gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); - host_impl_.SetViewportSize(layer_bounds); - - SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size); - - CreateHighLowResAndSetAllTilesVisible(); + SetupDefaultTreesWithFixedTileSize(layer_bounds, tile_size, Region()); Tile* some_active_tile = active_layer_->HighResTiling()->AllTilesForTesting()[0]; @@ -3355,6 +3313,7 @@ TEST_F(NoLowResPictureLayerImplTest, NothingRequiredIfActiveMissingTiles) { gfx::Size layer_bounds(400, 400); gfx::Size tile_size(100, 100); + scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); // This pile will create tilings, but has no recordings so will not create any @@ -3364,11 +3323,8 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings( tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); - pending_layer_->set_fixed_tile_size(tile_size); - active_layer_->set_fixed_tile_size(tile_size); - CreateHighLowResAndSetAllTilesVisible(); + SetupTreesWithFixedTileSize(pending_pile, active_pile, tile_size, Region()); // Active layer has tilings, but no tiles due to missing recordings. EXPECT_TRUE(active_layer_->CanHaveTilings()); @@ -3401,10 +3357,8 @@ scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); + SetupTreesWithInvalidation(pending_pile, active_pile, Region()); - Region invalidation; - AddDefaultTilingsWithInvalidation(invalidation); SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false); // UpdateTiles with valid viewport. Should update tile viewport. @@ -3484,7 +3438,6 @@ std::vector<PictureLayerTiling*> used_tilings; SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; EXPECT_LT(low_res_factor, 1.f); @@ -3493,6 +3446,8 @@ float page_scale = 3.2f; float scale = 1.f; + ResetTilingsAndRasterScales(); + SetContentsScaleOnBothLayers(scale, device_scale, page_scale, 1.f, false); ASSERT_EQ(1u, active_layer_->tilings()->num_tilings()); @@ -3578,80 +3533,6 @@ ASSERT_EQ(1u, active_layer_->tilings()->num_tilings()); } -TEST_F(PictureLayerImplTest, ScaleCollision) { - gfx::Size tile_size(400, 400); - gfx::Size layer_bounds(1300, 1900); - - scoped_refptr<FakePicturePileImpl> pending_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - scoped_refptr<FakePicturePileImpl> active_pile = - FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - - std::vector<PictureLayerTiling*> used_tilings; - - SetupTrees(pending_pile, active_pile); - - float pending_contents_scale = 1.f; - float active_contents_scale = 2.f; - float device_scale_factor = 1.f; - float page_scale_factor = 1.f; - float maximum_animation_contents_scale = 1.f; - bool animating_transform = false; - - EXPECT_TRUE(host_impl_.settings().create_low_res_tiling); - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - EXPECT_LT(low_res_factor, 1.f); - - SetupDrawPropertiesAndUpdateTiles(pending_layer_, - pending_contents_scale, - device_scale_factor, - page_scale_factor, - maximum_animation_contents_scale, - animating_transform); - SetupDrawPropertiesAndUpdateTiles(active_layer_, - active_contents_scale, - device_scale_factor, - page_scale_factor, - maximum_animation_contents_scale, - animating_transform); - - ASSERT_EQ(4u, pending_layer_->tilings()->num_tilings()); - ASSERT_EQ(4u, active_layer_->tilings()->num_tilings()); - - EXPECT_EQ(active_contents_scale, - pending_layer_->tilings()->tiling_at(0)->contents_scale()); - EXPECT_EQ(pending_contents_scale, - pending_layer_->tilings()->tiling_at(1)->contents_scale()); - EXPECT_EQ(active_contents_scale * low_res_factor, - pending_layer_->tilings()->tiling_at(2)->contents_scale()); - EXPECT_EQ(pending_contents_scale * low_res_factor, - pending_layer_->tilings()->tiling_at(3)->contents_scale()); - - EXPECT_EQ(active_contents_scale, - active_layer_->tilings()->tiling_at(0)->contents_scale()); - EXPECT_EQ(pending_contents_scale, - active_layer_->tilings()->tiling_at(1)->contents_scale()); - EXPECT_EQ(active_contents_scale * low_res_factor, - active_layer_->tilings()->tiling_at(2)->contents_scale()); - EXPECT_EQ(pending_contents_scale * low_res_factor, - active_layer_->tilings()->tiling_at(3)->contents_scale()); - - // The unused low res tiling from the pending tree must be kept or we may add - // it again on the active tree and collide with the pending tree. - used_tilings.push_back(active_layer_->tilings()->tiling_at(1)); - active_layer_->CleanUpTilingsOnActiveLayer(used_tilings); - ASSERT_EQ(4u, active_layer_->tilings()->num_tilings()); - - EXPECT_EQ(active_contents_scale, - active_layer_->tilings()->tiling_at(0)->contents_scale()); - EXPECT_EQ(pending_contents_scale, - active_layer_->tilings()->tiling_at(1)->contents_scale()); - EXPECT_EQ(active_contents_scale * low_res_factor, - active_layer_->tilings()->tiling_at(2)->contents_scale()); - EXPECT_EQ(pending_contents_scale * low_res_factor, - active_layer_->tilings()->tiling_at(3)->contents_scale()); -} - TEST_F(NoLowResPictureLayerImplTest, ReleaseResources) { gfx::Size tile_size(400, 400); gfx::Size layer_bounds(1300, 1900); @@ -3662,15 +3543,8 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupTrees(pending_pile, active_pile); - EXPECT_EQ(0u, pending_layer_->tilings()->num_tilings()); - - SetupDrawPropertiesAndUpdateTiles(pending_layer_, - 1.3f, // ideal contents scale - 2.7f, // device scale - 3.2f, // page scale - 1.f, // maximum animation scale - false); EXPECT_EQ(1u, pending_layer_->tilings()->num_tilings()); + EXPECT_EQ(1u, active_layer_->tilings()->num_tilings()); // All tilings should be removed when losing output surface. active_layer_->ReleaseResources(); @@ -3694,7 +3568,7 @@ gfx::Size tile_size(400, 400); gfx::Size layer_bounds(1000, 2000); - host_impl_.SetViewportSize(layer_bounds); + host_impl_.SetViewportSize(gfx::Size(10000, 20000)); scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); @@ -3703,14 +3577,12 @@ SetupTrees(pending_pile, active_pile); - SetupDrawPropertiesAndUpdateTiles(pending_layer_, 2.5f, 1.f, 1.f, 1.f, false); - host_impl_.pending_tree()->UpdateDrawProperties(); - - active_layer_->draw_properties().visible_content_rect = - gfx::Rect(layer_bounds); - host_impl_.active_tree()->UpdateDrawProperties(); + ResetTilingsAndRasterScales(); + SetupDrawPropertiesAndUpdateTiles(active_layer_, 2.5f, 1.f, 1.f, 1.f, false); float max_contents_scale = active_layer_->MaximumTilingContentsScale(); + EXPECT_EQ(2.5f, max_contents_scale); + gfx::Transform scaled_draw_transform = active_layer_->draw_transform(); scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale, SK_MScalar1 / max_contents_scale); @@ -3747,40 +3619,35 @@ scoped_ptr<FakePictureLayerImpl> layer_with_mask = FakePictureLayerImpl::Create(host_impl_.pending_tree(), 2); - layer_with_mask->SetBounds(bounds); layer_with_mask->SetContentBounds(bounds); scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, bounds); scoped_ptr<FakePictureLayerImpl> mask = - FakePictureLayerImpl::CreateWithRasterSource(host_impl_.pending_tree(), 3, - pending_pile); - mask->set_is_mask(true); - + FakePictureLayerImpl::CreateMaskWithRasterSource( + host_impl_.pending_tree(), 3, pending_pile); mask->SetBounds(bounds); mask->SetContentBounds(bounds); mask->SetDrawsContent(true); - - FakePictureLayerImpl* pending_mask_content = mask.get(); layer_with_mask->SetMaskLayer(mask.Pass()); + FakePictureLayerImpl* pending_mask = + static_cast<FakePictureLayerImpl*>(layer_with_mask->mask_layer()); + scoped_ptr<FakePictureLayerImpl> child_of_layer_with_mask = FakePictureLayerImpl::Create(host_impl_.pending_tree(), 4); - child_of_layer_with_mask->SetBounds(bounds); child_of_layer_with_mask->SetContentBounds(bounds); child_of_layer_with_mask->SetDrawsContent(true); - layer_with_mask->AddChild(child_of_layer_with_mask.Pass()); - root->AddChild(layer_with_mask.Pass()); host_impl_.pending_tree()->SetRootLayer(root.Pass()); - EXPECT_FALSE(pending_mask_content->tilings()); + EXPECT_EQ(0u, pending_mask->num_tilings()); host_impl_.pending_tree()->UpdateDrawProperties(); - EXPECT_NE(0u, pending_mask_content->num_tilings()); + EXPECT_NE(0u, pending_mask->num_tilings()); } class PictureLayerImplTestWithDelegatingRenderer : public PictureLayerImplTest { @@ -3804,7 +3671,6 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); SetupPendingTree(pending_pile); pending_layer_->SetBounds(layer_bounds); - host_impl_.SetViewportSize(layer_bounds); ActivateTree(); host_impl_.active_tree()->UpdateDrawProperties(); std::vector<Tile*> tiles = @@ -3851,14 +3717,17 @@ OcclusionTrackingPictureLayerImplTest() : PictureLayerImplTest(OcclusionTrackingSettings()) {} - void VerifyEvictionConsidersOcclusion( - PictureLayerImpl* layer, - size_t expected_occluded_tile_count[NUM_TREE_PRIORITIES]) { + void VerifyEvictionConsidersOcclusion(FakePictureLayerImpl* layer, + FakePictureLayerImpl* twin_layer, + WhichTree tree, + size_t expected_occluded_tile_count) { + WhichTree twin_tree = tree == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE; for (int priority_count = 0; priority_count < NUM_TREE_PRIORITIES; ++priority_count) { TreePriority tree_priority = static_cast<TreePriority>(priority_count); size_t occluded_tile_count = 0u; Tile* last_tile = nullptr; + std::set<Tile*> shared_tiles; scoped_ptr<TilingSetEvictionQueue> queue = layer->CreateEvictionQueue(tree_priority); @@ -3866,23 +3735,22 @@ Tile* tile = queue->Top(); if (!last_tile) last_tile = tile; + if (tile->is_shared()) + EXPECT_TRUE(shared_tiles.insert(tile).second); // The only way we will encounter an occluded tile after an unoccluded // tile is if the priorty bin decreased, the tile is required for // activation, or the scale changed. - bool tile_is_occluded = - tile->is_occluded_for_tree_priority(tree_priority); + bool tile_is_occluded = tile->is_occluded(tree); if (tile_is_occluded) { occluded_tile_count++; - bool last_tile_is_occluded = - last_tile->is_occluded_for_tree_priority(tree_priority); + bool last_tile_is_occluded = last_tile->is_occluded(tree); if (!last_tile_is_occluded) { TilePriority::PriorityBin tile_priority_bin = - tile->priority_for_tree_priority(tree_priority).priority_bin; + tile->priority(tree).priority_bin; TilePriority::PriorityBin last_tile_priority_bin = - last_tile->priority_for_tree_priority(tree_priority) - .priority_bin; + last_tile->priority(tree).priority_bin; EXPECT_TRUE( (tile_priority_bin < last_tile_priority_bin) || @@ -3893,8 +3761,74 @@ last_tile = tile; queue->Pop(); } - EXPECT_EQ(expected_occluded_tile_count[priority_count], - occluded_tile_count); + // Count also shared tiles which are occluded in the tree but which were + // not returned by the tiling set eviction queue. Those shared tiles + // shall be returned by the twin tiling set eviction queue. + queue = twin_layer->CreateEvictionQueue(tree_priority); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); + if (tile->is_shared()) { + EXPECT_TRUE(shared_tiles.insert(tile).second); + if (tile->is_occluded(tree)) + ++occluded_tile_count; + // Check the reasons why the shared tile was not returned by + // the first tiling set eviction queue. + switch (tree_priority) { + case SAME_PRIORITY_FOR_BOTH_TREES: { + const TilePriority& priority = tile->priority(tree); + const TilePriority& priority_for_tree_priority = + tile->priority_for_tree_priority(tree_priority); + const TilePriority& twin_priority = tile->priority(twin_tree); + // Check if the shared tile was not returned by the first tiling + // set eviction queue because it was out of order for the first + // tiling set eviction queue but not for the twin tiling set + // eviction queue. + if (priority.priority_bin != twin_priority.priority_bin) { + EXPECT_LT(priority_for_tree_priority.priority_bin, + priority.priority_bin); + EXPECT_EQ(priority_for_tree_priority.priority_bin, + twin_priority.priority_bin); + EXPECT_TRUE(priority_for_tree_priority.priority_bin < + priority.priority_bin); + } else if (tile->is_occluded(tree) != + 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)); + } else if (priority.distance_to_visible != + twin_priority.distance_to_visible) { + EXPECT_LT(priority_for_tree_priority.distance_to_visible, + priority.distance_to_visible); + EXPECT_EQ(priority_for_tree_priority.distance_to_visible, + twin_priority.distance_to_visible); + EXPECT_TRUE(priority_for_tree_priority.distance_to_visible < + priority.distance_to_visible); + } else { + // Shared tiles having the same active and pending priorities + // should be returned only by a pending tree eviction queue. + EXPECT_EQ(ACTIVE_TREE, tree); + } + break; + } + case SMOOTHNESS_TAKES_PRIORITY: + // Shared tiles should be returned only by an active tree + // eviction queue. + EXPECT_EQ(PENDING_TREE, tree); + break; + case NEW_CONTENT_TAKES_PRIORITY: + // Shared tiles should be returned only by a pending tree + // eviction queue. + EXPECT_EQ(ACTIVE_TREE, tree); + break; + case NUM_TREE_PRIORITIES: + NOTREACHED(); + break; + } + } + queue->Pop(); + } + EXPECT_EQ(expected_occluded_tile_count, occluded_tile_count); } } }; @@ -3911,13 +3845,11 @@ gfx::Size viewport_size(500, 500); gfx::Point occluding_layer_position(310, 0); + host_impl_.SetViewportSize(viewport_size); + scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); - pending_layer_->set_fixed_tile_size(tile_size); - - host_impl_.SetViewportSize(viewport_size); - host_impl_.pending_tree()->UpdateDrawProperties(); + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); // No occlusion. int unoccluded_tile_count = 0; @@ -4004,13 +3936,11 @@ gfx::Size viewport_size(500, 500); gfx::Point occluding_layer_position(310, 0); + host_impl_.SetViewportSize(viewport_size); + scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); - pending_layer_->set_fixed_tile_size(tile_size); - - host_impl_.SetViewportSize(viewport_size); - host_impl_.pending_tree()->UpdateDrawProperties(); + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); // No occlusion. int occluded_tile_count = 0; @@ -4125,6 +4055,11 @@ } TEST_F(OcclusionTrackingPictureLayerImplTest, OcclusionForDifferentScales) { + base::TimeTicks time_ticks; + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); gfx::Size viewport_size(500, 500); @@ -4132,20 +4067,12 @@ scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupPendingTree(pending_pile); - pending_layer_->set_fixed_tile_size(tile_size); + host_impl_.SetViewportSize(viewport_size); + + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, Region()); ASSERT_TRUE(pending_layer_->CanHaveTilings()); - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; - - std::vector<PictureLayerTiling*> tilings; - tilings.push_back(pending_layer_->AddTiling(low_res_factor)); - tilings.push_back(pending_layer_->AddTiling(0.3f)); - tilings.push_back(pending_layer_->AddTiling(0.7f)); - tilings.push_back(pending_layer_->AddTiling(1.0f)); - tilings.push_back(pending_layer_->AddTiling(2.0f)); - pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1)); LayerImpl* layer1 = pending_layer_->children()[0]; layer1->SetBounds(layer_bounds); @@ -4154,49 +4081,56 @@ layer1->SetContentsOpaque(true); layer1->SetPosition(occluding_layer_position); - host_impl_.SetViewportSize(viewport_size); + pending_layer_->tilings()->RemoveAllTilings(); + float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + pending_layer_->AddTiling(low_res_factor); + pending_layer_->AddTiling(0.3f); + pending_layer_->AddTiling(0.7f); + pending_layer_->AddTiling(1.0f); + pending_layer_->AddTiling(2.0f); + + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + // UpdateDrawProperties with the occluding layer. host_impl_.pending_tree()->UpdateDrawProperties(); - int tiling_count = 0; + EXPECT_EQ(5u, pending_layer_->num_tilings()); + int occluded_tile_count = 0; - for (std::vector<PictureLayerTiling*>::iterator tiling_iterator = - tilings.begin(); - tiling_iterator != tilings.end(); - ++tiling_iterator) { - (*tiling_iterator)->UpdateAllTilePrioritiesForTesting(); - std::vector<Tile*> tiles = (*tiling_iterator)->AllTilesForTesting(); + for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { + PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i); + tiling->UpdateAllTilePrioritiesForTesting(); + std::vector<Tile*> tiles = tiling->AllTilesForTesting(); occluded_tile_count = 0; - for (size_t i = 0; i < tiles.size(); ++i) { - if (tiles[i]->is_occluded(PENDING_TREE)) { + for (size_t j = 0; j < tiles.size(); ++j) { + if (tiles[j]->is_occluded(PENDING_TREE)) { gfx::Rect scaled_content_rect = ScaleToEnclosingRect( - tiles[i]->content_rect(), 1.0f / tiles[i]->contents_scale()); + tiles[j]->content_rect(), 1.0f / tiles[j]->contents_scale()); EXPECT_GE(scaled_content_rect.x(), occluding_layer_position.x()); occluded_tile_count++; } } - switch (tiling_count) { + + switch (i) { case 0: + EXPECT_EQ(occluded_tile_count, 30); + break; case 1: - EXPECT_EQ(occluded_tile_count, 2); + EXPECT_EQ(occluded_tile_count, 5); break; case 2: EXPECT_EQ(occluded_tile_count, 4); break; - case 3: - EXPECT_EQ(occluded_tile_count, 5); - break; case 4: - EXPECT_EQ(occluded_tile_count, 30); + case 3: + EXPECT_EQ(occluded_tile_count, 2); break; default: NOTREACHED(); } - - tiling_count++; } - - EXPECT_EQ(tiling_count, 5); } TEST_F(OcclusionTrackingPictureLayerImplTest, DifferentOcclusionOnTrees) { @@ -4210,24 +4144,23 @@ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); + + host_impl_.SetViewportSize(viewport_size); + SetupPendingTree(active_pile); // Partially occlude the active layer. - active_layer_->AddChild(LayerImpl::Create(host_impl_.active_tree(), 2)); - LayerImpl* layer1 = active_layer_->children()[0]; + pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 2)); + LayerImpl* layer1 = pending_layer_->children()[0]; layer1->SetBounds(layer_bounds); layer1->SetContentBounds(layer_bounds); layer1->SetDrawsContent(true); layer1->SetContentsOpaque(true); layer1->SetPosition(occluding_layer_position); + ActivateTree(); + // Partially invalidate the pending layer. - pending_layer_->set_invalidation(invalidation_rect); - - host_impl_.SetViewportSize(viewport_size); - - active_layer_->CreateDefaultTilingsAndTiles(); - pending_layer_->CreateDefaultTilingsAndTiles(); + SetupPendingTreeWithInvalidation(pending_pile, invalidation_rect); for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i); @@ -4306,36 +4239,45 @@ TEST_F(OcclusionTrackingPictureLayerImplTest, OccludedTilesConsideredDuringEviction) { + base::TimeTicks time_ticks; + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + gfx::Size tile_size(102, 102); gfx::Size layer_bounds(1000, 1000); - gfx::Size viewport_size(500, 500); + gfx::Size viewport_size(1000, 1000); gfx::Point pending_occluding_layer_position(310, 0); gfx::Point active_occluding_layer_position(0, 310); gfx::Rect invalidation_rect(230, 230, 102, 102); + host_impl_.SetViewportSize(viewport_size); + host_impl_.SetDeviceScaleFactor(2.f); + scoped_refptr<FakePicturePileImpl> pending_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); scoped_refptr<FakePicturePileImpl> active_pile = FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); - SetupTrees(pending_pile, active_pile); - pending_layer_->set_fixed_tile_size(tile_size); - active_layer_->set_fixed_tile_size(tile_size); + SetupPendingTreeWithFixedTileSize(active_pile, tile_size, Region()); - float low_res_factor = host_impl_.settings().low_res_contents_scale_factor; + // Partially occlude the active layer. + pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 2)); + LayerImpl* active_occluding_layer = pending_layer_->children()[0]; + active_occluding_layer->SetBounds(layer_bounds); + active_occluding_layer->SetContentBounds(layer_bounds); + active_occluding_layer->SetDrawsContent(true); + active_occluding_layer->SetContentsOpaque(true); + active_occluding_layer->SetPosition(active_occluding_layer_position); - std::vector<PictureLayerTiling*> tilings; - tilings.push_back(pending_layer_->AddTiling(low_res_factor)); - tilings.push_back(pending_layer_->AddTiling(0.3f)); - tilings.push_back(pending_layer_->AddTiling(0.7f)); - tilings.push_back(pending_layer_->AddTiling(1.0f)); - tilings.push_back(pending_layer_->AddTiling(2.0f)); + ActivateTree(); - EXPECT_EQ(5u, pending_layer_->num_tilings()); - EXPECT_EQ(5u, active_layer_->num_tilings()); + // Partially invalidate the pending layer. Tiles inside the invalidation rect + // are not shared between trees. + SetupPendingTreeWithFixedTileSize(pending_pile, tile_size, invalidation_rect); - // Partially occlude the pending layer. - pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 1)); + // Partially occlude the pending layer in a different way. + pending_layer_->AddChild(LayerImpl::Create(host_impl_.pending_tree(), 3)); LayerImpl* pending_occluding_layer = pending_layer_->children()[0]; pending_occluding_layer->SetBounds(layer_bounds); pending_occluding_layer->SetContentBounds(layer_bounds); @@ -4343,52 +4285,38 @@ pending_occluding_layer->SetContentsOpaque(true); pending_occluding_layer->SetPosition(pending_occluding_layer_position); - // Partially occlude the active layer. - active_layer_->AddChild(LayerImpl::Create(host_impl_.active_tree(), 2)); - LayerImpl* active_occluding_layer = active_layer_->children()[0]; - active_occluding_layer->SetBounds(layer_bounds); - active_occluding_layer->SetContentBounds(layer_bounds); - active_occluding_layer->SetDrawsContent(true); - active_occluding_layer->SetContentsOpaque(true); - active_occluding_layer->SetPosition(active_occluding_layer_position); + EXPECT_EQ(2u, pending_layer_->num_tilings()); + EXPECT_EQ(2u, active_layer_->num_tilings()); - // Partially invalidate the pending layer. Tiles inside the invalidation rect - // are not shared between trees. - pending_layer_->set_invalidation(invalidation_rect); - - host_impl_.SetViewportSize(viewport_size); - host_impl_.active_tree()->UpdateDrawProperties(); + time_ticks += base::TimeDelta::FromMilliseconds(1); + host_impl_.SetCurrentBeginFrameArgs( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); + // UpdateDrawProperties with the occluding layer. host_impl_.pending_tree()->UpdateDrawProperties(); - // The expected number of occluded tiles on each of the 5 tilings for each of + // The expected number of occluded tiles on each of the 2 tilings for each of // the 3 tree priorities. - size_t expected_occluded_tile_count_on_both[] = {9u, 1u, 1u, 1u, 1u}; - size_t expected_occluded_tile_count_on_active[] = {30u, 5u, 4u, 2u, 2u}; - size_t expected_occluded_tile_count_on_pending[] = {30u, 5u, 4u, 2u, 2u}; + size_t expected_occluded_tile_count_on_both[] = {9u, 1u}; + size_t expected_occluded_tile_count_on_active[] = {30u, 3u}; + size_t expected_occluded_tile_count_on_pending[] = {30u, 3u}; - // The total expected number of occluded tiles on all tilings for each of the - // 3 tree priorities. - size_t total_expected_occluded_tile_count[] = {13u, 43u, 43u}; - - ASSERT_EQ(arraysize(total_expected_occluded_tile_count), NUM_TREE_PRIORITIES); + size_t total_expected_occluded_tile_count_on_trees[] = {33u, 33u}; // Verify number of occluded tiles on the pending layer for each tiling. for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i); - tiling->CreateAllTilesForTesting(); tiling->UpdateAllTilePrioritiesForTesting(); size_t occluded_tile_count_on_pending = 0u; size_t occluded_tile_count_on_active = 0u; size_t occluded_tile_count_on_both = 0u; - for (PictureLayerTiling::CoverageIterator iter( - tiling, - pending_layer_->contents_scale_x(), - gfx::Rect(layer_bounds)); - iter; - ++iter) { + for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, + gfx::Rect(layer_bounds)); + iter; ++iter) { Tile* tile = *iter; + if (!tile) + continue; if (tile->is_occluded(PENDING_TREE)) occluded_tile_count_on_pending++; if (tile->is_occluded(ACTIVE_TREE)) @@ -4398,19 +4326,18 @@ } EXPECT_EQ(expected_occluded_tile_count_on_pending[i], occluded_tile_count_on_pending) - << i; + << tiling->contents_scale(); EXPECT_EQ(expected_occluded_tile_count_on_active[i], occluded_tile_count_on_active) - << i; + << tiling->contents_scale(); EXPECT_EQ(expected_occluded_tile_count_on_both[i], occluded_tile_count_on_both) - << i; + << tiling->contents_scale(); } // Verify number of occluded tiles on the active layer for each tiling. for (size_t i = 0; i < active_layer_->num_tilings(); ++i) { PictureLayerTiling* tiling = active_layer_->tilings()->tiling_at(i); - tiling->CreateAllTilesForTesting(); tiling->UpdateAllTilePrioritiesForTesting(); size_t occluded_tile_count_on_pending = 0u; @@ -4424,6 +4351,8 @@ ++iter) { Tile* tile = *iter; + if (!tile) + continue; if (tile->is_occluded(PENDING_TREE)) occluded_tile_count_on_pending++; if (tile->is_occluded(ACTIVE_TREE)) @@ -4443,20 +4372,38 @@ } std::vector<Tile*> all_tiles; - for (std::vector<PictureLayerTiling*>::iterator tiling_iterator = - tilings.begin(); - tiling_iterator != tilings.end(); - ++tiling_iterator) { - std::vector<Tile*> tiles = (*tiling_iterator)->AllTilesForTesting(); - std::copy(tiles.begin(), tiles.end(), std::back_inserter(all_tiles)); + for (size_t i = 0; i < pending_layer_->num_tilings(); ++i) { + PictureLayerTiling* tiling = pending_layer_->tilings()->tiling_at(i); + std::vector<Tile*> tiles = tiling->AllTilesForTesting(); + all_tiles.insert(all_tiles.end(), tiles.begin(), tiles.end()); } host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(all_tiles); - VerifyEvictionConsidersOcclusion(pending_layer_, - total_expected_occluded_tile_count); - VerifyEvictionConsidersOcclusion(active_layer_, - total_expected_occluded_tile_count); + VerifyEvictionConsidersOcclusion( + pending_layer_, active_layer_, PENDING_TREE, + total_expected_occluded_tile_count_on_trees[PENDING_TREE]); + VerifyEvictionConsidersOcclusion( + active_layer_, pending_layer_, ACTIVE_TREE, + total_expected_occluded_tile_count_on_trees[ACTIVE_TREE]); + + // Repeat the tests without valid active tree priorities. + active_layer_->set_has_valid_tile_priorities(false); + VerifyEvictionConsidersOcclusion( + pending_layer_, active_layer_, PENDING_TREE, + total_expected_occluded_tile_count_on_trees[PENDING_TREE]); + VerifyEvictionConsidersOcclusion( + active_layer_, pending_layer_, ACTIVE_TREE, 0u); + active_layer_->set_has_valid_tile_priorities(true); + + // Repeat the tests without valid pending tree priorities. + pending_layer_->set_has_valid_tile_priorities(false); + VerifyEvictionConsidersOcclusion( + active_layer_, pending_layer_, ACTIVE_TREE, + total_expected_occluded_tile_count_on_trees[ACTIVE_TREE]); + VerifyEvictionConsidersOcclusion( + pending_layer_, active_layer_, PENDING_TREE, 0u); + pending_layer_->set_has_valid_tile_priorities(true); } TEST_F(PictureLayerImplTest, PendingOrActiveTwinLayer) { @@ -4530,8 +4477,6 @@ host->SetRootLayer(layer); RecordingSource* recording_source = layer->GetRecordingSourceForTesting(); - host_impl_.SetViewportSize(layer_bounds); - int frame_number = 0; client.set_fill_with_nonsolid_color(!test_for_solid); @@ -4544,11 +4489,9 @@ scoped_refptr<RasterSource> pending_raster_source = recording_source->CreateRasterSource(); - SetupPendingTree(pending_raster_source); + SetupPendingTreeWithFixedTileSize(pending_raster_source, tile_size, Region()); ActivateTree(); - active_layer_->set_fixed_tile_size(tile_size); - host_impl_.active_tree()->UpdateDrawProperties(); if (test_for_solid) { EXPECT_EQ(0u, active_layer_->tilings()->num_tilings()); } else { @@ -4597,8 +4540,6 @@ host->SetRootLayer(layer); RecordingSource* recording_source = layer->GetRecordingSourceForTesting(); - host_impl_.SetViewportSize(layer_bounds); - int frame_number = 0; client.set_fill_with_nonsolid_color(true); @@ -4696,6 +4637,66 @@ EXPECT_TRUE(pending_layer_->AllTilesRequiredForActivationAreReadyToDraw()); } +TEST_F(PictureLayerImplTest, CloneMissingRecordings) { + gfx::Size tile_size(100, 100); + gfx::Size layer_bounds(400, 400); + + scoped_refptr<FakePicturePileImpl> filled_pile = + FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds); + scoped_refptr<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); + } + + SetupPendingTreeWithFixedTileSize(filled_pile, tile_size, Region()); + ActivateTree(); + + PictureLayerTiling* pending_tiling = old_pending_layer_->HighResTiling(); + PictureLayerTiling* active_tiling = active_layer_->HighResTiling(); + + // We should have all tiles in both tile sets. + EXPECT_EQ(5u * 5u, pending_tiling->AllTilesForTesting().size()); + EXPECT_EQ(5u * 5u, active_tiling->AllTilesForTesting().size()); + + // Now put a partially-recorded pile on the pending tree (and invalidate + // everything, since the main thread PicturePile will invalidate dropped + // recordings). This will cause us to be missing some tiles. + SetupPendingTreeWithFixedTileSize(partial_pile, tile_size, + Region(gfx::Rect(layer_bounds))); + EXPECT_EQ(3u * 3u, pending_tiling->AllTilesForTesting().size()); + EXPECT_FALSE(pending_tiling->TileAt(0, 0)); + EXPECT_FALSE(pending_tiling->TileAt(1, 1)); + EXPECT_TRUE(pending_tiling->TileAt(2, 2)); + + // Active is not affected yet. + EXPECT_EQ(5u * 5u, active_tiling->AllTilesForTesting().size()); + + // Activate the tree. The same tiles go missing on the active tree. + ActivateTree(); + EXPECT_EQ(3u * 3u, active_tiling->AllTilesForTesting().size()); + EXPECT_FALSE(active_tiling->TileAt(0, 0)); + EXPECT_FALSE(active_tiling->TileAt(1, 1)); + EXPECT_TRUE(active_tiling->TileAt(2, 2)); + + // Now put a full recording on the pending tree again. We'll get all our tiles + // back. + SetupPendingTreeWithFixedTileSize(filled_pile, tile_size, + Region(gfx::Rect(layer_bounds))); + EXPECT_EQ(5u * 5u, pending_tiling->AllTilesForTesting().size()); + + // Active is not affected yet. + EXPECT_EQ(3u * 3u, active_tiling->AllTilesForTesting().size()); + + // Activate the tree. The tiles are created and shared on the active tree. + ActivateTree(); + EXPECT_EQ(5u * 5u, active_tiling->AllTilesForTesting().size()); + EXPECT_TRUE(active_tiling->TileAt(0, 0)->is_shared()); + EXPECT_TRUE(active_tiling->TileAt(1, 1)->is_shared()); + EXPECT_TRUE(active_tiling->TileAt(2, 2)->is_shared()); +} + class TileSizeSettings : public ImplSidePaintingSettings { public: TileSizeSettings() {
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index b174348..6e9cea1 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -111,8 +111,7 @@ if (texture_copy_->id()) { std::vector<uint8> swizzled; - uint8* pixels = - static_cast<uint8*>(texture_mailbox_.shared_memory()->memory()); + uint8* pixels = texture_mailbox_.shared_bitmap()->pixels(); if (!PlatformColor::SameComponentOrder(texture_copy_->format())) { // Swizzle colors. This is slow, but should be really uncommon.
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index 4e2f675..f2dbb33 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc
@@ -101,7 +101,7 @@ uint32 sync_point, bool lost_resource)); MOCK_METHOD3(Release2, - void(base::SharedMemory* shared_memory, + void(SharedBitmap* shared_bitmap, uint32 sync_point, bool lost_resource)); MOCK_METHOD4(ReleaseImpl, @@ -110,19 +110,18 @@ bool lost_resource, BlockingTaskRunner* main_thread_task_runner)); MOCK_METHOD4(ReleaseImpl2, - void(base::SharedMemory* shared_memory, + void(SharedBitmap* shared_bitmap, uint32 sync_point, bool lost_resource, BlockingTaskRunner* main_thread_task_runner)); }; struct CommonMailboxObjects { - CommonMailboxObjects() + explicit CommonMailboxObjects(SharedBitmapManager* manager) : mailbox_name1_(MailboxFromChar('1')), mailbox_name2_(MailboxFromChar('2')), sync_point1_(1), - sync_point2_(2), - shared_memory_(new base::SharedMemory) { + sync_point2_(2) { release_mailbox1_ = base::Bind(&MockMailboxCallback::Release, base::Unretained(&mock_callback_), mailbox_name1_); @@ -140,14 +139,15 @@ mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_); mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_); gfx::Size size(128, 128); - EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea())); - release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2, - base::Unretained(&mock_callback_), - shared_memory_.get()); - release_mailbox3_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl2, - base::Unretained(&mock_callback_), - shared_memory_.get()); - mailbox3_ = TextureMailbox(shared_memory_.get(), size); + shared_bitmap_ = manager->AllocateSharedBitmap(size); + DCHECK(shared_bitmap_); + release_mailbox3_ = + base::Bind(&MockMailboxCallback::Release2, + base::Unretained(&mock_callback_), shared_bitmap_.get()); + release_mailbox3_impl_ = + base::Bind(&MockMailboxCallback::ReleaseImpl2, + base::Unretained(&mock_callback_), shared_bitmap_.get()); + mailbox3_ = TextureMailbox(shared_bitmap_.get(), size); } gpu::Mailbox mailbox_name1_; @@ -164,7 +164,7 @@ TextureMailbox mailbox3_; uint32 sync_point1_; uint32 sync_point2_; - scoped_ptr<base::SharedMemory> shared_memory_; + scoped_ptr<SharedBitmap> shared_bitmap_; }; class TextureLayerTest : public testing::Test { @@ -172,7 +172,8 @@ TextureLayerTest() : fake_client_( FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)), - host_impl_(&proxy_, &shared_bitmap_manager_) {} + host_impl_(&proxy_, &shared_bitmap_manager_), + test_data_(&shared_bitmap_manager_) {} protected: virtual void SetUp() { @@ -195,6 +196,7 @@ FakeLayerTreeHostClient fake_client_; TestSharedBitmapManager shared_bitmap_manager_; FakeLayerTreeHostImpl host_impl_; + CommonMailboxObjects test_data_; }; TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) { @@ -309,8 +311,6 @@ false)).Times(1); TextureLayerTest::TearDown(); } - - CommonMailboxObjects test_data_; }; TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { @@ -359,9 +359,7 @@ EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); EXPECT_CALL(test_data_.mock_callback_, - Release2(test_data_.shared_memory_.get(), - 0, false)) - .Times(1); + Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1); test_layer->SetTextureMailbox(TextureMailbox(), nullptr); Mock::VerifyAndClearExpectations(layer_tree_host_.get()); Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); @@ -452,7 +450,6 @@ main_ref_; base::Thread main_thread_; scoped_ptr<BlockingTaskRunner> main_thread_task_runner_; - CommonMailboxObjects test_data_; }; TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { @@ -946,7 +943,6 @@ return will_draw; } - CommonMailboxObjects test_data_; FakeLayerTreeHostClient fake_client_; }; @@ -958,7 +954,7 @@ ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _)) .Times(AnyNumber()); EXPECT_CALL(test_data_.mock_callback_, - ReleaseImpl2(test_data_.shared_memory_.get(), 0, false, _)) + ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _)) .Times(AnyNumber()); // Hardware mode. {
diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc index c66e124..a36c030 100644 --- a/cc/layers/tiled_layer_impl.cc +++ b/cc/layers/tiled_layer_impl.cc
@@ -262,7 +262,8 @@ tile->resource_id(), tex_coord_rect, texture_size, - tile->contents_swizzled()); + tile->contents_swizzled(), + false); } } }
diff --git a/cc/layers/tiled_layer_unittest.cc b/cc/layers/tiled_layer_unittest.cc index a9a1e78..b4ee30f 100644 --- a/cc/layers/tiled_layer_unittest.cc +++ b/cc/layers/tiled_layer_unittest.cc
@@ -45,18 +45,10 @@ } }; -class SynchronousOutputSurfaceLayerTreeHost : public LayerTreeHost { +class SynchronousOutputSurfaceClient : public FakeLayerTreeHostClient { public: - static scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> Create( - LayerTreeHostClient* client, - SharedBitmapManager* manager, - const LayerTreeSettings& settings, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { - return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost( - client, manager, settings, impl_task_runner)); - } - - ~SynchronousOutputSurfaceLayerTreeHost() override {} + SynchronousOutputSurfaceClient() + : FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D) {} bool EnsureOutputSurfaceCreated() { base::MessageLoop::current()->PostDelayedTask( @@ -67,25 +59,19 @@ return output_surface_created_; } - void OnCreateAndInitializeOutputSurfaceAttempted(bool success) override { - LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success); - output_surface_created_ = success; + void DidInitializeOutputSurface() override { + FakeLayerTreeHostClient::DidInitializeOutputSurface(); + output_surface_created_ = true; + run_loop_.Quit(); + } + + void DidFailToInitializeOutputSurface() override { + FakeLayerTreeHostClient::DidFailToInitializeOutputSurface(); + output_surface_created_ = false; run_loop_.Quit(); } private: - SynchronousOutputSurfaceLayerTreeHost( - LayerTreeHostClient* client, - SharedBitmapManager* manager, - const LayerTreeSettings& settings, - scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) - : LayerTreeHost(client, manager, NULL, settings), - output_surface_created_(false) { - LayerTreeHost::InitializeThreaded(base::MessageLoopProxy::current(), - impl_task_runner, - nullptr); - } - bool output_surface_created_; base::RunLoop run_loop_; }; @@ -97,7 +83,6 @@ output_surface_(FakeOutputSurface::Create3d()), queue_(make_scoped_ptr(new ResourceUpdateQueue)), impl_thread_("ImplThread"), - fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D), occlusion_(nullptr) { settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max(); settings_.layer_transforms_should_scale_layer_contents = true; @@ -106,16 +91,16 @@ void SetUp() override { impl_thread_.Start(); shared_bitmap_manager_.reset(new TestSharedBitmapManager()); - layer_tree_host_ = SynchronousOutputSurfaceLayerTreeHost::Create( - &fake_layer_tree_host_client_, - shared_bitmap_manager_.get(), - settings_, - impl_thread_.message_loop_proxy()); - fake_layer_tree_host_client_.SetLayerTreeHost(layer_tree_host_.get()); + layer_tree_host_ = LayerTreeHost::CreateThreaded( + &synchonous_output_surface_client_, shared_bitmap_manager_.get(), + nullptr, settings_, base::MessageLoopProxy::current(), + impl_thread_.message_loop_proxy(), nullptr); + synchonous_output_surface_client_.SetLayerTreeHost(layer_tree_host_.get()); proxy_ = layer_tree_host_->proxy(); resource_manager_ = PrioritizedResourceManager::Create(proxy_); layer_tree_host_->SetLayerTreeHostClientReady(); - CHECK(layer_tree_host_->EnsureOutputSurfaceCreated()); + CHECK(synchonous_output_surface_client_.EnsureOutputSurfaceCreated()); + layer_tree_host_->SetRootLayer(Layer::Create()); CHECK(output_surface_->BindToClient(&output_surface_client_)); @@ -253,8 +238,8 @@ scoped_ptr<ResourceUpdateQueue> queue_; PriorityCalculator priority_calculator_; base::Thread impl_thread_; - FakeLayerTreeHostClient fake_layer_tree_host_client_; - scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> layer_tree_host_; + SynchronousOutputSurfaceClient synchonous_output_surface_client_; + scoped_ptr<LayerTreeHost> layer_tree_host_; scoped_ptr<FakeLayerTreeHostImpl> host_impl_; scoped_ptr<PrioritizedResourceManager> resource_manager_; TestOcclusionTracker* occlusion_;
diff --git a/cc/output/delegating_renderer_unittest.cc b/cc/output/delegating_renderer_unittest.cc index fffa0ac..b72c76b 100644 --- a/cc/output/delegating_renderer_unittest.cc +++ b/cc/output/delegating_renderer_unittest.cc
@@ -17,7 +17,7 @@ DelegatingRendererTest() : LayerTreeTest(), output_surface_(NULL) {} virtual ~DelegatingRendererTest() {} - scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) override { + scoped_ptr<OutputSurface> CreateOutputSurface() override { scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::CreateDelegating3d(); output_surface_ = output_surface.get();
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc index 13cda6e..7896bb8 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc
@@ -154,8 +154,6 @@ public: static scoped_ptr<ScopedUseGrContext> Create(GLRenderer* renderer, DrawingFrame* frame) { - if (!renderer->output_surface_->context_provider()->GrContext()) - return nullptr; return make_scoped_ptr(new ScopedUseGrContext(renderer, frame)); } @@ -1627,7 +1625,8 @@ SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge); ResourceProvider::ScopedSamplerGL quad_resource_lock( - resource_provider_, resource_id, GL_LINEAR); + resource_provider_, resource_id, + quad->nearest_neighbor ? GL_NEAREST : GL_LINEAR); SamplerType sampler = SamplerTypeFromTextureTarget(quad_resource_lock.target()); @@ -1711,7 +1710,8 @@ bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f); GLenum filter = - (scaled || !quad->quadTransform().IsIdentityOrIntegerTranslation()) + (scaled || !quad->quadTransform().IsIdentityOrIntegerTranslation()) && + !quad->nearest_neighbor ? GL_LINEAR : GL_NEAREST;
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index cb14db3..58205a9 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc
@@ -1384,6 +1384,7 @@ gfx::Rect viewport(this->device_viewport_size_); // TODO(enne): the renderer should figure this out on its own. ResourceFormat texture_format = RGBA_8888; + bool nearest_neighbor = false; RenderPassId id(1, 1); gfx::Transform transform_to_root; @@ -1420,8 +1421,8 @@ blue_quad->SetNew(blue_shared_state, viewport, // Intentionally bigger than clip. gfx::Rect(), viewport, gfx::RectF(viewport), - viewport.size(), texture_format, viewport, 1.f, - blue_pile.get()); + viewport.size(), nearest_neighbor, texture_format, viewport, + 1.f, blue_pile.get()); // One viewport-filling green quad. scoped_refptr<FakePicturePileImpl> green_pile = @@ -1439,7 +1440,8 @@ pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport, gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(), - texture_format, viewport, 1.f, green_pile.get()); + nearest_neighbor, texture_format, viewport, 1.f, + green_pile.get()); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -1455,6 +1457,7 @@ gfx::Size pile_tile_size(1000, 1000); gfx::Rect viewport(this->device_viewport_size_); ResourceFormat texture_format = RGBA_8888; + bool nearest_neighbor = false; RenderPassId id(1, 1); gfx::Transform transform_to_root; @@ -1477,8 +1480,8 @@ PictureDrawQuad* green_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport, - gfx::RectF(0, 0, 1, 1), viewport.size(), texture_format, - viewport, 1.f, green_pile.get()); + gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor, + texture_format, viewport, 1.f, green_pile.get()); // One viewport-filling white quad. scoped_refptr<FakePicturePileImpl> white_pile = @@ -1495,8 +1498,8 @@ PictureDrawQuad* white_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); white_quad->SetNew(white_shared_state, viewport, gfx::Rect(), viewport, - gfx::RectF(0, 0, 1, 1), viewport.size(), texture_format, - viewport, 1.f, white_pile.get()); + gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor, + texture_format, viewport, 1.f, white_pile.get()); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -1532,6 +1535,7 @@ gfx::Size pile_tile_size(1000, 1000); gfx::Rect viewport(this->device_viewport_size_); ResourceFormat texture_format = RGBA_8888; + bool nearest_neighbor = false; RenderPassId id(1, 1); gfx::Transform transform_to_root; @@ -1562,8 +1566,8 @@ PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, - gfx::RectF(0, 0, 2, 2), viewport.size(), texture_format, - viewport, 1.f, pile.get()); + gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor, + texture_format, viewport, 1.f, pile.get()); RenderPassList pass_list; pass_list.push_back(pass.Pass()); @@ -1576,11 +1580,118 @@ ExactPixelComparator(true))); } +// This disables filtering by setting |nearest_neighbor| on the PictureDrawQuad. +TYPED_TEST(RendererPixelTest, PictureDrawQuadNearestNeighbor) { + gfx::Size pile_tile_size(1000, 1000); + gfx::Rect viewport(this->device_viewport_size_); + ResourceFormat texture_format = RGBA_8888; + bool nearest_neighbor = true; + + RenderPassId id(1, 1); + gfx::Transform transform_to_root; + scoped_ptr<RenderPass> pass = + CreateTestRenderPass(id, viewport, transform_to_root); + + SkBitmap bitmap; + bitmap.allocN32Pixels(2, 2); + { + SkAutoLockPixels lock(bitmap); + SkCanvas canvas(bitmap); + canvas.drawPoint(0, 0, SK_ColorGREEN); + canvas.drawPoint(0, 1, SK_ColorBLUE); + canvas.drawPoint(1, 0, SK_ColorBLUE); + canvas.drawPoint(1, 1, SK_ColorGREEN); + } + + scoped_refptr<FakePicturePileImpl> pile = + FakePicturePileImpl::CreateFilledPile(pile_tile_size, viewport.size()); + SkPaint paint; + paint.setFilterLevel(SkPaint::kLow_FilterLevel); + pile->add_draw_bitmap_with_paint(bitmap, gfx::Point(), paint); + pile->RerecordPile(); + + gfx::Transform content_to_target_transform; + SharedQuadState* shared_state = CreateTestSharedQuadState( + content_to_target_transform, viewport, pass.get()); + + PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); + quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, + gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor, + texture_format, viewport, 1.f, pile.get()); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")), + ExactPixelComparator(true))); +} + +// This disables filtering by setting |nearest_neighbor| on the TileDrawQuad. +TYPED_TEST(RendererPixelTest, TileDrawQuadNearestNeighbor) { + gfx::Rect viewport(this->device_viewport_size_); + bool swizzle_contents = true; + bool nearest_neighbor = true; + + SkBitmap bitmap; + bitmap.allocN32Pixels(2, 2); + { + SkAutoLockPixels lock(bitmap); + SkCanvas canvas(bitmap); + canvas.drawPoint(0, 0, SK_ColorGREEN); + canvas.drawPoint(0, 1, SK_ColorBLUE); + canvas.drawPoint(1, 0, SK_ColorBLUE); + canvas.drawPoint(1, 1, SK_ColorGREEN); + } + + gfx::Size tile_size(2, 2); + ResourceProvider::ResourceId resource = + this->resource_provider_->CreateResource( + tile_size, + GL_CLAMP_TO_EDGE, + ResourceProvider::TextureHintImmutable, + RGBA_8888); + + { + SkAutoLockPixels lock(bitmap); + this->resource_provider_->SetPixels( + resource, + static_cast<uint8_t*>(bitmap.getPixels()), + gfx::Rect(tile_size), + gfx::Rect(tile_size), + gfx::Vector2d()); + } + + RenderPassId id(1, 1); + gfx::Transform transform_to_root; + scoped_ptr<RenderPass> pass = + CreateTestRenderPass(id, viewport, transform_to_root); + + gfx::Transform content_to_target_transform; + SharedQuadState* shared_state = CreateTestSharedQuadState( + content_to_target_transform, viewport, pass.get()); + + TileDrawQuad* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>(); + quad->SetNew(shared_state, viewport, gfx::Rect(), viewport, resource, + gfx::Rect(tile_size), tile_size, swizzle_contents, + nearest_neighbor); + + RenderPassList pass_list; + pass_list.push_back(pass.Pass()); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")), + ExactPixelComparator(true))); +} + TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) { gfx::Size pile_tile_size(1000, 1000); gfx::Rect viewport(this->device_viewport_size_); // TODO(enne): the renderer should figure this out on its own. ResourceFormat texture_format = RGBA_8888; + bool nearest_neighbor = false; RenderPassId id(1, 1); gfx::Transform transform_to_root; @@ -1613,15 +1724,15 @@ pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); green_quad1->SetNew(top_right_green_shared_quad_state, green_rect1, gfx::Rect(), green_rect1, gfx::RectF(green_rect1.size()), - green_rect1.size(), texture_format, green_rect1, 1.f, - green_pile.get()); + green_rect1.size(), nearest_neighbor, texture_format, + green_rect1, 1.f, green_pile.get()); PictureDrawQuad* green_quad2 = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); green_quad2->SetNew(top_right_green_shared_quad_state, green_rect2, gfx::Rect(), green_rect2, gfx::RectF(green_rect2.size()), - green_rect2.size(), texture_format, green_rect2, 1.f, - green_pile.get()); + green_rect2.size(), nearest_neighbor, texture_format, + green_rect2, 1.f, green_pile.get()); // Add a green clipped checkerboard in the bottom right to help test // interleaving picture quad content and solid color content. @@ -1689,7 +1800,7 @@ PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); blue_quad->SetNew(blue_shared_state, quad_content_rect, gfx::Rect(), quad_content_rect, gfx::RectF(quad_content_rect), - content_union_rect.size(), texture_format, + content_union_rect.size(), nearest_neighbor, texture_format, content_union_rect, contents_scale, pile.get()); // Fill left half of viewport with green. @@ -1874,6 +1985,7 @@ gfx::Size pile_tile_size(1000, 1000); gfx::Rect viewport(this->device_viewport_size_); ResourceFormat texture_format = RGBA_4444; + bool nearest_neighbor = false; RenderPassId id(1, 1); gfx::Transform transform_to_root; @@ -1895,7 +2007,8 @@ PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); blue_quad->SetNew(blue_shared_state, viewport, gfx::Rect(), viewport, gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(), - texture_format, viewport, 1.f, blue_pile.get()); + nearest_neighbor, texture_format, viewport, 1.f, + blue_pile.get()); RenderPassList pass_list; pass_list.push_back(pass.Pass());
diff --git a/cc/output/shader.cc b/cc/output/shader.cc index e22e446..5bc7044 100644 --- a/cc/output/shader.cc +++ b/cc/output/shader.cc
@@ -695,14 +695,14 @@ // clang-format off static const std::string kFunctionApplyBlendMode = SHADER0( // clang-format on - uniform SamplerType s_backdropTexture; + 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 TextureLookup(s_backdropTexture, bgTexCoord); + return texture2D(s_backdropTexture, bgTexCoord); } vec4 ApplyBlendMode(vec4 src) {
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc index ddd3473..1b18648 100644 --- a/cc/output/software_renderer.cc +++ b/cc/output/software_renderer.cc
@@ -347,7 +347,8 @@ // (http://crbug.com/280374). skia::RefPtr<SkDrawFilter> opacity_filter = skia::AdoptRef(new skia::OpacityDrawFilter( - quad->opacity(), frame->disable_picture_quad_image_filtering)); + quad->opacity(), frame->disable_picture_quad_image_filtering || + quad->nearest_neighbor)); DCHECK(!current_canvas_->getDrawFilter()); current_canvas_->setDrawFilter(opacity_filter.get()); @@ -449,7 +450,9 @@ QuadVertexRect(), quad->rect, quad->visible_rect); SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect); - current_paint_.setFilterLevel(SkPaint::kLow_FilterLevel); + current_paint_.setFilterLevel(quad->nearest_neighbor + ? SkPaint::kNone_FilterLevel + : SkPaint::kLow_FilterLevel); current_canvas_->drawBitmapRectToRect( *lock.sk_bitmap(), &uv_rect,
diff --git a/cc/output/software_renderer_unittest.cc b/cc/output/software_renderer_unittest.cc index ea584ee..7f689a8 100644 --- a/cc/output/software_renderer_unittest.cc +++ b/cc/output/software_renderer_unittest.cc
@@ -211,6 +211,7 @@ resource_cyan, gfx::RectF(inner_size), inner_size, + false, false); TileDrawQuad* outer_quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); @@ -221,6 +222,7 @@ resource_yellow, gfx::RectF(outer_size), outer_size, + false, false); RenderPassList list; @@ -294,6 +296,7 @@ resource_cyan, gfx::RectF(tile_size), tile_size, + false, false); quad->visible_rect = visible_rect;
diff --git a/cc/quads/content_draw_quad_base.cc b/cc/quads/content_draw_quad_base.cc index fd6e91b..7304498 100644 --- a/cc/quads/content_draw_quad_base.cc +++ b/cc/quads/content_draw_quad_base.cc
@@ -25,13 +25,15 @@ const gfx::Rect& visible_rect, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents) { + bool swizzle_contents, + bool nearest_neighbor) { bool needs_blending = false; DrawQuad::SetAll(shared_quad_state, material, rect, opaque_rect, visible_rect, needs_blending); this->tex_coord_rect = tex_coord_rect; this->texture_size = texture_size; this->swizzle_contents = swizzle_contents; + this->nearest_neighbor = nearest_neighbor; } void ContentDrawQuadBase::SetAll(const SharedQuadState* shared_quad_state, @@ -42,12 +44,14 @@ bool needs_blending, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents) { + bool swizzle_contents, + bool nearest_neighbor) { DrawQuad::SetAll(shared_quad_state, material, rect, opaque_rect, visible_rect, needs_blending); this->tex_coord_rect = tex_coord_rect; this->texture_size = texture_size; this->swizzle_contents = swizzle_contents; + this->nearest_neighbor = nearest_neighbor; } void ContentDrawQuadBase::ExtendValue(base::debug::TracedValue* value) const { @@ -60,6 +64,7 @@ value->EndDictionary(); value->SetBoolean("swizzle_contents", swizzle_contents); + value->SetBoolean("nearest_neighbor", nearest_neighbor); } } // namespace cc
diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h index b0e53dc..58aa727 100644 --- a/cc/quads/content_draw_quad_base.h +++ b/cc/quads/content_draw_quad_base.h
@@ -23,7 +23,8 @@ const gfx::Rect& visible_rect, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents); + bool swizzle_contents, + bool nearest_neighbor); void SetAll(const SharedQuadState* shared_quad_state, DrawQuad::Material material, @@ -33,11 +34,13 @@ bool needs_blending, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents); + bool swizzle_contents, + bool nearest_neighbor); gfx::RectF tex_coord_rect; gfx::Size texture_size; bool swizzle_contents; + bool nearest_neighbor; protected: ContentDrawQuadBase();
diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc index e65b326..97fea32 100644 --- a/cc/quads/draw_quad_unittest.cc +++ b/cc/quads/draw_quad_unittest.cc
@@ -600,15 +600,17 @@ gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f); gfx::Size texture_size(85, 32); bool swizzle_contents = true; + bool nearest_neighbor = true; CREATE_SHARED_STATE(); - CREATE_QUAD_6_NEW(TileDrawQuad, + CREATE_QUAD_7_NEW(TileDrawQuad, opaque_rect, visible_rect, resource_id, tex_coord_rect, texture_size, - swizzle_contents); + swizzle_contents, + nearest_neighbor); EXPECT_EQ(DrawQuad::TILED_CONTENT, copy_quad->material); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); EXPECT_EQ(visible_rect, copy_quad->visible_rect); @@ -616,17 +618,20 @@ EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect); EXPECT_EQ(texture_size, copy_quad->texture_size); EXPECT_EQ(swizzle_contents, copy_quad->swizzle_contents); + EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor); - CREATE_QUAD_4_ALL(TileDrawQuad, + CREATE_QUAD_5_ALL(TileDrawQuad, resource_id, tex_coord_rect, texture_size, - swizzle_contents); + swizzle_contents, + nearest_neighbor); EXPECT_EQ(DrawQuad::TILED_CONTENT, copy_quad->material); EXPECT_EQ(resource_id, copy_quad->resource_id); EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect); EXPECT_EQ(texture_size, copy_quad->texture_size); EXPECT_EQ(swizzle_contents, copy_quad->swizzle_contents); + EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor); } TEST(DrawQuadTest, CopyYUVVideoDrawQuad) { @@ -680,31 +685,34 @@ gfx::Rect visible_rect(40, 50, 30, 20); gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f); gfx::Size texture_size(85, 32); + bool nearest_neighbor = true; ResourceFormat texture_format = RGBA_8888; gfx::Rect content_rect(30, 40, 20, 30); float contents_scale = 3.141592f; scoped_refptr<RasterSource> raster_source = PicturePileImpl::Create(); CREATE_SHARED_STATE(); - CREATE_QUAD_8_NEW(PictureDrawQuad, opaque_rect, visible_rect, tex_coord_rect, - texture_size, texture_format, content_rect, contents_scale, - raster_source); + CREATE_QUAD_9_NEW(PictureDrawQuad, opaque_rect, visible_rect, tex_coord_rect, + texture_size, nearest_neighbor, texture_format, + content_rect, contents_scale, raster_source); EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material); EXPECT_EQ(opaque_rect, copy_quad->opaque_rect); EXPECT_EQ(visible_rect, copy_quad->visible_rect); EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect); EXPECT_EQ(texture_size, copy_quad->texture_size); + EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor); EXPECT_EQ(texture_format, copy_quad->texture_format); EXPECT_EQ(content_rect, copy_quad->content_rect); EXPECT_EQ(contents_scale, copy_quad->contents_scale); EXPECT_EQ(raster_source, copy_quad->raster_source); - CREATE_QUAD_6_ALL(PictureDrawQuad, tex_coord_rect, texture_size, - texture_format, content_rect, contents_scale, - raster_source); + CREATE_QUAD_7_ALL(PictureDrawQuad, tex_coord_rect, texture_size, + nearest_neighbor, texture_format, content_rect, + contents_scale, raster_source); EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material); EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect); EXPECT_EQ(texture_size, copy_quad->texture_size); + EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor); EXPECT_EQ(texture_format, copy_quad->texture_format); EXPECT_EQ(content_rect, copy_quad->content_rect); EXPECT_EQ(contents_scale, copy_quad->contents_scale); @@ -871,15 +879,17 @@ gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f); gfx::Size texture_size(85, 32); bool swizzle_contents = true; + bool nearest_neighbor = true; CREATE_SHARED_STATE(); - CREATE_QUAD_6_NEW(TileDrawQuad, + CREATE_QUAD_7_NEW(TileDrawQuad, opaque_rect, visible_rect, resource_id, tex_coord_rect, texture_size, - swizzle_contents); + swizzle_contents, + nearest_neighbor); EXPECT_EQ(resource_id, quad_new->resource_id); EXPECT_EQ(1, IterateAndCount(quad_new)); EXPECT_EQ(resource_id + 1, quad_new->resource_id); @@ -924,15 +934,16 @@ gfx::Rect visible_rect(40, 50, 30, 20); gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f); gfx::Size texture_size(85, 32); + bool nearest_neighbor = true; ResourceFormat texture_format = RGBA_8888; gfx::Rect content_rect(30, 40, 20, 30); float contents_scale = 3.141592f; scoped_refptr<PicturePileImpl> raster_source = PicturePileImpl::Create(); CREATE_SHARED_STATE(); - CREATE_QUAD_8_NEW(PictureDrawQuad, opaque_rect, visible_rect, tex_coord_rect, - texture_size, texture_format, content_rect, contents_scale, - raster_source); + CREATE_QUAD_9_NEW(PictureDrawQuad, opaque_rect, visible_rect, tex_coord_rect, + texture_size, nearest_neighbor, texture_format, + content_rect, contents_scale, raster_source); EXPECT_EQ(0, IterateAndCount(quad_new)); }
diff --git a/cc/quads/picture_draw_quad.cc b/cc/quads/picture_draw_quad.cc index bf329c2..2171542 100644 --- a/cc/quads/picture_draw_quad.cc +++ b/cc/quads/picture_draw_quad.cc
@@ -23,6 +23,7 @@ const gfx::Rect& visible_rect, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, + bool nearest_neighbor, ResourceFormat texture_format, const gfx::Rect& content_rect, float contents_scale, @@ -35,7 +36,8 @@ visible_rect, tex_coord_rect, texture_size, - !PlatformColor::SameComponentOrder(texture_format)); + !PlatformColor::SameComponentOrder(texture_format), + nearest_neighbor); this->content_rect = content_rect; this->contents_scale = contents_scale; this->raster_source = raster_source; @@ -49,6 +51,7 @@ bool needs_blending, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, + bool nearest_neighbor, ResourceFormat texture_format, const gfx::Rect& content_rect, float contents_scale, @@ -62,7 +65,8 @@ tex_coord_rect, texture_size, !PlatformColor::SameComponentOrder( - texture_format)); + texture_format), + nearest_neighbor); this->content_rect = content_rect; this->contents_scale = contents_scale; this->raster_source = raster_source;
diff --git a/cc/quads/picture_draw_quad.h b/cc/quads/picture_draw_quad.h index 62c9f18..624b69c 100644 --- a/cc/quads/picture_draw_quad.h +++ b/cc/quads/picture_draw_quad.h
@@ -28,6 +28,7 @@ const gfx::Rect& visible_rect, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, + bool nearest_neighbor, ResourceFormat texture_format, const gfx::Rect& content_rect, float contents_scale, @@ -40,6 +41,7 @@ bool needs_blending, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, + bool nearest_neighbor, ResourceFormat texture_format, const gfx::Rect& content_rect, float contents_scale,
diff --git a/cc/quads/tile_draw_quad.cc b/cc/quads/tile_draw_quad.cc index ea3a14a..88a4b3a 100644 --- a/cc/quads/tile_draw_quad.cc +++ b/cc/quads/tile_draw_quad.cc
@@ -25,7 +25,8 @@ unsigned resource_id, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents) { + bool swizzle_contents, + bool nearest_neighbor) { ContentDrawQuadBase::SetNew(shared_quad_state, DrawQuad::TILED_CONTENT, rect, @@ -33,7 +34,8 @@ visible_rect, tex_coord_rect, texture_size, - swizzle_contents); + swizzle_contents, + nearest_neighbor); this->resource_id = resource_id; } @@ -45,10 +47,12 @@ unsigned resource_id, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents) { + bool swizzle_contents, + bool nearest_neighbor) { ContentDrawQuadBase::SetAll(shared_quad_state, DrawQuad::TILED_CONTENT, rect, opaque_rect, visible_rect, needs_blending, - tex_coord_rect, texture_size, swizzle_contents); + tex_coord_rect, texture_size, swizzle_contents, + nearest_neighbor); this->resource_id = resource_id; }
diff --git a/cc/quads/tile_draw_quad.h b/cc/quads/tile_draw_quad.h index d776057..e668ddb 100644 --- a/cc/quads/tile_draw_quad.h +++ b/cc/quads/tile_draw_quad.h
@@ -21,7 +21,8 @@ unsigned resource_id, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents); + bool swizzle_contents, + bool nearest_neighbor); void SetAll(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, @@ -31,7 +32,8 @@ unsigned resource_id, const gfx::RectF& tex_coord_rect, const gfx::Size& texture_size, - bool swizzle_contents); + bool swizzle_contents, + bool nearest_neighbor); unsigned resource_id;
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc index 3c0e0e4..ab4c646 100644 --- a/cc/resources/display_list_recording_source.cc +++ b/cc/resources/display_list_recording_source.cc
@@ -142,9 +142,8 @@ if (display_list_->ApproximateOpCount() > kOpCountThatIsOkToAnalyze) return; - skia::AnalysisCanvas canvas(recorded_viewport_.width(), - recorded_viewport_.height()); - canvas.translate(-recorded_viewport_.x(), -recorded_viewport_.y()); + gfx::Size layer_size = GetSize(); + skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height()); display_list_->Raster(&canvas, nullptr, 1.f); is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); }
diff --git a/cc/resources/eviction_tile_priority_queue.cc b/cc/resources/eviction_tile_priority_queue.cc index 4d66987..cd681ef 100644 --- a/cc/resources/eviction_tile_priority_queue.cc +++ b/cc/resources/eviction_tile_priority_queue.cc
@@ -200,6 +200,8 @@ const Tile* active_tile = active_queue->Top(); const Tile* pending_tile = pending_queue->Top(); + + // If tiles are the same, it doesn't matter which tree we return. if (active_tile == pending_tile) return ACTIVE_TREE; @@ -208,6 +210,15 @@ const TilePriority& pending_priority = pending_tile->priority_for_tree_priority(tree_priority); + // If the bins are the same and activation differs, then return the tree of + // the tile not required for activation. + if (active_priority.priority_bin == pending_priority.priority_bin && + active_tile->required_for_activation() != + pending_tile->required_for_activation()) { + return active_tile->required_for_activation() ? PENDING_TREE : ACTIVE_TREE; + } + + // Return tile with a lower priority. if (pending_priority.IsHigherPriorityThan(active_priority)) return ACTIVE_TREE; return PENDING_TREE;
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc index 6530866..ea7680c 100644 --- a/cc/resources/picture.cc +++ b/cc/resources/picture.cc
@@ -121,7 +121,7 @@ if (skpicture == NULL) return NULL; - gfx::Rect layer_rect(skpicture->width(), skpicture->height()); + gfx::Rect layer_rect(gfx::SkIRectToRect(skpicture->cullRect().roundOut())); return make_scoped_refptr(new Picture(skpicture, layer_rect)); }
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc index e9e3b86..d2d5484 100644 --- a/cc/resources/picture_layer_tiling.cc +++ b/cc/resources/picture_layer_tiling.cc
@@ -25,63 +25,44 @@ const float kSoonBorderDistanceInScreenPixels = 312.f; -class TileEvictionOrder { - public: - explicit TileEvictionOrder(TreePriority tree_priority) - : tree_priority_(tree_priority) {} - ~TileEvictionOrder() {} - - bool operator()(const Tile* a, const Tile* b) { - const TilePriority& a_priority = - a->priority_for_tree_priority(tree_priority_); - const TilePriority& b_priority = - b->priority_for_tree_priority(tree_priority_); - - DCHECK(a_priority.priority_bin == b_priority.priority_bin); - DCHECK(a->required_for_activation() == b->required_for_activation()); - - // Or if a is occluded and b is unoccluded. - bool a_is_occluded = a->is_occluded_for_tree_priority(tree_priority_); - bool b_is_occluded = b->is_occluded_for_tree_priority(tree_priority_); - if (a_is_occluded != b_is_occluded) - return a_is_occluded; - - // Or if a is farther away from visible. - return a_priority.distance_to_visible > b_priority.distance_to_visible; - } - - private: - TreePriority tree_priority_; -}; - } // namespace scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( float contents_scale, const gfx::Size& layer_bounds, - PictureLayerTilingClient* client) { - return make_scoped_ptr(new PictureLayerTiling(contents_scale, - layer_bounds, - client)); + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content_pixels) { + return make_scoped_ptr(new PictureLayerTiling( + contents_scale, layer_bounds, client, max_tiles_for_interest_area, + skewport_target_time_in_seconds, + skewport_extrapolation_limit_in_content_pixels)); } -PictureLayerTiling::PictureLayerTiling(float contents_scale, - const gfx::Size& layer_bounds, - PictureLayerTilingClient* client) - : contents_scale_(contents_scale), +PictureLayerTiling::PictureLayerTiling( + float contents_scale, + const gfx::Size& layer_bounds, + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content_pixels) + : max_tiles_for_interest_area_(max_tiles_for_interest_area), + skewport_target_time_in_seconds_(skewport_target_time_in_seconds), + skewport_extrapolation_limit_in_content_pixels_( + skewport_extrapolation_limit_in_content_pixels), + contents_scale_(contents_scale), layer_bounds_(layer_bounds), resolution_(NON_IDEAL_RESOLUTION), client_(client), tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), last_impl_frame_time_in_seconds_(0.0), - content_to_screen_scale_(0.f), can_require_tiles_for_activation_(false), + current_content_to_screen_scale_(0.f), has_visible_rect_tiles_(false), has_skewport_rect_tiles_(false), has_soon_border_rect_tiles_(false), - has_eventually_rect_tiles_(false), - eviction_tiles_cache_valid_(false), - eviction_cache_tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES) { + has_eventually_rect_tiles_(false) { gfx::Size content_bounds = gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); gfx::Size tile_size = client_->CalculateTileSize(content_bounds); @@ -105,13 +86,13 @@ it->second->set_shared(false); } -void PictureLayerTiling::SetClient(PictureLayerTilingClient* client) { - client_ = client; -} - Tile* PictureLayerTiling::CreateTile(int i, int j, - const PictureLayerTiling* twin_tiling) { + const PictureLayerTiling* twin_tiling, + PictureLayerTiling* recycled_twin) { + // Can't have both a (pending or active) twin and a recycled twin tiling. + DCHECK_IMPLIES(twin_tiling, !recycled_twin); + DCHECK_IMPLIES(recycled_twin, !twin_tiling); TileMapKey key(i, j); DCHECK(tiles_.find(key) == tiles_.end()); @@ -144,14 +125,24 @@ DCHECK(!tile->is_shared()); tile->set_tiling_index(i, j); tiles_[key] = tile; + + if (recycled_twin) { + DCHECK(recycled_twin->tiles_.find(key) == recycled_twin->tiles_.end()); + // Do what recycled_twin->CreateTile() would do. + tile->set_shared(true); + recycled_twin->tiles_[key] = tile; + } } - eviction_tiles_cache_valid_ = false; return tile.get(); } void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { const PictureLayerTiling* twin_tiling = client_->GetPendingOrActiveTwinTiling(this); + // There is no recycled twin during commit from the main thread which is when + // this occurs. + PictureLayerTiling* null_recycled_twin = nullptr; + DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); bool include_borders = false; for (TilingData::Iterator iter( &tiling_data_, live_tiles_rect_, include_borders); @@ -161,116 +152,160 @@ TileMap::iterator find = tiles_.find(key); if (find != tiles_.end()) continue; - CreateTile(key.first, key.second, twin_tiling); + CreateTile(key.first, key.second, twin_tiling, null_recycled_twin); } - VerifyLiveTilesRect(); + VerifyLiveTilesRect(false); } -void PictureLayerTiling::UpdateTilesToCurrentRasterSource( - RasterSource* raster_source, - const Region& layer_invalidation, - const gfx::Size& new_layer_bounds) { - DCHECK(!new_layer_bounds.IsEmpty()); +void PictureLayerTiling::CloneTilesAndPropertiesFrom( + const PictureLayerTiling& twin_tiling) { + DCHECK_EQ(&twin_tiling, client_->GetPendingOrActiveTwinTiling(this)); + Resize(twin_tiling.layer_bounds_); + DCHECK_EQ(twin_tiling.contents_scale_, contents_scale_); + DCHECK_EQ(twin_tiling.layer_bounds().ToString(), layer_bounds().ToString()); + DCHECK_EQ(twin_tiling.tile_size().ToString(), tile_size().ToString()); + + resolution_ = twin_tiling.resolution_; + + SetLiveTilesRect(twin_tiling.live_tiles_rect()); + + // Recreate unshared tiles. + std::vector<TileMapKey> to_remove; + for (const auto& tile_map_pair : tiles_) { + TileMapKey key = tile_map_pair.first; + Tile* tile = tile_map_pair.second.get(); + if (!tile->is_shared()) + to_remove.push_back(key); + } + // The recycled twin does not exist since there is a pending twin (which is + // |twin_tiling|). + PictureLayerTiling* null_recycled_twin = nullptr; + DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); + for (const auto& key : to_remove) { + RemoveTileAt(key.first, key.second, null_recycled_twin); + CreateTile(key.first, key.second, &twin_tiling, null_recycled_twin); + } + + // Create any missing tiles from the |twin_tiling|. + for (const auto& tile_map_pair : twin_tiling.tiles_) { + TileMapKey key = tile_map_pair.first; + Tile* tile = tile_map_pair.second.get(); + if (!tile->is_shared()) + CreateTile(key.first, key.second, &twin_tiling, null_recycled_twin); + } + + DCHECK_EQ(twin_tiling.tiles_.size(), tiles_.size()); +#if DCHECK_IS_ON + for (const auto& tile_map_pair : tiles_) + DCHECK(tile_map_pair.second->is_shared()); + VerifyLiveTilesRect(false); +#endif + + UpdateTilePriorityRects(twin_tiling.current_content_to_screen_scale_, + twin_tiling.current_visible_rect_, + twin_tiling.current_skewport_rect_, + twin_tiling.current_soon_border_rect_, + twin_tiling.current_eventually_rect_, + twin_tiling.current_occlusion_in_layer_space_); +} + +void PictureLayerTiling::Resize(const gfx::Size& new_layer_bounds) { + gfx::Size layer_bounds = new_layer_bounds; gfx::Size content_bounds = gfx::ToCeiledSize(gfx::ScaleSize(new_layer_bounds, contents_scale_)); gfx::Size tile_size = client_->CalculateTileSize(content_bounds); - if (new_layer_bounds != layer_bounds_) { - if (tile_size.IsEmpty()) { - layer_bounds_ = gfx::Size(); - content_bounds = gfx::Size(); - } else { - layer_bounds_ = new_layer_bounds; - } - - // The SetLiveTilesRect() method would drop tiles outside the new bounds, - // but may do so incorrectly if resizing the tiling causes the number of - // tiles in the tiling_data_ to change. - gfx::Rect content_rect(content_bounds); - int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); - int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); - int before_right = - tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); - int before_bottom = - tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); - - // The live_tiles_rect_ is clamped to stay within the tiling size as we - // change it. - live_tiles_rect_.Intersect(content_rect); - tiling_data_.SetTilingSize(content_bounds); - - int after_right = -1; - int after_bottom = -1; - if (!live_tiles_rect_.IsEmpty()) { - after_right = - tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); - after_bottom = - tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); - } - - // There is no recycled twin since this is run on the pending tiling. - PictureLayerTiling* recycled_twin = NULL; - DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); - DCHECK_EQ(PENDING_TREE, client_->GetTree()); - - // Drop tiles outside the new layer bounds if the layer shrank. - for (int i = after_right + 1; i <= before_right; ++i) { - for (int j = before_top; j <= before_bottom; ++j) - RemoveTileAt(i, j, recycled_twin); - } - for (int i = before_left; i <= after_right; ++i) { - for (int j = after_bottom + 1; j <= before_bottom; ++j) - RemoveTileAt(i, j, recycled_twin); - } - - // If the layer grew, the live_tiles_rect_ is not changed, but a new row - // and/or column of tiles may now exist inside the same live_tiles_rect_. - const PictureLayerTiling* twin_tiling = - client_->GetPendingOrActiveTwinTiling(this); - if (after_right > before_right) { - DCHECK_EQ(after_right, before_right + 1); - for (int j = before_top; j <= after_bottom; ++j) - CreateTile(after_right, j, twin_tiling); - } - if (after_bottom > before_bottom) { - DCHECK_EQ(after_bottom, before_bottom + 1); - for (int i = before_left; i <= before_right; ++i) - CreateTile(i, after_bottom, twin_tiling); - } + if (tile_size.IsEmpty()) { + layer_bounds = gfx::Size(); + content_bounds = gfx::Size(); } + // The layer bounds are only allowed to be empty when the tile size is empty. + // Otherwise we should not have such a tiling in the first place. + DCHECK_IMPLIES(!tile_size.IsEmpty(), !layer_bounds_.IsEmpty()); + + bool resized = layer_bounds != layer_bounds_; + layer_bounds_ = layer_bounds; + if (tile_size != tiling_data_.max_texture_size()) { + tiling_data_.SetTilingSize(content_bounds); tiling_data_.SetMaxTextureSize(tile_size); // When the tile size changes, the TilingData positions no longer work - // as valid keys to the TileMap, so just drop all tiles. + // as valid keys to the TileMap, so just drop all tiles and clear the live + // tiles rect. Reset(); - } else { - Invalidate(layer_invalidation); + return; } - for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) - it->second->set_raster_source(raster_source); - VerifyLiveTilesRect(); + if (!resized) + return; + + // The SetLiveTilesRect() method would drop tiles outside the new bounds, + // but may do so incorrectly if resizing the tiling causes the number of + // tiles in the tiling_data_ to change. + gfx::Rect content_rect(content_bounds); + int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); + int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); + int before_right = + tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); + int before_bottom = + tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); + + // The live_tiles_rect_ is clamped to stay within the tiling size as we + // change it. + live_tiles_rect_.Intersect(content_rect); + tiling_data_.SetTilingSize(content_bounds); + + int after_right = -1; + int after_bottom = -1; + if (!live_tiles_rect_.IsEmpty()) { + after_right = + tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); + after_bottom = + tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); + } + + // There is no recycled twin since this is run on the pending tiling + // during commit, and on the active tree during activate. + PictureLayerTiling* null_recycled_twin = nullptr; + DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); + + // Drop tiles outside the new layer bounds if the layer shrank. + for (int i = after_right + 1; i <= before_right; ++i) { + for (int j = before_top; j <= before_bottom; ++j) + RemoveTileAt(i, j, null_recycled_twin); + } + for (int i = before_left; i <= after_right; ++i) { + for (int j = after_bottom + 1; j <= before_bottom; ++j) + RemoveTileAt(i, j, null_recycled_twin); + } + + // If the layer grew, the live_tiles_rect_ is not changed, but a new row + // and/or column of tiles may now exist inside the same live_tiles_rect_. + const PictureLayerTiling* twin_tiling = + client_->GetPendingOrActiveTwinTiling(this); + if (after_right > before_right) { + DCHECK_EQ(after_right, before_right + 1); + for (int j = before_top; j <= after_bottom; ++j) + CreateTile(after_right, j, twin_tiling, null_recycled_twin); + } + if (after_bottom > before_bottom) { + DCHECK_EQ(after_bottom, before_bottom + 1); + for (int i = before_left; i <= before_right; ++i) + CreateTile(i, after_bottom, twin_tiling, null_recycled_twin); + } } -void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_region) { - bool recreate_invalidated_tiles = false; - DoInvalidate(layer_region, recreate_invalidated_tiles); -} - -void PictureLayerTiling::Invalidate(const Region& layer_region) { - bool recreate_invalidated_tiles = true; - DoInvalidate(layer_region, recreate_invalidated_tiles); -} - -void PictureLayerTiling::DoInvalidate(const Region& layer_region, - bool recreate_invalidated_tiles) { +void PictureLayerTiling::Invalidate(const Region& layer_invalidation) { + if (live_tiles_rect_.IsEmpty()) + return; std::vector<TileMapKey> new_tile_keys; gfx::Rect expanded_live_tiles_rect = tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_); - for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) { + for (Region::Iterator iter(layer_invalidation); iter.has_rect(); + iter.next()) { gfx::Rect layer_rect = iter.rect(); gfx::Rect content_rect = gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); @@ -291,25 +326,40 @@ &tiling_data_, content_rect, include_borders); iter; ++iter) { - // There is no recycled twin since this is run on the pending tiling. - PictureLayerTiling* recycled_twin = NULL; - DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); - DCHECK_EQ(PENDING_TREE, client_->GetTree()); - if (RemoveTileAt(iter.index_x(), iter.index_y(), recycled_twin)) + // There is no recycled twin for the pending tree during commit, or for + // the active tree during activation. + PictureLayerTiling* null_recycled_twin = nullptr; + DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); + if (RemoveTileAt(iter.index_x(), iter.index_y(), null_recycled_twin)) new_tile_keys.push_back(iter.index()); } } - if (recreate_invalidated_tiles && !new_tile_keys.empty()) { + if (!new_tile_keys.empty()) { + // During commit from the main thread, invalidations can never be shared + // with the active tree since the active tree has different content there. + // And when invalidating an active-tree tiling, it means there was no + // pending tiling to clone from. + const PictureLayerTiling* null_twin_tiling = nullptr; + PictureLayerTiling* null_recycled_twin = nullptr; + DCHECK_EQ(null_recycled_twin, client_->GetRecycledTwinTiling(this)); for (size_t i = 0; i < new_tile_keys.size(); ++i) { - // Don't try to share a tile with the twin layer, it's been invalidated so - // we have to make our own tile here. - const PictureLayerTiling* twin_tiling = NULL; - CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, twin_tiling); + CreateTile(new_tile_keys[i].first, new_tile_keys[i].second, + null_twin_tiling, null_recycled_twin); } } } +void PictureLayerTiling::SetRasterSource( + scoped_refptr<RasterSource> raster_source) { + // Shared (ie. non-invalidated) tiles on the pending tree are updated to use + // the new raster source. When this raster source is activated, the raster + // source will remain valid for shared tiles in the active tree. + for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) + it->second->set_raster_source(raster_source); + VerifyLiveTilesRect(false); +} + PictureLayerTiling::CoverageIterator::CoverageIterator() : tiling_(NULL), current_tile_(NULL), @@ -468,10 +518,9 @@ return false; found->second->set_shared(false); tiles_.erase(found); - eviction_tiles_cache_valid_ = false; if (recycled_twin) { - // Recycled twin does not also have a recycled twin, so pass NULL. - recycled_twin->RemoveTileAt(i, j, NULL); + // Recycled twin does not also have a recycled twin, so pass null. + recycled_twin->RemoveTileAt(i, j, nullptr); } return true; } @@ -482,10 +531,9 @@ for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { it->second->set_shared(false); if (recycled_twin) - recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); + recycled_twin->RemoveTileAt(it->first.first, it->first.second, nullptr); } tiles_.clear(); - eviction_tiles_cache_valid_ = false; } gfx::Rect PictureLayerTiling::ComputeSkewport( @@ -500,10 +548,8 @@ if (time_delta == 0.0) return skewport; - float skewport_target_time_in_seconds = - client_->GetSkewportTargetTimeInSeconds(); double extrapolation_multiplier = - skewport_target_time_in_seconds / time_delta; + skewport_target_time_in_seconds_ / time_delta; int old_x = last_visible_rect_in_content_space_.x(); int old_y = last_visible_rect_in_content_space_.y(); @@ -515,12 +561,11 @@ int new_right = visible_rect_in_content_space.right(); int new_bottom = visible_rect_in_content_space.bottom(); - int skewport_limit = client_->GetSkewportExtrapolationLimitInContentPixels(); - - // Compute the maximum skewport based on |skewport_limit|. + // Compute the maximum skewport based on + // |skewport_extrapolation_limit_in_content_pixels_|. gfx::Rect max_skewport = skewport; - max_skewport.Inset( - -skewport_limit, -skewport_limit, -skewport_limit, -skewport_limit); + max_skewport.Inset(-skewport_extrapolation_limit_in_content_pixels_, + -skewport_extrapolation_limit_in_content_pixels_); // Inset the skewport by the needed adjustment. skewport.Inset(extrapolation_multiplier * (new_x - old_x), @@ -564,11 +609,9 @@ DCHECK(skewport.Contains(visible_rect_in_content_space)); // Calculate the eventually/live tiles rect. - size_t max_tiles_for_interest_area = client_->GetMaxTilesForInterestArea(); - gfx::Size tile_size = tiling_data_.max_texture_size(); int64 eventually_rect_area = - max_tiles_for_interest_area * tile_size.width() * tile_size.height(); + max_tiles_for_interest_area_ * tile_size.width() * tile_size.height(); gfx::Rect eventually_rect = ExpandRectEquallyToAreaBoundedBy(visible_rect_in_content_space, @@ -582,29 +625,36 @@ << " eventually_rect: " << eventually_rect.ToString(); // Calculate the soon border rect. - content_to_screen_scale_ = ideal_contents_scale / contents_scale_; + 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 = kSoonBorderDistanceInScreenPixels / content_to_screen_scale; soon_border_rect.Inset(-border, -border, -border, -border); - // Update the tiling state. - SetLiveTilesRect(eventually_rect); - last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; last_viewport_in_layer_space_ = viewport_in_layer_space; last_visible_rect_in_content_space_ = visible_rect_in_content_space; - eviction_tiles_cache_valid_ = false; + SetLiveTilesRect(eventually_rect); + UpdateTilePriorityRects( + content_to_screen_scale, visible_rect_in_content_space, skewport, + soon_border_rect, eventually_rect, occlusion_in_layer_space); +} +void PictureLayerTiling::UpdateTilePriorityRects( + float content_to_screen_scale, + const gfx::Rect& visible_rect_in_content_space, + const gfx::Rect& skewport, + const gfx::Rect& soon_border_rect, + const gfx::Rect& eventually_rect, + const Occlusion& occlusion_in_layer_space) { current_visible_rect_ = visible_rect_in_content_space; current_skewport_rect_ = skewport; current_soon_border_rect_ = soon_border_rect; current_eventually_rect_ = eventually_rect; current_occlusion_in_layer_space_ = occlusion_in_layer_space; + current_content_to_screen_scale_ = content_to_screen_scale; - // Update has_*_tiles state. gfx::Rect tiling_rect(tiling_size()); - has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_); has_soon_border_rect_tiles_ = @@ -621,8 +671,9 @@ if (live_tiles_rect_ == new_live_tiles_rect) return; - // Iterate to delete all tiles outside of our new live_tiles rect. PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); + + // Iterate to delete all tiles outside of our new live_tiles rect. for (TilingData::DifferenceIterator iter(&tiling_data_, live_tiles_rect_, new_live_tiles_rect); @@ -641,16 +692,20 @@ iter; ++iter) { TileMapKey key(iter.index()); - CreateTile(key.first, key.second, twin_tiling); + CreateTile(key.first, key.second, twin_tiling, recycled_twin); } live_tiles_rect_ = new_live_tiles_rect; - VerifyLiveTilesRect(); + VerifyLiveTilesRect(false); + if (recycled_twin) { + recycled_twin->live_tiles_rect_ = live_tiles_rect_; + recycled_twin->VerifyLiveTilesRect(true); + } } -void PictureLayerTiling::VerifyLiveTilesRect() { +void PictureLayerTiling::VerifyLiveTilesRect(bool is_on_recycle_tree) const { #if DCHECK_IS_ON - for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { + for (auto it = tiles_.begin(); it != tiles_.end(); ++it) { if (!it->second.get()) continue; DCHECK(it->first.first < tiling_data_.num_tiles_x()) @@ -667,6 +722,7 @@ << " tile bounds " << tiling_data_.TileBounds(it->first.first, it->first.second).ToString() << " live_tiles_rect " << live_tiles_rect_.ToString(); + DCHECK_IMPLIES(is_on_recycle_tree, it->second->is_shared()); } #endif } @@ -805,10 +861,10 @@ tile->set_required_for_draw(false); tile->set_is_occluded(tree, false); - DCHECK_GT(content_to_screen_scale_, 0.f); + DCHECK_GT(current_content_to_screen_scale_, 0.f); float distance_to_visible = current_visible_rect_.ManhattanInternalDistance(tile_bounds) * - content_to_screen_scale_; + current_content_to_screen_scale_; if (max_tile_priority_bin <= TilePriority::SOON && (current_soon_border_rect_.Intersects(tile_bounds) || @@ -998,92 +1054,6 @@ return result; } -void PictureLayerTiling::UpdateEvictionCacheIfNeeded( - TreePriority tree_priority) { - if (eviction_tiles_cache_valid_ && - eviction_cache_tree_priority_ == tree_priority) - return; - - eviction_tiles_now_.clear(); - eviction_tiles_now_and_required_for_activation_.clear(); - eviction_tiles_soon_.clear(); - eviction_tiles_soon_and_required_for_activation_.clear(); - eviction_tiles_eventually_.clear(); - eviction_tiles_eventually_and_required_for_activation_.clear(); - - for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { - Tile* tile = it->second.get(); - UpdateTileAndTwinPriority(tile); - const TilePriority& priority = - tile->priority_for_tree_priority(tree_priority); - switch (priority.priority_bin) { - case TilePriority::EVENTUALLY: - if (tile->required_for_activation()) - eviction_tiles_eventually_and_required_for_activation_.push_back( - tile); - else - eviction_tiles_eventually_.push_back(tile); - break; - case TilePriority::SOON: - if (tile->required_for_activation()) - eviction_tiles_soon_and_required_for_activation_.push_back(tile); - else - eviction_tiles_soon_.push_back(tile); - break; - case TilePriority::NOW: - if (tile->required_for_activation()) - eviction_tiles_now_and_required_for_activation_.push_back(tile); - else - eviction_tiles_now_.push_back(tile); - break; - } - } - - // TODO(vmpstr): Do this lazily. One option is to have a "sorted" flag that - // can be updated for each of the queues. - TileEvictionOrder sort_order(tree_priority); - std::sort(eviction_tiles_now_.begin(), eviction_tiles_now_.end(), sort_order); - std::sort(eviction_tiles_now_and_required_for_activation_.begin(), - eviction_tiles_now_and_required_for_activation_.end(), - sort_order); - std::sort( - eviction_tiles_soon_.begin(), eviction_tiles_soon_.end(), sort_order); - std::sort(eviction_tiles_soon_and_required_for_activation_.begin(), - eviction_tiles_soon_and_required_for_activation_.end(), - sort_order); - std::sort(eviction_tiles_eventually_.begin(), - eviction_tiles_eventually_.end(), - sort_order); - std::sort(eviction_tiles_eventually_and_required_for_activation_.begin(), - eviction_tiles_eventually_and_required_for_activation_.end(), - sort_order); - - eviction_tiles_cache_valid_ = true; - eviction_cache_tree_priority_ = tree_priority; -} - -const std::vector<Tile*>* PictureLayerTiling::GetEvictionTiles( - TreePriority tree_priority, - EvictionCategory category) { - UpdateEvictionCacheIfNeeded(tree_priority); - switch (category) { - case EVENTUALLY: - return &eviction_tiles_eventually_; - case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: - return &eviction_tiles_eventually_and_required_for_activation_; - case SOON: - return &eviction_tiles_soon_; - case SOON_AND_REQUIRED_FOR_ACTIVATION: - return &eviction_tiles_soon_and_required_for_activation_; - case NOW: - return &eviction_tiles_now_; - case NOW_AND_REQUIRED_FOR_ACTIVATION: - return &eviction_tiles_now_and_required_for_activation_; - } - NOTREACHED(); - return &eviction_tiles_eventually_; -} - PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() : tiling_(NULL), current_tile_(NULL) {}
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h index daa0485..4b80aa0 100644 --- a/cc/resources/picture_layer_tiling.h +++ b/cc/resources/picture_layer_tiling.h
@@ -48,9 +48,6 @@ virtual PictureLayerTiling* GetRecycledTwinTiling( const PictureLayerTiling* tiling) = 0; virtual TilePriority::PriorityBin GetMaxTilePriorityBin() const = 0; - virtual size_t GetMaxTilesForInterestArea() const = 0; - virtual float GetSkewportTargetTimeInSeconds() const = 0; - virtual int GetSkewportExtrapolationLimitInContentPixels() const = 0; virtual WhichTree GetTree() const = 0; virtual bool RequiresHighResToDraw() const = 0; @@ -62,15 +59,6 @@ public: static const int kBorderTexels = 1; - enum EvictionCategory { - EVENTUALLY, - EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION, - SOON, - SOON_AND_REQUIRED_FOR_ACTIVATION, - NOW, - NOW_AND_REQUIRED_FOR_ACTIVATION - }; - class CC_EXPORT TilingRasterTileIterator { public: TilingRasterTileIterator(); @@ -121,18 +109,24 @@ ~PictureLayerTiling(); // Create a tiling with no tiles. CreateTiles must be called to add some. + // TODO(danakj): Pass the raster_source here instead of the size, store the + // raster source instead of layer bounds? static scoped_ptr<PictureLayerTiling> Create( float contents_scale, const gfx::Size& layer_bounds, - PictureLayerTilingClient* client); - gfx::Size layer_bounds() const { return layer_bounds_; } - void UpdateTilesToCurrentRasterSource(RasterSource* raster_source, - const Region& layer_invalidation, - const gfx::Size& new_layer_bounds); - void CreateMissingTilesInLiveTilesRect(); - void RemoveTilesInRegion(const Region& layer_region); + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content_pixels); - void SetClient(PictureLayerTilingClient* client); + gfx::Size layer_bounds() const { return layer_bounds_; } + void Resize(const gfx::Size& new_layer_bounds); + void Invalidate(const Region& layer_invalidation); + void SetRasterSource(scoped_refptr<RasterSource> raster_source); + void CreateMissingTilesInLiveTilesRect(); + + void CloneTilesAndPropertiesFrom(const PictureLayerTiling& twin_tiling); + void set_resolution(TileResolution resolution) { resolution_ = resolution; } TileResolution resolution() const { return resolution_; } void set_can_require_tiles_for_activation(bool can_require_tiles) { @@ -288,10 +282,16 @@ PictureLayerTiling(float contents_scale, const gfx::Size& layer_bounds, - PictureLayerTilingClient* client); + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content_pixels); void SetLiveTilesRect(const gfx::Rect& live_tiles_rect); - void VerifyLiveTilesRect(); - Tile* CreateTile(int i, int j, const PictureLayerTiling* twin_tiling); + void VerifyLiveTilesRect(bool is_on_recycle_tree) const; + Tile* CreateTile(int i, + int j, + const PictureLayerTiling* twin_tiling, + PictureLayerTiling* recycled_twin); // Returns true if the Tile existed and was removed from the tiling. bool RemoveTileAt(int i, int j, PictureLayerTiling* recycled_twin); @@ -303,18 +303,21 @@ const gfx::Rect& visible_rect_in_content_space) const; - void UpdateEvictionCacheIfNeeded(TreePriority tree_priority); - const std::vector<Tile*>* GetEvictionTiles(TreePriority tree_priority, - EvictionCategory category); - - void Invalidate(const Region& layer_region); - - void DoInvalidate(const Region& layer_region, - bool recreate_invalidated_tiles); + // Save the required data for computing tile priorities later. + void UpdateTilePriorityRects(float content_to_screen_scale_, + const gfx::Rect& visible_rect_in_content_space, + const gfx::Rect& skewport, + const gfx::Rect& soon_border_rect, + const gfx::Rect& eventually_rect, + const Occlusion& occlusion_in_layer_space); void UpdateTileAndTwinPriority(Tile* tile) const; void UpdateTilePriority(Tile* tile) const; + const size_t max_tiles_for_interest_area_; + const float skewport_target_time_in_seconds_; + const int skewport_extrapolation_limit_in_content_pixels_; + // Given properties. float contents_scale_; gfx::Size layer_bounds_; @@ -330,36 +333,23 @@ double last_impl_frame_time_in_seconds_; gfx::Rect last_viewport_in_layer_space_; gfx::Rect last_visible_rect_in_content_space_; - float content_to_screen_scale_; bool can_require_tiles_for_activation_; - // Iteration rects in content space + // Iteration rects in content space. gfx::Rect current_visible_rect_; gfx::Rect current_skewport_rect_; gfx::Rect current_soon_border_rect_; gfx::Rect current_eventually_rect_; + // Other properties used for tile iteration and prioritization. + float current_content_to_screen_scale_; + Occlusion current_occlusion_in_layer_space_; bool has_visible_rect_tiles_; bool has_skewport_rect_tiles_; bool has_soon_border_rect_tiles_; bool has_eventually_rect_tiles_; - Occlusion current_occlusion_in_layer_space_; - - // TODO(reveman): Remove this in favour of an array of eviction_tiles_ when we - // change all enums to have a consistent way of getting the count/last - // element. - std::vector<Tile*> eviction_tiles_now_; - std::vector<Tile*> eviction_tiles_now_and_required_for_activation_; - std::vector<Tile*> eviction_tiles_soon_; - std::vector<Tile*> eviction_tiles_soon_and_required_for_activation_; - std::vector<Tile*> eviction_tiles_eventually_; - std::vector<Tile*> eviction_tiles_eventually_and_required_for_activation_; - - bool eviction_tiles_cache_valid_; - TreePriority eviction_cache_tree_priority_; - private: DISALLOW_ASSIGN(PictureLayerTiling);
diff --git a/cc/resources/picture_layer_tiling_perftest.cc b/cc/resources/picture_layer_tiling_perftest.cc index 3944e46..ee41bef 100644 --- a/cc/resources/picture_layer_tiling_perftest.cc +++ b/cc/resources/picture_layer_tiling_perftest.cc
@@ -44,11 +44,14 @@ } void SetUp() override { + LayerTreeSettings defaults; picture_layer_tiling_client_.SetTileSize(gfx::Size(256, 256)); - picture_layer_tiling_client_.set_max_tiles_for_interest_area(250); picture_layer_tiling_client_.set_tree(PENDING_TREE); picture_layer_tiling_ = PictureLayerTiling::Create( - 1, gfx::Size(256 * 50, 256 * 50), &picture_layer_tiling_client_); + 1, gfx::Size(256 * 50, 256 * 50), &picture_layer_tiling_client_, + defaults.max_tiles_for_interest_area, + defaults.skewport_target_time_in_seconds, + defaults.skewport_extrapolation_limit_in_content_pixels); picture_layer_tiling_->CreateAllTilesForTesting(); } @@ -57,9 +60,7 @@ void RunInvalidateTest(const std::string& test_name, const Region& region) { timer_.Reset(); do { - picture_layer_tiling_->UpdateTilesToCurrentRasterSource( - picture_layer_tiling_client_.raster_source(), region, - picture_layer_tiling_->tiling_size()); + picture_layer_tiling_->Invalidate(region); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -126,8 +127,12 @@ void RunRasterIteratorConstructTest(const std::string& test_name, const gfx::Rect& viewport) { gfx::Size bounds(viewport.size()); - picture_layer_tiling_ = - PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_); + LayerTreeSettings defaults; + picture_layer_tiling_ = PictureLayerTiling::Create( + 1, bounds, &picture_layer_tiling_client_, + defaults.max_tiles_for_interest_area, + defaults.skewport_target_time_in_seconds, + defaults.skewport_extrapolation_limit_in_content_pixels); picture_layer_tiling_client_.set_tree(ACTIVE_TREE); picture_layer_tiling_->ComputeTilePriorityRects(viewport, 1.0f, 1.0, Occlusion()); @@ -151,8 +156,12 @@ int num_tiles, const gfx::Rect& viewport) { gfx::Size bounds(10000, 10000); - picture_layer_tiling_ = - PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_); + LayerTreeSettings defaults; + picture_layer_tiling_ = PictureLayerTiling::Create( + 1, bounds, &picture_layer_tiling_client_, + defaults.max_tiles_for_interest_area, + defaults.skewport_target_time_in_seconds, + defaults.skewport_extrapolation_limit_in_content_pixels); picture_layer_tiling_client_.set_tree(ACTIVE_TREE); picture_layer_tiling_->ComputeTilePriorityRects(viewport, 1.0f, 1.0, Occlusion());
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc index 51896a5..a3348bc 100644 --- a/cc/resources/picture_layer_tiling_set.cc +++ b/cc/resources/picture_layer_tiling_set.cc
@@ -29,26 +29,98 @@ // static scoped_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create( - PictureLayerTilingClient* client) { - return make_scoped_ptr(new PictureLayerTilingSet(client)); + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content_pixels) { + return make_scoped_ptr(new PictureLayerTilingSet( + client, max_tiles_for_interest_area, skewport_target_time_in_seconds, + skewport_extrapolation_limit_in_content_pixels)); } -PictureLayerTilingSet::PictureLayerTilingSet(PictureLayerTilingClient* client) - : client_(client) { +PictureLayerTilingSet::PictureLayerTilingSet( + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content_pixels) + : max_tiles_for_interest_area_(max_tiles_for_interest_area), + skewport_target_time_in_seconds_(skewport_target_time_in_seconds), + skewport_extrapolation_limit_in_content_pixels_( + skewport_extrapolation_limit_in_content_pixels), + client_(client) { } PictureLayerTilingSet::~PictureLayerTilingSet() { } -void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) { - client_ = client; - for (size_t i = 0; i < tilings_.size(); ++i) - tilings_[i]->SetClient(client_); -} +void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSource( + RasterSource* raster_source, + const PictureLayerTilingSet* twin_set, + const gfx::Size& layer_bounds, + const Region& layer_invalidation, + float minimum_contents_scale) { + RemoveTilingsBelowScale(minimum_contents_scale); -void PictureLayerTilingSet::RemoveTilesInRegion(const Region& region) { - for (size_t i = 0; i < tilings_.size(); ++i) - tilings_[i]->RemoveTilesInRegion(region); + // Copy over tilings that are shared with the |twin_set| tiling set (if it + // exists). + if (twin_set) { + for (PictureLayerTiling* twin_tiling : twin_set->tilings_) { + float contents_scale = twin_tiling->contents_scale(); + DCHECK_GE(contents_scale, minimum_contents_scale); + + PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale); + if (!this_tiling) { + scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create( + contents_scale, layer_bounds, client_, max_tiles_for_interest_area_, + skewport_target_time_in_seconds_, + skewport_extrapolation_limit_in_content_pixels_); + tilings_.push_back(new_tiling.Pass()); + this_tiling = tilings_.back(); + } + this_tiling->CloneTilesAndPropertiesFrom(*twin_tiling); + } + } + + // For unshared tilings, invalidate tiles and update them to the new raster + // source. + for (PictureLayerTiling* tiling : tilings_) { + if (twin_set && twin_set->FindTilingWithScale(tiling->contents_scale())) + continue; + + tiling->Resize(layer_bounds); + tiling->Invalidate(layer_invalidation); + tiling->SetRasterSource(raster_source); + // This is needed for cases where the live tiles rect didn't change but + // recordings exist in the raster source that did not exist on the last + // raster source. + tiling->CreateMissingTilesInLiveTilesRect(); + + // If |twin_set| is present, use the resolutions from there. Otherwise leave + // all resolutions as they are. + if (twin_set) + tiling->set_resolution(NON_IDEAL_RESOLUTION); + } + + tilings_.sort(LargestToSmallestScaleFunctor()); + +#if DCHECK_IS_ON + for (PictureLayerTiling* tiling : tilings_) { + DCHECK(tiling->tile_size() == + client_->CalculateTileSize(tiling->tiling_size())) + << "tile_size: " << tiling->tile_size().ToString() + << " tiling_size: " << tiling->tiling_size().ToString() + << " CalculateTileSize: " + << client_->CalculateTileSize(tiling->tiling_size()).ToString(); + } + + if (!tilings_.empty()) { + size_t num_high_res = std::count_if(tilings_.begin(), tilings_.end(), + [](PictureLayerTiling* tiling) { + return tiling->resolution() == HIGH_RESOLUTION; + }); + DCHECK_EQ(1u, num_high_res); + } +#endif } void PictureLayerTilingSet::CleanUpTilings( @@ -91,14 +163,6 @@ } for (auto* tiling : to_remove) { - PictureLayerTiling* twin_tiling = - twin_set ? twin_set->FindTilingWithScale(tiling->contents_scale()) - : nullptr; - // Only remove tilings from the twin layer if they have - // NON_IDEAL_RESOLUTION. - if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION) - twin_set->Remove(twin_tiling); - PictureLayerTiling* recycled_twin_tiling = recycled_twin_set ? recycled_twin_set->FindTilingWithScale(tiling->contents_scale()) @@ -113,16 +177,24 @@ } } +void PictureLayerTilingSet::RemoveNonIdealTilings() { + auto to_remove = tilings_.remove_if([](PictureLayerTiling* t) { + return t->resolution() == NON_IDEAL_RESOLUTION; + }); + tilings_.erase(to_remove, tilings_.end()); +} + void PictureLayerTilingSet::MarkAllTilingsNonIdeal() { for (auto* tiling : tilings_) tiling->set_resolution(NON_IDEAL_RESOLUTION); } -bool PictureLayerTilingSet::SyncTilings(const PictureLayerTilingSet& other, - const gfx::Size& new_layer_bounds, - const Region& layer_invalidation, - float minimum_contents_scale, - RasterSource* raster_source) { +bool PictureLayerTilingSet::SyncTilingsForTesting( + const PictureLayerTilingSet& other, + const gfx::Size& new_layer_bounds, + const Region& layer_invalidation, + float minimum_contents_scale, + RasterSource* raster_source) { if (new_layer_bounds.IsEmpty()) { RemoveAllTilings(); return false; @@ -151,8 +223,9 @@ if (PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale)) { this_tiling->set_resolution(other.tilings_[i]->resolution()); - this_tiling->UpdateTilesToCurrentRasterSource( - raster_source, layer_invalidation, new_layer_bounds); + this_tiling->Resize(new_layer_bounds); + this_tiling->Invalidate(layer_invalidation); + this_tiling->SetRasterSource(raster_source); this_tiling->CreateMissingTilesInLiveTilesRect(); if (this_tiling->resolution() == HIGH_RESOLUTION) have_high_res_tiling = true; @@ -166,9 +239,9 @@ continue; } scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create( - contents_scale, - new_layer_bounds, - client_); + contents_scale, new_layer_bounds, client_, max_tiles_for_interest_area_, + skewport_target_time_in_seconds_, + skewport_extrapolation_limit_in_content_pixels_); new_tiling->set_resolution(other.tilings_[i]->resolution()); if (new_tiling->resolution() == HIGH_RESOLUTION) have_high_res_tiling = true; @@ -185,8 +258,10 @@ for (size_t i = 0; i < tilings_.size(); ++i) DCHECK_NE(tilings_[i]->contents_scale(), contents_scale); - tilings_.push_back( - PictureLayerTiling::Create(contents_scale, layer_bounds, client_)); + tilings_.push_back(PictureLayerTiling::Create( + contents_scale, layer_bounds, client_, max_tiles_for_interest_area_, + skewport_target_time_in_seconds_, + skewport_extrapolation_limit_in_content_pixels_)); PictureLayerTiling* appended = tilings_.back(); tilings_.sort(LargestToSmallestScaleFunctor()); @@ -222,6 +297,14 @@ return *iter; } +void PictureLayerTilingSet::RemoveTilingsBelowScale(float minimum_scale) { + auto to_remove = + tilings_.remove_if([minimum_scale](PictureLayerTiling* tiling) { + return tiling->contents_scale() < minimum_scale; + }); + tilings_.erase(to_remove, tilings_.end()); +} + void PictureLayerTilingSet::RemoveAllTilings() { tilings_.clear(); }
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h index f0d0fd7..4038b32 100644 --- a/cc/resources/picture_layer_tiling_set.h +++ b/cc/resources/picture_layer_tiling_set.h
@@ -38,31 +38,42 @@ }; static scoped_ptr<PictureLayerTilingSet> Create( - PictureLayerTilingClient* client); + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content); ~PictureLayerTilingSet(); - void SetClient(PictureLayerTilingClient* client); const PictureLayerTilingClient* client() const { return client_; } - void RemoveTilesInRegion(const Region& region); void CleanUpTilings(float min_acceptable_high_res_scale, float max_acceptable_high_res_scale, const std::vector<PictureLayerTiling*>& needed_tilings, bool should_have_low_res, PictureLayerTilingSet* twin_set, PictureLayerTilingSet* recycled_twin_set); - + void RemoveNonIdealTilings(); // Make this set of tilings match the same set of content scales from |other|. // Delete any tilings that don't meet |minimum_contents_scale|. Recreate // any tiles that intersect |layer_invalidation|. Update the size of all // tilings to |new_layer_bounds|. // Returns true if we had at least one high res tiling synced. - bool SyncTilings(const PictureLayerTilingSet& other, - const gfx::Size& new_layer_bounds, - const Region& layer_invalidation, - float minimum_contents_scale, - RasterSource* raster_source); + // TODO(danakj): Remove this !!! + bool SyncTilingsForTesting(const PictureLayerTilingSet& other, + const gfx::Size& new_layer_bounds, + const Region& layer_invalidation, + float minimum_contents_scale, + RasterSource* raster_source); + + void UpdateTilingsToCurrentRasterSource( + RasterSource* raster_source, + const PictureLayerTilingSet* twin_set, + // TODO(danakj): Don't need to pass layer bounds here, we have the raster + // source already, and they are the same as the raster source size. + const gfx::Size& layer_bounds, + const Region& layer_invalidation, + float minimum_contents_scale); PictureLayerTiling* AddTiling(float contents_scale, const gfx::Size& layer_bounds); @@ -89,6 +100,9 @@ // exist. float GetMaximumContentsScale() const; + // Removes all tilings with a contents scale < |minimum_scale|. + void RemoveTilingsBelowScale(float minimum_scale); + // Remove all tilings. void RemoveAllTilings(); @@ -155,14 +169,22 @@ TilingRange GetTilingRange(TilingRangeType type) const; private: - explicit PictureLayerTilingSet(PictureLayerTilingClient* client); + explicit PictureLayerTilingSet( + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time_in_seconds, + int skewport_extrapolation_limit_in_content_pixels); // Remove one tiling. void Remove(PictureLayerTiling* tiling); - PictureLayerTilingClient* client_; ScopedPtrVector<PictureLayerTiling> tilings_; + const size_t max_tiles_for_interest_area_; + const float skewport_target_time_in_seconds_; + const int skewport_extrapolation_limit_in_content_pixels_; + PictureLayerTilingClient* client_; + friend class Iterator; DISALLOW_COPY_AND_ASSIGN(PictureLayerTilingSet); };
diff --git a/cc/resources/picture_layer_tiling_set_unittest.cc b/cc/resources/picture_layer_tiling_set_unittest.cc index 7acc55b..cfde42e 100644 --- a/cc/resources/picture_layer_tiling_set_unittest.cc +++ b/cc/resources/picture_layer_tiling_set_unittest.cc
@@ -18,10 +18,19 @@ namespace cc { namespace { +scoped_ptr<PictureLayerTilingSet> CreateTilingSet( + PictureLayerTilingClient* client) { + LayerTreeSettings defaults; + return PictureLayerTilingSet::Create( + client, defaults.max_tiles_for_interest_area, + defaults.skewport_target_time_in_seconds, + defaults.skewport_extrapolation_limit_in_content_pixels); +} + TEST(PictureLayerTilingSetTest, NoResources) { FakePictureLayerTilingClient client; gfx::Size layer_bounds(1000, 800); - auto set = PictureLayerTilingSet::Create(&client); + auto set = CreateTilingSet(&client); client.SetTileSize(gfx::Size(256, 256)); set->AddTiling(1.0, layer_bounds); @@ -59,7 +68,7 @@ PictureLayerTiling* high_res_tiling; PictureLayerTiling* low_res_tiling; - auto set = PictureLayerTilingSet::Create(&client); + auto set = CreateTilingSet(&client); set->AddTiling(2.0, layer_bounds); high_res_tiling = set->AddTiling(1.0, layer_bounds); high_res_tiling->set_resolution(HIGH_RESOLUTION); @@ -91,7 +100,7 @@ EXPECT_EQ(4u, lower_than_low_res_range.start); EXPECT_EQ(5u, lower_than_low_res_range.end); - auto set_without_low_res = PictureLayerTilingSet::Create(&client); + auto set_without_low_res = CreateTilingSet(&client); set_without_low_res->AddTiling(2.0, layer_bounds); high_res_tiling = set_without_low_res->AddTiling(1.0, layer_bounds); high_res_tiling->set_resolution(HIGH_RESOLUTION); @@ -121,7 +130,7 @@ PictureLayerTilingSet::LOWER_THAN_LOW_RES); EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); - auto set_with_only_high_and_low_res = PictureLayerTilingSet::Create(&client); + auto set_with_only_high_and_low_res = CreateTilingSet(&client); high_res_tiling = set_with_only_high_and_low_res->AddTiling(1.0, layer_bounds); high_res_tiling->set_resolution(HIGH_RESOLUTION); @@ -153,7 +162,7 @@ PictureLayerTilingSet::LOWER_THAN_LOW_RES); EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); - auto set_with_only_high_res = PictureLayerTilingSet::Create(&client); + auto set_with_only_high_res = CreateTilingSet(&client); high_res_tiling = set_with_only_high_res->AddTiling(1.0, layer_bounds); high_res_tiling->set_resolution(HIGH_RESOLUTION); @@ -209,7 +218,7 @@ client.SetTileSize(gfx::Size(256, 256)); client.set_tree(PENDING_TREE); gfx::Size layer_bounds(1000, 800); - auto set = PictureLayerTilingSet::Create(&client); + auto set = CreateTilingSet(&client); float scale = min_scale; for (int i = 0; i < num_tilings; ++i, scale += scale_increment) { @@ -288,8 +297,8 @@ source_client_.set_tree(PENDING_TREE); target_client_.SetTileSize(tile_size_); target_client_.set_tree(PENDING_TREE); - source_ = PictureLayerTilingSet::Create(&source_client_); - target_ = PictureLayerTilingSet::Create(&target_client_); + source_ = CreateTilingSet(&source_client_); + target_ = CreateTilingSet(&target_client_); } // Sync from source to target. @@ -301,8 +310,9 @@ for (size_t i = 0; i < target_->num_tilings(); ++i) target_->tiling_at(i)->CreateAllTilesForTesting(); - target_->SyncTilings(*source_.get(), new_bounds, invalidation, - minimum_scale, target_client_.raster_source()); + target_->SyncTilingsForTesting(*source_.get(), new_bounds, invalidation, + minimum_scale, + target_client_.raster_source()); } void SyncTilings(const gfx::Size& new_bounds) { Region invalidation;
diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc index 9190b98..1ed4613 100644 --- a/cc/resources/picture_layer_tiling_unittest.cc +++ b/cc/resources/picture_layer_tiling_unittest.cc
@@ -54,17 +54,16 @@ static scoped_ptr<TestablePictureLayerTiling> Create( float contents_scale, const gfx::Size& layer_bounds, - PictureLayerTilingClient* client) { + PictureLayerTilingClient* client, + const LayerTreeSettings& settings) { return make_scoped_ptr(new TestablePictureLayerTiling( - contents_scale, - layer_bounds, - client)); + contents_scale, layer_bounds, client, + settings.max_tiles_for_interest_area, + settings.skewport_target_time_in_seconds, + settings.skewport_extrapolation_limit_in_content_pixels)); } gfx::Rect live_tiles_rect() const { return live_tiles_rect_; } - bool eviction_tiles_cache_valid() const { - return eviction_tiles_cache_valid_; - } using PictureLayerTiling::ComputeSkewport; using PictureLayerTiling::RemoveTileAt; @@ -72,8 +71,16 @@ protected: TestablePictureLayerTiling(float contents_scale, const gfx::Size& layer_bounds, - PictureLayerTilingClient* client) - : PictureLayerTiling(contents_scale, layer_bounds, client) { } + PictureLayerTilingClient* client, + size_t max_tiles_for_interest_area, + float skewport_target_time, + int skewport_extrapolation_limit) + : PictureLayerTiling(contents_scale, + layer_bounds, + client, + max_tiles_for_interest_area, + skewport_target_time, + skewport_extrapolation_limit) {} }; class PictureLayerTilingIteratorTest : public testing::Test { @@ -86,9 +93,8 @@ const gfx::Size& layer_bounds) { client_.SetTileSize(tile_size); client_.set_tree(PENDING_TREE); - tiling_ = TestablePictureLayerTiling::Create(contents_scale, - layer_bounds, - &client_); + tiling_ = TestablePictureLayerTiling::Create(contents_scale, layer_bounds, + &client_, LayerTreeSettings()); } void SetLiveRectAndVerifyTiles(const gfx::Rect& live_tiles_rect) { @@ -180,10 +186,6 @@ VerifyTilesExactlyCoverRect(rect_scale, dest_rect, clamped_rect); } - void set_max_tiles_for_interest_area(size_t area) { - client_.set_max_tiles_for_interest_area(area); - } - protected: FakePictureLayerTilingClient client_; scoped_ptr<TestablePictureLayerTiling> tiling_; @@ -208,14 +210,15 @@ Region invalidation = SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size)); - tiling_->UpdateTilesToCurrentRasterSource(client_.raster_source(), - invalidation, gfx::Size(200, 200)); + tiling_->Resize(gfx::Size(200, 200)); + EXPECT_TRUE(tiling_->TileAt(0, 0)); + tiling_->Invalidate(invalidation); EXPECT_FALSE(tiling_->TileAt(0, 0)); } TEST_F(PictureLayerTilingIteratorTest, CreateMissingTilesStaysInsideLiveRect) { // The tiling has three rows and columns. - Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 250)); + Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 250)); EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x()); EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y()); @@ -243,7 +246,7 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeTilingOverTileBorders) { // The tiling has four rows and three columns. - Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350)); + Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 350)); EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x()); EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y()); @@ -263,9 +266,7 @@ // Shrink the tiling so that the last tile row/column is entirely in the // border pixels of the interior tiles. That row/column is removed. - Region invalidation; - tiling_->UpdateTilesToCurrentRasterSource( - client_.raster_source(), invalidation, gfx::Size(right + 1, bottom + 1)); + tiling_->Resize(gfx::Size(right + 1, bottom + 1)); EXPECT_EQ(2, tiling_->TilingDataForTesting().num_tiles_x()); EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_y()); @@ -282,8 +283,7 @@ // Growing outside the current right/bottom tiles border pixels should create // the tiles again, even though the live rect has not changed size. - tiling_->UpdateTilesToCurrentRasterSource( - client_.raster_source(), invalidation, gfx::Size(right + 2, bottom + 2)); + tiling_->Resize(gfx::Size(right + 2, bottom + 2)); EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x()); EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y()); @@ -306,7 +306,7 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverTileBorders) { // The tiling has three rows and columns. - Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350)); + Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 350)); EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x()); EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y()); @@ -371,7 +371,7 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeLiveTileRectOverSameTiles) { // The tiling has four rows and three columns. - Initialize(gfx::Size(100, 100), 1, gfx::Size(250, 350)); + Initialize(gfx::Size(100, 100), 1.f, gfx::Size(250, 350)); EXPECT_EQ(3, tiling_->TilingDataForTesting().num_tiles_x()); EXPECT_EQ(4, tiling_->TilingDataForTesting().num_tiles_y()); @@ -419,8 +419,9 @@ Region invalidation = SubtractRegions(gfx::Rect(tile_size), gfx::Rect(original_layer_size)); - tiling_->UpdateTilesToCurrentRasterSource(client_.raster_source(), - invalidation, gfx::Size(200, 200)); + tiling_->Resize(gfx::Size(200, 200)); + EXPECT_TRUE(tiling_->TileAt(0, 0)); + tiling_->Invalidate(invalidation); EXPECT_FALSE(tiling_->TileAt(0, 0)); // The original tile was the same size after resize, but it would include new @@ -430,7 +431,7 @@ } TEST_F(PictureLayerTilingIteratorTest, LiveTilesExactlyCoverLiveTileRect) { - Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801)); + Initialize(gfx::Size(100, 100), 1.f, gfx::Size(1099, 801)); SetLiveRectAndVerifyTiles(gfx::Rect(100, 100)); SetLiveRectAndVerifyTiles(gfx::Rect(101, 99)); SetLiveRectAndVerifyTiles(gfx::Rect(1099, 1)); @@ -440,13 +441,13 @@ } TEST_F(PictureLayerTilingIteratorTest, IteratorCoversLayerBoundsNoScale) { - Initialize(gfx::Size(100, 100), 1, gfx::Size(1099, 801)); + Initialize(gfx::Size(100, 100), 1.f, gfx::Size(1099, 801)); VerifyTilesExactlyCoverRect(1, gfx::Rect()); VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1099, 801)); VerifyTilesExactlyCoverRect(1, gfx::Rect(52, 83, 789, 412)); // With borders, a size of 3x3 = 1 pixel of content. - Initialize(gfx::Size(3, 3), 1, gfx::Size(10, 10)); + Initialize(gfx::Size(3, 3), 1.f, gfx::Size(10, 10)); VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 1, 1)); VerifyTilesExactlyCoverRect(1, gfx::Rect(0, 0, 2, 2)); VerifyTilesExactlyCoverRect(1, gfx::Rect(1, 1, 2, 2)); @@ -532,7 +533,6 @@ TEST(PictureLayerTilingTest, SkewportLimits) { FakePictureLayerTilingClient client; - client.set_skewport_extrapolation_limit_in_content_pixels(75); client.set_tree(ACTIVE_TREE); scoped_ptr<TestablePictureLayerTiling> tiling; @@ -540,7 +540,11 @@ gfx::Size layer_bounds(200, 200); client.SetTileSize(gfx::Size(100, 100)); - tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 10000; + settings.skewport_extrapolation_limit_in_content_pixels = 75; + tiling = + TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client, settings); tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion()); @@ -606,7 +610,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); - tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client); + tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport, 1.f, 1.0, Occlusion()); @@ -665,13 +670,16 @@ client.SetTileSize(gfx::Size(10, 10)); client.set_tree(ACTIVE_TREE); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 10000; // Tiling at 0.25 scale: this should create 47x47 tiles of size 10x10. // The reason is that each tile has a one pixel border, so tile at (1, 2) // for instance begins at (8, 16) pixels. So tile at (46, 46) will begin at // (368, 368) and extend to the end of 1500 * 0.25 = 375 edge of the // tiling. - tiling = TestablePictureLayerTiling::Create(0.25f, layer_bounds, &client); + tiling = TestablePictureLayerTiling::Create(0.25f, layer_bounds, &client, + settings); gfx::Rect viewport_in_content_space = gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f)); @@ -825,7 +833,8 @@ EXPECT_FLOAT_EQ(8.f, priority.distance_to_visible); // Test additional scales. - tiling = TestablePictureLayerTiling::Create(0.2f, layer_bounds, &client); + tiling = TestablePictureLayerTiling::Create(0.2f, layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport, 1.0f, 4.0, Occlusion()); tiling->UpdateAllTilePrioritiesForTesting(); @@ -1085,8 +1094,11 @@ client.SetTileSize(gfx::Size(30, 30)); client.set_tree(ACTIVE_TREE); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 10000; - tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client); + tiling = + TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client, settings); tiling->ComputeTilePriorityRects(viewport, 1.0f, 1.0, Occlusion()); tiling->UpdateAllTilePrioritiesForTesting(); @@ -1190,8 +1202,11 @@ client.SetTileSize(gfx::Size(30, 30)); client.set_tree(ACTIVE_TREE); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 10000; - tiling = TestablePictureLayerTiling::Create(1.f, layer_bounds, &client); + tiling = + TestablePictureLayerTiling::Create(1.f, layer_bounds, &client, settings); tiling->ComputeTilePriorityRects(viewport, 1.0f, 1.0, Occlusion()); tiling->ComputeTilePriorityRects(moved_viewport, 1.0f, 2.0, Occlusion()); tiling->UpdateAllTilePrioritiesForTesting(); @@ -1326,14 +1341,19 @@ TEST_F(PictureLayerTilingIteratorTest, TilesExistLargeViewportAndLayerWithSmallVisibleArea) { gfx::Size layer_bounds(10000, 10000); - Initialize(gfx::Size(100, 100), 1.f, layer_bounds); + client_.SetTileSize(gfx::Size(100, 100)); + client_.set_tree(PENDING_TREE); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 1; + + tiling_ = + TestablePictureLayerTiling::Create(1.f, layer_bounds, &client_, settings); VerifyTilesExactlyCoverRect(1.f, gfx::Rect(layer_bounds)); VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false)); gfx::Rect visible_rect(8000, 8000, 50, 50); client_.set_tree(ACTIVE_TREE); - set_max_tiles_for_interest_area(1); tiling_->ComputeTilePriorityRects(visible_rect, // visible content rect 1.f, // current contents scale 1.0, // current frame time @@ -1350,7 +1370,10 @@ client_.SetTileSize(tile_size); client_.set_tree(PENDING_TREE); - auto active_set = PictureLayerTilingSet::Create(&client_); + LayerTreeSettings defaults; + auto active_set = PictureLayerTilingSet::Create( + &client_, 10000, defaults.skewport_target_time_in_seconds, + defaults.skewport_extrapolation_limit_in_content_pixels); active_set->AddTiling(1.f, layer_bounds); @@ -1367,10 +1390,12 @@ base::Bind(&TileExists, true)); // Add the same tilings to the pending set. - auto pending_set = PictureLayerTilingSet::Create(&client_); + auto pending_set = PictureLayerTilingSet::Create( + &client_, 10000, defaults.skewport_target_time_in_seconds, + defaults.skewport_extrapolation_limit_in_content_pixels); Region invalidation; - pending_set->SyncTilings(*active_set, layer_bounds, invalidation, 0.f, - client_.raster_source()); + pending_set->SyncTilingsForTesting(*active_set, layer_bounds, invalidation, + 0.f, client_.raster_source()); // The pending tiling starts with no tiles. VerifyTiles(pending_set->tiling_at(0), 1.f, gfx::Rect(layer_bounds), @@ -1407,8 +1432,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport_in_layer_space, current_layer_contents_scale, @@ -1461,8 +1486,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport_in_layer_space, current_layer_contents_scale, @@ -1525,8 +1550,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport_in_layer_space, current_layer_contents_scale, @@ -1583,8 +1608,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport_in_layer_space, current_layer_contents_scale, @@ -1665,8 +1690,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport_in_layer_space, current_layer_contents_scale, @@ -1757,8 +1782,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + LayerTreeSettings()); tiling->ComputeTilePriorityRects(viewport_in_layer_space, current_layer_contents_scale, @@ -1818,9 +1843,11 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 10000; tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + settings); // previous ("last") frame tiling->ComputeTilePriorityRects(viewport_in_layer_space, @@ -1894,8 +1921,8 @@ client.SetTileSize(gfx::Size(100, 100)); client.set_tree(ACTIVE_TREE); tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - current_layer_bounds, - &client); + current_layer_bounds, &client, + LayerTreeSettings()); // previous ("last") frame tiling->ComputeTilePriorityRects(viewport_in_layer_space, @@ -1942,10 +1969,11 @@ active_client.SetTileSize(gfx::Size(100, 100)); active_client.set_tree(ACTIVE_TREE); - active_client.set_max_tiles_for_interest_area(10); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 10; active_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale gfx::Size(10000, 10000), - &active_client); + &active_client, settings); // Create all tiles on this tiling. active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion()); @@ -1954,12 +1982,11 @@ recycle_client.SetTileSize(gfx::Size(100, 100)); recycle_client.set_tree(PENDING_TREE); recycle_client.set_twin_tiling(active_tiling.get()); - recycle_client.set_max_tiles_for_interest_area(10); scoped_ptr<TestablePictureLayerTiling> recycle_tiling; - recycle_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - gfx::Size(10000, 10000), - &recycle_client); + recycle_tiling = TestablePictureLayerTiling::Create( + 1.0f, // contents_scale + gfx::Size(10000, 10000), &recycle_client, settings); // Create all tiles on the second tiling. All tiles should be shared. recycle_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, @@ -1986,9 +2013,9 @@ active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 3.0, Occlusion()); - // Ensure that we now have a tile here, but the recycle tiling does not. + // Ensure that we now have a tile here on both tilings again. EXPECT_TRUE(active_tiling->TileAt(0, 0)); - EXPECT_FALSE(recycle_tiling->TileAt(0, 0)); + EXPECT_TRUE(recycle_tiling->TileAt(0, 0)); } TEST(PictureLayerTilingTest, RecycledTilesClearedOnReset) { @@ -1997,9 +2024,9 @@ active_client.SetTileSize(gfx::Size(100, 100)); active_client.set_tree(ACTIVE_TREE); - active_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - gfx::Size(100, 100), - &active_client); + active_tiling = TestablePictureLayerTiling::Create( + 1.0f, // contents_scale + gfx::Size(100, 100), &active_client, LayerTreeSettings()); // Create all tiles on this tiling. active_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion()); @@ -2008,12 +2035,13 @@ recycle_client.SetTileSize(gfx::Size(100, 100)); recycle_client.set_tree(PENDING_TREE); recycle_client.set_twin_tiling(active_tiling.get()); - recycle_client.set_max_tiles_for_interest_area(10); + LayerTreeSettings settings; + settings.max_tiles_for_interest_area = 10; scoped_ptr<TestablePictureLayerTiling> recycle_tiling; - recycle_tiling = TestablePictureLayerTiling::Create(1.0f, // contents_scale - gfx::Size(100, 100), - &recycle_client); + recycle_tiling = TestablePictureLayerTiling::Create( + 1.0f, // contents_scale + gfx::Size(100, 100), &recycle_client, settings); // Create all tiles on the recycle tiling. All tiles should be shared. recycle_tiling->ComputeTilePriorityRects(gfx::Rect(0, 0, 100, 100), 1.0f, @@ -2037,7 +2065,7 @@ TEST_F(PictureLayerTilingIteratorTest, ResizeTilesAndUpdateToCurrent) { // The tiling has four rows and three columns. - Initialize(gfx::Size(150, 100), 1, gfx::Size(250, 150)); + Initialize(gfx::Size(150, 100), 1.f, gfx::Size(250, 150)); tiling_->CreateAllTilesForTesting(); EXPECT_EQ(150, tiling_->TilingDataForTesting().max_texture_size().width()); EXPECT_EQ(100, tiling_->TilingDataForTesting().max_texture_size().height()); @@ -2050,9 +2078,7 @@ EXPECT_EQ(150, tiling_->TilingDataForTesting().max_texture_size().width()); EXPECT_EQ(100, tiling_->TilingDataForTesting().max_texture_size().height()); - Region invalidation; - tiling_->UpdateTilesToCurrentRasterSource(client_.raster_source(), - invalidation, gfx::Size(250, 150)); + tiling_->Resize(gfx::Size(250, 150)); // Tile size in the tiling should be resized to 250x200. EXPECT_EQ(250, tiling_->TilingDataForTesting().max_texture_size().width());
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc index 698fe2c..31bc2d3 100644 --- a/cc/resources/picture_pile.cc +++ b/cc/resources/picture_pile.cc
@@ -693,9 +693,10 @@ if (it->second.GetPicture() != picture) return; } - skia::AnalysisCanvas canvas(recorded_viewport_.width(), - recorded_viewport_.height()); - canvas.translate(-recorded_viewport_.x(), -recorded_viewport_.y()); + + gfx::Size layer_size = GetSize(); + skia::AnalysisCanvas canvas(layer_size.width(), layer_size.height()); + picture->Raster(&canvas, nullptr, Region(), 1.0f); is_solid_color_ = canvas.GetColorIfSolid(&solid_color_); }
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index c0e8f1b..5b8bcd2 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -622,21 +622,11 @@ RGBA_8888); } else { DCHECK(mailbox.IsSharedMemory()); - base::SharedMemory* shared_memory = mailbox.shared_memory(); - DCHECK(shared_memory->memory()); - uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory()); + SharedBitmap* shared_bitmap = mailbox.shared_bitmap(); + uint8_t* pixels = shared_bitmap->pixels(); DCHECK(pixels); - scoped_ptr<SharedBitmap> shared_bitmap; - if (shared_bitmap_manager_) { - shared_bitmap = - shared_bitmap_manager_->GetBitmapForSharedMemory(shared_memory); - } - resource = Resource(pixels, - shared_bitmap.release(), - mailbox.shared_memory_size(), - Resource::External, - GL_LINEAR, - GL_CLAMP_TO_EDGE); + resource = Resource(pixels, shared_bitmap, mailbox.shared_memory_size(), + Resource::External, GL_LINEAR, GL_CLAMP_TO_EDGE); } resource.allocated = true; resource.mailbox = mailbox; @@ -714,13 +704,8 @@ } } else { DCHECK(resource->mailbox.IsSharedMemory()); - base::SharedMemory* shared_memory = resource->mailbox.shared_memory(); - if (resource->pixels && shared_memory) { - DCHECK(shared_memory->memory() == resource->pixels); - resource->pixels = NULL; - delete resource->shared_bitmap; - resource->shared_bitmap = NULL; - } + resource->shared_bitmap = nullptr; + resource->pixels = nullptr; } resource->release_callback_impl.Run( sync_point, lost_resource, blocking_main_thread_task_runner_); @@ -1123,11 +1108,6 @@ !resource_->sk_surface.get() || !SurfaceHasMatchingProperties(use_distance_field_text, can_use_lcd_text); if (create_surface) { - class GrContext* gr_context = resource_provider_->GrContext(); - // TODO(alokp): Implement TestContextProvider::GrContext(). - if (!gr_context) - return nullptr; - resource_provider_->LazyAllocate(resource_); GrBackendTextureDesc desc; @@ -1137,6 +1117,8 @@ desc.fConfig = ToGrPixelConfig(resource_->format); desc.fOrigin = kTopLeft_GrSurfaceOrigin; desc.fTextureHandle = resource_->gl_id; + + class GrContext* gr_context = resource_provider_->GrContext(); skia::RefPtr<GrTexture> gr_texture = skia::AdoptRef(gr_context->wrapBackendTexture(desc)); if (!gr_texture)
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 2c8ed58..53741ab 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc
@@ -59,15 +59,15 @@ *release_main_thread_task_runner = main_thread_task_runner; } -static void SharedMemoryReleaseCallback( - scoped_ptr<base::SharedMemory> memory, +static void SharedBitmapReleaseCallback( + scoped_ptr<SharedBitmap> bitmap, uint32 sync_point, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) { } -static void ReleaseSharedMemoryCallback( - scoped_ptr<base::SharedMemory> shared_memory, +static void ReleaseSharedBitmapCallback( + scoped_ptr<SharedBitmap> shared_bitmap, bool* release_called, uint32* release_sync_point, bool* lost_resource_result, @@ -79,15 +79,16 @@ *lost_resource_result = lost_resource; } -static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory( +static scoped_ptr<SharedBitmap> CreateAndFillSharedBitmap( + SharedBitmapManager* manager, const gfx::Size& size, uint32_t value) { - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory); - CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea())); - uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory()); + scoped_ptr<SharedBitmap> shared_bitmap = manager->AllocateSharedBitmap(size); + CHECK(shared_bitmap); + uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels()); CHECK(pixels); std::fill_n(pixels, size.GetArea(), value); - return shared_memory.Pass(); + return shared_bitmap.Pass(); } class TextureStateTrackingContext : public TestWebGraphicsContext3D { @@ -466,32 +467,26 @@ *sync_point = child_context_->insertSyncPoint(); EXPECT_LT(0u, *sync_point); - scoped_ptr<base::SharedMemory> shared_memory; + scoped_ptr<SharedBitmap> shared_bitmap; scoped_ptr<SingleReleaseCallbackImpl> callback = - SingleReleaseCallbackImpl::Create( - base::Bind(ReleaseSharedMemoryCallback, - base::Passed(&shared_memory), - release_called, - release_sync_point, - lost_resource)); + SingleReleaseCallbackImpl::Create(base::Bind( + ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), + release_called, release_sync_point, lost_resource)); return child_resource_provider_->CreateResourceFromTextureMailbox( TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point), callback.Pass()); } else { gfx::Size size(64, 64); - scoped_ptr<base::SharedMemory> shared_memory( - CreateAndFillSharedMemory(size, 0)); + scoped_ptr<SharedBitmap> shared_bitmap( + CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0)); - base::SharedMemory* shared_memory_ptr = shared_memory.get(); + SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); scoped_ptr<SingleReleaseCallbackImpl> callback = - SingleReleaseCallbackImpl::Create( - base::Bind(ReleaseSharedMemoryCallback, - base::Passed(&shared_memory), - release_called, - release_sync_point, - lost_resource)); + SingleReleaseCallbackImpl::Create(base::Bind( + ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap), + release_called, release_sync_point, lost_resource)); return child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(shared_memory_ptr, size), callback.Pass()); + TextureMailbox(shared_bitmap_ptr, size), callback.Pass()); } } @@ -982,14 +977,14 @@ uint8_t data2[4] = { 5, 5, 5, 5 }; child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d()); - scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); - shared_memory->CreateAndMapAnonymous(1); - base::SharedMemory* shared_memory_ptr = shared_memory.get(); + scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap( + shared_bitmap_manager_.get(), gfx::Size(1, 1), 0)); + SharedBitmap* shared_bitmap_ptr = shared_bitmap.get(); ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox( - TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)), + TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)), SingleReleaseCallbackImpl::Create(base::Bind( - &SharedMemoryReleaseCallback, base::Passed(&shared_memory)))); + &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap)))); ReturnedResourceArray returned_to_child; int child_id = @@ -2556,8 +2551,8 @@ gfx::Size size(64, 64); const uint32_t kBadBeef = 0xbadbeef; - scoped_ptr<base::SharedMemory> shared_memory( - CreateAndFillSharedMemory(size, kBadBeef)); + scoped_ptr<SharedBitmap> shared_bitmap( + CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef)); FakeOutputSurfaceClient output_surface_client; scoped_ptr<OutputSurface> output_surface( @@ -2582,7 +2577,7 @@ &release_sync_point, &lost_resource, &main_thread_task_runner)); - TextureMailbox mailbox(shared_memory.get(), size); + TextureMailbox mailbox(shared_bitmap.get(), size); ResourceProvider::ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
diff --git a/cc/resources/scoped_gpu_raster.cc b/cc/resources/scoped_gpu_raster.cc index 517c7a7..9d1dfe5 100644 --- a/cc/resources/scoped_gpu_raster.cc +++ b/cc/resources/scoped_gpu_raster.cc
@@ -30,18 +30,14 @@ gl->PushGroupMarkerEXT(0, "GpuRasterization"); class GrContext* gr_context = context_provider_->GrContext(); - // TODO(sohanjg): Remove when TestContextProvider gives a GrContext. - if (gr_context) - gr_context->resetContext(); + gr_context->resetContext(); } void ScopedGpuRaster::EndGpuRaster() { GLES2Interface* gl = context_provider_->ContextGL(); class GrContext* gr_context = context_provider_->GrContext(); - // TODO(sohanjg): Remove when TestContextProvider gives a GrContext. - if (gr_context) - gr_context->flush(); + gr_context->flush(); // TODO(alokp): Use a trace macro to push/pop markers. // Using push/pop functions directly incurs cost to evaluate function
diff --git a/cc/resources/shared_bitmap.h b/cc/resources/shared_bitmap.h index bbf0823..6980afb 100644 --- a/cc/resources/shared_bitmap.h +++ b/cc/resources/shared_bitmap.h
@@ -6,13 +6,10 @@ #define CC_RESOURCES_SHARED_BITMAP_H_ #include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" #include "gpu/command_buffer/common/mailbox.h" #include "ui/gfx/geometry/size.h" -namespace base { class SharedMemory; } - namespace cc { typedef gpu::Mailbox SharedBitmapId; @@ -24,8 +21,6 @@ uint8* pixels() { return pixels_; } - virtual base::SharedMemory* memory() = 0; - const SharedBitmapId& id() { return id_; } // Returns true if the size is valid and false otherwise.
diff --git a/cc/resources/shared_bitmap_manager.h b/cc/resources/shared_bitmap_manager.h index fe61b09..d5239e4 100644 --- a/cc/resources/shared_bitmap_manager.h +++ b/cc/resources/shared_bitmap_manager.h
@@ -6,6 +6,7 @@ #define CC_RESOURCES_SHARED_BITMAP_MANAGER_H_ #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" #include "cc/resources/shared_bitmap.h" #include "ui/gfx/geometry/size.h" @@ -21,8 +22,6 @@ virtual scoped_ptr<SharedBitmap> GetSharedBitmapFromId( const gfx::Size&, const SharedBitmapId&) = 0; - virtual scoped_ptr<SharedBitmap> GetBitmapForSharedMemory( - base::SharedMemory*) = 0; private: DISALLOW_COPY_AND_ASSIGN(SharedBitmapManager);
diff --git a/cc/resources/texture_mailbox.cc b/cc/resources/texture_mailbox.cc index 07cbec0..9bf242e 100644 --- a/cc/resources/texture_mailbox.cc +++ b/cc/resources/texture_mailbox.cc
@@ -9,25 +9,28 @@ namespace cc { -TextureMailbox::TextureMailbox() : shared_memory_(NULL) {} +TextureMailbox::TextureMailbox() : shared_bitmap_(NULL) { +} TextureMailbox::TextureMailbox(const gpu::MailboxHolder& mailbox_holder) : mailbox_holder_(mailbox_holder), - shared_memory_(NULL), + shared_bitmap_(NULL), allow_overlay_(false), - nearest_neighbor_(false) {} + nearest_neighbor_(false) { +} TextureMailbox::TextureMailbox(const gpu::Mailbox& mailbox, uint32 target, uint32 sync_point) : mailbox_holder_(mailbox, target, sync_point), - shared_memory_(NULL), + shared_bitmap_(NULL), allow_overlay_(false), - nearest_neighbor_(false) {} + nearest_neighbor_(false) { +} -TextureMailbox::TextureMailbox(base::SharedMemory* shared_memory, +TextureMailbox::TextureMailbox(SharedBitmap* shared_bitmap, const gfx::Size& size) - : shared_memory_(shared_memory), + : shared_bitmap_(shared_bitmap), shared_memory_size_(size), allow_overlay_(false), nearest_neighbor_(false) { @@ -44,8 +47,7 @@ other.mailbox_holder_.mailbox.name, sizeof(mailbox_holder_.mailbox.name)); } else if (other.IsSharedMemory()) { - return IsSharedMemory() && - shared_memory_->handle() == other.shared_memory_->handle(); + return IsSharedMemory() && (shared_bitmap_ == other.shared_bitmap_); } DCHECK(!other.IsValid());
diff --git a/cc/resources/texture_mailbox.h b/cc/resources/texture_mailbox.h index 9bf41e1..cec60ce 100644 --- a/cc/resources/texture_mailbox.h +++ b/cc/resources/texture_mailbox.h
@@ -13,6 +13,7 @@ #include "ui/gfx/geometry/size.h" namespace cc { +class SharedBitmap; // TODO(skaslev, danakj) Rename this class more apropriately since now it // can hold a shared memory resource as well as a texture mailbox. @@ -21,13 +22,13 @@ TextureMailbox(); explicit TextureMailbox(const gpu::MailboxHolder& mailbox_holder); TextureMailbox(const gpu::Mailbox& mailbox, uint32 target, uint32 sync_point); - TextureMailbox(base::SharedMemory* shared_memory, const gfx::Size& size); + TextureMailbox(SharedBitmap* shared_bitmap, const gfx::Size& size); ~TextureMailbox(); bool IsValid() const { return IsTexture() || IsSharedMemory(); } bool IsTexture() const { return !mailbox_holder_.mailbox.IsZero(); } - bool IsSharedMemory() const { return shared_memory_ != NULL; } + bool IsSharedMemory() const { return shared_bitmap_ != NULL; } bool Equals(const TextureMailbox&) const; @@ -46,13 +47,13 @@ nearest_neighbor_ = nearest_neighbor; } - base::SharedMemory* shared_memory() const { return shared_memory_; } + SharedBitmap* shared_bitmap() const { return shared_bitmap_; } gfx::Size shared_memory_size() const { return shared_memory_size_; } size_t SharedMemorySizeInBytes() const; private: gpu::MailboxHolder mailbox_holder_; - base::SharedMemory* shared_memory_; + SharedBitmap* shared_bitmap_; gfx::Size shared_memory_size_; bool allow_overlay_; bool nearest_neighbor_;
diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc index 7ab1fbf..309c2b3 100644 --- a/cc/resources/tile_manager.cc +++ b/cc/resources/tile_manager.cc
@@ -41,7 +41,6 @@ const void* tile_id, int source_frame_number, bool analyze_picture, - RenderingStatsInstrumentation* rendering_stats, const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)>& reply, ImageDecodeTask::Vector* dependencies) @@ -54,7 +53,6 @@ tile_id_(tile_id), source_frame_number_(source_frame_number), analyze_picture_(analyze_picture), - rendering_stats_(rendering_stats), reply_(reply) {} // Overridden from Task: @@ -128,7 +126,6 @@ const void* tile_id_; int source_frame_number_; bool analyze_picture_; - RenderingStatsInstrumentation* rendering_stats_; const base::Callback<void(const RasterSource::SolidColorAnalysis&, bool)> reply_; scoped_ptr<RasterBuffer> raster_buffer_; @@ -140,11 +137,9 @@ public: ImageDecodeTaskImpl(SkPixelRef* pixel_ref, int layer_id, - RenderingStatsInstrumentation* rendering_stats, const base::Callback<void(bool was_canceled)>& reply) : pixel_ref_(skia::SharePtr(pixel_ref)), layer_id_(layer_id), - rendering_stats_(rendering_stats), reply_(reply) {} // Overridden from Task: @@ -169,7 +164,6 @@ private: skia::RefPtr<SkPixelRef> pixel_ref_; int layer_id_; - RenderingStatsInstrumentation* rendering_stats_; const base::Callback<void(bool was_canceled)> reply_; DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); @@ -209,11 +203,10 @@ base::SequencedTaskRunner* task_runner, ResourcePool* resource_pool, TileTaskRunner* tile_task_runner, - RenderingStatsInstrumentation* rendering_stats_instrumentation, size_t scheduled_raster_task_limit) { - return make_scoped_ptr(new TileManager( - client, task_runner, resource_pool, tile_task_runner, - rendering_stats_instrumentation, scheduled_raster_task_limit)); + return make_scoped_ptr(new TileManager(client, task_runner, resource_pool, + tile_task_runner, + scheduled_raster_task_limit)); } TileManager::TileManager( @@ -221,7 +214,6 @@ const scoped_refptr<base::SequencedTaskRunner>& task_runner, ResourcePool* resource_pool, TileTaskRunner* tile_task_runner, - RenderingStatsInstrumentation* rendering_stats_instrumentation, size_t scheduled_raster_task_limit) : client_(client), task_runner_(task_runner), @@ -229,7 +221,6 @@ tile_task_runner_(tile_task_runner), scheduled_raster_task_limit_(scheduled_raster_task_limit), all_tiles_that_need_to_be_rasterized_are_scheduled_(true), - rendering_stats_instrumentation_(rendering_stats_instrumentation), did_check_for_completed_tasks_since_last_schedule_tasks_(true), did_oom_on_last_assign_(false), ready_to_activate_check_notifier_( @@ -719,7 +710,6 @@ return make_scoped_refptr(new ImageDecodeTaskImpl( pixel_ref, tile->layer_id(), - rendering_stats_instrumentation_, base::Bind(&TileManager::OnImageDecodeTaskCompleted, base::Unretained(this), tile->layer_id(), @@ -766,7 +756,6 @@ static_cast<const void*>(tile), tile->source_frame_number(), tile->use_picture_analysis(), - rendering_stats_instrumentation_, base::Bind(&TileManager::OnRasterTaskCompleted, base::Unretained(this), tile->id(),
diff --git a/cc/resources/tile_manager.h b/cc/resources/tile_manager.h index 638fecb..a5005bf 100644 --- a/cc/resources/tile_manager.h +++ b/cc/resources/tile_manager.h
@@ -16,7 +16,6 @@ #include "base/values.h" #include "cc/base/ref_counted_managed.h" #include "cc/base/unique_notifier.h" -#include "cc/debug/rendering_stats_instrumentation.h" #include "cc/resources/eviction_tile_priority_queue.h" #include "cc/resources/managed_tile_state.h" #include "cc/resources/memory_history.h" @@ -102,7 +101,6 @@ base::SequencedTaskRunner* task_runner, ResourcePool* resource_pool, TileTaskRunner* tile_task_runner, - RenderingStatsInstrumentation* rendering_stats_instrumentation, size_t scheduled_raster_task_limit); ~TileManager() override; @@ -176,7 +174,6 @@ const scoped_refptr<base::SequencedTaskRunner>& task_runner, ResourcePool* resource_pool, TileTaskRunner* tile_task_runner, - RenderingStatsInstrumentation* rendering_stats_instrumentation, size_t scheduled_raster_task_limit); void FreeResourcesForReleasedTiles(); @@ -260,8 +257,6 @@ bool all_tiles_that_need_to_be_rasterized_are_scheduled_; MemoryHistory::Entry memory_stats_from_last_assign_; - RenderingStatsInstrumentation* rendering_stats_instrumentation_; - bool did_check_for_completed_tasks_since_last_schedule_tasks_; bool did_oom_on_last_assign_;
diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc index fdd876e..eb5d737 100644 --- a/cc/resources/tile_manager_unittest.cc +++ b/cc/resources/tile_manager_unittest.cc
@@ -109,7 +109,7 @@ if (old_pending_root) { pending_layer.reset( static_cast<FakePictureLayerImpl*>(old_pending_root.release())); - pending_layer->SetRasterSource(pile); + pending_layer->SetRasterSourceOnPending(pile, Region()); } else { pending_layer = FakePictureLayerImpl::CreateWithRasterSource(pending_tree, id_, pile); @@ -124,14 +124,6 @@ pending_layer_->DoPostCommitInitializationIfNeeded(); } - void CreateHighLowResAndSetAllTilesVisible() { - // Active layer must get updated first so pending layer can share from it. - active_layer_->CreateDefaultTilingsAndTiles(); - active_layer_->SetAllTilesVisible(); - pending_layer_->CreateDefaultTilingsAndTiles(); - pending_layer_->SetAllTilesVisible(); - } - TileManager* tile_manager() { return host_impl_.tile_manager(); } protected: @@ -195,10 +187,8 @@ // Invalidate the pending tree. pending_layer_->set_invalidation(invalidation); - pending_layer_->HighResTiling()->UpdateTilesToCurrentRasterSource( - pending_layer_->raster_source(), invalidation, gfx::Size(1000, 1000)); - pending_layer_->LowResTiling()->UpdateTilesToCurrentRasterSource( - pending_layer_->raster_source(), invalidation, gfx::Size(1000, 1000)); + pending_layer_->HighResTiling()->Invalidate(invalidation); + pending_layer_->LowResTiling()->Invalidate(invalidation); active_layer_->ResetAllTilesPriorities(); pending_layer_->ResetAllTilesPriorities(); @@ -445,10 +435,8 @@ // Invalidate the pending tree. pending_layer_->set_invalidation(invalidation); - pending_layer_->HighResTiling()->UpdateTilesToCurrentRasterSource( - pending_layer_->raster_source(), invalidation, gfx::Size(1000, 1000)); - pending_layer_->LowResTiling()->UpdateTilesToCurrentRasterSource( - pending_layer_->raster_source(), invalidation, gfx::Size(1000, 1000)); + pending_layer_->HighResTiling()->Invalidate(invalidation); + pending_layer_->LowResTiling()->Invalidate(invalidation); active_layer_->ResetAllTilesPriorities(); pending_layer_->ResetAllTilesPriorities(); @@ -495,6 +483,8 @@ // Here we expect to get increasing ACTIVE_TREE priority_bin. queue.Reset(); host_impl_.BuildEvictionQueue(&queue, SMOOTHNESS_TAKES_PRIORITY); + int distance_increasing = 0; + int distance_decreasing = 0; while (!queue.IsEmpty()) { Tile* tile = queue.Top(); EXPECT_TRUE(tile); @@ -511,8 +501,11 @@ tile->required_for_activation()); if (last_tile->required_for_activation() == tile->required_for_activation()) { - EXPECT_GE(last_tile->priority(ACTIVE_TREE).distance_to_visible, - tile->priority(ACTIVE_TREE).distance_to_visible); + if (last_tile->priority(ACTIVE_TREE).distance_to_visible >= + tile->priority(ACTIVE_TREE).distance_to_visible) + ++distance_decreasing; + else + ++distance_increasing; } } @@ -522,6 +515,8 @@ queue.Pop(); } + EXPECT_EQ(3, distance_increasing); + EXPECT_EQ(16, distance_decreasing); EXPECT_EQ(tile_count, smoothness_tiles.size()); EXPECT_EQ(all_tiles, smoothness_tiles); @@ -530,6 +525,8 @@ // Here we expect to get increasing PENDING_TREE priority_bin. queue.Reset(); host_impl_.BuildEvictionQueue(&queue, NEW_CONTENT_TAKES_PRIORITY); + distance_decreasing = 0; + distance_increasing = 0; while (!queue.IsEmpty()) { Tile* tile = queue.Top(); EXPECT_TRUE(tile); @@ -545,8 +542,11 @@ tile->required_for_activation()); if (last_tile->required_for_activation() == tile->required_for_activation()) { - EXPECT_GE(last_tile->priority(PENDING_TREE).distance_to_visible, - tile->priority(PENDING_TREE).distance_to_visible); + if (last_tile->priority(PENDING_TREE).distance_to_visible >= + tile->priority(PENDING_TREE).distance_to_visible) + ++distance_decreasing; + else + ++distance_increasing; } } @@ -555,6 +555,8 @@ queue.Pop(); } + EXPECT_EQ(3, distance_increasing); + EXPECT_EQ(16, distance_decreasing); EXPECT_EQ(tile_count, new_content_tiles.size()); EXPECT_EQ(all_tiles, new_content_tiles); }
diff --git a/cc/resources/tiling_set_eviction_queue.cc b/cc/resources/tiling_set_eviction_queue.cc index 8c5ff52..18f659e 100644 --- a/cc/resources/tiling_set_eviction_queue.cc +++ b/cc/resources/tiling_set_eviction_queue.cc
@@ -2,38 +2,53 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "cc/resources/tiling_set_eviction_queue.h" namespace cc { TilingSetEvictionQueue::TilingSetEvictionQueue() : tiling_set_(nullptr), + tree_(ACTIVE_TREE), tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES), - current_category_(PictureLayerTiling::EVENTUALLY), + skip_all_shared_tiles_(false), + skip_shared_out_of_order_tiles_(false), + processing_soon_border_rect_(false), + processing_tiling_with_required_for_activation_tiles_(false), + tiling_index_with_required_for_activation_tiles_(0u), + current_priority_bin_(TilePriority::EVENTUALLY), current_tiling_index_(0u), current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES), - current_eviction_tile_(nullptr), - eviction_tiles_(nullptr), - next_eviction_tile_index_(0u) { + current_eviction_tile_(nullptr) { } TilingSetEvictionQueue::TilingSetEvictionQueue( PictureLayerTilingSet* tiling_set, - TreePriority tree_priority) + TreePriority tree_priority, + bool skip_shared_out_of_order_tiles) : tiling_set_(tiling_set), + tree_(tiling_set->client()->GetTree()), tree_priority_(tree_priority), - current_category_(PictureLayerTiling::EVENTUALLY), + skip_all_shared_tiles_( + skip_shared_out_of_order_tiles && + tree_priority == (tree_ == ACTIVE_TREE ? NEW_CONTENT_TAKES_PRIORITY + : SMOOTHNESS_TAKES_PRIORITY)), + skip_shared_out_of_order_tiles_(skip_shared_out_of_order_tiles), + processing_soon_border_rect_(false), + processing_tiling_with_required_for_activation_tiles_(false), + tiling_index_with_required_for_activation_tiles_(0u), + current_priority_bin_(TilePriority::EVENTUALLY), current_tiling_index_(0u), current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES), - current_eviction_tile_(nullptr), - eviction_tiles_(nullptr), - next_eviction_tile_index_(0u) { - DCHECK(tiling_set_); - + current_eviction_tile_(nullptr) { // Early out if the layer has no tilings. if (!tiling_set_->num_tilings()) return; + tiling_index_with_required_for_activation_tiles_ = + TilingIndexWithRequiredForActivationTiles(); + current_tiling_index_ = CurrentTilingRange().start - 1u; AdvanceToNextValidTiling(); } @@ -62,60 +77,132 @@ return current_eviction_tile_; } -bool TilingSetEvictionQueue::AdvanceToNextCategory() { - // Advance to the next category. This is done only after all tiling range - // types within the previous category have been gone through. - DCHECK_EQ(current_tiling_range_type_, PictureLayerTilingSet::HIGH_RES); - - switch (current_category_) { - case PictureLayerTiling::EVENTUALLY: - current_category_ = - PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION; - return true; - case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: - current_category_ = PictureLayerTiling::SOON; - return true; - case PictureLayerTiling::SOON: - current_category_ = PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION; - return true; - case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION: - current_category_ = PictureLayerTiling::NOW; - return true; - case PictureLayerTiling::NOW: - current_category_ = PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION; - return true; - case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION: - return false; - } - NOTREACHED(); - return false; -} - bool TilingSetEvictionQueue::AdvanceToNextEvictionTile() { - // Advance to the next eviction tile within the current category and tiling. - // This is done while advancing to a new tiling (in which case the next - // eviction tile index is 0) and while popping the current tile (in which - // case the next eviction tile index is greater than 0). - DCHECK_EQ(next_eviction_tile_index_ > 0, current_eviction_tile_ != nullptr); + // Advance to the next eviction tile within the current priority bin and + // tiling. This is done while advancing to a new tiling and while popping + // the current tile. - while (next_eviction_tile_index_ < eviction_tiles_->size()) { - Tile* tile = (*eviction_tiles_)[next_eviction_tile_index_]; - ++next_eviction_tile_index_; - if (tile->HasResources()) { + bool required_for_activation = + processing_tiling_with_required_for_activation_tiles_; + + for (;;) { + while (spiral_iterator_) { + std::pair<int, int> next_index = spiral_iterator_.index(); + Tile* tile = current_tiling_->TileAt(next_index.first, next_index.second); + ++spiral_iterator_; + if (!tile || !tile->HasResources()) + continue; + if (skip_all_shared_tiles_ && tile->is_shared()) + continue; + current_tiling_->UpdateTileAndTwinPriority(tile); + if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tile)) + continue; + if (tile->required_for_activation() != required_for_activation) + continue; current_eviction_tile_ = tile; return true; } + if (processing_soon_border_rect_) { + // Advance from soon border rect to skewport rect. + processing_soon_border_rect_ = false; + if (current_tiling_->has_skewport_rect_tiles_) { + spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ¤t_tiling_->tiling_data_, + current_tiling_->current_skewport_rect_, + current_tiling_->current_visible_rect_, + current_tiling_->current_visible_rect_); + continue; + } + } + break; + } + + TilePriority::PriorityBin max_tile_priority_bin = + current_tiling_->client_->GetMaxTilePriorityBin(); + while (visible_iterator_) { + std::pair<int, int> next_index = visible_iterator_.index(); + Tile* tile = current_tiling_->TileAt(next_index.first, next_index.second); + ++visible_iterator_; + if (!tile || !tile->HasResources()) + continue; + if (skip_all_shared_tiles_ && tile->is_shared()) + continue; + // If the max tile priority is not NOW, updated priorities for tiles + // returned by the visible iterator will not have NOW (but EVENTUALLY) + // priority bin and cannot therefore be required for activation tiles nor + // occluded NOW tiles in the current tiling. + if (max_tile_priority_bin <= TilePriority::NOW) { + // If the current tiling is a pending tree tiling, required for + // activation tiles can be detected without updating tile priorities. + if (tree_ == PENDING_TREE && + current_tiling_->IsTileRequiredForActivationIfVisible(tile) != + required_for_activation) { + continue; + } + // Unoccluded NOW tiles should be evicted (and thus returned) only after + // all occluded NOW tiles. + if (!current_tiling_->IsTileOccluded(tile)) { + unoccluded_now_tiles_.push_back(tile); + continue; + } + } + current_tiling_->UpdateTileAndTwinPriority(tile); + if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tile)) + continue; + if (tile->required_for_activation() != required_for_activation) + continue; + current_eviction_tile_ = tile; + return true; + } + + while (!unoccluded_now_tiles_.empty()) { + // All (unoccluded) NOW tiles have the same priority bin (NOW) and the same + // distance to visible (0.0), so it does not matter that tiles are popped + // in reversed (FILO) order. + Tile* tile = unoccluded_now_tiles_.back(); + unoccluded_now_tiles_.pop_back(); + DCHECK(tile); + if (!tile->HasResources()) + continue; + current_tiling_->UpdateTileAndTwinPriority(tile); + if (skip_shared_out_of_order_tiles_ && IsSharedOutOfOrderTile(tile)) + continue; + if (tile->required_for_activation() != required_for_activation) + continue; + current_eviction_tile_ = tile; + return true; } current_eviction_tile_ = nullptr; return false; } +bool TilingSetEvictionQueue::AdvanceToNextPriorityBin() { + // Advance to the next priority bin. This is done only after all tiling range + // types (including the required for activation tiling) within the previous + // priority bin have been gone through. + DCHECK_EQ(current_tiling_range_type_, PictureLayerTilingSet::HIGH_RES); + + switch (current_priority_bin_) { + case TilePriority::EVENTUALLY: + current_priority_bin_ = TilePriority::SOON; + return true; + case TilePriority::SOON: + current_priority_bin_ = TilePriority::NOW; + return true; + case TilePriority::NOW: + return false; + } + NOTREACHED(); + return false; +} + bool TilingSetEvictionQueue::AdvanceToNextTilingRangeType() { - // Advance to the next tiling range type within the current category or to - // the first tiling range type within the next category. This is done only - // after all tilings within the previous tiling range type have been gone - // through. + // Advance to the next tiling range type within the current priority bin, to + // the required for activation tiling range type within the current priority + // bin or to the first tiling range type within the next priority bin. This + // is done only after all tilings within the previous tiling range type have + // been gone through. DCHECK_EQ(current_tiling_index_, CurrentTilingRange().end); switch (current_tiling_range_type_) { @@ -133,7 +220,15 @@ current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES; return true; case PictureLayerTilingSet::HIGH_RES: - if (!AdvanceToNextCategory()) + if (!processing_tiling_with_required_for_activation_tiles_ && + tiling_index_with_required_for_activation_tiles_ < + tiling_set_->num_tilings()) { + processing_tiling_with_required_for_activation_tiles_ = true; + return true; + } + processing_tiling_with_required_for_activation_tiles_ = false; + + if (!AdvanceToNextPriorityBin()) return false; current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES; @@ -145,10 +240,10 @@ bool TilingSetEvictionQueue::AdvanceToNextValidTiling() { // Advance to the next tiling within current tiling range type or to - // the first tiling within the next tiling range type or category until + // the first tiling within the next tiling range type or priority bin until // the next eviction tile is found. This is done only after all eviction - // tiles within the previous tiling within the current category and tiling - // range type have been gone through. + // tiles within the previous tiling within the current priority bin and + // tiling range type have been gone through. DCHECK(!current_eviction_tile_); DCHECK_NE(current_tiling_index_, CurrentTilingRange().end); @@ -159,18 +254,54 @@ return false; current_tiling_index_ = CurrentTilingRange().start; } + current_tiling_ = tiling_set_->tiling_at(CurrentTilingIndex()); - PictureLayerTiling* tiling = tiling_set_->tiling_at(CurrentTilingIndex()); - eviction_tiles_ = - tiling->GetEvictionTiles(tree_priority_, current_category_); - next_eviction_tile_index_ = 0u; - if (AdvanceToNextEvictionTile()) - return true; + switch (current_priority_bin_) { + case TilePriority::EVENTUALLY: + if (current_tiling_->has_eventually_rect_tiles_) { + spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ¤t_tiling_->tiling_data_, + current_tiling_->current_eventually_rect_, + current_tiling_->current_skewport_rect_, + current_tiling_->current_soon_border_rect_); + if (AdvanceToNextEvictionTile()) + return true; + } + break; + case TilePriority::SOON: + if (current_tiling_->has_skewport_rect_tiles_ || + current_tiling_->has_soon_border_rect_tiles_) { + processing_soon_border_rect_ = true; + if (current_tiling_->has_soon_border_rect_tiles_) + spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( + ¤t_tiling_->tiling_data_, + current_tiling_->current_soon_border_rect_, + current_tiling_->current_skewport_rect_, + current_tiling_->current_visible_rect_); + if (AdvanceToNextEvictionTile()) + return true; + } + break; + case TilePriority::NOW: + if (current_tiling_->has_visible_rect_tiles_) { + visible_iterator_ = + TilingData::Iterator(¤t_tiling_->tiling_data_, + current_tiling_->current_visible_rect_, + false /* include_borders */); + if (AdvanceToNextEvictionTile()) + return true; + } + break; + } } } PictureLayerTilingSet::TilingRange TilingSetEvictionQueue::CurrentTilingRange() const { + if (processing_tiling_with_required_for_activation_tiles_) + return PictureLayerTilingSet::TilingRange( + tiling_index_with_required_for_activation_tiles_, + tiling_index_with_required_for_activation_tiles_ + 1); return tiling_set_->GetTilingRange(current_tiling_range_type_); } @@ -194,4 +325,77 @@ return 0; } +bool TilingSetEvictionQueue::IsSharedOutOfOrderTile(const Tile* tile) const { + if (!tile->is_shared()) + return false; + + switch (tree_priority_) { + case SMOOTHNESS_TAKES_PRIORITY: + DCHECK_EQ(ACTIVE_TREE, tree_); + return false; + case NEW_CONTENT_TAKES_PRIORITY: + DCHECK_EQ(PENDING_TREE, tree_); + return false; + case SAME_PRIORITY_FOR_BOTH_TREES: + break; + case NUM_TREE_PRIORITIES: + NOTREACHED(); + break; + } + + // The priority for tile priority of a shared tile will be a combined + // priority thus return shared tiles from a higher priority tree as + // it is out of order for a lower priority tree. + WhichTree twin_tree = tree_ == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE; + const TilePriority& priority = tile->priority(tree_); + const TilePriority& twin_priority = tile->priority(twin_tree); + if (priority.priority_bin != twin_priority.priority_bin) + return priority.priority_bin > twin_priority.priority_bin; + const bool occluded = tile->is_occluded(tree_); + const bool twin_occluded = tile->is_occluded(twin_tree); + if (occluded != twin_occluded) + return occluded; + if (priority.distance_to_visible != twin_priority.distance_to_visible) + return priority.distance_to_visible > twin_priority.distance_to_visible; + + // If priorities are the same, it does not matter which tree returns + // the tile. Let's pick the pending tree. + return tree_ != PENDING_TREE; } + +size_t TilingSetEvictionQueue::TilingIndexWithRequiredForActivationTiles() + const { + // Returns the tiling index of the tiling with requuired for activation tiles. + // If no such tiling exists, returns the past-the-last index (num_tilings). + size_t num_tilings = tiling_set_->num_tilings(); + + if (tree_ == PENDING_TREE) { + // For the pending tree, the tiling with required for activation tiles is + // the high res one. + PictureLayerTilingSet::TilingRange high_res_tiling_range = + tiling_set_->GetTilingRange(PictureLayerTilingSet::HIGH_RES); + if (high_res_tiling_range.start != high_res_tiling_range.end) + return high_res_tiling_range.start; + } else { + DCHECK_EQ(ACTIVE_TREE, tree_); + // Only pending tree tiles can be required for activation. They can appear + // also in the active tree only if they are shared. If we skip all shared + // tiles, there is no need to find them as they will not be returned. + if (skip_all_shared_tiles_) + return num_tilings; + + // For the active tree, the tiling with required for activation tiles is + // the one whose twin tiling is the high res pending tiling. + for (size_t i = 0; i < num_tilings; ++i) { + const PictureLayerTiling* tiling = tiling_set_->tiling_at(i); + const PictureLayerTiling* pending_tiling = + tiling_set_->client()->GetPendingOrActiveTwinTiling(tiling); + if (pending_tiling && pending_tiling->resolution() == HIGH_RESOLUTION) + return i; + } + } + + return num_tilings; +} + +} // namespace cc
diff --git a/cc/resources/tiling_set_eviction_queue.h b/cc/resources/tiling_set_eviction_queue.h index f88ce3b..4463cc3 100644 --- a/cc/resources/tiling_set_eviction_queue.h +++ b/cc/resources/tiling_set_eviction_queue.h
@@ -5,16 +5,79 @@ #ifndef CC_RESOURCES_TILING_SET_EVICTION_QUEUE_H_ #define CC_RESOURCES_TILING_SET_EVICTION_QUEUE_H_ +#include <vector> + #include "cc/base/cc_export.h" #include "cc/resources/picture_layer_tiling_set.h" namespace cc { +// This eviction queue returned tiles from all tilings in a tiling set in +// the following order: +// 1) Eventually rect tiles (EVENTUALLY tiles). +// 1) Eventually rect tiles not required for activation from each tiling in +// the tiling set, in turn, in the following order: +// 1) the first higher than high res tiling, the second one and so on +// 2) the first lower than low res tiling, the second one and so on +// 3) the first between high and low res tiling, the second one and so on +// 4) low res tiling +// 5) high res tiling +// 2) Eventually rect tiles required for activation from the tiling with +// required for activation tiles. In the case of a pending tree tiling +// set that is the high res tiling. In the case of an active tree tiling +// set that is a tiling whose twin tiling is a pending tree high res +// tiling. +// 2) Soon border rect and skewport rect tiles (whose priority bin is SOON +// unless the max tile priority bin is lowered by PictureLayerTilingClient). +// 1) Soon border rect and skewport rect tiles not required for activation +// from each tiling in the tiling set. +// * Tilings are iterated in the same order as in the case of eventually +// rect tiles not required for activation. +// * For each tiling, first soon border rect tiles and then skewport +// rect tiles are returned. +// 2) Soon border rect and skewport rect tiles required for activation from +// the tiling with required for activation tiles. +// * First soon border rect tiles and then skewport rect tiles are +// returned. +// 3) Visible rect tiles (whose priority bin is NOW unless the max tile +// priority bin is lowered by PictureLayerTilingClient). +// 1) Visible rect tiles not required for activation from each tiling in +// the tiling set. +// * Tilings are iterated in the same order as in the case of eventually +// rect tiles not required for activation. +// * For each tiling, first occluded tiles and then unoccluded tiles +// are returned. +// 2) Visible rect tiles required for activation from the tiling with +// required for activation tiles. +// * First occluded tiles and then unoccluded tiles are returned. +// If the max tile priority bin is lowered by PictureLayerTilingClient, +// occlusion is not taken into account as occlusion is meaningful only for +// NOW tiles. +// +// Within each tiling and tile priority rect, tiles are returned in reverse +// spiral order i.e. in (mostly) decreasing distance-to-visible order. +// +// If the skip_shared_out_of_order_tiles value passed to the constructor is +// true (like it should be when there is a twin layer with a twin tiling set), +// eviction queue does not return shared which are out of order because their +// priority for tree priority is lowered or raised by a twin layer. +// * If tree_priority is SAME_PRIORITY_FOR_BOTH_TREES, this happens for +// a tile specific lower priority tree eviction queue (because priority for +// tree priority is a merged priority). +// * If tree priority is NEW_CONTENT_TAKES_PRIORITY, this happens for +// an active tree eviction queue (because priority for tree priority is +// the pending priority). +// * If tree_priority is SMOOTHNESS_TAKES_PRIORITY, this happens for a pending +// tree eviction queue (because priority for tree priority is the active +// priority). +// Those skipped shared out of order tiles are when returned only by the twin +// eviction queue. class CC_EXPORT TilingSetEvictionQueue { public: TilingSetEvictionQueue(); TilingSetEvictionQueue(PictureLayerTilingSet* tiling_set, - TreePriority tree_priority); + TreePriority tree_priority, + bool skip_shared_out_of_order_tiles); ~TilingSetEvictionQueue(); Tile* Top(); @@ -23,26 +86,36 @@ bool IsEmpty() const; private: - bool AdvanceToNextCategory(); bool AdvanceToNextEvictionTile(); + bool AdvanceToNextPriorityBin(); bool AdvanceToNextTilingRangeType(); bool AdvanceToNextValidTiling(); PictureLayerTilingSet::TilingRange CurrentTilingRange() const; size_t CurrentTilingIndex() const; + bool IsSharedOutOfOrderTile(const Tile* tile) const; + size_t TilingIndexWithRequiredForActivationTiles() const; PictureLayerTilingSet* tiling_set_; + WhichTree tree_; TreePriority tree_priority_; + bool skip_all_shared_tiles_; + bool skip_shared_out_of_order_tiles_; + bool processing_soon_border_rect_; + bool processing_tiling_with_required_for_activation_tiles_; + size_t tiling_index_with_required_for_activation_tiles_; - PictureLayerTiling::EvictionCategory current_category_; + TilePriority::PriorityBin current_priority_bin_; + PictureLayerTiling* current_tiling_; size_t current_tiling_index_; PictureLayerTilingSet::TilingRangeType current_tiling_range_type_; Tile* current_eviction_tile_; - const std::vector<Tile*>* eviction_tiles_; - size_t next_eviction_tile_index_; + TilingData::ReverseSpiralDifferenceIterator spiral_iterator_; + TilingData::Iterator visible_iterator_; + std::vector<Tile*> unoccluded_now_tiles_; }; } // namespace cc -#endif // CC_RESOURCES_TILING_SET_RASTER_QUEUE_H_ +#endif // CC_RESOURCES_TILING_SET_EVICTION_QUEUE_H_
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index 2c9a688..edbea9b 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -4,6 +4,8 @@ #include "cc/resources/video_resource_updater.h" +#include <algorithm> + #include "base/bind.h" #include "base/debug/trace_event.h" #include "cc/output/gl_renderer.h" @@ -48,6 +50,7 @@ resource_size(resource_size), resource_format(resource_format), mailbox(mailbox), + ref_count(0), frame_ptr(nullptr), plane_index(0) { } @@ -81,17 +84,43 @@ } VideoResourceUpdater::~VideoResourceUpdater() { - while (!all_resources_.empty()) { - resource_provider_->DeleteResource(all_resources_.back()); - all_resources_.pop_back(); - } + for (const PlaneResource& plane_resource : all_resources_) + resource_provider_->DeleteResource(plane_resource.resource_id); } -void VideoResourceUpdater::DeleteResource(unsigned resource_id) { - resource_provider_->DeleteResource(resource_id); - all_resources_.erase(std::remove(all_resources_.begin(), - all_resources_.end(), - resource_id)); +VideoResourceUpdater::ResourceList::iterator +VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, + ResourceFormat format, + bool has_mailbox) { + // TODO(danakj): Abstract out hw/sw resource create/delete from + // ResourceProvider and stop using ResourceProvider in this class. + const ResourceProvider::ResourceId resource_id = + resource_provider_->CreateResource(plane_size, GL_CLAMP_TO_EDGE, + ResourceProvider::TextureHintImmutable, + format); + if (resource_id == 0) + return all_resources_.end(); + + gpu::Mailbox mailbox; + if (has_mailbox) { + DCHECK(context_provider_); + + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); + + GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name)); + ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id); + GLC(gl, gl->ProduceTextureDirectCHROMIUM(lock.texture_id(), GL_TEXTURE_2D, + mailbox.name)); + } + all_resources_.push_front( + PlaneResource(resource_id, plane_size, format, mailbox)); + return all_resources_.begin(); +} + +void VideoResourceUpdater::DeleteResource(ResourceList::iterator resource_it) { + DCHECK_EQ(resource_it->ref_count, 0); + resource_provider_->DeleteResource(resource_it->resource_id); + all_resources_.erase(resource_it); } VideoFrameExternalResources VideoResourceUpdater:: @@ -157,19 +186,15 @@ #endif // defined(VIDEO_HOLE) // Only YUV software video frames are supported. - DCHECK(input_frame_format == media::VideoFrame::YV12 || - input_frame_format == media::VideoFrame::I420 || - input_frame_format == media::VideoFrame::YV12A || - input_frame_format == media::VideoFrame::YV12J || - input_frame_format == media::VideoFrame::YV16 || - input_frame_format == media::VideoFrame::YV24); if (input_frame_format != media::VideoFrame::YV12 && input_frame_format != media::VideoFrame::I420 && input_frame_format != media::VideoFrame::YV12A && input_frame_format != media::VideoFrame::YV12J && input_frame_format != media::VideoFrame::YV16 && - input_frame_format != media::VideoFrame::YV24) + input_frame_format != media::VideoFrame::YV24) { + NOTREACHED() << input_frame_format; return VideoFrameExternalResources(); + } bool software_compositor = context_provider_ == NULL; @@ -186,81 +211,69 @@ output_plane_count = 1; } - int max_resource_size = resource_provider_->max_texture_size(); - std::vector<PlaneResource> plane_resources; - bool allocation_success = true; + // Drop recycled resources that are the wrong format. + for (auto it = all_resources_.begin(); it != all_resources_.end();) { + if (it->ref_count == 0 && it->resource_format != output_resource_format) + DeleteResource(it++); + else + ++it; + } + const int max_resource_size = resource_provider_->max_texture_size(); + std::vector<ResourceList::iterator> plane_resources; for (size_t i = 0; i < output_plane_count; ++i) { gfx::Size output_plane_resource_size = SoftwarePlaneDimension(video_frame, software_compositor, i); if (output_plane_resource_size.IsEmpty() || output_plane_resource_size.width() > max_resource_size || output_plane_resource_size.height() > max_resource_size) { - allocation_success = false; break; } // Try recycle a previously-allocated resource. - auto recycled_it = recycled_resources_.end(); - for (auto it = recycled_resources_.begin(); it != recycled_resources_.end(); - ++it) { - const bool resource_matches = - it->resource_format == output_resource_format && - it->resource_size == output_plane_resource_size; - const bool in_use = software_compositor && - resource_provider_->InUseByConsumer(it->resource_id); - if (resource_matches && !in_use) { - // We found a recycled resource with the allocation size and format we - // are looking for. - recycled_it = it; - // Keep looking for a recycled resource that also contains the data we - // are planning to put in it. - if (PlaneResourceMatchesUniqueID(*it, video_frame.get(), i)) + ResourceList::iterator resource_it = all_resources_.end(); + for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { + if (it->resource_size == output_plane_resource_size && + it->resource_format == output_resource_format) { + if (PlaneResourceMatchesUniqueID(*it, video_frame.get(), i)) { + // Bingo, we found a resource that already contains the data we are + // planning to put in it. It's safe to reuse it even if + // resource_provider_ holds some references to it, because those + // references are read-only. + resource_it = it; break; + } + + // This extra check is needed because resources backed by SharedMemory + // are not ref-counted, unlike mailboxes. Full discussion in + // codereview.chromium.org/145273021. + const bool in_use = + software_compositor && + resource_provider_->InUseByConsumer(it->resource_id); + if (it->ref_count == 0 && !in_use) { + // We found a resource with the correct size that we can overwrite. + resource_it = it; + } } } - // Check if we can avoid allocating a new resource. - if (recycled_it != recycled_resources_.end()) { - plane_resources.push_back(*recycled_it); - recycled_resources_.erase(recycled_it); - continue; + // Check if we need to allocate a new resource. + if (resource_it == all_resources_.end()) { + resource_it = + AllocateResource(output_plane_resource_size, output_resource_format, + !software_compositor); } - - // TODO(danakj): Abstract out hw/sw resource create/delete from - // ResourceProvider and stop using ResourceProvider in this class. - const ResourceProvider::ResourceId resource_id = - resource_provider_->CreateResource( - output_plane_resource_size, GL_CLAMP_TO_EDGE, - ResourceProvider::TextureHintImmutable, output_resource_format); - if (resource_id == 0) { - allocation_success = false; + if (resource_it == all_resources_.end()) break; - } - all_resources_.push_back(resource_id); - gpu::Mailbox mailbox; - if (!software_compositor) { - DCHECK(context_provider_); - - gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); - - GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name)); - ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id); - GLC(gl, gl->ProduceTextureDirectCHROMIUM(lock.texture_id(), GL_TEXTURE_2D, - mailbox.name)); - } - - DCHECK(software_compositor || !mailbox.IsZero()); - plane_resources.push_back(PlaneResource(resource_id, - output_plane_resource_size, - output_resource_format, - mailbox)); + ++resource_it->ref_count; + plane_resources.push_back(resource_it); } - if (!allocation_success) { - for (size_t i = 0; i < plane_resources.size(); ++i) - DeleteResource(plane_resources[i].resource_id); + if (plane_resources.size() != output_plane_count) { + // Allocation failed, nothing will be returned so restore reference counts. + for (ResourceList::iterator resource_it : plane_resources) + --resource_it->ref_count; return VideoFrameExternalResources(); } @@ -268,54 +281,52 @@ if (software_compositor) { DCHECK_EQ(plane_resources.size(), 1u); - DCHECK_EQ(plane_resources[0].resource_format, kRGBResourceFormat); - DCHECK(plane_resources[0].mailbox.IsZero()); + PlaneResource& plane_resource = *plane_resources[0]; + DCHECK_EQ(plane_resource.resource_format, kRGBResourceFormat); + DCHECK(plane_resource.mailbox.IsZero()); - if (!PlaneResourceMatchesUniqueID(plane_resources[0], video_frame.get(), - 0)) { + if (!PlaneResourceMatchesUniqueID(plane_resource, video_frame.get(), 0)) { // We need to transfer data from |video_frame| to the plane resource. if (!video_renderer_) video_renderer_.reset(new media::SkCanvasVideoRenderer); ResourceProvider::ScopedWriteLockSoftware lock( - resource_provider_, plane_resources[0].resource_id); + resource_provider_, plane_resource.resource_id); SkCanvas canvas(lock.sk_bitmap()); video_renderer_->Copy(video_frame, &canvas); - SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resources[0]); + SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resource); } - external_resources.software_resources.push_back( - plane_resources[0].resource_id); + external_resources.software_resources.push_back(plane_resource.resource_id); external_resources.software_release_callback = - base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[0]); + base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id); external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; - return external_resources; } for (size_t i = 0; i < plane_resources.size(); ++i) { + PlaneResource& plane_resource = *plane_resources[i]; // Update each plane's resource id with its content. - DCHECK_EQ(plane_resources[i].resource_format, + DCHECK_EQ(plane_resource.resource_format, resource_provider_->yuv_resource_format()); - if (!PlaneResourceMatchesUniqueID(plane_resources[i], video_frame.get(), - i)) { + if (!PlaneResourceMatchesUniqueID(plane_resource, video_frame.get(), i)) { // We need to transfer data from |video_frame| to the plane resource. const uint8_t* input_plane_pixels = video_frame->data(i); gfx::Rect image_rect(0, 0, video_frame->stride(i), - plane_resources[i].resource_size.height()); - gfx::Rect source_rect(plane_resources[i].resource_size); - resource_provider_->SetPixels(plane_resources[i].resource_id, + plane_resource.resource_size.height()); + gfx::Rect source_rect(plane_resource.resource_size); + resource_provider_->SetPixels(plane_resource.resource_id, input_plane_pixels, image_rect, source_rect, gfx::Vector2d()); - SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resources[i]); + SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resource); } external_resources.mailboxes.push_back( - TextureMailbox(plane_resources[i].mailbox, GL_TEXTURE_2D, 0)); + TextureMailbox(plane_resource.mailbox, GL_TEXTURE_2D, 0)); external_resources.release_callbacks.push_back( - base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[i])); + base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id)); } external_resources.type = VideoFrameExternalResources::YUV_RESOURCE; @@ -382,7 +393,7 @@ // static void VideoResourceUpdater::RecycleResource( base::WeakPtr<VideoResourceUpdater> updater, - PlaneResource data, + ResourceProvider::ResourceId resource_id, uint32 sync_point, bool lost_resource, BlockingTaskRunner* main_thread_task_runner) { @@ -391,6 +402,14 @@ return; } + const ResourceList::iterator resource_it = std::find_if( + updater->all_resources_.begin(), updater->all_resources_.end(), + [resource_id](const PlaneResource& plane_resource) { + return plane_resource.resource_id == resource_id; + }); + if (resource_it == updater->all_resources_.end()) + return; + ContextProvider* context_provider = updater->context_provider_; if (context_provider && sync_point) { GLC(context_provider->ContextGL(), @@ -398,19 +417,13 @@ } if (lost_resource) { - updater->DeleteResource(data.resource_id); + resource_it->ref_count = 0; + updater->DeleteResource(resource_it); return; } - // Drop recycled resources that are the wrong format. - while (!updater->recycled_resources_.empty() && - updater->recycled_resources_.back().resource_format != - data.resource_format) { - updater->DeleteResource(updater->recycled_resources_.back().resource_id); - updater->recycled_resources_.pop_back(); - } - - updater->recycled_resources_.push_back(data); + --resource_it->ref_count; + DCHECK_GE(resource_it->ref_count, 0); } } // namespace cc
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h index 38f6033..622fe68 100644 --- a/cc/resources/video_resource_updater.h +++ b/cc/resources/video_resource_updater.h
@@ -5,6 +5,7 @@ #ifndef CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_ #define CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_ +#include <list> #include <vector> #include "base/basictypes.h" @@ -78,6 +79,9 @@ gfx::Size resource_size; ResourceFormat resource_format; gpu::Mailbox mailbox; + // The balance between the number of times this resource has been returned + // from CreateForSoftwarePlanes vs released in RecycleResource. + int ref_count; // These last three members will be used for identifying the data stored in // this resource, and uniquely identifies a media::VideoFrame plane. The // frame pointer will only be used for pointer comparison, i.e. the @@ -100,7 +104,13 @@ int plane_index, PlaneResource* plane_resource); - void DeleteResource(unsigned resource_id); + // This needs to be a container where iterators can be erased without + // invalidating other iterators. + typedef std::list<PlaneResource> ResourceList; + ResourceList::iterator AllocateResource(const gfx::Size& plane_size, + ResourceFormat format, + bool has_mailbox); + void DeleteResource(ResourceList::iterator resource_it); bool VerifyFrame(const scoped_refptr<media::VideoFrame>& video_frame); VideoFrameExternalResources CreateForHardwarePlanes( const scoped_refptr<media::VideoFrame>& video_frame); @@ -108,7 +118,7 @@ const scoped_refptr<media::VideoFrame>& video_frame); static void RecycleResource(base::WeakPtr<VideoResourceUpdater> updater, - PlaneResource data, + unsigned resource_id, uint32 sync_point, bool lost_resource, BlockingTaskRunner* main_thread_task_runner); @@ -122,10 +132,9 @@ ResourceProvider* resource_provider_; scoped_ptr<media::SkCanvasVideoRenderer> video_renderer_; - std::vector<unsigned> all_resources_; // Recycle resources so that we can reduce the number of allocations and // data transfers. - std::vector<PlaneResource> recycled_resources_; + ResourceList all_resources_; DISALLOW_COPY_AND_ASSIGN(VideoResourceUpdater); };
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc index 1e3481b..5433bcf 100644 --- a/cc/resources/video_resource_updater_unittest.cc +++ b/cc/resources/video_resource_updater_unittest.cc
@@ -115,26 +115,36 @@ // Expect exactly three texture uploads, one for each plane. EXPECT_EQ(3, context3d_->UploadCount()); - const ResourceProvider::ResourceId y_resource = - resource_provider3d_->CreateResourceFromTextureMailbox( - resources.mailboxes[media::VideoFrame::kYPlane], - SingleReleaseCallbackImpl::Create( - resources.release_callbacks[media::VideoFrame::kYPlane])); - const ResourceProvider::ResourceId u_resource = - resource_provider3d_->CreateResourceFromTextureMailbox( - resources.mailboxes[media::VideoFrame::kUPlane], - SingleReleaseCallbackImpl::Create( - resources.release_callbacks[media::VideoFrame::kUPlane])); - const ResourceProvider::ResourceId v_resource = - resource_provider3d_->CreateResourceFromTextureMailbox( - resources.mailboxes[media::VideoFrame::kVPlane], - SingleReleaseCallbackImpl::Create( - resources.release_callbacks[media::VideoFrame::kVPlane])); + // Simulate the ResourceProvider releasing the resources back to the video + // updater. + for (ReleaseCallbackImpl& release_callback : resources.release_callbacks) + release_callback.Run(0, false, nullptr); - // Delete the resources. - resource_provider3d_->DeleteResource(y_resource); - resource_provider3d_->DeleteResource(u_resource); - resource_provider3d_->DeleteResource(v_resource); + // Allocate resources for the same frame. + context3d_->ResetUploadCount(); + resources = updater.CreateExternalResourcesFromVideoFrame(video_frame); + EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); + EXPECT_EQ(size_t(3), resources.mailboxes.size()); + EXPECT_EQ(size_t(3), resources.release_callbacks.size()); + // The data should be reused so expect no texture uploads. + EXPECT_EQ(0, context3d_->UploadCount()); +} + +TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDelete) { + VideoResourceUpdater updater(output_surface3d_->context_provider(), + resource_provider3d_.get()); + scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame(); + video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234)); + + // Allocate the resources for a YUV video frame. + context3d_->ResetUploadCount(); + VideoFrameExternalResources resources = + updater.CreateExternalResourcesFromVideoFrame(video_frame); + EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type); + EXPECT_EQ(size_t(3), resources.mailboxes.size()); + EXPECT_EQ(size_t(3), resources.release_callbacks.size()); + // Expect exactly three texture uploads, one for each plane. + EXPECT_EQ(3, context3d_->UploadCount()); // Allocate resources for the same frame. context3d_->ResetUploadCount();
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 3e7653f..143c3ff 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -723,10 +723,6 @@ RescheduleBeginImplFrameDeadlineIfNeeded(); } -bool Scheduler::WillDrawIfNeeded() const { - return !state_machine_.PendingDrawsShouldBeAborted(); -} - scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() const { scoped_refptr<base::debug::TracedValue> state =
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 27dbee3..dea7c3e 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h
@@ -153,8 +153,6 @@ return !begin_impl_frame_deadline_task_.IsCancelled(); } - bool WillDrawIfNeeded() const; - base::TimeTicks AnticipatedDrawTime() const; void NotifyBeginMainFrameStarted();
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index 7bbfa37..5f413b3 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -9,24 +9,44 @@ #include "cc/test/begin_frame_args_test.h" #include "testing/gtest/include/gtest/gtest.h" -#define EXPECT_ACTION_UPDATE_STATE(action) \ - EXPECT_STREQ(SchedulerStateMachine::ActionToString(action), \ - SchedulerStateMachine::ActionToString(state.NextAction())) \ - << state.AsValue()->ToString(); \ - if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE || \ - action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) { \ - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, \ - state.begin_impl_frame_state()) \ - << state.AsValue()->ToString(); \ - } \ - state.UpdateState(action); \ - if (action == SchedulerStateMachine::ACTION_NONE) { \ - if (state.begin_impl_frame_state() == \ - SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) \ - state.OnBeginImplFrameDeadlinePending(); \ - if (state.begin_impl_frame_state() == \ - SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) \ - state.OnBeginImplFrameIdle(); \ +// Macro to compare two enum values and get nice output. +// Without: +// Value of: actual() Actual: 7 +// Expected: expected() Which is: 0 +// With: +// Value of: actual() Actual: "ACTION_ANIMATE" +// Expected: expected() Which is: "ACTION_NONE" +#define EXPECT_ENUM_EQ(enum_tostring, expected, actual) \ + EXPECT_STREQ(SchedulerStateMachine::enum_tostring(expected), \ + SchedulerStateMachine::enum_tostring(actual)) + +#define EXPECT_IMPL_FRAME_STATE(expected) \ + EXPECT_ENUM_EQ(BeginImplFrameStateToString, expected, \ + state.begin_impl_frame_state()) \ + << state.AsValue()->ToString() + +#define EXPECT_COMMIT_STATE(expected) \ + EXPECT_ENUM_EQ(CommitStateToString, expected, state.CommitState()) + +#define EXPECT_ACTION(expected) \ + EXPECT_ENUM_EQ(ActionToString, expected, state.NextAction()) \ + << state.AsValue()->ToString() + +#define EXPECT_ACTION_UPDATE_STATE(action) \ + EXPECT_ACTION(action); \ + if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE || \ + action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) { \ + EXPECT_IMPL_FRAME_STATE( \ + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); \ + } \ + state.UpdateState(action); \ + if (action == SchedulerStateMachine::ACTION_NONE) { \ + if (state.begin_impl_frame_state() == \ + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING) \ + state.OnBeginImplFrameDeadlinePending(); \ + if (state.begin_impl_frame_state() == \ + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) \ + state.OnBeginImplFrameIdle(); \ } namespace cc { @@ -177,8 +197,8 @@ state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.UpdateState(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); } } @@ -210,7 +230,7 @@ state.NotifyReadyToCommit(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -243,7 +263,7 @@ state.DidSwapBuffersComplete(); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); } TEST(SchedulerStateMachineTest, @@ -621,19 +641,16 @@ expected_action = SchedulerStateMachine::ACTION_COMMIT; } else { expected_action = SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE; - EXPECT_EQ(state.NextAction(), SchedulerStateMachine::ACTION_ANIMATE) - << state.AsValue()->ToString(); + EXPECT_ACTION(SchedulerStateMachine::ACTION_ANIMATE); state.UpdateState(state.NextAction()); } // Case 1: needs_commit=false. - EXPECT_EQ(state.NextAction(), expected_action) - << state.AsValue()->ToString(); + EXPECT_ACTION(expected_action); // Case 2: needs_commit=true. state.SetNeedsCommit(); - EXPECT_EQ(state.NextAction(), expected_action) - << state.AsValue()->ToString(); + EXPECT_ACTION(expected_action); } } @@ -740,8 +757,8 @@ state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); // Now, while the frame is in progress, set another commit. state.SetNeedsCommit(); @@ -750,33 +767,31 @@ // Let the frame finish. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, - state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT); // Expect to commit regardless of BeginImplFrame state. - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING); + EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); state.OnBeginImplFrameDeadlinePending(); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME); + EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); state.OnBeginImplFrameDeadline(); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); state.OnBeginImplFrameIdle(); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); + EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING); + EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); // Finish the commit, then make sure we start the next commit immediately // and draw on the next BeginImplFrame. @@ -813,16 +828,15 @@ state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // Tell the scheduler the frame finished. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, - state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT); // Commit. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); @@ -843,7 +857,7 @@ // Should be synchronized, no draw needed, no action needed. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_FALSE(state.needs_redraw()); } @@ -864,16 +878,15 @@ state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // Tell the scheduler the frame finished. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, - state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT); // Commit. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); @@ -881,8 +894,7 @@ EXPECT_TRUE(state.needs_redraw()); // Now commit should wait for draw. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW, - state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW); // Swap throttled. Do not draw. state.DidSwapBuffers(); @@ -906,7 +918,7 @@ state.DidSwapBuffersComplete(); // Now will be able to start main frame. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_FALSE(state.needs_redraw()); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); @@ -931,23 +943,22 @@ state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // Tell the scheduler the frame finished. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, - state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT); // Commit. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); // Now commit should wait for activation. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION); // No activation yet, so this commit is not drawn yet. Force to draw this // frame, and still block BeginMainFrame. @@ -961,8 +972,8 @@ // Cannot BeginMainFrame yet since last commit is not yet activated and drawn. state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_ACTIVATION); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // Now activate sync tree. @@ -971,8 +982,7 @@ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.active_tree_needs_first_draw()); EXPECT_TRUE(state.needs_redraw()); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW, - state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_DRAW); // Swap throttled. Do not draw. state.DidSwapBuffers(); @@ -995,7 +1005,7 @@ state.DidSwapBuffersComplete(); // Now will be able to start main frame. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_FALSE(state.needs_redraw()); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); @@ -1017,8 +1027,8 @@ state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -1029,8 +1039,7 @@ // Tell the scheduler the frame finished. state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT, - state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_READY_TO_COMMIT); // First commit. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); @@ -1051,7 +1060,7 @@ // Should be synchronized, no draw needed, no action needed. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_FALSE(state.needs_redraw()); // Next BeginImplFrame should initiate second commit. @@ -1086,8 +1095,8 @@ state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -1096,7 +1105,7 @@ state.BeginMainFrameAborted(false); // We should now be back in the idle state as if we never started the frame. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // We shouldn't do anything on the BeginImplFrame deadline. @@ -1108,8 +1117,8 @@ // Although we have aborted on this frame and haven't cancelled the commit // (i.e. need another), don't send another BeginMainFrame yet. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.NeedsCommit()); // Start a new frame. @@ -1118,8 +1127,8 @@ SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); // We should be starting the commit now. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); } @@ -1137,17 +1146,17 @@ EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); // Abort the commit, cancelling future commits. state.BeginMainFrameAborted(true); // Verify that another commit doesn't start on the same frame. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_FALSE(state.NeedsCommit()); // Start a new frame; draw because this is the first frame since output @@ -1162,15 +1171,14 @@ state.DidSwapBuffersComplete(); // Verify another commit doesn't start on another frame either. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_FALSE(state.NeedsCommit()); // Verify another commit can start if requested, though. state.SetNeedsCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, - state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); } TEST(SchedulerStateMachineTest, @@ -1188,18 +1196,18 @@ EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); // Become invisible and abort BeginMainFrame. state.SetVisible(false); state.BeginMainFrameAborted(true); // Verify that another commit doesn't start on the same frame. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_FALSE(state.NeedsCommit()); // Become visible and start a new frame. @@ -1216,15 +1224,14 @@ state.DidSwapBuffersComplete(); // Verify another commit doesn't start on another frame either. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_FALSE(state.NeedsCommit()); // Verify another commit can start if requested, though. state.SetNeedsCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, - state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); } TEST(SchedulerStateMachineTest, @@ -1242,30 +1249,30 @@ EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); // Become invisible and abort BeginMainFrame. state.SetVisible(false); state.BeginMainFrameAborted(true); // Verify that another commit doesn't start on the same frame. - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_FALSE(state.NeedsCommit()); // Asking for a commit while not visible won't make it happen. state.SetNeedsCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.NeedsCommit()); // Become visible but nothing happens until the next frame. state.SetVisible(true); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.NeedsCommit()); // We should get that commit when we begin the next frame. @@ -1290,10 +1297,10 @@ EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); EXPECT_FALSE(state.NeedsCommit()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); // Become invisible and abort BeginMainFrame. state.SetVisible(false); @@ -1301,20 +1308,20 @@ // Asking for a commit while not visible won't make it happen. state.SetNeedsCommit(); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.NeedsCommit()); // Begin a frame when not visible, the scheduler animates but does not commit. state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); EXPECT_TRUE(state.NeedsCommit()); // Become visible and the requested commit happens immediately. state.SetVisible(true); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_IDLE, state.CommitState()); + EXPECT_COMMIT_STATE(SchedulerStateMachine::COMMIT_STATE_IDLE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); } @@ -1358,8 +1365,7 @@ state.NextAction()); state.DidLoseOutputSurface(); - EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, - state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); state.UpdateState(state.NextAction()); // Once context recreation begins, nothing should happen. @@ -1413,8 +1419,8 @@ EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); - EXPECT_EQ(SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT, - state.CommitState()); + EXPECT_COMMIT_STATE( + SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); @@ -1430,14 +1436,11 @@ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); - EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, - state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); state.SetCanDraw(false); - EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT, - state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); state.SetCanDraw(true); - EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, - state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); } TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) { @@ -1471,7 +1474,7 @@ // Ask for another draw. Expect nothing happens. state.SetNeedsRedraw(true); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); // Finish the frame, and commit. state.NotifyBeginMainFrameStarted(); @@ -1484,25 +1487,23 @@ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, - state.NextAction()); + EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadlinePending(); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); } TEST(SchedulerStateMachineTest, @@ -1551,25 +1552,23 @@ EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT); // Expect to begin context recreation only in BEGIN_IMPL_FRAME_STATE_IDLE - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, - state.NextAction()); + EXPECT_IMPL_FRAME_STATE(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadlinePending(); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); - EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, - state.begin_impl_frame_state()); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_IMPL_FRAME_STATE( + SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameIdle(); EXPECT_ACTION_UPDATE_STATE( @@ -1607,15 +1606,13 @@ // Cause a lost output surface, and restore it. state.DidLoseOutputSurface(); - EXPECT_EQ(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, - state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION); state.UpdateState(state.NextAction()); state.DidCreateAndInitializeOutputSurface(); EXPECT_FALSE(state.RedrawPending()); state.OnBeginImplFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); - EXPECT_EQ(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME, - state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); } TEST(SchedulerStateMachineTest, @@ -1654,7 +1651,7 @@ state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(false); state.SetNeedsCommit(); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); } TEST(SchedulerStateMachineTest, TestFinishCommitWhenCommitInProgress) { @@ -1670,7 +1667,7 @@ state.NotifyBeginMainFrameStarted(); state.NotifyReadyToCommit(); - EXPECT_EQ(SchedulerStateMachine::ACTION_COMMIT, state.NextAction()); + EXPECT_ACTION(SchedulerStateMachine::ACTION_COMMIT); state.UpdateState(state.NextAction()); EXPECT_TRUE(state.active_tree_needs_first_draw()); @@ -1701,8 +1698,7 @@ // lost the output surface and are trying to get the first commit, since the // main thread will just abort anyway. state.SetVisible(false); - EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()) - << state.AsValue()->ToString(); + EXPECT_ACTION(SchedulerStateMachine::ACTION_NONE); } TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc index 9257446..8833037 100644 --- a/cc/surfaces/display.cc +++ b/cc/surfaces/display.cc
@@ -118,6 +118,13 @@ TRACE_EVENT0("cc", "Display::Draw"); benchmark_instrumentation::IssueDisplayRenderingStatsEvent(); + + // Run callbacks early to allow pipelining. + for (const auto& id_entry : aggregator_->previous_contained_surfaces()) { + Surface* surface = manager_->GetSurfaceForId(id_entry.first); + if (surface) + surface->RunDrawCallbacks(); + } DelegatedFrameData* frame_data = frame->delegated_frame_data.get(); gfx::Size surface_size = @@ -134,23 +141,13 @@ device_clip_rect, disable_picture_quad_image_filtering); - bool disable_swap = surface_size != current_surface_size_; - if (disable_swap) { + if (surface_size != current_surface_size_) { DidSwapBuffers(); + DidSwapBuffersComplete(); } else { renderer_->SwapBuffers(frame->metadata); } - for (SurfaceAggregator::SurfaceIndexMap::iterator it = - aggregator_->previous_contained_surfaces().begin(); - it != aggregator_->previous_contained_surfaces().end(); - ++it) { - Surface* surface = manager_->GetSurfaceForId(it->first); - if (surface) - surface->RunDrawCallbacks(); - } - if (disable_swap) - DidSwapBuffersComplete(); return true; } @@ -172,8 +169,11 @@ } void Display::OnSurfaceDamaged(SurfaceId surface) { - if (aggregator_ && aggregator_->previous_contained_surfaces().count(surface)) + if (aggregator_ && + aggregator_->previous_contained_surfaces().count(surface)) { + aggregator_->ReleaseResources(surface); client_->DisplayDamaged(); + } } SurfaceId Display::CurrentSurfaceId() {
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index c7b1145..98ae58c 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc
@@ -33,10 +33,12 @@ ¤t_resources); factory_->UnrefResources(current_resources); } + if (!draw_callback_.is_null()) + draw_callback_.Run(false); } void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame, - const base::Closure& callback) { + const DrawCallback& callback) { DCHECK(factory_); ClearCopyRequests(); TakeLatencyInfo(&frame->metadata.latency_info); @@ -54,7 +56,7 @@ factory_->UnrefResources(previous_resources); } if (!draw_callback_.is_null()) - draw_callback_.Run(); + draw_callback_.Run(false); draw_callback_ = callback; factory_->manager()->DidSatisfySequences( SurfaceIdAllocator::NamespaceForId(surface_id_), @@ -106,9 +108,9 @@ void Surface::RunDrawCallbacks() { if (!draw_callback_.is_null()) { - base::Closure callback = draw_callback_; - draw_callback_ = base::Closure(); - callback.Run(); + DrawCallback callback = draw_callback_; + draw_callback_ = DrawCallback(); + callback.Run(true); } }
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index ed0061d..96152a0 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h
@@ -34,13 +34,15 @@ class CC_SURFACES_EXPORT Surface { public: + using DrawCallback = base::Callback<void(bool)>; + Surface(SurfaceId id, SurfaceFactory* factory); ~Surface(); SurfaceId surface_id() const { return surface_id_; } void QueueFrame(scoped_ptr<CompositorFrame> frame, - const base::Closure& draw_callback); + const DrawCallback& draw_callback); void RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request); // Adds each CopyOutputRequest in the current frame to copy_requests. The // caller takes ownership of them. @@ -79,7 +81,7 @@ int frame_index_; std::vector<SurfaceSequence> destruction_dependencies_; - base::Closure draw_callback_; + DrawCallback draw_callback_; DISALLOW_COPY_AND_ASSIGN(Surface); };
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index 2334d14..4c44084 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -438,4 +438,13 @@ return frame.Pass(); } +void SurfaceAggregator::ReleaseResources(SurfaceId surface_id) { + SurfaceToResourceChildIdMap::iterator it = + surface_id_to_resource_child_id_.find(surface_id); + if (it != surface_id_to_resource_child_id_.end()) { + provider_->DestroyChild(it->second); + surface_id_to_resource_child_id_.erase(it); + } +} + } // namespace cc
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h index 1e68643..9cb0578 100644 --- a/cc/surfaces/surface_aggregator.h +++ b/cc/surfaces/surface_aggregator.h
@@ -32,6 +32,7 @@ ~SurfaceAggregator(); scoped_ptr<CompositorFrame> Aggregate(SurfaceId surface_id); + void ReleaseResources(SurfaceId surface_id); SurfaceIndexMap& previous_contained_surfaces() { return previous_contained_surfaces_; }
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc index 3e48311..7f6943c 100644 --- a/cc/surfaces/surface_aggregator_unittest.cc +++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -123,7 +123,8 @@ scoped_ptr<CompositorFrame> frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitFrame(surface_id, frame.Pass(), base::Closure()); + factory_.SubmitFrame(surface_id, frame.Pass(), + SurfaceFactory::DrawCallback()); } void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) { @@ -133,7 +134,8 @@ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = delegated_frame_data.Pass(); - factory_.SubmitFrame(surface_id, child_frame.Pass(), base::Closure()); + factory_.SubmitFrame(surface_id, child_frame.Pass(), + SurfaceFactory::DrawCallback()); } protected: @@ -380,7 +382,8 @@ scoped_ptr<CompositorFrame> frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitFrame(root_surface_id_, frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); } scoped_ptr<CompositorFrame> aggregated_frame = @@ -937,7 +940,8 @@ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = child_frame_data.Pass(); - factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure()); + factory_.SubmitFrame(child_surface_id, child_frame.Pass(), + SurfaceFactory::DrawCallback()); test::Quad root_quads[] = {test::Quad::SolidColorQuad(1), test::Quad::SurfaceQuad(child_surface_id, 1.f)}; @@ -962,7 +966,8 @@ scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); root_frame->delegated_frame_data = root_frame_data.Pass(); - factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), + SurfaceFactory::DrawCallback()); scoped_ptr<CompositorFrame> aggregated_frame = aggregator_.Aggregate(root_surface_id_); @@ -1061,7 +1066,8 @@ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = child_frame_data.Pass(); - factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure()); + factory_.SubmitFrame(child_surface_id, child_frame.Pass(), + SurfaceFactory::DrawCallback()); test::Quad root_quads[] = {test::Quad::SurfaceQuad(child_surface_id, 1.f)}; test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))}; @@ -1083,7 +1089,8 @@ scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); root_frame->delegated_frame_data = root_frame_data.Pass(); - factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), + SurfaceFactory::DrawCallback()); scoped_ptr<CompositorFrame> aggregated_frame = aggregator_.Aggregate(root_surface_id_); @@ -1119,7 +1126,8 @@ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = child_frame_data.Pass(); - factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure()); + factory_.SubmitFrame(child_surface_id, child_frame.Pass(), + SurfaceFactory::DrawCallback()); scoped_ptr<CompositorFrame> aggregated_frame = aggregator_.Aggregate(root_surface_id_); @@ -1158,7 +1166,8 @@ scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); root_frame->delegated_frame_data = root_frame_data.Pass(); - factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), + SurfaceFactory::DrawCallback()); } { @@ -1179,7 +1188,8 @@ scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); root_frame->delegated_frame_data = root_frame_data.Pass(); - factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id_, root_frame.Pass(), + SurfaceFactory::DrawCallback()); scoped_ptr<CompositorFrame> aggregated_frame = aggregator_.Aggregate(root_surface_id_); @@ -1295,7 +1305,8 @@ frame_data->render_pass_list.push_back(pass.Pass()); scoped_ptr<CompositorFrame> frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory->SubmitFrame(surface_id, frame.Pass(), base::Closure()); + factory->SubmitFrame(surface_id, frame.Pass(), + SurfaceFactory::DrawCallback()); } TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc index fd5a6d4..7af7cb7 100644 --- a/cc/surfaces/surface_factory.cc +++ b/cc/surfaces/surface_factory.cc
@@ -46,7 +46,7 @@ void SurfaceFactory::SubmitFrame(SurfaceId surface_id, scoped_ptr<CompositorFrame> frame, - const base::Closure& callback) { + const DrawCallback& callback) { OwningSurfaceMap::iterator it = surface_map_.find(surface_id); DCHECK(it != surface_map_.end()); DCHECK(it->second->factory().get() == this);
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h index eba32d2..7abd929 100644 --- a/cc/surfaces/surface_factory.h +++ b/cc/surfaces/surface_factory.h
@@ -35,6 +35,10 @@ class CC_SURFACES_EXPORT SurfaceFactory : public base::SupportsWeakPtr<SurfaceFactory> { public: + // This callback is called with true if the frame was drawn, or false if it + // was discarded. + using DrawCallback = base::Callback<void(bool)>; + SurfaceFactory(SurfaceManager* manager, SurfaceFactoryClient* client); ~SurfaceFactory(); @@ -43,10 +47,11 @@ void DestroyAll(); // A frame can only be submitted to a surface created by this factory, // although the frame may reference surfaces created by other factories. - // The callback is called the first time this frame is used to draw. + // The callback is called the first time this frame is used to draw, or if + // the frame is discarded. void SubmitFrame(SurfaceId surface_id, scoped_ptr<CompositorFrame> frame, - const base::Closure& callback); + const DrawCallback& callback); void RequestCopyOfSurface(SurfaceId surface_id, scoped_ptr<CopyOutputRequest> copy_request);
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc index 84dcc5e..1a87c0f 100644 --- a/cc/surfaces/surface_factory_unittest.cc +++ b/cc/surfaces/surface_factory_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/bind.h" #include "cc/output/compositor_frame.h" #include "cc/output/delegated_frame_data.h" #include "cc/surfaces/surface.h" @@ -58,7 +59,8 @@ } scoped_ptr<CompositorFrame> frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitFrame(surface_id_, frame.Pass(), base::Closure()); + factory_.SubmitFrame(surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); } void UnrefResources(ResourceProvider::ResourceId* ids_to_unref, @@ -358,6 +360,11 @@ } } +void DrawCallback(bool* executed, bool* result, bool drawn) { + *executed = true; + *result = drawn; +} + // Tests doing a DestroyAll before shutting down the factory; TEST_F(SurfaceFactoryTest, DestroyAll) { SurfaceId id(7); @@ -370,10 +377,17 @@ frame_data->resource_list.push_back(resource); scoped_ptr<CompositorFrame> frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - factory_.SubmitFrame(id, frame.Pass(), base::Closure()); + bool executed = false; + bool drawn = false; + + factory_.SubmitFrame(id, frame.Pass(), + base::Bind(&DrawCallback, &executed, &drawn)); surface_id_ = SurfaceId(); + EXPECT_FALSE(executed); factory_.DestroyAll(); + EXPECT_TRUE(executed); + EXPECT_FALSE(drawn); } TEST_F(SurfaceFactoryTest, DestroySequence) { @@ -391,7 +405,8 @@ frame->metadata.satisfies_sequences.push_back(4); frame->delegated_frame_data = frame_data.Pass(); DCHECK(manager_.GetSurfaceForId(id2)); - factory_.SubmitFrame(surface_id_, frame.Pass(), base::Closure()); + factory_.SubmitFrame(surface_id_, frame.Pass(), + SurfaceFactory::DrawCallback()); DCHECK(!manager_.GetSurfaceForId(id2)); // Check that waiting after the sequence is satisfied works.
diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc index bf9d483..528684b 100644 --- a/cc/surfaces/surfaces_pixeltest.cc +++ b/cc/surfaces/surfaces_pixeltest.cc
@@ -86,7 +86,8 @@ SurfaceId root_surface_id = allocator_.GenerateId(); factory_.Create(root_surface_id); - factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id, root_frame.Pass(), + SurfaceFactory::DrawCallback()); SurfaceAggregator aggregator(&manager_, resource_provider_.get()); scoped_ptr<CompositorFrame> aggregated_frame = @@ -140,7 +141,8 @@ scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); root_frame->delegated_frame_data = delegated_frame_data.Pass(); - factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id, root_frame.Pass(), + SurfaceFactory::DrawCallback()); } { @@ -167,7 +169,8 @@ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = delegated_frame_data.Pass(); - factory_.SubmitFrame(child_surface_id, child_frame.Pass(), base::Closure()); + factory_.SubmitFrame(child_surface_id, child_frame.Pass(), + SurfaceFactory::DrawCallback()); } SurfaceAggregator aggregator(&manager_, resource_provider_.get()); @@ -237,7 +240,8 @@ scoped_ptr<CompositorFrame> root_frame(new CompositorFrame); root_frame->delegated_frame_data = delegated_frame_data.Pass(); - factory_.SubmitFrame(root_surface_id, root_frame.Pass(), base::Closure()); + factory_.SubmitFrame(root_surface_id, root_frame.Pass(), + SurfaceFactory::DrawCallback()); } { @@ -272,7 +276,8 @@ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = delegated_frame_data.Pass(); - factory_.SubmitFrame(left_child_id, child_frame.Pass(), base::Closure()); + factory_.SubmitFrame(left_child_id, child_frame.Pass(), + SurfaceFactory::DrawCallback()); } { @@ -307,7 +312,8 @@ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame); child_frame->delegated_frame_data = delegated_frame_data.Pass(); - factory_.SubmitFrame(right_child_id, child_frame.Pass(), base::Closure()); + factory_.SubmitFrame(right_child_id, child_frame.Pass(), + SurfaceFactory::DrawCallback()); } SurfaceAggregator aggregator(&manager_, resource_provider_.get());
diff --git a/cc/test/failure_output_surface.cc b/cc/test/failure_output_surface.cc new file mode 100644 index 0000000..2c87853 --- /dev/null +++ b/cc/test/failure_output_surface.cc
@@ -0,0 +1,19 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/test/failure_output_surface.h" + +namespace cc { + +FailureOutputSurface::FailureOutputSurface(bool is_delegating) + : FakeOutputSurface(nullptr, nullptr, is_delegating) { +} + +bool FailureOutputSurface::BindToClient(OutputSurfaceClient* client) { + // This will force this output surface to not initialize in LTHI + // and eventually get back to LTH::DidFailToInitializeOutputSurface; + return false; +} + +} // namespace cc
diff --git a/cc/test/failure_output_surface.h b/cc/test/failure_output_surface.h new file mode 100644 index 0000000..4878ea5 --- /dev/null +++ b/cc/test/failure_output_surface.h
@@ -0,0 +1,24 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TEST_FAILURE_OUTPUT_SURFACE_H_ +#define CC_TEST_FAILURE_OUTPUT_SURFACE_H_ + +#include "cc/test/fake_output_surface.h" + +namespace cc { + +class FailureOutputSurface : public FakeOutputSurface { + public: + explicit FailureOutputSurface(bool is_delegating); + + bool BindToClient(OutputSurfaceClient* client) override; + + private: + DISALLOW_COPY_AND_ASSIGN(FailureOutputSurface); +}; + +} // namespace cc + +#endif // CC_TEST_FAILURE_OUTPUT_SURFACE_H_
diff --git a/cc/test/fake_layer_tree_host_client.cc b/cc/test/fake_layer_tree_host_client.cc index 17ed10c..a4a5d7e 100644 --- a/cc/test/fake_layer_tree_host_client.cc +++ b/cc/test/fake_layer_tree_host_client.cc
@@ -21,7 +21,7 @@ FakeLayerTreeHostClient::~FakeLayerTreeHostClient() {} -void FakeLayerTreeHostClient::RequestNewOutputSurface(bool fallback) { +void FakeLayerTreeHostClient::RequestNewOutputSurface() { DCHECK(host_); scoped_ptr<OutputSurface> surface; if (use_software_rendering_) { @@ -40,4 +40,8 @@ host_->SetOutputSurface(surface.Pass()); } +void FakeLayerTreeHostClient::DidFailToInitializeOutputSurface() { + RequestNewOutputSurface(); +} + } // namespace cc
diff --git a/cc/test/fake_layer_tree_host_client.h b/cc/test/fake_layer_tree_host_client.h index 6f24116..f256ab1 100644 --- a/cc/test/fake_layer_tree_host_client.h +++ b/cc/test/fake_layer_tree_host_client.h
@@ -43,8 +43,9 @@ float page_scale, float top_controls_delta) override {} - void RequestNewOutputSurface(bool fallback) override; + void RequestNewOutputSurface() override; void DidInitializeOutputSurface() override {} + void DidFailToInitializeOutputSurface() override; void WillCommit() override {} void DidCommit() override {} void DidCommitAndDrawFrame() override {}
diff --git a/cc/test/fake_picture_layer_impl.cc b/cc/test/fake_picture_layer_impl.cc index 13b20ad..8153442 100644 --- a/cc/test/fake_picture_layer_impl.cc +++ b/cc/test/fake_picture_layer_impl.cc
@@ -13,36 +13,40 @@ FakePictureLayerImpl::FakePictureLayerImpl( LayerTreeImpl* tree_impl, int id, - scoped_refptr<RasterSource> raster_source) - : PictureLayerImpl(tree_impl, id), + scoped_refptr<RasterSource> raster_source, + bool is_mask) + : PictureLayerImpl(tree_impl, id, is_mask), append_quads_count_(0), did_become_active_call_count_(0), has_valid_tile_priorities_(false), use_set_valid_tile_priorities_flag_(false), release_resources_count_(0) { - raster_source_ = raster_source; - SetBounds(raster_source_->GetSize()); - SetContentBounds(raster_source_->GetSize()); + SetBounds(raster_source->GetSize()); + SetContentBounds(raster_source->GetSize()); + SetRasterSourceOnPending(raster_source, Region()); } FakePictureLayerImpl::FakePictureLayerImpl( LayerTreeImpl* tree_impl, int id, scoped_refptr<RasterSource> raster_source, + bool is_mask, const gfx::Size& layer_bounds) - : PictureLayerImpl(tree_impl, id), + : PictureLayerImpl(tree_impl, id, is_mask), append_quads_count_(0), did_become_active_call_count_(0), has_valid_tile_priorities_(false), use_set_valid_tile_priorities_flag_(false), release_resources_count_(0) { - raster_source_ = raster_source; SetBounds(layer_bounds); SetContentBounds(layer_bounds); + SetRasterSourceOnPending(raster_source, Region()); } -FakePictureLayerImpl::FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id) - : PictureLayerImpl(tree_impl, id), +FakePictureLayerImpl::FakePictureLayerImpl(LayerTreeImpl* tree_impl, + int id, + bool is_mask) + : PictureLayerImpl(tree_impl, id, is_mask), append_quads_count_(0), did_become_active_call_count_(0), has_valid_tile_priorities_(false), @@ -52,7 +56,14 @@ scoped_ptr<LayerImpl> FakePictureLayerImpl::CreateLayerImpl( LayerTreeImpl* tree_impl) { - return make_scoped_ptr(new FakePictureLayerImpl(tree_impl, id())); + return make_scoped_ptr(new FakePictureLayerImpl(tree_impl, id(), is_mask_)); +} + +void FakePictureLayerImpl::PushPropertiesTo(LayerImpl* layer_impl) { + FakePictureLayerImpl* picture_layer_impl = + static_cast<FakePictureLayerImpl*>(layer_impl); + picture_layer_impl->fixed_tile_size_ = fixed_tile_size_; + PictureLayerImpl::PushPropertiesTo(layer_impl); } void FakePictureLayerImpl::AppendQuads( @@ -99,15 +110,13 @@ return result; } -void FakePictureLayerImpl::SetRasterSource( - scoped_refptr<RasterSource> raster_source) { - raster_source_.swap(raster_source); - if (tilings()) { - for (size_t i = 0; i < num_tilings(); ++i) { - tilings()->tiling_at(i)->UpdateTilesToCurrentRasterSource( - raster_source_.get(), Region(), raster_source_->GetSize()); - } - } +void FakePictureLayerImpl::SetRasterSourceOnPending( + scoped_refptr<RasterSource> raster_source, + const Region& invalidation) { + DCHECK(layer_tree_impl()->IsPendingTree()); + Region invalidation_temp = invalidation; + const PictureLayerTilingSet* pending_set = nullptr; + UpdateRasterSource(raster_source, &invalidation_temp, pending_set); } void FakePictureLayerImpl::SetAllTilesVisible() {
diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h index b10b357..d633051 100644 --- a/cc/test/fake_picture_layer_impl.h +++ b/cc/test/fake_picture_layer_impl.h
@@ -14,7 +14,8 @@ public: static scoped_ptr<FakePictureLayerImpl> Create( LayerTreeImpl* tree_impl, int id) { - return make_scoped_ptr(new FakePictureLayerImpl(tree_impl, id)); + bool is_mask = false; + return make_scoped_ptr(new FakePictureLayerImpl(tree_impl, id, is_mask)); } // Create layer from a raster source that covers the entire layer. @@ -22,8 +23,9 @@ LayerTreeImpl* tree_impl, int id, scoped_refptr<RasterSource> raster_source) { + bool is_mask = false; return make_scoped_ptr( - new FakePictureLayerImpl(tree_impl, id, raster_source)); + new FakePictureLayerImpl(tree_impl, id, raster_source, is_mask)); } // Create layer from a raster source that only covers part of the layer. @@ -32,11 +34,24 @@ int id, scoped_refptr<RasterSource> raster_source, const gfx::Size& layer_bounds) { + bool is_mask = false; + return make_scoped_ptr(new FakePictureLayerImpl( + tree_impl, id, raster_source, is_mask, layer_bounds)); + } + + // Create layer from a raster source that covers the entire layer and is a + // mask. + static scoped_ptr<FakePictureLayerImpl> CreateMaskWithRasterSource( + LayerTreeImpl* tree_impl, + int id, + scoped_refptr<RasterSource> raster_source) { + bool is_mask = true; return make_scoped_ptr( - new FakePictureLayerImpl(tree_impl, id, raster_source, layer_bounds)); + new FakePictureLayerImpl(tree_impl, id, raster_source, is_mask)); } 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; @@ -91,7 +106,8 @@ PictureLayerTilingSet* tilings() { return tilings_.get(); } RasterSource* raster_source() { return raster_source_.get(); } - void SetRasterSource(scoped_refptr<RasterSource> raster_source); + void SetRasterSourceOnPending(scoped_refptr<RasterSource> raster_source, + const Region& invalidation); size_t append_quads_count() { return append_quads_count_; } const Region& invalidation() const { return invalidation_; } @@ -103,7 +119,9 @@ void set_fixed_tile_size(const gfx::Size& size) { fixed_tile_size_ = size; } + // TODO(danakj): Remove this darn thing. void CreateDefaultTilingsAndTiles(); + void SetAllTilesVisible(); void SetAllTilesReady(); void SetAllTilesReadyInTiling(PictureLayerTiling* tiling); @@ -123,12 +141,14 @@ protected: FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id, - scoped_refptr<RasterSource> raster_source); + scoped_refptr<RasterSource> raster_source, + bool is_mask); FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id, scoped_refptr<RasterSource> raster_source, + bool is_mask, const gfx::Size& layer_bounds); - FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id); + FakePictureLayerImpl(LayerTreeImpl* tree_impl, int id, bool is_mask); private: gfx::Size fixed_tile_size_;
diff --git a/cc/test/fake_picture_layer_tiling_client.cc b/cc/test/fake_picture_layer_tiling_client.cc index b21e011..6c1dc98 100644 --- a/cc/test/fake_picture_layer_tiling_client.cc +++ b/cc/test/fake_picture_layer_tiling_client.cc
@@ -17,10 +17,7 @@ twin_tiling_(NULL), recycled_twin_tiling_(NULL), allow_create_tile_(true), - max_tile_priority_bin_(TilePriority::NOW), - max_tiles_for_interest_area_(10000), - skewport_target_time_in_seconds_(1.0f), - skewport_extrapolation_limit_in_content_pixels_(2000) { + max_tile_priority_bin_(TilePriority::NOW) { } FakePictureLayerTilingClient::FakePictureLayerTilingClient( @@ -33,9 +30,7 @@ twin_tiling_(NULL), recycled_twin_tiling_(NULL), allow_create_tile_(true), - max_tile_priority_bin_(TilePriority::NOW), - max_tiles_for_interest_area_(10000), - skewport_target_time_in_seconds_(1.0f) { + max_tile_priority_bin_(TilePriority::NOW) { } FakePictureLayerTilingClient::~FakePictureLayerTilingClient() { @@ -63,19 +58,6 @@ return max_tile_priority_bin_; } -size_t FakePictureLayerTilingClient::GetMaxTilesForInterestArea() const { - return max_tiles_for_interest_area_; -} - -float FakePictureLayerTilingClient::GetSkewportTargetTimeInSeconds() const { - return skewport_target_time_in_seconds_; -} - -int FakePictureLayerTilingClient::GetSkewportExtrapolationLimitInContentPixels() - const { - return skewport_extrapolation_limit_in_content_pixels_; -} - const Region* FakePictureLayerTilingClient::GetPendingInvalidation() { return &invalidation_; }
diff --git a/cc/test/fake_picture_layer_tiling_client.h b/cc/test/fake_picture_layer_tiling_client.h index acf26d0..935765b 100644 --- a/cc/test/fake_picture_layer_tiling_client.h +++ b/cc/test/fake_picture_layer_tiling_client.h
@@ -25,10 +25,6 @@ const gfx::Rect& rect) override; gfx::Size CalculateTileSize(const gfx::Size& content_bounds) const override; TilePriority::PriorityBin GetMaxTilePriorityBin() const override; - size_t GetMaxTilesForInterestArea() const override; - float GetSkewportTargetTimeInSeconds() const override; - int GetSkewportExtrapolationLimitInContentPixels() const override; - bool RequiresHighResToDraw() const override; void SetTileSize(const gfx::Size& tile_size); gfx::Size TileSize() const { return tile_size_; } @@ -38,6 +34,7 @@ const PictureLayerTiling* tiling) const override; PictureLayerTiling* GetRecycledTwinTiling( const PictureLayerTiling* tiling) override; + bool RequiresHighResToDraw() const override; WhichTree GetTree() const override; void set_twin_tiling(PictureLayerTiling* tiling) { twin_tiling_ = tiling; } @@ -50,15 +47,6 @@ void set_max_tile_priority_bin(TilePriority::PriorityBin bin) { max_tile_priority_bin_ = bin; } - void set_max_tiles_for_interest_area(size_t area) { - max_tiles_for_interest_area_ = area; - } - void set_skewport_target_time_in_seconds(float time) { - skewport_target_time_in_seconds_ = time; - } - void set_skewport_extrapolation_limit_in_content_pixels(int limit) { - skewport_extrapolation_limit_in_content_pixels_ = limit; - } void set_tree(WhichTree tree) { tree_ = tree; } RasterSource* raster_source() { return pile_.get(); } @@ -78,9 +66,6 @@ bool allow_create_tile_; Region invalidation_; TilePriority::PriorityBin max_tile_priority_bin_; - size_t max_tiles_for_interest_area_; - float skewport_target_time_in_seconds_; - int skewport_extrapolation_limit_in_content_pixels_; WhichTree tree_; };
diff --git a/cc/test/fake_tile_manager.cc b/cc/test/fake_tile_manager.cc index f85946a..bb23aa8 100644 --- a/cc/test/fake_tile_manager.cc +++ b/cc/test/fake_tile_manager.cc
@@ -67,7 +67,6 @@ base::MessageLoopProxy::current(), NULL, g_fake_tile_task_runner.Pointer(), - NULL, std::numeric_limits<size_t>::max()) { } @@ -77,7 +76,6 @@ base::MessageLoopProxy::current(), resource_pool, g_fake_tile_task_runner.Pointer(), - NULL, std::numeric_limits<size_t>::max()) { }
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc index e2b768a..83a338e 100644 --- a/cc/test/layer_tree_pixel_resource_test.cc +++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -217,6 +217,9 @@ if (!IsTestCaseSupported(test_case_)) return; RunPixelTest(test_type_, content_root, file_name); + + if (layer_tree_host()) + EXPECT_TRUE(layer_tree_host()->settings().impl_side_painting); } ParameterizedPixelResourceTest::ParameterizedPixelResourceTest()
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 23bfcf2..8a053fa 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc
@@ -35,8 +35,7 @@ LayerTreePixelTest::~LayerTreePixelTest() {} -scoped_ptr<OutputSurface> LayerTreePixelTest::CreateOutputSurface( - bool fallback) { +scoped_ptr<OutputSurface> LayerTreePixelTest::CreateOutputSurface() { gfx::Size surface_expansion_size(40, 60); scoped_ptr<PixelTestOutputSurface> output_surface;
diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h index c3c324a..60ea727 100644 --- a/cc/test/layer_tree_pixel_test.h +++ b/cc/test/layer_tree_pixel_test.h
@@ -40,7 +40,7 @@ LayerTreePixelTest(); virtual ~LayerTreePixelTest(); - scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) override; + scoped_ptr<OutputSurface> CreateOutputSurface() override; void CommitCompleteOnThread(LayerTreeHostImpl* impl) override; virtual scoped_ptr<CopyOutputRequest> CreateCopyOutputRequest();
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index d6411ec..e5a5687 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -377,8 +377,8 @@ top_controls_delta); } - void RequestNewOutputSurface(bool fallback) override { - test_hooks_->RequestNewOutputSurface(fallback); + void RequestNewOutputSurface() override { + test_hooks_->RequestNewOutputSurface(); } void DidInitializeOutputSurface() override { @@ -391,6 +391,7 @@ void DidFailToInitializeOutputSurface() override { test_hooks_->DidFailToInitializeOutputSurface(); + RequestNewOutputSurface(); } void WillCommit() override { test_hooks_->WillCommit(); } @@ -785,17 +786,14 @@ RunTest(true, false, true); } -void LayerTreeTest::RequestNewOutputSurface(bool fallback) { - layer_tree_host_->SetOutputSurface(CreateOutputSurface(fallback)); +void LayerTreeTest::RequestNewOutputSurface() { + layer_tree_host_->SetOutputSurface(CreateOutputSurface()); } -scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface(bool fallback) { - scoped_ptr<FakeOutputSurface> output_surface = - CreateFakeOutputSurface(fallback); - if (output_surface) { - DCHECK_EQ(delegating_renderer_, - output_surface->capabilities().delegated_rendering); - } +scoped_ptr<OutputSurface> LayerTreeTest::CreateOutputSurface() { + scoped_ptr<FakeOutputSurface> output_surface = CreateFakeOutputSurface(); + DCHECK_EQ(delegating_renderer_, + output_surface->capabilities().delegated_rendering); output_surface_ = output_surface.get(); if (settings_.use_external_begin_frame_source && @@ -806,8 +804,7 @@ return output_surface.Pass(); } -scoped_ptr<FakeOutputSurface> LayerTreeTest::CreateFakeOutputSurface( - bool fallback) { +scoped_ptr<FakeOutputSurface> LayerTreeTest::CreateFakeOutputSurface() { if (delegating_renderer_) return FakeOutputSurface::CreateDelegating3d(); else
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 4176265..02f18b7 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h
@@ -110,7 +110,7 @@ Animation::TargetProperty target_property, int group) override {} - virtual void RequestNewOutputSurface(bool fallback) = 0; + virtual void RequestNewOutputSurface() = 0; }; class BeginTask; @@ -202,11 +202,11 @@ void DestroyLayerTreeHost(); // By default, output surface recreation is synchronous. - void RequestNewOutputSurface(bool fallback) override; + void RequestNewOutputSurface() override; // Override this for pixel tests, where you need a real output surface. - virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback); + virtual scoped_ptr<OutputSurface> CreateOutputSurface(); // Override this for unit tests, which should not produce pixel output. - virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback); + virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(); TestWebGraphicsContext3D* TestContext();
diff --git a/cc/test/render_pass_test_common.cc b/cc/test/render_pass_test_common.cc index b79fc1f..7237ce1 100644 --- a/cc/test/render_pass_test_common.cc +++ b/cc/test/render_pass_test_common.cc
@@ -198,6 +198,7 @@ resource2, gfx::RectF(0, 0, 50, 50), gfx::Size(50, 50), + false, false); SharedQuadState* transformed_state = this->CreateAndAppendSharedQuadState(); @@ -215,6 +216,7 @@ resource3, gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), + false, false); SharedQuadState* shared_state2 = this->CreateAndAppendSharedQuadState(); @@ -235,6 +237,7 @@ resource4, gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), + false, false); ResourceProvider::ResourceId plane_resources[4];
diff --git a/cc/test/test_context_provider.cc b/cc/test/test_context_provider.cc index e7697f1..2a2b6f6 100644 --- a/cc/test/test_context_provider.cc +++ b/cc/test/test_context_provider.cc
@@ -12,6 +12,8 @@ #include "base/logging.h" #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" namespace cc { @@ -90,8 +92,14 @@ DCHECK(bound_); DCHECK(context_thread_checker_.CalledOnValidThread()); - // TODO(danakj): Make a test GrContext that works with a test Context3d. - return NULL; + if (gr_context_) + return gr_context_.get(); + + auto null_interface = skia::AdoptRef(GrGLCreateNullInterface()); + gr_context_ = skia::AdoptRef(GrContext::Create( + kOpenGL_GrBackend, + reinterpret_cast<GrBackendContext>(null_interface.get()))); + return gr_context_.get(); } bool TestContextProvider::IsContextLost() {
diff --git a/cc/test/test_context_provider.h b/cc/test/test_context_provider.h index 66ae998..3be8b43 100644 --- a/cc/test/test_context_provider.h +++ b/cc/test/test_context_provider.h
@@ -13,6 +13,7 @@ #include "cc/output/context_provider.h" #include "cc/test/test_context_support.h" #include "gpu/command_buffer/client/gles2_interface_stub.h" +#include "skia/ext/refptr.h" namespace cc { class TestWebGraphicsContext3D; @@ -75,6 +76,7 @@ LostContextCallback lost_context_callback_; MemoryPolicyChangedCallback memory_policy_changed_callback_; + skia::RefPtr<class GrContext> gr_context_; base::WeakPtrFactory<TestContextProvider> weak_ptr_factory_;
diff --git a/cc/test/test_shared_bitmap_manager.cc b/cc/test/test_shared_bitmap_manager.cc index 933dcd2..7e14b2f 100644 --- a/cc/test/test_shared_bitmap_manager.cc +++ b/cc/test/test_shared_bitmap_manager.cc
@@ -18,26 +18,10 @@ ~OwnedSharedBitmap() override {} - base::SharedMemory* memory() override { return shared_memory_.get(); } - private: scoped_ptr<base::SharedMemory> shared_memory_; }; -class UnownedSharedBitmap : public SharedBitmap { - public: - UnownedSharedBitmap(base::SharedMemory* shared_memory, - const SharedBitmapId& id) - : SharedBitmap(static_cast<uint8*>(shared_memory->memory()), id), - shared_memory_(shared_memory) {} - - ~UnownedSharedBitmap() override {} - - base::SharedMemory* memory() override { return shared_memory_; } - - private: - base::SharedMemory* shared_memory_; -}; } // namespace TestSharedBitmapManager::TestSharedBitmapManager() {} @@ -60,15 +44,8 @@ base::AutoLock lock(lock_); if (bitmap_map_.find(id) == bitmap_map_.end()) return nullptr; - return make_scoped_ptr(new UnownedSharedBitmap(bitmap_map_[id], id)); -} - -scoped_ptr<SharedBitmap> TestSharedBitmapManager::GetBitmapForSharedMemory( - base::SharedMemory* memory) { - base::AutoLock lock(lock_); - SharedBitmapId id = SharedBitmap::GenerateId(); - bitmap_map_[id] = memory; - return make_scoped_ptr(new UnownedSharedBitmap(memory, id)); + uint8* pixels = static_cast<uint8*>(bitmap_map_[id]->memory()); + return make_scoped_ptr(new SharedBitmap(pixels, id)); } } // namespace cc
diff --git a/cc/test/test_shared_bitmap_manager.h b/cc/test/test_shared_bitmap_manager.h index 9163c79..acba096 100644 --- a/cc/test/test_shared_bitmap_manager.h +++ b/cc/test/test_shared_bitmap_manager.h
@@ -10,6 +10,10 @@ #include "base/synchronization/lock.h" #include "cc/resources/shared_bitmap_manager.h" +namespace base { +class SharedMemory; +} // namespace base + namespace cc { class TestSharedBitmapManager : public SharedBitmapManager { @@ -23,9 +27,6 @@ const gfx::Size&, const SharedBitmapId& id) override; - scoped_ptr<SharedBitmap> GetBitmapForSharedMemory( - base::SharedMemory* memory) override; - private: base::Lock lock_; std::map<SharedBitmapId, base::SharedMemory*> bitmap_map_;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 4d03449..d192a9a 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -114,7 +114,6 @@ source_frame_number_(0), rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()), output_surface_lost_(true), - num_failed_recreate_attempts_(0), settings_(settings), debug_state_(settings.initial_debug_state), top_controls_shrink_blink_size_(false), @@ -217,40 +216,6 @@ layer->OnOutputSurfaceCreated(); } -void LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(bool success) { - DCHECK(output_surface_lost_); - TRACE_EVENT1("cc", - "LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted", - "success", - success); - - if (!success) { - // Tolerate a certain number of recreation failures to work around races - // in the output-surface-lost machinery. - ++num_failed_recreate_attempts_; - if (num_failed_recreate_attempts_ >= 5) - LOG(FATAL) << "Failed to create a fallback OutputSurface."; - client_->DidFailToInitializeOutputSurface(); - return; - } - - output_surface_lost_ = false; - - if (!contents_texture_manager_ && !settings_.impl_side_painting) { - contents_texture_manager_ = - PrioritizedResourceManager::Create(proxy_.get()); - surface_memory_placeholder_ = - contents_texture_manager_->CreateTexture(gfx::Size(), RGBA_8888); - } - - if (root_layer()) { - LayerTreeHostCommon::CallFunctionForSubtree( - root_layer(), base::Bind(&LayerTreeHostOnOutputSurfaceCreatedCallback)); - } - - client_->DidInitializeOutputSurface(); -} - void LayerTreeHost::DeleteContentsTexturesOnImplThread( ResourceProvider* resource_provider) { DCHECK(proxy_->IsImplThread()); @@ -328,12 +293,6 @@ sync_tree->SetRootLayer(TreeSynchronizer::SynchronizeTrees( root_layer(), sync_tree->DetachLayerTree(), sync_tree)); } - - { - TRACE_EVENT0("cc", "LayerTreeHost::PushProperties"); - TreeSynchronizer::PushProperties(root_layer(), sync_tree->root_layer()); - } - sync_tree->set_needs_full_tree_sync(needs_full_tree_sync_); needs_full_tree_sync_ = false; @@ -355,6 +314,7 @@ page_scale_layer_->id(), inner_viewport_scroll_layer_->id(), outer_viewport_scroll_layer_.get() ? outer_viewport_scroll_layer_->id() : Layer::INVALID_ID); + DCHECK(inner_viewport_scroll_layer_->IsContainerForFixedPositionLayers()); } else { sync_tree->ClearViewportLayers(); } @@ -415,6 +375,11 @@ sync_tree->set_has_ever_been_drawn(false); + { + TRACE_EVENT0("cc", "LayerTreeHost::PushProperties"); + TreeSynchronizer::PushProperties(root_layer(), sync_tree->root_layer()); + } + micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl); } @@ -441,11 +406,38 @@ } void LayerTreeHost::SetOutputSurface(scoped_ptr<OutputSurface> surface) { + TRACE_EVENT0("cc", "LayerTreeHost::SetOutputSurface"); + DCHECK(output_surface_lost_); + DCHECK(surface); + proxy_->SetOutputSurface(surface.Pass()); } void LayerTreeHost::RequestNewOutputSurface() { - client_->RequestNewOutputSurface(num_failed_recreate_attempts_ >= 4); + client_->RequestNewOutputSurface(); +} + +void LayerTreeHost::DidInitializeOutputSurface() { + output_surface_lost_ = false; + + if (!contents_texture_manager_ && !settings_.impl_side_painting) { + contents_texture_manager_ = + PrioritizedResourceManager::Create(proxy_.get()); + surface_memory_placeholder_ = + contents_texture_manager_->CreateTexture(gfx::Size(), RGBA_8888); + } + + if (root_layer()) { + LayerTreeHostCommon::CallFunctionForSubtree( + root_layer(), base::Bind(&LayerTreeHostOnOutputSurfaceCreatedCallback)); + } + + client_->DidInitializeOutputSurface(); +} + +void LayerTreeHost::DidFailToInitializeOutputSurface() { + DCHECK(output_surface_lost_); + client_->DidFailToInitializeOutputSurface(); } scoped_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl( @@ -478,7 +470,6 @@ if (output_surface_lost_) return; - num_failed_recreate_attempts_ = 0; output_surface_lost_ = true; SetNeedsCommit(); }
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 75165ad..e60f96e 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -125,11 +125,12 @@ void CommitComplete(); void SetOutputSurface(scoped_ptr<OutputSurface> output_surface); void RequestNewOutputSurface(); + void DidInitializeOutputSurface(); + void DidFailToInitializeOutputSurface(); virtual scoped_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl( LayerTreeHostImplClient* client); void DidLoseOutputSurface(); bool output_surface_lost() const { return output_surface_lost_; } - virtual void OnCreateAndInitializeOutputSurfaceAttempted(bool success); void DidCommitAndDrawFrame() { client_->DidCommitAndDrawFrame(); } void DidCompleteSwapBuffers() { client_->DidCompleteSwapBuffers(); } void DeleteContentsTexturesOnImplThread(ResourceProvider* resource_provider); @@ -402,7 +403,6 @@ scoped_ptr<RenderingStatsInstrumentation> rendering_stats_instrumentation_; bool output_surface_lost_; - int num_failed_recreate_attempts_; scoped_refptr<Layer> root_layer_; scoped_refptr<HeadsUpDisplayLayer> hud_layer_;
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h index 5846343..a09693f 100644 --- a/cc/trees/layer_tree_host_client.h +++ b/cc/trees/layer_tree_host_client.h
@@ -38,11 +38,12 @@ float page_scale, float top_controls_delta) = 0; // Request an OutputSurface from the client. When the client has one it should - // call LayerTreeHost::SetOutputSurface. If fallback is true, it should - // attempt to create an OutputSurface that is guaranteed to initialize - // correctly. - virtual void RequestNewOutputSurface(bool fallback) = 0; + // call LayerTreeHost::SetOutputSurface. This will result in either + // DidFailToInitializeOutputSurface or DidInitializeOutputSurface being + // called. + virtual void RequestNewOutputSurface() = 0; virtual void DidInitializeOutputSurface() = 0; + virtual void DidFailToInitializeOutputSurface() = 0; virtual void WillCommit() = 0; virtual void DidCommit() = 0; virtual void DidCommitAndDrawFrame() = 0; @@ -58,9 +59,6 @@ // a TextureLayer that calls SetRateLimitContext(true). virtual void RateLimitSharedMainThreadContext() {} - // This hook is for testing. - virtual void DidFailToInitializeOutputSurface() {} - protected: virtual ~LayerTreeHostClient() {} };
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index dd485ba..ea8a29f 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -1589,11 +1589,13 @@ if (use_gpu == use_gpu_rasterization_) return; + // Note that this must happen first, in case the rest of the calls want to + // query the new state of |use_gpu_rasterization_|. use_gpu_rasterization_ = use_gpu; - ReleaseTreeResources(); - // Replace existing tile manager with another one that uses appropriate - // rasterizer. + // Clean up and replace existing tile manager with another one that uses + // appropriate rasterizer. + ReleaseTreeResources(); if (tile_manager_) { DestroyTileManager(); CreateAndSetTileManager(); @@ -1964,8 +1966,7 @@ : settings_.scheduled_raster_task_limit; tile_manager_ = TileManager::Create( this, task_runner, resource_pool_.get(), - tile_task_worker_pool_->AsTileTaskRunner(), - rendering_stats_instrumentation_, scheduled_raster_task_limit); + tile_task_worker_pool_->AsTileTaskRunner(), scheduled_raster_task_limit); UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy()); }
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 9049a84..61bda89 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -4181,6 +4181,7 @@ resource_id_, gfx::RectF(0.f, 0.f, 1.f, 1.f), gfx::Size(1, 1), + false, false); test_blending_draw_quad->visible_rect = quad_visible_rect_; EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending()); @@ -7768,7 +7769,7 @@ TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) { host_impl_->CreatePendingTree(); host_impl_->pending_tree()->SetRootLayer( - PictureLayerImpl::Create(host_impl_->pending_tree(), 10)); + PictureLayerImpl::Create(host_impl_->pending_tree(), 10, false)); LayerTreeImpl* pending_tree = host_impl_->pending_tree(); LayerImpl* pending_layer = pending_tree->root_layer(); @@ -7809,7 +7810,7 @@ // should get two pairs. host_impl_->CreatePendingTree(); host_impl_->pending_tree()->root_layer()->AddChild( - PictureLayerImpl::Create(host_impl_->pending_tree(), 11)); + PictureLayerImpl::Create(host_impl_->pending_tree(), 11, false)); LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[0];
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc index 6b6b2af..b31d3e8 100644 --- a/cc/trees/layer_tree_host_pixeltest_blending.cc +++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "cc/layers/image_layer.h" +#include "cc/layers/picture_image_layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/test/layer_tree_pixel_resource_test.h" #include "cc/test/pixel_comparator.h" @@ -137,7 +137,7 @@ canvas.drawRect( SkRect::MakeXYWH(0, i * kLaneHeight, kLaneWidth, kLaneHeight), paint); } - scoped_refptr<ImageLayer> layer = ImageLayer::Create(); + scoped_refptr<PictureImageLayer> layer = PictureImageLayer::Create(); layer->SetIsDrawable(true); layer->SetBounds(gfx::Size(width, height)); layer->SetBitmap(backing_store); @@ -147,7 +147,7 @@ void SetupMaskLayer(scoped_refptr<Layer> layer) { const int kMaskOffset = 2; gfx::Size bounds = layer->bounds(); - scoped_refptr<ImageLayer> mask = ImageLayer::Create(); + scoped_refptr<PictureImageLayer> mask = PictureImageLayer::Create(); mask->SetIsDrawable(true); mask->SetIsMask(true); mask->SetBounds(bounds); @@ -237,7 +237,6 @@ CreateBlendingColorLayers(kLaneWidth, kLaneHeight, background.get(), flags); - this->impl_side_painting_ = false; this->force_antialiasing_ = (flags & kUseAntialiasing); this->force_blending_with_shaders_ = (flags & kForceShaders); @@ -437,6 +436,13 @@ } TEST_F(LayerTreeHostBlendingPixelTest, + BlendingWithRenderPassShadersWithMask_GL_TextureRect) { + RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW, + FILE_PATH_LITERAL("blending_render_pass_mask.png"), + kUseMasks | kForceShaders); +} + +TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShadersWithMaskAA_GL) { RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW, FILE_PATH_LITERAL("blending_render_pass_mask.png"), @@ -444,6 +450,13 @@ } TEST_F(LayerTreeHostBlendingPixelTest, + BlendingWithRenderPassShadersWithMaskAA_GL_TextureRect) { + RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW, + FILE_PATH_LITERAL("blending_render_pass_mask.png"), + kUseMasks | kUseAntialiasing | kForceShaders); +} + +TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShadersColorMatrix_GL) { RunBlendingWithRenderPass(GL_ASYNC_UPLOAD_2D_DRAW, FILE_PATH_LITERAL("blending_render_pass.png"), @@ -465,6 +478,13 @@ } TEST_F(LayerTreeHostBlendingPixelTest, + BlendingWithRenderPassShadersWithMaskColorMatrix_GL_TextureRect) { + RunBlendingWithRenderPass(GL_ZERO_COPY_RECT_DRAW, + FILE_PATH_LITERAL("blending_render_pass_mask.png"), + kUseMasks | kUseColorMatrix | kForceShaders); +} + +TEST_F(LayerTreeHostBlendingPixelTest, BlendingWithRenderPassShadersWithMaskColorMatrixAA_GL) { RunBlendingWithRenderPass( GL_ASYNC_UPLOAD_2D_DRAW,
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 06c522a..eee6275 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -2090,7 +2090,6 @@ settings.max_partial_texture_updates = 10; LayerTreeHostWithProxy host(&client, settings, proxy.Pass()); - host.OnCreateAndInitializeOutputSurfaceAttempted(true); EXPECT_EQ(0u, host.MaxPartialTextureUpdates()); } @@ -2108,7 +2107,6 @@ settings.max_partial_texture_updates = 10; LayerTreeHostWithProxy host(&client, settings, proxy.Pass()); - host.OnCreateAndInitializeOutputSurfaceAttempted(true); EXPECT_EQ(5u, host.MaxPartialTextureUpdates()); } @@ -2126,7 +2124,6 @@ settings.max_partial_texture_updates = 10; LayerTreeHostWithProxy host(&client, settings, proxy.Pass()); - host.OnCreateAndInitializeOutputSurfaceAttempted(true); EXPECT_EQ(10u, host.MaxPartialTextureUpdates()); } @@ -2688,8 +2685,7 @@ class LayerTreeHostTestIOSurfaceDrawing : public LayerTreeHostTest { protected: - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { scoped_ptr<MockIOSurfaceWebGraphicsContext3D> mock_context_owned( new MockIOSurfaceWebGraphicsContext3D); mock_context_ = mock_context_owned.get(); @@ -2883,8 +2879,7 @@ PostSetNeedsCommitToMainThread(); } - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { scoped_ptr<TestWebGraphicsContext3D> context3d( TestWebGraphicsContext3D::Create()); @@ -4380,8 +4375,7 @@ settings->use_one_copy = false; } - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { scoped_refptr<TestContextProvider> context_provider = TestContextProvider::Create(); context_provider->SetMaxTransferBufferUsageBytes(512 * 512); @@ -4522,8 +4516,7 @@ : first_output_surface_memory_limit_(4321234), second_output_surface_memory_limit_(1234321) {} - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { if (!first_context_provider_.get()) { first_context_provider_ = TestContextProvider::Create(); } else { @@ -5108,7 +5101,7 @@ class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest { protected: void InitializeSettings(LayerTreeSettings* settings) override { - settings->impl_side_painting = true; + ASSERT_TRUE(settings->impl_side_painting); EXPECT_FALSE(settings->gpu_rasterization_forced); settings->gpu_rasterization_forced = true; @@ -5169,7 +5162,7 @@ FakeContentLayerClient layer_client_; }; -MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationForced); +SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostTestGpuRasterizationForced); class LayerTreeHostTestContinuousPainting : public LayerTreeHostTest { public: @@ -5714,8 +5707,7 @@ settings->use_one_copy = true; } - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { scoped_ptr<TestWebGraphicsContext3D> context3d = TestWebGraphicsContext3D::Create(); context3d->set_support_image(true);
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index b646e6a..cc4f28f 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -17,6 +17,7 @@ #include "cc/layers/texture_layer_impl.h" #include "cc/output/filter_operations.h" #include "cc/resources/single_release_callback.h" +#include "cc/test/failure_output_surface.h" #include "cc/test/fake_content_layer.h" #include "cc/test/fake_content_layer_client.h" #include "cc/test/fake_content_layer_impl.h" @@ -74,12 +75,11 @@ return TestWebGraphicsContext3D::Create(); } - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { if (times_to_fail_create_) { --times_to_fail_create_; ExpectCreateToFail(); - return nullptr; + return make_scoped_ptr(new FailureOutputSurface(delegating_renderer())); } scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d(); @@ -167,22 +167,22 @@ void BeginTest() override { PostSetNeedsCommitToMainThread(); } - void RequestNewOutputSurface(bool fallback) override { + void RequestNewOutputSurface() override { if (async_output_surface_creation_) { MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&LayerTreeHostContextTestLostContextSucceeds:: - CreateAndSetOutputSurface, - base::Unretained(this), - fallback)); + FROM_HERE, base::Bind(&LayerTreeHostContextTestLostContextSucceeds:: + CreateAndSetOutputSurface, + base::Unretained(this))); } else { - CreateAndSetOutputSurface(fallback); + CreateAndSetOutputSurface(); } } - void CreateAndSetOutputSurface(bool fallback) { - layer_tree_host()->SetOutputSurface( - LayerTreeHostContextTest::CreateOutputSurface(fallback)); + void CreateAndSetOutputSurface() { + scoped_ptr<OutputSurface> surface( + LayerTreeHostContextTest::CreateOutputSurface()); + CHECK(surface); + layer_tree_host()->SetOutputSurface(surface.Pass()); } void DidInitializeOutputSurface() override { @@ -357,7 +357,7 @@ EndTest(); } - scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) override { + scoped_ptr<OutputSurface> CreateOutputSurface() override { EXPECT_TRUE(false); return nullptr; } @@ -380,7 +380,7 @@ settings->single_thread_proxy_scheduler = false; } - void RequestNewOutputSurface(bool fallback) override { + void RequestNewOutputSurface() override { EXPECT_GE(1, ++request_count_); EndTest(); } @@ -390,7 +390,7 @@ layer_tree_host()->Composite(base::TimeTicks()); } - scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) override { + scoped_ptr<OutputSurface> CreateOutputSurface() override { EXPECT_TRUE(false); return nullptr; } @@ -414,13 +414,12 @@ settings->single_thread_proxy_scheduler = false; } - void RequestNewOutputSurface(bool fallback) override { + void RequestNewOutputSurface() override { if (request_count_ == 0) { ExpectCreateToFail(); - layer_tree_host()->SetOutputSurface(nullptr); + layer_tree_host()->SetOutputSurface( + make_scoped_ptr(new FailureOutputSurface(false))); } - EXPECT_GE(2, ++request_count_); - EndTest(); } void BeginTest() override { @@ -428,13 +427,14 @@ layer_tree_host()->Composite(base::TimeTicks()); } - scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback) override { - EXPECT_TRUE(false); - return nullptr; - } - void DidInitializeOutputSurface() override { EXPECT_TRUE(false); } + void DidFailToInitializeOutputSurface() override { + LayerTreeHostContextTest::DidFailToInitializeOutputSurface(); + EXPECT_GE(2, ++request_count_); + EndTest(); + } + void AfterTest() override {} int request_count_; @@ -452,19 +452,18 @@ settings->single_thread_proxy_scheduler = false; } - void RequestNewOutputSurface(bool fallback) override { + void RequestNewOutputSurface() override { MainThreadTaskRunner()->PostTask( FROM_HERE, base::Bind(&LayerTreeHostContextTestCommitAfterDelayedOutputSurface:: CreateAndSetOutputSurface, - base::Unretained(this), - fallback)); + base::Unretained(this))); } - void CreateAndSetOutputSurface(bool fallback) { + void CreateAndSetOutputSurface() { creating_output_ = true; layer_tree_host()->SetOutputSurface( - LayerTreeHostContextTest::CreateOutputSurface(fallback)); + LayerTreeHostContextTest::CreateOutputSurface()); } void BeginTest() override { layer_tree_host()->Composite(base::TimeTicks()); } @@ -492,9 +491,9 @@ settings->single_thread_proxy_scheduler = false; } - void RequestNewOutputSurface(bool fallback) override { + void RequestNewOutputSurface() override { layer_tree_host()->SetOutputSurface( - LayerTreeHostContextTest::CreateOutputSurface(fallback)); + LayerTreeHostContextTest::CreateOutputSurface()); EndTest(); } @@ -572,35 +571,16 @@ SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostContextTestLostContextSucceedsWithContent); -class LayerTreeHostContextTestCreateOutputSurfaceFails +class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce : public LayerTreeHostContextTest { public: - // Run a test that initially fails OutputSurface creation |times_to_fail| - // times. If |expect_fallback_attempt| is |true|, an attempt to create a - // fallback/software OutputSurface is expected to occur. - LayerTreeHostContextTestCreateOutputSurfaceFails(int times_to_fail, - bool expect_fallback_attempt) - : times_to_fail_(times_to_fail), - expect_fallback_attempt_(expect_fallback_attempt), - did_attempt_fallback_(false), - times_initialized_(0) { + LayerTreeHostContextTestCreateOutputSurfaceFailsOnce() + : times_to_fail_(1), times_initialized_(0) { times_to_fail_create_ = times_to_fail_; } void BeginTest() override { PostSetNeedsCommitToMainThread(); } - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { - scoped_ptr<FakeOutputSurface> surface = - LayerTreeHostContextTest::CreateFakeOutputSurface(fallback); - - if (surface) - EXPECT_EQ(times_to_fail_, times_create_failed_); - - did_attempt_fallback_ = fallback; - return surface.Pass(); - } - void DidInitializeOutputSurface() override { times_initialized_++; } void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EndTest(); } @@ -608,38 +588,16 @@ void AfterTest() override { EXPECT_EQ(times_to_fail_, times_create_failed_); EXPECT_NE(0, times_initialized_); - EXPECT_EQ(expect_fallback_attempt_, did_attempt_fallback_); } private: int times_to_fail_; - bool expect_fallback_attempt_; - bool did_attempt_fallback_; int times_initialized_; }; -class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce - : public LayerTreeHostContextTestCreateOutputSurfaceFails { - public: - LayerTreeHostContextTestCreateOutputSurfaceFailsOnce() - : LayerTreeHostContextTestCreateOutputSurfaceFails(1, false) {} -}; - SINGLE_AND_MULTI_THREAD_TEST_F( LayerTreeHostContextTestCreateOutputSurfaceFailsOnce); -// After 4 failures we expect an attempt to create a fallback/software -// OutputSurface. -class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback - : public LayerTreeHostContextTestCreateOutputSurfaceFails { - public: - LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback() - : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true) {} -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback); - class LayerTreeHostContextTestLostContextAndEvictTextures : public LayerTreeHostContextTest { public: @@ -1118,15 +1076,14 @@ return draw_result; } - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { // This will get called twice: // First when we create the initial output surface... if (layer_tree_host()->source_frame_number() > 0) { // ... and then again after we forced the context to be lost. lost_context_ = true; } - return LayerTreeHostContextTest::CreateFakeOutputSurface(fallback); + return LayerTreeHostContextTest::CreateFakeOutputSurface(); } void DidCommitAndDrawFrame() override {
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc index 1b68cca..de20b6c 100644 --- a/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -103,8 +103,7 @@ void AfterTest() override { EXPECT_EQ(4u, callbacks_.size()); } - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { if (use_gl_renderer_) return FakeOutputSurface::Create3d(); return FakeOutputSurface::CreateSoftware( @@ -534,8 +533,7 @@ class LayerTreeHostCopyRequestTestLostOutputSurface : public LayerTreeHostCopyRequestTest { protected: - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { if (!first_context_provider_.get()) { first_context_provider_ = TestContextProvider::Create(); return FakeOutputSurface::Create3d(first_context_provider_); @@ -663,8 +661,7 @@ class LayerTreeHostCopyRequestTestCountTextures : public LayerTreeHostCopyRequestTest { protected: - scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface( - bool fallback) override { + scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override { context_provider_ = TestContextProvider::Create(); return FakeOutputSurface::Create3d(context_provider_); }
diff --git a/cc/trees/layer_tree_host_unittest_no_message_loop.cc b/cc/trees/layer_tree_host_unittest_no_message_loop.cc index 1e04ad9..9e6611a 100644 --- a/cc/trees/layer_tree_host_unittest_no_message_loop.cc +++ b/cc/trees/layer_tree_host_unittest_no_message_loop.cc
@@ -66,13 +66,14 @@ void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, float page_scale, float top_controls_delta) override {} - void RequestNewOutputSurface(bool fallback) override { + void RequestNewOutputSurface() override { layer_tree_host_->SetOutputSurface( make_scoped_ptr<OutputSurface>(new NoMessageLoopOutputSurface)); } void DidInitializeOutputSurface() override { did_initialize_output_surface_ = true; } + void DidFailToInitializeOutputSurface() override {} void WillCommit() override {} void DidCommit() override { did_commit_ = true; } void DidCommitAndDrawFrame() override { did_commit_and_draw_frame_ = true; }
diff --git a/cc/trees/layer_tree_host_unittest_picture.cc b/cc/trees/layer_tree_host_unittest_picture.cc index 2d485b4..773798a 100644 --- a/cc/trees/layer_tree_host_unittest_picture.cc +++ b/cc/trees/layer_tree_host_unittest_picture.cc
@@ -16,20 +16,25 @@ // These tests deal with picture layers. class LayerTreeHostPictureTest : public LayerTreeTest { protected: - void InitializeSettings(LayerTreeSettings* settings) override { - // PictureLayer can only be used with impl side painting enabled. - settings->impl_side_painting = true; + void SetupTreeWithSinglePictureLayer(const gfx::Size& size) { + scoped_refptr<Layer> root = Layer::Create(); + root->SetBounds(size); + + root_picture_layer_ = FakePictureLayer::Create(&client_); + root_picture_layer_->SetBounds(size); + root->AddChild(root_picture_layer_); + + layer_tree_host()->SetRootLayer(root); } + + scoped_refptr<FakePictureLayer> root_picture_layer_; + FakeContentLayerClient client_; }; class LayerTreeHostPictureTestTwinLayer : public LayerTreeHostPictureTest { void SetupTree() override { - LayerTreeHostPictureTest::SetupTree(); - - scoped_refptr<FakePictureLayer> picture = - FakePictureLayer::Create(&client_); - layer_tree_host()->root_layer()->AddChild(picture); + SetupTreeWithSinglePictureLayer(gfx::Size(1, 1)); } void BeginTest() override { @@ -117,11 +122,200 @@ void AfterTest() override {} - FakeContentLayerClient client_; int activates_; }; -MULTI_THREAD_TEST_F(LayerTreeHostPictureTestTwinLayer); +SINGLE_AND_MULTI_THREAD_IMPL_TEST_F(LayerTreeHostPictureTestTwinLayer); + +class LayerTreeHostPictureTestResizeViewportWithGpuRaster + : public LayerTreeHostPictureTest { + void InitializeSettings(LayerTreeSettings* settings) override { + settings->gpu_rasterization_forced = true; + } + + void SetupTree() override { + scoped_refptr<Layer> root = Layer::Create(); + root->SetBounds(gfx::Size(768, 960)); + + client_.set_fill_with_nonsolid_color(true); + picture_ = FakePictureLayer::Create(&client_); + picture_->SetBounds(gfx::Size(768, 960)); + root->AddChild(picture_); + + layer_tree_host()->SetRootLayer(root); + LayerTreeHostPictureTest::SetupTree(); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override { + LayerImpl* child = impl->sync_tree()->root_layer()->children()[0]; + FakePictureLayerImpl* picture_impl = + static_cast<FakePictureLayerImpl*>(child); + gfx::Size tile_size = + picture_impl->HighResTiling()->TileAt(0, 0)->content_rect().size(); + + switch (impl->sync_tree()->source_frame_number()) { + case 0: + tile_size_ = tile_size; + // GPU Raster picks a tile size based on the viewport size. + EXPECT_EQ(gfx::Size(768, 256), tile_size); + break; + case 1: + // When the viewport changed size, the new frame's tiles should change + // along with it. + EXPECT_NE(gfx::Size(768, 256), tile_size); + } + } + + void DidCommit() override { + switch (layer_tree_host()->source_frame_number()) { + case 1: + // Change the picture layer's size along with the viewport, so it will + // consider picking a new tile size. + picture_->SetBounds(gfx::Size(768, 1056)); + layer_tree_host()->SetViewportSize(gfx::Size(768, 1056)); + break; + case 2: + EndTest(); + } + } + + void AfterTest() override {} + + gfx::Size tile_size_; + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> picture_; +}; + +SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( + LayerTreeHostPictureTestResizeViewportWithGpuRaster); + +class LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree + : public LayerTreeHostPictureTest { + void SetupTree() override { + frame_ = 0; + did_post_commit_ = false; + + scoped_refptr<Layer> root = Layer::Create(); + root->SetBounds(gfx::Size(100, 100)); + + // The layer is big enough that the live tiles rect won't cover the full + // layer. + client_.set_fill_with_nonsolid_color(true); + picture_ = FakePictureLayer::Create(&client_); + picture_->SetBounds(gfx::Size(100, 100000)); + root->AddChild(picture_); + + layer_tree_host()->SetRootLayer(root); + LayerTreeHostPictureTest::SetupTree(); + } + + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { + LayerImpl* child = impl->active_tree()->root_layer()->children()[0]; + FakePictureLayerImpl* picture_impl = + static_cast<FakePictureLayerImpl*>(child); + FakePictureLayerImpl* recycled_impl = static_cast<FakePictureLayerImpl*>( + picture_impl->GetRecycledTwinLayer()); + + switch (++frame_) { + case 1: { + PictureLayerTiling* tiling = picture_impl->HighResTiling(); + PictureLayerTiling* recycled_tiling = recycled_impl->HighResTiling(); + int num_tiles_y = tiling->TilingDataForTesting().num_tiles_y(); + + // There should be tiles at the top of the picture layer but not at the + // bottom. + EXPECT_TRUE(tiling->TileAt(0, 0)); + EXPECT_FALSE(tiling->TileAt(0, num_tiles_y)); + + // The recycled tiling matches it. + EXPECT_TRUE(recycled_tiling->TileAt(0, 0)); + EXPECT_FALSE(recycled_tiling->TileAt(0, num_tiles_y)); + + // The live tiles rect matches on the recycled tree. + EXPECT_EQ(tiling->live_tiles_rect(), + recycled_tiling->live_tiles_rect()); + + // Make the bottom of the layer visible. + picture_impl->SetPosition(gfx::PointF(0.f, -100000.f + 100.f)); + impl->SetNeedsRedraw(); + break; + } + case 2: { + PictureLayerTiling* tiling = picture_impl->HighResTiling(); + PictureLayerTiling* recycled_tiling = recycled_impl->HighResTiling(); + + // There not be tiles at the top of the layer now. + EXPECT_FALSE(tiling->TileAt(0, 0)); + + // The recycled twin tiling should not have unshared tiles at the top + // either. + EXPECT_FALSE(recycled_tiling->TileAt(0, 0)); + + // The live tiles rect matches on the recycled tree. + EXPECT_EQ(tiling->live_tiles_rect(), + recycled_tiling->live_tiles_rect()); + + // Make the top of the layer visible again. + picture_impl->SetPosition(gfx::PointF()); + impl->SetNeedsRedraw(); + break; + } + case 3: { + PictureLayerTiling* tiling = picture_impl->HighResTiling(); + PictureLayerTiling* recycled_tiling = recycled_impl->HighResTiling(); + int num_tiles_y = tiling->TilingDataForTesting().num_tiles_y(); + + // There should be tiles at the top of the picture layer again. + EXPECT_TRUE(tiling->TileAt(0, 0)); + EXPECT_FALSE(tiling->TileAt(0, num_tiles_y)); + + // The recycled tiling should also have tiles at the top. + EXPECT_TRUE(recycled_tiling->TileAt(0, 0)); + EXPECT_FALSE(recycled_tiling->TileAt(0, num_tiles_y)); + + // The live tiles rect matches on the recycled tree. + EXPECT_EQ(tiling->live_tiles_rect(), + recycled_tiling->live_tiles_rect()); + + // Make a new main frame without changing the picture layer at all, so + // it won't need to update or push properties. + did_post_commit_ = true; + PostSetNeedsCommitToMainThread(); + break; + } + } + } + + void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override { + LayerImpl* child = impl->sync_tree()->root_layer()->children()[0]; + FakePictureLayerImpl* picture_impl = + static_cast<FakePictureLayerImpl*>(child); + PictureLayerTiling* tiling = picture_impl->HighResTiling(); + int num_tiles_y = tiling->TilingDataForTesting().num_tiles_y(); + + // The pending layer should always have tiles at the top of it each commit. + // The tile is part of the required for activation set so it should exist. + EXPECT_TRUE(tiling->TileAt(0, 0)); + EXPECT_FALSE(tiling->TileAt(0, num_tiles_y)); + + if (did_post_commit_) + EndTest(); + } + + void AfterTest() override {} + + int frame_; + bool did_post_commit_; + FakeContentLayerClient client_; + scoped_refptr<FakePictureLayer> picture_; +}; + +SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( + LayerTreeHostPictureTestChangeLiveTilesRectWithRecycleTree); } // namespace } // namespace cc
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index b1248e0..6498f0e 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -129,8 +129,8 @@ output_surface_creation_requested_ = false; renderer_capabilities_for_main_thread_ = RendererCapabilities(); - bool success = !!output_surface; - if (success) { + bool success; + { DebugScopedSetMainThreadBlocked main_thread_blocked(this); DebugScopedSetImplThread impl(this); layer_tree_host_->DeleteContentsTexturesOnImplThread( @@ -138,15 +138,14 @@ success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass()); } - layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success); - if (success) { + layer_tree_host_->DidInitializeOutputSurface(); if (scheduler_on_impl_thread_) scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface(); else if (!inside_synchronous_composite_) SetNeedsCommit(); - } else if (Proxy::MainThreadTaskRunner()) { - ScheduleRequestNewOutputSurface(); + } else { + layer_tree_host_->DidFailToInitializeOutputSurface(); } }
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index e6ab017..73bf79e 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc
@@ -215,16 +215,10 @@ } void ThreadProxy::SetOutputSurface(scoped_ptr<OutputSurface> output_surface) { - if (output_surface) { - Proxy::ImplThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread, - impl_thread_weak_ptr_, - base::Passed(&output_surface))); - return; - } - - DidInitializeOutputSurface(false, RendererCapabilities()); + Proxy::ImplThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread, + impl_thread_weak_ptr_, base::Passed(&output_surface))); } void ThreadProxy::DidInitializeOutputSurface( @@ -232,15 +226,13 @@ const RendererCapabilities& capabilities) { TRACE_EVENT0("cc", "ThreadProxy::DidInitializeOutputSurface"); DCHECK(IsMainThread()); - main().renderer_capabilities_main_thread_copy = capabilities; - layer_tree_host()->OnCreateAndInitializeOutputSurfaceAttempted(success); if (!success) { - Proxy::MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&ThreadProxy::RequestNewOutputSurface, - main_thread_weak_ptr_)); + layer_tree_host()->DidFailToInitializeOutputSurface(); + return; } + main().renderer_capabilities_main_thread_copy = capabilities; + layer_tree_host()->DidInitializeOutputSurface(); } void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index d35de42..5a506df 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -19,7 +19,9 @@ #define glBindBuffer GLES2_GET_FUN(BindBuffer) #define glBindFramebuffer GLES2_GET_FUN(BindFramebuffer) #define glBindRenderbuffer GLES2_GET_FUN(BindRenderbuffer) +#define glBindSampler GLES2_GET_FUN(BindSampler) #define glBindTexture GLES2_GET_FUN(BindTexture) +#define glBindTransformFeedback GLES2_GET_FUN(BindTransformFeedback) #define glBlendColor GLES2_GET_FUN(BlendColor) #define glBlendEquation GLES2_GET_FUN(BlendEquation) #define glBlendEquationSeparate GLES2_GET_FUN(BlendEquationSeparate) @@ -46,8 +48,10 @@ #define glDeleteFramebuffers GLES2_GET_FUN(DeleteFramebuffers) #define glDeleteProgram GLES2_GET_FUN(DeleteProgram) #define glDeleteRenderbuffers GLES2_GET_FUN(DeleteRenderbuffers) +#define glDeleteSamplers GLES2_GET_FUN(DeleteSamplers) #define glDeleteShader GLES2_GET_FUN(DeleteShader) #define glDeleteTextures GLES2_GET_FUN(DeleteTextures) +#define glDeleteTransformFeedbacks GLES2_GET_FUN(DeleteTransformFeedbacks) #define glDepthFunc GLES2_GET_FUN(DepthFunc) #define glDepthMask GLES2_GET_FUN(DepthMask) #define glDepthRangef GLES2_GET_FUN(DepthRangef) @@ -68,7 +72,9 @@ #define glGenerateMipmap GLES2_GET_FUN(GenerateMipmap) #define glGenFramebuffers GLES2_GET_FUN(GenFramebuffers) #define glGenRenderbuffers GLES2_GET_FUN(GenRenderbuffers) +#define glGenSamplers GLES2_GET_FUN(GenSamplers) #define glGenTextures GLES2_GET_FUN(GenTextures) +#define glGenTransformFeedbacks GLES2_GET_FUN(GenTransformFeedbacks) #define glGetActiveAttrib GLES2_GET_FUN(GetActiveAttrib) #define glGetActiveUniform GLES2_GET_FUN(GetActiveUniform) #define glGetAttachedShaders GLES2_GET_FUN(GetAttachedShaders) @@ -84,6 +90,8 @@ #define glGetProgramiv GLES2_GET_FUN(GetProgramiv) #define glGetProgramInfoLog GLES2_GET_FUN(GetProgramInfoLog) #define glGetRenderbufferParameteriv GLES2_GET_FUN(GetRenderbufferParameteriv) +#define glGetSamplerParameterfv GLES2_GET_FUN(GetSamplerParameterfv) +#define glGetSamplerParameteriv GLES2_GET_FUN(GetSamplerParameteriv) #define glGetShaderiv GLES2_GET_FUN(GetShaderiv) #define glGetShaderInfoLog GLES2_GET_FUN(GetShaderInfoLog) #define glGetShaderPrecisionFormat GLES2_GET_FUN(GetShaderPrecisionFormat) @@ -105,17 +113,25 @@ #define glIsFramebuffer GLES2_GET_FUN(IsFramebuffer) #define glIsProgram GLES2_GET_FUN(IsProgram) #define glIsRenderbuffer GLES2_GET_FUN(IsRenderbuffer) +#define glIsSampler GLES2_GET_FUN(IsSampler) #define glIsShader GLES2_GET_FUN(IsShader) #define glIsTexture GLES2_GET_FUN(IsTexture) +#define glIsTransformFeedback GLES2_GET_FUN(IsTransformFeedback) #define glLineWidth GLES2_GET_FUN(LineWidth) #define glLinkProgram GLES2_GET_FUN(LinkProgram) +#define glPauseTransformFeedback GLES2_GET_FUN(PauseTransformFeedback) #define glPixelStorei GLES2_GET_FUN(PixelStorei) #define glPolygonOffset GLES2_GET_FUN(PolygonOffset) #define glReadBuffer GLES2_GET_FUN(ReadBuffer) #define glReadPixels GLES2_GET_FUN(ReadPixels) #define glReleaseShaderCompiler GLES2_GET_FUN(ReleaseShaderCompiler) #define glRenderbufferStorage GLES2_GET_FUN(RenderbufferStorage) +#define glResumeTransformFeedback GLES2_GET_FUN(ResumeTransformFeedback) #define glSampleCoverage GLES2_GET_FUN(SampleCoverage) +#define glSamplerParameterf GLES2_GET_FUN(SamplerParameterf) +#define glSamplerParameterfv GLES2_GET_FUN(SamplerParameterfv) +#define glSamplerParameteri GLES2_GET_FUN(SamplerParameteri) +#define glSamplerParameteriv GLES2_GET_FUN(SamplerParameteriv) #define glScissor GLES2_GET_FUN(Scissor) #define glShaderBinary GLES2_GET_FUN(ShaderBinary) #define glShaderSource GLES2_GET_FUN(ShaderSource) @@ -196,7 +212,9 @@ #define glDeleteQueriesEXT GLES2_GET_FUN(DeleteQueriesEXT) #define glIsQueryEXT GLES2_GET_FUN(IsQueryEXT) #define glBeginQueryEXT GLES2_GET_FUN(BeginQueryEXT) +#define glBeginTransformFeedback GLES2_GET_FUN(BeginTransformFeedback) #define glEndQueryEXT GLES2_GET_FUN(EndQueryEXT) +#define glEndTransformFeedback GLES2_GET_FUN(EndTransformFeedback) #define glGetQueryivEXT GLES2_GET_FUN(GetQueryivEXT) #define glGetQueryObjectuivEXT GLES2_GET_FUN(GetQueryObjectuivEXT) #define glInsertEventMarkerEXT GLES2_GET_FUN(InsertEventMarkerEXT)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 0b86db6..418612a 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -10,6 +10,7 @@ import os.path import sys import re +import platform from optparse import OptionParser from subprocess import call @@ -709,6 +710,26 @@ 'GL_TEXTURE_3D', ], }, + 'TransformFeedbackBindTarget': { + 'type': 'GLenum', + 'valid': [ + 'GL_TRANSFORM_FEEDBACK', + ], + 'invalid': [ + 'GL_TEXTURE_2D', + ], + }, + 'TransformFeedbackPrimitiveMode': { + 'type': 'GLenum', + 'valid': [ + 'GL_POINTS', + 'GL_LINES', + 'GL_TRIANGLES', + ], + 'invalid': [ + 'GL_LINE_LOOP', + ], + }, 'ShaderType': { 'type': 'GLenum', 'valid': [ @@ -939,6 +960,23 @@ 'GL_RENDERBUFFER_INTERNAL_FORMAT', ], }, + 'SamplerParameter': { + 'type': 'GLenum', + 'valid': [ + 'GL_TEXTURE_MAG_FILTER', + 'GL_TEXTURE_MIN_FILTER', + 'GL_TEXTURE_MIN_LOD', + 'GL_TEXTURE_MAX_LOD', + 'GL_TEXTURE_WRAP_S', + 'GL_TEXTURE_WRAP_T', + 'GL_TEXTURE_WRAP_R', + 'GL_TEXTURE_COMPARE_MODE', + 'GL_TEXTURE_COMPARE_FUNC', + ], + 'invalid': [ + 'GL_GENERATE_MIPMAP', + ], + }, 'ShaderParameter': { 'type': 'GLenum', 'valid': [ @@ -1327,7 +1365,7 @@ # command. # impl_decl: Whether or not to generate the GLES2Implementation declaration # for this command. -# needs_size: If true a data_size field is added to the command. +# needs_size: If True a data_size field is added to the command. # count: The number of units per element. For PUTn or PUT types. # unit_test: If False no service side unit test will be generated. # client_test: If False no client side unit test will be generated. @@ -1359,6 +1397,8 @@ # not_shared: For GENn types, True if objects can't be shared between contexts # unsafe: True = no validation is implemented on the service side and the # command is only available with --enable-unsafe-es3-apis. +# id_mapping: A list of resource type names whose client side IDs need to be +# mapped to service side IDs. This is only used for unsafe APIs. _FUNCTION_INFO = { 'ActiveTexture': { @@ -1391,6 +1431,11 @@ 'gl_test_func': 'glBindRenderbufferEXT', 'gen_func': 'GenRenderbuffersEXT', }, + 'BindSampler': { + 'type': 'Bind', + 'id_mapping': [ 'Sampler' ], + 'unsafe': True, + }, 'BindTexture': { 'type': 'Bind', 'decoder_func': 'DoBindTexture', @@ -1399,6 +1444,11 @@ 'client_test': False, 'trace_level': 1, }, + 'BindTransformFeedback': { + 'type': 'Bind', + 'id_mapping': [ 'TransformFeedback' ], + 'unsafe': True, + }, 'BlitFramebufferCHROMIUM': { 'decoder_func': 'DoBlitFramebufferCHROMIUM', 'unit_test': False, @@ -1690,12 +1740,24 @@ 'resource_type': 'Renderbuffer', 'resource_types': 'Renderbuffers', }, + 'DeleteSamplers': { + 'type': 'DELn', + 'resource_type': 'Sampler', + 'resource_types': 'Samplers', + 'unsafe': True, + }, 'DeleteShader': {'type': 'Delete', 'decoder_func': 'DoDeleteShader'}, 'DeleteTextures': { 'type': 'DELn', 'resource_type': 'Texture', 'resource_types': 'Textures', }, + 'DeleteTransformFeedbacks': { + 'type': 'DELn', + 'resource_type': 'TransformFeedback', + 'resource_types': 'TransformFeedbacks', + 'unsafe': True, + }, 'DepthRangef': { 'decoder_func': 'DoDepthRangef', 'gl_test_func': 'glDepthRange', @@ -1797,12 +1859,26 @@ 'resource_type': 'Renderbuffer', 'resource_types': 'Renderbuffers', }, + 'GenSamplers': { + 'type': 'GENn', + 'gl_test_func': 'glGenSamplers', + 'resource_type': 'Sampler', + 'resource_types': 'Samplers', + 'unsafe': True, + }, 'GenTextures': { 'type': 'GENn', 'gl_test_func': 'glGenTextures', 'resource_type': 'Texture', 'resource_types': 'Textures', }, + 'GenTransformFeedbacks': { + 'type': 'GENn', + 'gl_test_func': 'glGenTransformFeedbacks', + 'resource_type': 'TransformFeedback', + 'resource_types': 'TransformFeedbacks', + 'unsafe': True, + }, 'GetActiveAttrib': { 'type': 'Custom', 'data_transfer_methods': ['shm'], @@ -1924,6 +2000,18 @@ 'gl_test_func': 'glGetRenderbufferParameterivEXT', 'result': ['SizedResult<GLint>'], }, + 'GetSamplerParameterfv': { + 'type': 'GETn', + 'result': ['SizedResult<GLfloat>'], + 'id_mapping': [ 'Sampler' ], + 'unsafe': True, + }, + 'GetSamplerParameteriv': { + 'type': 'GETn', + 'result': ['SizedResult<GLint>'], + 'id_mapping': [ 'Sampler' ], + 'unsafe': True, + }, 'GetShaderiv': { 'type': 'GETn', 'decoder_func': 'DoGetShaderiv', @@ -2062,11 +2150,21 @@ 'decoder_func': 'DoIsShader', 'expectation': False, }, + 'IsSampler': { + 'type': 'Is', + 'id_mapping': [ 'Sampler' ], + 'unsafe': True, + }, 'IsTexture': { 'type': 'Is', 'decoder_func': 'DoIsTexture', 'expectation': False, }, + 'IsTransformFeedback': { + 'type': 'Is', + 'id_mapping': [ 'TransformFeedback' ], + 'unsafe': True, + }, 'LinkProgram': { 'decoder_func': 'DoLinkProgram', 'impl_func': False, @@ -2091,6 +2189,9 @@ 'client_test': False, 'pepper_interface': 'ChromiumMapSub', }, + 'PauseTransformFeedback': { + 'unsafe': True, + }, 'PixelStorei': {'type': 'Manual'}, 'PostSubBufferCHROMIUM': { 'type': 'Custom', @@ -2172,6 +2273,42 @@ 'decoder_func': 'DoReleaseShaderCompiler', 'unit_test': False, }, + 'ResumeTransformFeedback': { + 'unsafe': True, + }, + 'SamplerParameterf': { + 'valid_args': { + '2': 'GL_NEAREST' + }, + 'id_mapping': [ 'Sampler' ], + 'unsafe': True, + }, + 'SamplerParameterfv': { + 'type': 'PUT', + 'data_value': 'GL_NEAREST', + 'count': 1, + 'gl_test_func': 'glSamplerParameterf', + 'decoder_func': 'DoSamplerParameterfv', + 'first_element_only': True, + 'id_mapping': [ 'Sampler' ], + 'unsafe': True, + }, + 'SamplerParameteri': { + 'valid_args': { + '2': 'GL_NEAREST' + }, + 'id_mapping': [ 'Sampler' ], + 'unsafe': True, + }, + 'SamplerParameteriv': { + 'type': 'PUT', + 'data_value': 'GL_NEAREST', + 'count': 1, + 'gl_test_func': 'glSamplerParameteri', + 'decoder_func': 'DoSamplerParameteriv', + 'first_element_only': True, + 'unsafe': True, + }, 'ShaderBinary': { 'type': 'Custom', 'client_test': False, @@ -2599,6 +2736,9 @@ 'gl_test_func': 'glBeginQuery', 'pepper_interface': 'Query', }, + 'BeginTransformFeedback': { + 'unsafe': True, + }, 'EndQueryEXT': { 'type': 'Manual', 'cmd_args': 'GLenumQueryTarget target, GLuint submit_count', @@ -2606,6 +2746,9 @@ 'client_test': False, 'pepper_interface': 'Query', }, + 'EndTransformFeedback': { + 'unsafe': True, + }, 'GetQueryivEXT': { 'gen_cmd': False, 'client_test': False, @@ -3061,6 +3204,10 @@ def WriteHandlerImplementation(self, func, file): """Writes the handler implementation for this command.""" + if func.IsUnsafe() and func.GetInfo('id_mapping'): + for id_type in func.GetInfo('id_mapping'): + file.Write(" group_->Get%sServiceId(%s, &%s);\n" % + (id_type, id_type.lower(), id_type.lower())) file.Write(" %s(%s);\n" % (func.GetGLFunctionName(), func.MakeOriginalArgString(""))) @@ -3110,6 +3257,10 @@ def WriteImmediateHandlerImplementation (self, func, file): """Writes the handler impl for the immediate version of a command.""" + if func.IsUnsafe() and func.GetInfo('id_mapping'): + for id_type in func.GetInfo('id_mapping'): + file.Write(" group_->Get%sServiceId(%s, &%s);\n" % + (id_type, id_type.lower(), id_type.lower())) file.Write(" %s(%s);\n" % (func.GetGLFunctionName(), func.MakeOriginalArgString(""))) @@ -3233,6 +3384,8 @@ def WriteInvalidUnitTest(self, func, file, test, *extras): """Writes an invalid unit test for the service implementation.""" + if func.IsUnsafe(): + return for invalid_arg_index, invalid_arg in enumerate(func.GetOriginalArgs()): # Service implementation does not test constants, as they are not part of # the call in the service side. @@ -3270,7 +3423,7 @@ 'all_but_last_args': ", ".join(arg_strings[:-1]), 'gl_args': ", ".join(gl_arg_strings), 'parse_result': parse_result, - 'gl_error_test': gl_error_test, + 'gl_error_test': gl_error_test, } for extra in extras: vars.update(extra) @@ -4154,7 +4307,18 @@ EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)); SpecializedSetup<cmds::%(name)s, 0>(true); cmds::%(name)s cmd; - cmd.Init(%(args)s); + cmd.Init(%(args)s);""" + if func.IsUnsafe(): + valid_test += """ + 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)); +} +""" + else: + valid_test += """ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } @@ -4183,7 +4347,18 @@ EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)); SpecializedSetup<cmds::%(name)s, 0>(true); cmds::%(name)s cmd; - cmd.Init(%(args)s); + cmd.Init(%(args)s);""" + if func.IsUnsafe(): + valid_test += """ + 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)); +} +""" + else: + valid_test += """ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); } @@ -4239,7 +4414,14 @@ for arg in func.GetOriginalArgs(): arg.WriteClientSideValidationCode(file, func) - code = """ if (Is%(type)sReservedId(%(id)s)) { + if func.IsUnsafe(): + code = """ helper_->%(name)s(%(arg_string)s); + CheckGLError(); +} + +""" + else: + code = """ if (Is%(type)sReservedId(%(id)s)) { SetGLError(GL_INVALID_OPERATION, "%(name)s\", \"%(id)s reserved id"); return; } @@ -4278,10 +4460,13 @@ expected.cmd.Init(%(cmd_args)s); gl_->%(name)s(%(args)s); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));""" + if not func.IsUnsafe(): + code += """ ClearCommands(); gl_->%(name)s(%(args)s); - EXPECT_TRUE(NoCommandsWritten()); + EXPECT_TRUE(NoCommandsWritten());""" + code += """ } """ cmd_arg_strings = [ @@ -4326,10 +4511,25 @@ def WriteImmediateHandlerImplementation(self, func, file): """Overrriden from TypeHandler.""" - file.Write(" if (!%sHelper(n, %s)) {\n" - " return error::kInvalidArguments;\n" - " }\n" % - (func.original_name, func.GetLastOriginalArg().name)) + if func.IsUnsafe(): + file.Write(""" for (GLsizei ii = 0; ii < n; ++ii) { + if (group_->Get%(resource_name)sServiceId(%(last_arg_name)s[ii], NULL)) { + return error::kInvalidArguments; + } + } + scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + gl%(func_name)s(n, service_ids.get()); + for (GLsizei ii = 0; ii < n; ++ii) { + group_->Add%(resource_name)sId(%(last_arg_name)s[ii], service_ids[ii]); + } +""" % { 'func_name': func.original_name, + 'last_arg_name': func.GetLastOriginalArg().name, + 'resource_name': func.GetInfo('resource_type') }) + else: + file.Write(" if (!%sHelper(n, %s)) {\n" + " return error::kInvalidArguments;\n" + " }\n" % + (func.original_name, func.GetLastOriginalArg().name)) def WriteGLES2Implementation(self, func, file): """Overrriden from TypeHandler.""" @@ -4415,8 +4615,17 @@ cmds::%(name)s cmd; cmd.Init(%(args)s); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); - EXPECT_TRUE(Get%(resource_name)s(kNewClientId) != NULL); + EXPECT_EQ(GL_NO_ERROR, GetGLError());""" + if func.IsUnsafe(): + valid_test += """ + GLuint service_id; + EXPECT_TRUE(Get%(resource_name)sServiceId(kNewClientId, &service_id)); + EXPECT_EQ(kNewServiceId, service_id) +} +""" + else: + valid_test += """ + EXPECT_TRUE(Get%(resource_name)s(kNewClientId, &service_id) != NULL); } """ self.WriteValidUnitTest(func, file, valid_test, { @@ -4444,11 +4653,27 @@ .WillOnce(SetArgumentPointee<1>(kNewServiceId)); cmds::%(name)s* cmd = GetImmediateAs<cmds::%(name)s>(); GLuint temp = kNewClientId; - SpecializedSetup<cmds::%(name)s, 0>(true); + SpecializedSetup<cmds::%(name)s, 0>(true);""" + if func.IsUnsafe(): + valid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true);""" + valid_test += """ cmd->Init(1, &temp); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError());""" + if func.IsUnsafe(): + valid_test += """ + GLuint service_id; + EXPECT_TRUE(Get%(resource_name)sServiceId(kNewClientId, &service_id)); + EXPECT_EQ(kNewServiceId, service_id); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, + ExecuteImmediateCmd(*cmd, sizeof(temp))); +} +""" + else: + valid_test += """ EXPECT_TRUE(Get%(resource_name)s(kNewClientId) != NULL); } """ @@ -4460,7 +4685,17 @@ EXPECT_CALL(*gl_, %(gl_func_name)s(_, _)).Times(0); cmds::%(name)s* cmd = GetImmediateAs<cmds::%(name)s>(); SpecializedSetup<cmds::%(name)s, 0>(false); - cmd->Init(1, &client_%(resource_name)s_id_); + cmd->Init(1, &client_%(resource_name)s_id_);""" + if func.IsUnsafe(): + invalid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kInvalidArguments, + ExecuteImmediateCmd(*cmd, sizeof(&client_%(resource_name)s_id_))); + decoder_->set_unsafe_es3_apis_enabled(false); +} +""" + else: + invalid_test += """ EXPECT_EQ(error::kInvalidArguments, ExecuteImmediateCmd(*cmd, sizeof(&client_%(resource_name)s_id_))); } @@ -4744,10 +4979,25 @@ .Times(1); cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>(); SpecializedSetup<cmds::%(name)s, 0>(true); - cmd.Init(1, &client_%(resource_name)s_id_); + cmd.Init(1, &client_%(resource_name)s_id_);""" + if func.IsUnsafe(): + valid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true);""" + valid_test += """ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(client_%(resource_name)s_id_))); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError());""" + if func.IsUnsafe(): + valid_test += """ + EXPECT_FALSE(Get%(upper_resource_name)sServiceId( + client_%(resource_name)s_id_, NULL)); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, + ExecuteImmediateCmd(cmd, sizeof(client_%(resource_name)s_id_))); +} +""" + else: + valid_test += """ EXPECT_TRUE( Get%(upper_resource_name)s(client_%(resource_name)s_id_) == NULL); } @@ -4761,7 +5011,19 @@ cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>(); SpecializedSetup<cmds::%(name)s, 0>(false); GLuint temp = kInvalidClientId; - cmd.Init(1, &temp); + cmd.Init(1, &temp);""" + if func.IsUnsafe(): + invalid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(temp))); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, + ExecuteImmediateCmd(cmd, sizeof(temp))); +} +""" + else: + invalid_test += """ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } @@ -4775,8 +5037,20 @@ def WriteImmediateHandlerImplementation (self, func, file): """Overrriden from TypeHandler.""" - file.Write(" %sHelper(n, %s);\n" % - (func.original_name, func.GetLastOriginalArg().name)) + if func.IsUnsafe(): + file.Write(""" for (GLsizei ii = 0; ii < n; ++ii) { + GLuint service_id = 0; + if (group_->Get%(resource_type)sServiceId( + %(last_arg_name)s[ii], &service_id)) { + glDelete%(resource_type)ss(1, &service_id); + group_->Remove%(resource_type)sId(%(last_arg_name)s[ii]); + } + } +""" % { 'resource_type': func.GetInfo('resource_type'), + 'last_arg_name': func.GetLastOriginalArg().name }) + else: + file.Write(" %sHelper(n, %s);\n" % + (func.original_name, func.GetLastOriginalArg().name)) def WriteGLES2Implementation(self, func, file): """Overrriden from TypeHandler.""" @@ -5230,13 +5504,32 @@ invalid_test = """ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { - cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>(); + cmds::%(name)s& cmd = *GetImmediateAs<cmds::%(name)s>();""" + if func.IsUnsafe(): + invalid_test += """ + EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_any_args)s, _)).Times(1); +""" + else: + invalid_test += """ EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_any_args)s, _)).Times(0); +""" + invalid_test += """ SpecializedSetup<cmds::%(name)s, 0>(false); %(data_type)s temp[%(data_count)s] = { %(data_value)s, }; - cmd.Init(%(all_but_last_args)s, &temp[0]); + cmd.Init(%(all_but_last_args)s, &temp[0]);""" + if func.IsUnsafe(): + invalid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true); EXPECT_EQ(error::%(parse_result)s, - ExecuteImmediateCmd(cmd, sizeof(temp)));%(gl_error_test)s + ExecuteImmediateCmd(cmd, sizeof(temp))); + decoder_->set_unsafe_es3_apis_enabled(false); +} +""" + else: + invalid_test += """ + EXPECT_EQ(error::%(parse_result)s, + ExecuteImmediateCmd(cmd, sizeof(temp))); + %(gl_error_test)s } """ self.WriteInvalidUnitTest(func, file, invalid_test, extra, *extras) @@ -6026,9 +6319,18 @@ EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)); SpecializedSetup<cmds::%(name)s, 0>(true); cmds::%(name)s cmd; - cmd.Init(%(args)s%(comma)sshared_memory_id_, shared_memory_offset_); + cmd.Init(%(args)s%(comma)sshared_memory_id_, shared_memory_offset_);""" + if func.IsUnsafe(): + valid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true);""" + valid_test += """ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(GL_NO_ERROR, GetGLError());""" + if func.IsUnsafe(): + valid_test += """ + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd));""" + valid_test += """ } """ comma = "" @@ -6054,12 +6356,20 @@ invalid_test = """ TEST_P(%(test_name)s, %(name)sInvalidArgsBadSharedMemoryId) { EXPECT_CALL(*gl_, %(gl_func_name)s(%(gl_args)s)).Times(0); - SpecializedSetup<cmds::%(name)s, 0>(false); + SpecializedSetup<cmds::%(name)s, 0>(false);""" + if func.IsUnsafe(): + invalid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true);""" + invalid_test += """ cmds::%(name)s cmd; cmd.Init(%(args)s%(comma)skInvalidSharedMemoryId, shared_memory_offset_); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); cmd.Init(%(args)s%(comma)sshared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));""" + if func.IsUnsafe(): + invalid_test += """ + decoder_->set_unsafe_es3_apis_enabled(true);""" + invalid_test += """ } """ self.WriteValidUnitTest(func, file, invalid_test, { @@ -6082,6 +6392,10 @@ """ file.Write(code % {'func_name': func.name}) func.WriteHandlerValidation(file) + if func.IsUnsafe() and func.GetInfo('id_mapping'): + for id_type in func.GetInfo('id_mapping'): + file.Write(" group_->Get%sServiceId(%s, &%s);\n" % + (id_type, id_type.lower(), id_type.lower())) file.Write(" *result_dst = %s(%s);\n" % (func.GetGLFunctionName(), func.MakeOriginalArgString(""))) file.Write(" return error::kNoError;\n") @@ -8803,8 +9117,11 @@ self.generated_cpp_filenames.append(file.filename) def Format(generated_files): + formatter = "clang-format" + if platform.system() == "Windows": + formatter += ".bat" for filename in generated_files: - call(["clang-format", "-i", "-style=chromium", filename]) + call([formatter, "-i", "-style=chromium", filename]) def main(argv): """This is the main function."""
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 766ce56..bd41c8f 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -30,9 +30,15 @@ void GLES2BindRenderbuffer(GLenum target, GLuint renderbuffer) { gles2::GetGLContext()->BindRenderbuffer(target, renderbuffer); } +void GLES2BindSampler(GLuint unit, GLuint sampler) { + gles2::GetGLContext()->BindSampler(unit, sampler); +} void GLES2BindTexture(GLenum target, GLuint texture) { gles2::GetGLContext()->BindTexture(target, texture); } +void GLES2BindTransformFeedback(GLenum target, GLuint transformfeedback) { + gles2::GetGLContext()->BindTransformFeedback(target, transformfeedback); +} void GLES2BlendColor(GLclampf red, GLclampf green, GLclampf blue, @@ -167,12 +173,18 @@ void GLES2DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { gles2::GetGLContext()->DeleteRenderbuffers(n, renderbuffers); } +void GLES2DeleteSamplers(GLsizei n, const GLuint* samplers) { + gles2::GetGLContext()->DeleteSamplers(n, samplers); +} void GLES2DeleteShader(GLuint shader) { gles2::GetGLContext()->DeleteShader(shader); } void GLES2DeleteTextures(GLsizei n, const GLuint* textures) { gles2::GetGLContext()->DeleteTextures(n, textures); } +void GLES2DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) { + gles2::GetGLContext()->DeleteTransformFeedbacks(n, ids); +} void GLES2DepthFunc(GLenum func) { gles2::GetGLContext()->DepthFunc(func); } @@ -250,9 +262,15 @@ void GLES2GenRenderbuffers(GLsizei n, GLuint* renderbuffers) { gles2::GetGLContext()->GenRenderbuffers(n, renderbuffers); } +void GLES2GenSamplers(GLsizei n, GLuint* samplers) { + gles2::GetGLContext()->GenSamplers(n, samplers); +} void GLES2GenTextures(GLsizei n, GLuint* textures) { gles2::GetGLContext()->GenTextures(n, textures); } +void GLES2GenTransformFeedbacks(GLsizei n, GLuint* ids) { + gles2::GetGLContext()->GenTransformFeedbacks(n, ids); +} void GLES2GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, @@ -326,6 +344,12 @@ GLint* params) { gles2::GetGLContext()->GetRenderbufferParameteriv(target, pname, params); } +void GLES2GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) { + gles2::GetGLContext()->GetSamplerParameterfv(sampler, pname, params); +} +void GLES2GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) { + gles2::GetGLContext()->GetSamplerParameteriv(sampler, pname, params); +} void GLES2GetShaderiv(GLuint shader, GLenum pname, GLint* params) { gles2::GetGLContext()->GetShaderiv(shader, pname, params); } @@ -408,18 +432,27 @@ GLboolean GLES2IsRenderbuffer(GLuint renderbuffer) { return gles2::GetGLContext()->IsRenderbuffer(renderbuffer); } +GLboolean GLES2IsSampler(GLuint sampler) { + return gles2::GetGLContext()->IsSampler(sampler); +} GLboolean GLES2IsShader(GLuint shader) { return gles2::GetGLContext()->IsShader(shader); } GLboolean GLES2IsTexture(GLuint texture) { return gles2::GetGLContext()->IsTexture(texture); } +GLboolean GLES2IsTransformFeedback(GLuint transformfeedback) { + return gles2::GetGLContext()->IsTransformFeedback(transformfeedback); +} void GLES2LineWidth(GLfloat width) { gles2::GetGLContext()->LineWidth(width); } void GLES2LinkProgram(GLuint program) { gles2::GetGLContext()->LinkProgram(program); } +void GLES2PauseTransformFeedback() { + gles2::GetGLContext()->PauseTransformFeedback(); +} void GLES2PixelStorei(GLenum pname, GLint param) { gles2::GetGLContext()->PixelStorei(pname, param); } @@ -448,9 +481,28 @@ gles2::GetGLContext()->RenderbufferStorage(target, internalformat, width, height); } +void GLES2ResumeTransformFeedback() { + gles2::GetGLContext()->ResumeTransformFeedback(); +} void GLES2SampleCoverage(GLclampf value, GLboolean invert) { gles2::GetGLContext()->SampleCoverage(value, invert); } +void GLES2SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { + gles2::GetGLContext()->SamplerParameterf(sampler, pname, param); +} +void GLES2SamplerParameterfv(GLuint sampler, + GLenum pname, + const GLfloat* params) { + gles2::GetGLContext()->SamplerParameterfv(sampler, pname, params); +} +void GLES2SamplerParameteri(GLuint sampler, GLenum pname, GLint param) { + gles2::GetGLContext()->SamplerParameteri(sampler, pname, param); +} +void GLES2SamplerParameteriv(GLuint sampler, + GLenum pname, + const GLint* params) { + gles2::GetGLContext()->SamplerParameteriv(sampler, pname, params); +} void GLES2Scissor(GLint x, GLint y, GLsizei width, GLsizei height) { gles2::GetGLContext()->Scissor(x, y, width, height); } @@ -799,9 +851,15 @@ void GLES2BeginQueryEXT(GLenum target, GLuint id) { gles2::GetGLContext()->BeginQueryEXT(target, id); } +void GLES2BeginTransformFeedback(GLenum primitivemode) { + gles2::GetGLContext()->BeginTransformFeedback(primitivemode); +} void GLES2EndQueryEXT(GLenum target) { gles2::GetGLContext()->EndQueryEXT(target); } +void GLES2EndTransformFeedback() { + gles2::GetGLContext()->EndTransformFeedback(); +} void GLES2GetQueryivEXT(GLenum target, GLenum pname, GLint* params) { gles2::GetGLContext()->GetQueryivEXT(target, pname, params); } @@ -1124,10 +1182,18 @@ reinterpret_cast<GLES2FunctionPointer>(glBindRenderbuffer), }, { + "glBindSampler", + reinterpret_cast<GLES2FunctionPointer>(glBindSampler), + }, + { "glBindTexture", reinterpret_cast<GLES2FunctionPointer>(glBindTexture), }, { + "glBindTransformFeedback", + reinterpret_cast<GLES2FunctionPointer>(glBindTransformFeedback), + }, + { "glBlendColor", reinterpret_cast<GLES2FunctionPointer>(glBlendColor), }, @@ -1232,6 +1298,10 @@ reinterpret_cast<GLES2FunctionPointer>(glDeleteRenderbuffers), }, { + "glDeleteSamplers", + reinterpret_cast<GLES2FunctionPointer>(glDeleteSamplers), + }, + { "glDeleteShader", reinterpret_cast<GLES2FunctionPointer>(glDeleteShader), }, @@ -1240,6 +1310,10 @@ reinterpret_cast<GLES2FunctionPointer>(glDeleteTextures), }, { + "glDeleteTransformFeedbacks", + reinterpret_cast<GLES2FunctionPointer>(glDeleteTransformFeedbacks), + }, + { "glDepthFunc", reinterpret_cast<GLES2FunctionPointer>(glDepthFunc), }, @@ -1320,10 +1394,18 @@ reinterpret_cast<GLES2FunctionPointer>(glGenRenderbuffers), }, { + "glGenSamplers", + reinterpret_cast<GLES2FunctionPointer>(glGenSamplers), + }, + { "glGenTextures", reinterpret_cast<GLES2FunctionPointer>(glGenTextures), }, { + "glGenTransformFeedbacks", + reinterpret_cast<GLES2FunctionPointer>(glGenTransformFeedbacks), + }, + { "glGetActiveAttrib", reinterpret_cast<GLES2FunctionPointer>(glGetActiveAttrib), }, @@ -1381,6 +1463,14 @@ reinterpret_cast<GLES2FunctionPointer>(glGetRenderbufferParameteriv), }, { + "glGetSamplerParameterfv", + reinterpret_cast<GLES2FunctionPointer>(glGetSamplerParameterfv), + }, + { + "glGetSamplerParameteriv", + reinterpret_cast<GLES2FunctionPointer>(glGetSamplerParameteriv), + }, + { "glGetShaderiv", reinterpret_cast<GLES2FunctionPointer>(glGetShaderiv), }, @@ -1465,6 +1555,10 @@ reinterpret_cast<GLES2FunctionPointer>(glIsRenderbuffer), }, { + "glIsSampler", + reinterpret_cast<GLES2FunctionPointer>(glIsSampler), + }, + { "glIsShader", reinterpret_cast<GLES2FunctionPointer>(glIsShader), }, @@ -1473,6 +1567,10 @@ reinterpret_cast<GLES2FunctionPointer>(glIsTexture), }, { + "glIsTransformFeedback", + reinterpret_cast<GLES2FunctionPointer>(glIsTransformFeedback), + }, + { "glLineWidth", reinterpret_cast<GLES2FunctionPointer>(glLineWidth), }, @@ -1481,6 +1579,10 @@ reinterpret_cast<GLES2FunctionPointer>(glLinkProgram), }, { + "glPauseTransformFeedback", + reinterpret_cast<GLES2FunctionPointer>(glPauseTransformFeedback), + }, + { "glPixelStorei", reinterpret_cast<GLES2FunctionPointer>(glPixelStorei), }, @@ -1505,10 +1607,30 @@ reinterpret_cast<GLES2FunctionPointer>(glRenderbufferStorage), }, { + "glResumeTransformFeedback", + reinterpret_cast<GLES2FunctionPointer>(glResumeTransformFeedback), + }, + { "glSampleCoverage", reinterpret_cast<GLES2FunctionPointer>(glSampleCoverage), }, { + "glSamplerParameterf", + reinterpret_cast<GLES2FunctionPointer>(glSamplerParameterf), + }, + { + "glSamplerParameterfv", + reinterpret_cast<GLES2FunctionPointer>(glSamplerParameterfv), + }, + { + "glSamplerParameteri", + reinterpret_cast<GLES2FunctionPointer>(glSamplerParameteri), + }, + { + "glSamplerParameteriv", + reinterpret_cast<GLES2FunctionPointer>(glSamplerParameteriv), + }, + { "glScissor", reinterpret_cast<GLES2FunctionPointer>(glScissor), }, @@ -1820,10 +1942,18 @@ reinterpret_cast<GLES2FunctionPointer>(glBeginQueryEXT), }, { + "glBeginTransformFeedback", + reinterpret_cast<GLES2FunctionPointer>(glBeginTransformFeedback), + }, + { "glEndQueryEXT", reinterpret_cast<GLES2FunctionPointer>(glEndQueryEXT), }, { + "glEndTransformFeedback", + reinterpret_cast<GLES2FunctionPointer>(glEndTransformFeedback), + }, + { "glGetQueryivEXT", reinterpret_cast<GLES2FunctionPointer>(glGetQueryivEXT), },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 7b2faae..8d4553a 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -57,6 +57,13 @@ } } +void BindSampler(GLuint unit, GLuint sampler) { + gles2::cmds::BindSampler* c = GetCmdSpace<gles2::cmds::BindSampler>(); + if (c) { + c->Init(unit, sampler); + } +} + void BindTexture(GLenum target, GLuint texture) { gles2::cmds::BindTexture* c = GetCmdSpace<gles2::cmds::BindTexture>(); if (c) { @@ -64,6 +71,14 @@ } } +void BindTransformFeedback(GLenum target, GLuint transformfeedback) { + gles2::cmds::BindTransformFeedback* c = + GetCmdSpace<gles2::cmds::BindTransformFeedback>(); + if (c) { + c->Init(target, transformfeedback); + } +} + void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { gles2::cmds::BlendColor* c = GetCmdSpace<gles2::cmds::BlendColor>(); if (c) { @@ -342,6 +357,15 @@ } } +void DeleteSamplersImmediate(GLsizei n, const GLuint* samplers) { + const uint32_t size = gles2::cmds::DeleteSamplersImmediate::ComputeSize(n); + gles2::cmds::DeleteSamplersImmediate* c = + GetImmediateCmdSpaceTotalSize<gles2::cmds::DeleteSamplersImmediate>(size); + if (c) { + c->Init(n, samplers); + } +} + void DeleteShader(GLuint shader) { gles2::cmds::DeleteShader* c = GetCmdSpace<gles2::cmds::DeleteShader>(); if (c) { @@ -358,6 +382,17 @@ } } +void DeleteTransformFeedbacksImmediate(GLsizei n, const GLuint* ids) { + const uint32_t size = + gles2::cmds::DeleteTransformFeedbacksImmediate::ComputeSize(n); + gles2::cmds::DeleteTransformFeedbacksImmediate* c = + GetImmediateCmdSpaceTotalSize< + gles2::cmds::DeleteTransformFeedbacksImmediate>(size); + if (c) { + c->Init(n, ids); + } +} + void DepthFunc(GLenum func) { gles2::cmds::DepthFunc* c = GetCmdSpace<gles2::cmds::DepthFunc>(); if (c) { @@ -524,6 +559,15 @@ } } +void GenSamplersImmediate(GLsizei n, GLuint* samplers) { + const uint32_t size = gles2::cmds::GenSamplersImmediate::ComputeSize(n); + gles2::cmds::GenSamplersImmediate* c = + GetImmediateCmdSpaceTotalSize<gles2::cmds::GenSamplersImmediate>(size); + if (c) { + c->Init(n, samplers); + } +} + void GenTexturesImmediate(GLsizei n, GLuint* textures) { const uint32_t size = gles2::cmds::GenTexturesImmediate::ComputeSize(n); gles2::cmds::GenTexturesImmediate* c = @@ -533,6 +577,17 @@ } } +void GenTransformFeedbacksImmediate(GLsizei n, GLuint* ids) { + const uint32_t size = + gles2::cmds::GenTransformFeedbacksImmediate::ComputeSize(n); + gles2::cmds::GenTransformFeedbacksImmediate* c = + GetImmediateCmdSpaceTotalSize< + gles2::cmds::GenTransformFeedbacksImmediate>(size); + if (c) { + c->Init(n, ids); + } +} + void GetActiveAttrib(GLuint program, GLuint index, uint32_t name_bucket_id, @@ -677,6 +732,28 @@ } } +void GetSamplerParameterfv(GLuint sampler, + GLenum pname, + uint32_t params_shm_id, + uint32_t params_shm_offset) { + gles2::cmds::GetSamplerParameterfv* c = + GetCmdSpace<gles2::cmds::GetSamplerParameterfv>(); + if (c) { + c->Init(sampler, pname, params_shm_id, params_shm_offset); + } +} + +void GetSamplerParameteriv(GLuint sampler, + GLenum pname, + uint32_t params_shm_id, + uint32_t params_shm_offset) { + gles2::cmds::GetSamplerParameteriv* c = + GetCmdSpace<gles2::cmds::GetSamplerParameteriv>(); + if (c) { + c->Init(sampler, pname, params_shm_id, params_shm_offset); + } +} + void GetShaderiv(GLuint shader, GLenum pname, uint32_t params_shm_id, @@ -886,6 +963,15 @@ } } +void IsSampler(GLuint sampler, + uint32_t result_shm_id, + uint32_t result_shm_offset) { + gles2::cmds::IsSampler* c = GetCmdSpace<gles2::cmds::IsSampler>(); + if (c) { + c->Init(sampler, result_shm_id, result_shm_offset); + } +} + void IsShader(GLuint shader, uint32_t result_shm_id, uint32_t result_shm_offset) { @@ -904,6 +990,16 @@ } } +void IsTransformFeedback(GLuint transformfeedback, + uint32_t result_shm_id, + uint32_t result_shm_offset) { + gles2::cmds::IsTransformFeedback* c = + GetCmdSpace<gles2::cmds::IsTransformFeedback>(); + if (c) { + c->Init(transformfeedback, result_shm_id, result_shm_offset); + } +} + void LineWidth(GLfloat width) { gles2::cmds::LineWidth* c = GetCmdSpace<gles2::cmds::LineWidth>(); if (c) { @@ -918,6 +1014,14 @@ } } +void PauseTransformFeedback() { + gles2::cmds::PauseTransformFeedback* c = + GetCmdSpace<gles2::cmds::PauseTransformFeedback>(); + if (c) { + c->Init(); + } +} + void PixelStorei(GLenum pname, GLint param) { gles2::cmds::PixelStorei* c = GetCmdSpace<gles2::cmds::PixelStorei>(); if (c) { @@ -976,6 +1080,14 @@ } } +void ResumeTransformFeedback() { + gles2::cmds::ResumeTransformFeedback* c = + GetCmdSpace<gles2::cmds::ResumeTransformFeedback>(); + if (c) { + c->Init(); + } +} + void SampleCoverage(GLclampf value, GLboolean invert) { gles2::cmds::SampleCoverage* c = GetCmdSpace<gles2::cmds::SampleCoverage>(); if (c) { @@ -983,6 +1095,46 @@ } } +void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { + gles2::cmds::SamplerParameterf* c = + GetCmdSpace<gles2::cmds::SamplerParameterf>(); + if (c) { + c->Init(sampler, pname, param); + } +} + +void SamplerParameterfvImmediate(GLuint sampler, + GLenum pname, + const GLfloat* params) { + const uint32_t size = gles2::cmds::SamplerParameterfvImmediate::ComputeSize(); + gles2::cmds::SamplerParameterfvImmediate* c = + GetImmediateCmdSpaceTotalSize<gles2::cmds::SamplerParameterfvImmediate>( + size); + if (c) { + c->Init(sampler, pname, params); + } +} + +void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) { + gles2::cmds::SamplerParameteri* c = + GetCmdSpace<gles2::cmds::SamplerParameteri>(); + if (c) { + c->Init(sampler, pname, param); + } +} + +void SamplerParameterivImmediate(GLuint sampler, + GLenum pname, + const GLint* params) { + const uint32_t size = gles2::cmds::SamplerParameterivImmediate::ComputeSize(); + gles2::cmds::SamplerParameterivImmediate* c = + GetImmediateCmdSpaceTotalSize<gles2::cmds::SamplerParameterivImmediate>( + size); + if (c) { + c->Init(sampler, pname, params); + } +} + void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) { gles2::cmds::Scissor* c = GetCmdSpace<gles2::cmds::Scissor>(); if (c) { @@ -1689,6 +1841,14 @@ } } +void BeginTransformFeedback(GLenum primitivemode) { + gles2::cmds::BeginTransformFeedback* c = + GetCmdSpace<gles2::cmds::BeginTransformFeedback>(); + if (c) { + c->Init(primitivemode); + } +} + void EndQueryEXT(GLenum target, GLuint submit_count) { gles2::cmds::EndQueryEXT* c = GetCmdSpace<gles2::cmds::EndQueryEXT>(); if (c) { @@ -1696,6 +1856,14 @@ } } +void EndTransformFeedback() { + gles2::cmds::EndTransformFeedback* c = + GetCmdSpace<gles2::cmds::EndTransformFeedback>(); + if (c) { + c->Init(); + } +} + void InsertEventMarkerEXT(GLuint bucket_id) { gles2::cmds::InsertEventMarkerEXT* c = GetCmdSpace<gles2::cmds::InsertEventMarkerEXT>();
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 19a005f..88b9c72 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -2314,6 +2314,14 @@ const GLuint* /* valuebuffers */) { } +void GLES2Implementation::GenSamplersHelper( + GLsizei /* n */, const GLuint* /* samplers */) { +} + +void GLES2Implementation::GenTransformFeedbacksHelper( + GLsizei /* n */, const GLuint* /* transformfeedbacks */) { +} + // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id // generates a new resource. On newer versions of OpenGL they don't. The code // related to binding below will need to change if we switch to the new OpenGL @@ -2684,6 +2692,39 @@ } } +void GLES2Implementation::DeleteSamplersStub( + GLsizei n, const GLuint* samplers) { + helper_->DeleteSamplersImmediate(n, samplers); +} + +void GLES2Implementation::DeleteSamplersHelper( + GLsizei n, const GLuint* samplers) { + if (!GetIdHandler(id_namespaces::kSamplers)->FreeIds( + this, n, samplers, &GLES2Implementation::DeleteSamplersStub)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteSamplers", "id not created by this context."); + return; + } +} + +void GLES2Implementation::DeleteTransformFeedbacksStub( + GLsizei n, const GLuint* transformfeedbacks) { + helper_->DeleteTransformFeedbacksImmediate(n, transformfeedbacks); +} + +void GLES2Implementation::DeleteTransformFeedbacksHelper( + GLsizei n, const GLuint* transformfeedbacks) { + if (!GetIdHandler(id_namespaces::kTransformFeedbacks)->FreeIds( + this, n, transformfeedbacks, + &GLES2Implementation::DeleteTransformFeedbacksStub)) { + SetGLError( + GL_INVALID_VALUE, + "glDeleteTransformFeedbacks", "id not created by this context."); + return; + } +} + void GLES2Implementation::DeleteValuebuffersCHROMIUMStub( GLsizei n, const GLuint* valuebuffers) { @@ -3985,6 +4026,18 @@ return true; } +bool GLES2Implementation::GetSamplerParameterfvHelper( + GLuint /* sampler */, GLenum /* pname */, GLfloat* /* params */) { + // TODO(zmo): Implement client side caching. + return false; +} + +bool GLES2Implementation::GetSamplerParameterivHelper( + GLuint /* sampler */, GLenum /* pname */, GLint* /* params */) { + // TODO(zmo): Implement client side caching. + return false; +} + // 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 e473006..7d17d64 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -431,6 +431,8 @@ bool IsVertexArrayReservedId(GLuint id) { return false; } bool IsProgramReservedId(GLuint id) { return false; } bool IsValuebufferReservedId(GLuint id) { return false; } + bool IsSamplerReservedId(GLuint id) { return false; } + bool IsTransformFeedbackReservedId(GLuint id) { return false; } void BindBufferHelper(GLenum target, GLuint buffer); void BindFramebufferHelper(GLenum target, GLuint framebuffer); @@ -453,6 +455,8 @@ void GenVertexArraysOESHelper(GLsizei n, const GLuint* arrays); void GenQueriesEXTHelper(GLsizei n, const GLuint* queries); void GenValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* valuebuffers); + void GenSamplersHelper(GLsizei n, const GLuint* samplers); + void GenTransformFeedbacksHelper(GLsizei n, const GLuint* transformfeedbacks); void DeleteBuffersHelper(GLsizei n, const GLuint* buffers); void DeleteFramebuffersHelper(GLsizei n, const GLuint* framebuffers); @@ -463,6 +467,9 @@ void DeleteQueriesEXTHelper(GLsizei n, const GLuint* queries); void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* arrays); void DeleteValuebuffersCHROMIUMHelper(GLsizei n, const GLuint* valuebuffers); + void DeleteSamplersHelper(GLsizei n, const GLuint* samplers); + void DeleteTransformFeedbacksHelper( + GLsizei n, const GLuint* transformfeedbacks); void DeleteBuffersStub(GLsizei n, const GLuint* buffers); void DeleteFramebuffersStub(GLsizei n, const GLuint* framebuffers); @@ -472,6 +479,9 @@ void DeleteShaderStub(GLsizei n, const GLuint* shaders); void DeleteVertexArraysOESStub(GLsizei n, const GLuint* arrays); void DeleteValuebuffersCHROMIUMStub(GLsizei n, const GLuint* valuebuffers); + void DeleteSamplersStub(GLsizei n, const GLuint* samplers); + void DeleteTransformFeedbacksStub( + GLsizei n, const GLuint* transformfeedbacks); void BufferDataHelper( GLenum target, GLsizeiptr size, const void* data, GLenum usage); @@ -520,6 +530,10 @@ GLenum target, GLenum format, GLenum pname, GLsizei bufSize, GLint* params); bool GetProgramivHelper(GLuint program, GLenum pname, GLint* params); + bool GetSamplerParameterfvHelper( + GLuint sampler, GLenum pname, GLfloat* params); + bool GetSamplerParameterivHelper( + GLuint sampler, GLenum pname, GLint* params); bool GetRenderbufferParameterivHelper( GLenum target, GLenum pname, GLint* params); bool GetShaderivHelper(GLuint shader, GLenum pname, GLint* params);
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 7d03d88..3a5253a 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -27,8 +27,12 @@ void BindRenderbuffer(GLenum target, GLuint renderbuffer) override; +void BindSampler(GLuint unit, GLuint sampler) override; + void BindTexture(GLenum target, GLuint texture) override; +void BindTransformFeedback(GLenum target, GLuint transformfeedback) override; + void BlendColor(GLclampf red, GLclampf green, GLclampf blue, @@ -132,10 +136,14 @@ void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) override; +void DeleteSamplers(GLsizei n, const GLuint* samplers) override; + void DeleteShader(GLuint shader) override; void DeleteTextures(GLsizei n, const GLuint* textures) override; +void DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) override; + void DepthFunc(GLenum func) override; void DepthMask(GLboolean flag) override; @@ -186,8 +194,12 @@ void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override; +void GenSamplers(GLsizei n, GLuint* samplers) override; + void GenTextures(GLsizei n, GLuint* textures) override; +void GenTransformFeedbacks(GLsizei n, GLuint* ids) override; + void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, @@ -243,6 +255,14 @@ GLenum pname, GLint* params) override; +void GetSamplerParameterfv(GLuint sampler, + GLenum pname, + GLfloat* params) override; + +void GetSamplerParameteriv(GLuint sampler, + GLenum pname, + GLint* params) override; + void GetShaderiv(GLuint shader, GLenum pname, GLint* params) override; void GetShaderInfoLog(GLuint shader, @@ -300,14 +320,20 @@ GLboolean IsRenderbuffer(GLuint renderbuffer) override; +GLboolean IsSampler(GLuint sampler) override; + GLboolean IsShader(GLuint shader) override; GLboolean IsTexture(GLuint texture) override; +GLboolean IsTransformFeedback(GLuint transformfeedback) override; + void LineWidth(GLfloat width) override; void LinkProgram(GLuint program) override; +void PauseTransformFeedback() override; + void PixelStorei(GLenum pname, GLint param) override; void PolygonOffset(GLfloat factor, GLfloat units) override; @@ -329,8 +355,22 @@ GLsizei width, GLsizei height) override; +void ResumeTransformFeedback() override; + void SampleCoverage(GLclampf value, GLboolean invert) override; +void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) override; + +void SamplerParameterfv(GLuint sampler, + GLenum pname, + const GLfloat* params) override; + +void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) override; + +void SamplerParameteriv(GLuint sampler, + GLenum pname, + const GLint* params) override; + void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) override; void ShaderBinary(GLsizei n, @@ -599,8 +639,12 @@ void BeginQueryEXT(GLenum target, GLuint id) override; +void BeginTransformFeedback(GLenum primitivemode) override; + void EndQueryEXT(GLenum target) override; +void EndTransformFeedback() override; + void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) override; void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override;
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index d7a45ce..e7ef769 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -62,6 +62,14 @@ CheckGLError(); } +void GLES2Implementation::BindSampler(GLuint unit, GLuint sampler) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindSampler(" << unit << ", " + << sampler << ")"); + helper_->BindSampler(unit, sampler); + CheckGLError(); +} + void GLES2Implementation::BindTexture(GLenum target, GLuint texture) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindTexture(" @@ -75,6 +83,16 @@ CheckGLError(); } +void GLES2Implementation::BindTransformFeedback(GLenum target, + GLuint transformfeedback) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBindTransformFeedback(" + << GLES2Util::GetStringTransformFeedbackBindTarget(target) + << ", " << transformfeedback << ")"); + helper_->BindTransformFeedback(target, transformfeedback); + CheckGLError(); +} + void GLES2Implementation::BlendColor(GLclampf red, GLclampf green, GLclampf blue, @@ -397,6 +415,28 @@ CheckGLError(); } +void GLES2Implementation::DeleteSamplers(GLsizei n, const GLuint* samplers) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteSamplers(" << n << ", " + << static_cast<const void*>(samplers) << ")"); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << samplers[i]); + } + }); + GPU_CLIENT_DCHECK_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + DCHECK(samplers[i] != 0); + } + }); + if (n < 0) { + SetGLError(GL_INVALID_VALUE, "glDeleteSamplers", "n < 0"); + return; + } + DeleteSamplersHelper(n, samplers); + CheckGLError(); +} + void GLES2Implementation::DeleteShader(GLuint shader) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteShader(" << shader << ")"); @@ -427,6 +467,29 @@ CheckGLError(); } +void GLES2Implementation::DeleteTransformFeedbacks(GLsizei n, + const GLuint* ids) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDeleteTransformFeedbacks(" << n + << ", " << static_cast<const void*>(ids) << ")"); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << ids[i]); + } + }); + GPU_CLIENT_DCHECK_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + DCHECK(ids[i] != 0); + } + }); + if (n < 0) { + SetGLError(GL_INVALID_VALUE, "glDeleteTransformFeedbacks", "n < 0"); + return; + } + DeleteTransformFeedbacksHelper(n, ids); + CheckGLError(); +} + void GLES2Implementation::DepthFunc(GLenum func) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDepthFunc(" @@ -588,6 +651,27 @@ CheckGLError(); } +void GLES2Implementation::GenSamplers(GLsizei n, GLuint* samplers) { + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenSamplers(" << n << ", " + << static_cast<const void*>(samplers) << ")"); + if (n < 0) { + SetGLError(GL_INVALID_VALUE, "glGenSamplers", "n < 0"); + return; + } + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GetIdHandler(id_namespaces::kSamplers)->MakeIds(this, 0, n, samplers); + GenSamplersHelper(n, samplers); + helper_->GenSamplersImmediate(n, samplers); + if (share_group_->bind_generates_resource()) + helper_->CommandBufferHelper::Flush(); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << samplers[i]); + } + }); + CheckGLError(); +} + void GLES2Implementation::GenTextures(GLsizei n, GLuint* textures) { GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenTextures(" << n << ", " << static_cast<const void*>(textures) << ")"); @@ -609,6 +693,27 @@ CheckGLError(); } +void GLES2Implementation::GenTransformFeedbacks(GLsizei n, GLuint* ids) { + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenTransformFeedbacks(" << n + << ", " << static_cast<const void*>(ids) << ")"); + if (n < 0) { + SetGLError(GL_INVALID_VALUE, "glGenTransformFeedbacks", "n < 0"); + return; + } + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GetIdHandler(id_namespaces::kTransformFeedbacks)->MakeIds(this, 0, n, ids); + GenTransformFeedbacksHelper(n, ids); + helper_->GenTransformFeedbacksImmediate(n, ids); + if (share_group_->bind_generates_resource()) + helper_->CommandBufferHelper::Flush(); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (GLsizei i = 0; i < n; ++i) { + GPU_CLIENT_LOG(" " << i << ": " << ids[i]); + } + }); + CheckGLError(); +} + void GLES2Implementation::GetBooleanv(GLenum pname, GLboolean* params) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLboolean, params); @@ -874,6 +979,65 @@ }); CheckGLError(); } +void GLES2Implementation::GetSamplerParameterfv(GLuint sampler, + GLenum pname, + GLfloat* params) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetSamplerParameterfv(" + << sampler << ", " + << GLES2Util::GetStringSamplerParameter(pname) << ", " + << static_cast<const void*>(params) << ")"); + TRACE_EVENT0("gpu", "GLES2Implementation::GetSamplerParameterfv"); + if (GetSamplerParameterfvHelper(sampler, pname, params)) { + return; + } + typedef cmds::GetSamplerParameterfv::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return; + } + result->SetNumResults(0); + helper_->GetSamplerParameterfv(sampler, pname, GetResultShmId(), + GetResultShmOffset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + CheckGLError(); +} +void GLES2Implementation::GetSamplerParameteriv(GLuint sampler, + GLenum pname, + GLint* params) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetSamplerParameteriv(" + << sampler << ", " + << GLES2Util::GetStringSamplerParameter(pname) << ", " + << static_cast<const void*>(params) << ")"); + TRACE_EVENT0("gpu", "GLES2Implementation::GetSamplerParameteriv"); + if (GetSamplerParameterivHelper(sampler, pname, params)) { + return; + } + typedef cmds::GetSamplerParameteriv::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return; + } + result->SetNumResults(0); + helper_->GetSamplerParameteriv(sampler, pname, GetResultShmId(), + GetResultShmOffset()); + WaitForCmd(); + result->CopyResult(params); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + CheckGLError(); +} void GLES2Implementation::GetShaderiv(GLuint shader, GLenum pname, GLint* params) { @@ -1154,6 +1318,24 @@ return result_value; } +GLboolean GLES2Implementation::IsSampler(GLuint sampler) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + TRACE_EVENT0("gpu", "GLES2Implementation::IsSampler"); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsSampler(" << sampler << ")"); + typedef cmds::IsSampler::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return GL_FALSE; + } + *result = 0; + helper_->IsSampler(sampler, GetResultShmId(), GetResultShmOffset()); + WaitForCmd(); + GLboolean result_value = *result != 0; + GPU_CLIENT_LOG("returned " << result_value); + CheckGLError(); + return result_value; +} + GLboolean GLES2Implementation::IsShader(GLuint shader) { GPU_CLIENT_SINGLE_THREAD_CHECK(); TRACE_EVENT0("gpu", "GLES2Implementation::IsShader"); @@ -1190,6 +1372,26 @@ return result_value; } +GLboolean GLES2Implementation::IsTransformFeedback(GLuint transformfeedback) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + TRACE_EVENT0("gpu", "GLES2Implementation::IsTransformFeedback"); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glIsTransformFeedback(" + << transformfeedback << ")"); + typedef cmds::IsTransformFeedback::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return GL_FALSE; + } + *result = 0; + helper_->IsTransformFeedback(transformfeedback, GetResultShmId(), + GetResultShmOffset()); + WaitForCmd(); + GLboolean result_value = *result != 0; + GPU_CLIENT_LOG("returned " << result_value); + CheckGLError(); + return result_value; +} + void GLES2Implementation::LineWidth(GLfloat width) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLineWidth(" << width << ")"); @@ -1197,6 +1399,14 @@ CheckGLError(); } +void GLES2Implementation::PauseTransformFeedback() { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPauseTransformFeedback(" + << ")"); + helper_->PauseTransformFeedback(); + CheckGLError(); +} + void GLES2Implementation::PolygonOffset(GLfloat factor, GLfloat units) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glPolygonOffset(" << factor << ", " @@ -1242,6 +1452,14 @@ CheckGLError(); } +void GLES2Implementation::ResumeTransformFeedback() { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glResumeTransformFeedback(" + << ")"); + helper_->ResumeTransformFeedback(); + CheckGLError(); +} + void GLES2Implementation::SampleCoverage(GLclampf value, GLboolean invert) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSampleCoverage(" << value << ", " @@ -1250,6 +1468,52 @@ CheckGLError(); } +void GLES2Implementation::SamplerParameterf(GLuint sampler, + GLenum pname, + GLfloat param) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSamplerParameterf(" << sampler + << ", " << GLES2Util::GetStringSamplerParameter(pname) + << ", " << param << ")"); + helper_->SamplerParameterf(sampler, pname, param); + CheckGLError(); +} + +void GLES2Implementation::SamplerParameterfv(GLuint sampler, + GLenum pname, + const GLfloat* params) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSamplerParameterfv(" << sampler + << ", " << GLES2Util::GetStringSamplerParameter(pname) + << ", " << static_cast<const void*>(params) << ")"); + GPU_CLIENT_LOG("values: " << params[0]); + helper_->SamplerParameterfvImmediate(sampler, pname, params); + CheckGLError(); +} + +void GLES2Implementation::SamplerParameteri(GLuint sampler, + GLenum pname, + GLint param) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSamplerParameteri(" << sampler + << ", " << GLES2Util::GetStringSamplerParameter(pname) + << ", " << param << ")"); + helper_->SamplerParameteri(sampler, pname, param); + CheckGLError(); +} + +void GLES2Implementation::SamplerParameteriv(GLuint sampler, + GLenum pname, + const GLint* params) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glSamplerParameteriv(" << sampler + << ", " << GLES2Util::GetStringSamplerParameter(pname) + << ", " << static_cast<const void*>(params) << ")"); + GPU_CLIENT_LOG("values: " << params[0]); + helper_->SamplerParameterivImmediate(sampler, pname, params); + CheckGLError(); +} + void GLES2Implementation::Scissor(GLint x, GLint y, GLsizei width, @@ -2391,6 +2655,23 @@ CheckGLError(); } +void GLES2Implementation::BeginTransformFeedback(GLenum primitivemode) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBeginTransformFeedback(" + << GLES2Util::GetStringTransformFeedbackPrimitiveMode( + primitivemode) << ")"); + helper_->BeginTransformFeedback(primitivemode); + CheckGLError(); +} + +void GLES2Implementation::EndTransformFeedback() { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glEndTransformFeedback(" + << ")"); + helper_->EndTransformFeedback(); + CheckGLError(); +} + void GLES2Implementation::GenVertexArraysOES(GLsizei n, GLuint* arrays) { GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGenVertexArraysOES(" << n << ", " << static_cast<const void*>(arrays) << ")");
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index d772b8e..3d0f1b0 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -384,7 +384,9 @@ static const GLuint kFramebuffersStartId = 1; static const GLuint kProgramsAndShadersStartId = 1; static const GLuint kRenderbuffersStartId = 1; + static const GLuint kSamplersStartId = 1; static const GLuint kTexturesStartId = 1; + static const GLuint kTransformFeedbacksStartId = 1; static const GLuint kQueriesStartId = 1; static const GLuint kVertexArraysStartId = 1; static const GLuint kValuebuffersStartId = 1; @@ -754,7 +756,9 @@ const GLuint GLES2ImplementationTest::kFramebuffersStartId; const GLuint GLES2ImplementationTest::kProgramsAndShadersStartId; const GLuint GLES2ImplementationTest::kRenderbuffersStartId; +const GLuint GLES2ImplementationTest::kSamplersStartId; const GLuint GLES2ImplementationTest::kTexturesStartId; +const GLuint GLES2ImplementationTest::kTransformFeedbacksStartId; const GLuint GLES2ImplementationTest::kQueriesStartId; const GLuint GLES2ImplementationTest::kVertexArraysStartId; const GLuint GLES2ImplementationTest::kValuebuffersStartId;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 3d0eaa2..f501cd9 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -67,6 +67,28 @@ EXPECT_TRUE(NoCommandsWritten()); } +TEST_F(GLES2ImplementationTest, BindSampler) { + struct Cmds { + cmds::BindSampler cmd; + }; + Cmds expected; + expected.cmd.Init(1, 2); + + gl_->BindSampler(1, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, BindTransformFeedback) { + struct Cmds { + cmds::BindTransformFeedback cmd; + }; + Cmds expected; + expected.cmd.Init(GL_TRANSFORM_FEEDBACK, 2); + + gl_->BindTransformFeedback(GL_TRANSFORM_FEEDBACK, 2); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, BlendColor) { struct Cmds { cmds::BlendColor cmd; @@ -312,6 +334,20 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, DeleteSamplers) { + GLuint ids[2] = {kSamplersStartId, kSamplersStartId + 1}; + struct Cmds { + cmds::DeleteSamplersImmediate del; + GLuint data[2]; + }; + Cmds expected; + expected.del.Init(arraysize(ids), &ids[0]); + expected.data[0] = kSamplersStartId; + expected.data[1] = kSamplersStartId + 1; + gl_->DeleteSamplers(arraysize(ids), &ids[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, DeleteShader) { struct Cmds { cmds::DeleteShader cmd; @@ -337,6 +373,20 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, DeleteTransformFeedbacks) { + GLuint ids[2] = {kTransformFeedbacksStartId, kTransformFeedbacksStartId + 1}; + struct Cmds { + cmds::DeleteTransformFeedbacksImmediate del; + GLuint data[2]; + }; + Cmds expected; + expected.del.Init(arraysize(ids), &ids[0]); + expected.data[0] = kTransformFeedbacksStartId; + expected.data[1] = kTransformFeedbacksStartId + 1; + gl_->DeleteTransformFeedbacks(arraysize(ids), &ids[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, DepthFunc) { struct Cmds { cmds::DepthFunc cmd; @@ -543,6 +593,24 @@ EXPECT_EQ(kRenderbuffersStartId + 1, ids[1]); } +TEST_F(GLES2ImplementationTest, GenSamplers) { + GLuint ids[2] = { + 0, + }; + struct Cmds { + cmds::GenSamplersImmediate gen; + GLuint data[2]; + }; + Cmds expected; + expected.gen.Init(arraysize(ids), &ids[0]); + expected.data[0] = kSamplersStartId; + expected.data[1] = kSamplersStartId + 1; + gl_->GenSamplers(arraysize(ids), &ids[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(kSamplersStartId, ids[0]); + EXPECT_EQ(kSamplersStartId + 1, ids[1]); +} + TEST_F(GLES2ImplementationTest, GenTextures) { GLuint ids[2] = { 0, @@ -560,6 +628,24 @@ EXPECT_EQ(kTexturesStartId, ids[0]); EXPECT_EQ(kTexturesStartId + 1, ids[1]); } + +TEST_F(GLES2ImplementationTest, GenTransformFeedbacks) { + GLuint ids[2] = { + 0, + }; + struct Cmds { + cmds::GenTransformFeedbacksImmediate gen; + GLuint data[2]; + }; + Cmds expected; + expected.gen.Init(arraysize(ids), &ids[0]); + expected.data[0] = kTransformFeedbacksStartId; + expected.data[1] = kTransformFeedbacksStartId + 1; + gl_->GenTransformFeedbacks(arraysize(ids), &ids[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(kTransformFeedbacksStartId, ids[0]); + EXPECT_EQ(kTransformFeedbacksStartId + 1, ids[1]); +} // TODO: Implement unit test for GetActiveAttrib // TODO: Implement unit test for GetActiveUniform // TODO: Implement unit test for GetAttachedShaders @@ -707,6 +793,40 @@ EXPECT_EQ(static_cast<Result::Type>(1), result); } +TEST_F(GLES2ImplementationTest, GetSamplerParameterfv) { + struct Cmds { + cmds::GetSamplerParameterfv cmd; + }; + typedef cmds::GetSamplerParameterfv::Result Result; + Result::Type result = 0; + Cmds expected; + ExpectedMemoryInfo result1 = GetExpectedResultMemory(4); + expected.cmd.Init(123, GL_TEXTURE_MAG_FILTER, result1.id, result1.offset); + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result1.ptr, SizedResultHelper<Result::Type>(1))) + .RetiresOnSaturation(); + gl_->GetSamplerParameterfv(123, GL_TEXTURE_MAG_FILTER, &result); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(static_cast<Result::Type>(1), result); +} + +TEST_F(GLES2ImplementationTest, GetSamplerParameteriv) { + struct Cmds { + cmds::GetSamplerParameteriv cmd; + }; + typedef cmds::GetSamplerParameteriv::Result Result; + Result::Type result = 0; + Cmds expected; + ExpectedMemoryInfo result1 = GetExpectedResultMemory(4); + expected.cmd.Init(123, GL_TEXTURE_MAG_FILTER, result1.id, result1.offset); + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result1.ptr, SizedResultHelper<Result::Type>(1))) + .RetiresOnSaturation(); + gl_->GetSamplerParameteriv(123, GL_TEXTURE_MAG_FILTER, &result); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(static_cast<Result::Type>(1), result); +} + TEST_F(GLES2ImplementationTest, GetShaderiv) { struct Cmds { cmds::GetShaderiv cmd; @@ -941,6 +1061,25 @@ EXPECT_TRUE(result); } +TEST_F(GLES2ImplementationTest, IsSampler) { + struct Cmds { + cmds::IsSampler cmd; + }; + + Cmds expected; + ExpectedMemoryInfo result1 = + GetExpectedResultMemory(sizeof(cmds::IsSampler::Result)); + expected.cmd.Init(1, result1.id, result1.offset); + + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result1.ptr, uint32_t(1))) + .RetiresOnSaturation(); + + GLboolean result = gl_->IsSampler(1); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_TRUE(result); +} + TEST_F(GLES2ImplementationTest, IsShader) { struct Cmds { cmds::IsShader cmd; @@ -979,6 +1118,25 @@ EXPECT_TRUE(result); } +TEST_F(GLES2ImplementationTest, IsTransformFeedback) { + struct Cmds { + cmds::IsTransformFeedback cmd; + }; + + Cmds expected; + ExpectedMemoryInfo result1 = + GetExpectedResultMemory(sizeof(cmds::IsTransformFeedback::Result)); + expected.cmd.Init(1, result1.id, result1.offset); + + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result1.ptr, uint32_t(1))) + .RetiresOnSaturation(); + + GLboolean result = gl_->IsTransformFeedback(1); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_TRUE(result); +} + TEST_F(GLES2ImplementationTest, LineWidth) { struct Cmds { cmds::LineWidth cmd; @@ -1001,6 +1159,17 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, PauseTransformFeedback) { + struct Cmds { + cmds::PauseTransformFeedback cmd; + }; + Cmds expected; + expected.cmd.Init(); + + gl_->PauseTransformFeedback(); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, PixelStorei) { struct Cmds { cmds::PixelStorei cmd; @@ -1056,6 +1225,17 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, ResumeTransformFeedback) { + struct Cmds { + cmds::ResumeTransformFeedback cmd; + }; + Cmds expected; + expected.cmd.Init(); + + gl_->ResumeTransformFeedback(); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, SampleCoverage) { struct Cmds { cmds::SampleCoverage cmd; @@ -1067,6 +1247,60 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, SamplerParameterf) { + struct Cmds { + cmds::SamplerParameterf cmd; + }; + Cmds expected; + expected.cmd.Init(1, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + gl_->SamplerParameterf(1, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, SamplerParameterfv) { + GLfloat data[1] = {0}; + struct Cmds { + cmds::SamplerParameterfvImmediate cmd; + GLfloat data[1]; + }; + + for (int jj = 0; jj < 1; ++jj) { + data[jj] = static_cast<GLfloat>(jj); + } + Cmds expected; + expected.cmd.Init(1, GL_TEXTURE_MAG_FILTER, &data[0]); + gl_->SamplerParameterfv(1, GL_TEXTURE_MAG_FILTER, &data[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, SamplerParameteri) { + struct Cmds { + cmds::SamplerParameteri cmd; + }; + Cmds expected; + expected.cmd.Init(1, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + gl_->SamplerParameteri(1, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, SamplerParameteriv) { + GLint data[1] = {0}; + struct Cmds { + cmds::SamplerParameterivImmediate cmd; + GLint data[1]; + }; + + for (int jj = 0; jj < 1; ++jj) { + data[jj] = static_cast<GLint>(jj); + } + Cmds expected; + expected.cmd.Init(1, GL_TEXTURE_MAG_FILTER, &data[0]); + gl_->SamplerParameteriv(1, GL_TEXTURE_MAG_FILTER, &data[0]); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, Scissor) { struct Cmds { cmds::Scissor cmd; @@ -2122,6 +2356,28 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } // TODO: Implement unit test for BeginQueryEXT + +TEST_F(GLES2ImplementationTest, BeginTransformFeedback) { + struct Cmds { + cmds::BeginTransformFeedback cmd; + }; + Cmds expected; + expected.cmd.Init(GL_POINTS); + + gl_->BeginTransformFeedback(GL_POINTS); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, EndTransformFeedback) { + struct Cmds { + cmds::EndTransformFeedback cmd; + }; + Cmds expected; + expected.cmd.Init(); + + gl_->EndTransformFeedback(); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} // TODO: Implement unit test for InsertEventMarkerEXT // TODO: Implement unit test for PushGroupMarkerEXT
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index f6317bb..5a5d289 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -21,7 +21,9 @@ virtual void BindBuffer(GLenum target, GLuint buffer) = 0; virtual void BindFramebuffer(GLenum target, GLuint framebuffer) = 0; virtual void BindRenderbuffer(GLenum target, GLuint renderbuffer) = 0; +virtual void BindSampler(GLuint unit, GLuint sampler) = 0; virtual void BindTexture(GLenum target, GLuint texture) = 0; +virtual void BindTransformFeedback(GLenum target, GLuint transformfeedback) = 0; virtual void BlendColor(GLclampf red, GLclampf green, GLclampf blue, @@ -99,8 +101,10 @@ virtual void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) = 0; virtual void DeleteProgram(GLuint program) = 0; virtual void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) = 0; +virtual void DeleteSamplers(GLsizei n, const GLuint* samplers) = 0; virtual void DeleteShader(GLuint shader) = 0; virtual void DeleteTextures(GLsizei n, const GLuint* textures) = 0; +virtual void DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) = 0; virtual void DepthFunc(GLenum func) = 0; virtual void DepthMask(GLboolean flag) = 0; virtual void DepthRangef(GLclampf zNear, GLclampf zFar) = 0; @@ -135,7 +139,9 @@ virtual void GenerateMipmap(GLenum target) = 0; virtual void GenFramebuffers(GLsizei n, GLuint* framebuffers) = 0; virtual void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) = 0; +virtual void GenSamplers(GLsizei n, GLuint* samplers) = 0; virtual void GenTextures(GLsizei n, GLuint* textures) = 0; +virtual void GenTransformFeedbacks(GLsizei n, GLuint* ids) = 0; virtual void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, @@ -179,6 +185,12 @@ virtual void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) = 0; +virtual void GetSamplerParameterfv(GLuint sampler, + GLenum pname, + GLfloat* params) = 0; +virtual void GetSamplerParameteriv(GLuint sampler, + GLenum pname, + GLint* params) = 0; virtual void GetShaderiv(GLuint shader, GLenum pname, GLint* params) = 0; virtual void GetShaderInfoLog(GLuint shader, GLsizei bufsize, @@ -221,10 +233,13 @@ virtual GLboolean IsFramebuffer(GLuint framebuffer) = 0; virtual GLboolean IsProgram(GLuint program) = 0; virtual GLboolean IsRenderbuffer(GLuint renderbuffer) = 0; +virtual GLboolean IsSampler(GLuint sampler) = 0; virtual GLboolean IsShader(GLuint shader) = 0; virtual GLboolean IsTexture(GLuint texture) = 0; +virtual GLboolean IsTransformFeedback(GLuint transformfeedback) = 0; virtual void LineWidth(GLfloat width) = 0; virtual void LinkProgram(GLuint program) = 0; +virtual void PauseTransformFeedback() = 0; virtual void PixelStorei(GLenum pname, GLint param) = 0; virtual void PolygonOffset(GLfloat factor, GLfloat units) = 0; virtual void ReadBuffer(GLenum src) = 0; @@ -240,7 +255,16 @@ GLenum internalformat, GLsizei width, GLsizei height) = 0; +virtual void ResumeTransformFeedback() = 0; virtual void SampleCoverage(GLclampf value, GLboolean invert) = 0; +virtual void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) = 0; +virtual void SamplerParameterfv(GLuint sampler, + GLenum pname, + const GLfloat* params) = 0; +virtual void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) = 0; +virtual void SamplerParameteriv(GLuint sampler, + GLenum pname, + const GLint* params) = 0; virtual void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) = 0; virtual void ShaderBinary(GLsizei n, const GLuint* shaders, @@ -438,7 +462,9 @@ virtual void DeleteQueriesEXT(GLsizei n, const GLuint* queries) = 0; virtual GLboolean IsQueryEXT(GLuint id) = 0; virtual void BeginQueryEXT(GLenum target, GLuint id) = 0; +virtual void BeginTransformFeedback(GLenum primitivemode) = 0; virtual void EndQueryEXT(GLenum target) = 0; +virtual void EndTransformFeedback() = 0; virtual void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) = 0; virtual void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) = 0; virtual void InsertEventMarkerEXT(GLsizei length, const GLchar* marker) = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index cbab14f..c2f4920 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -20,7 +20,9 @@ void BindBuffer(GLenum target, GLuint buffer) override; void BindFramebuffer(GLenum target, GLuint framebuffer) override; void BindRenderbuffer(GLenum target, GLuint renderbuffer) override; +void BindSampler(GLuint unit, GLuint sampler) override; void BindTexture(GLenum target, GLuint texture) override; +void BindTransformFeedback(GLenum target, GLuint transformfeedback) override; void BlendColor(GLclampf red, GLclampf green, GLclampf blue, @@ -98,8 +100,10 @@ void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) override; void DeleteProgram(GLuint program) override; void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) override; +void DeleteSamplers(GLsizei n, const GLuint* samplers) override; void DeleteShader(GLuint shader) override; void DeleteTextures(GLsizei n, const GLuint* textures) override; +void DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) override; void DepthFunc(GLenum func) override; void DepthMask(GLboolean flag) override; void DepthRangef(GLclampf zNear, GLclampf zFar) override; @@ -134,7 +138,9 @@ void GenerateMipmap(GLenum target) override; void GenFramebuffers(GLsizei n, GLuint* framebuffers) override; void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override; +void GenSamplers(GLsizei n, GLuint* samplers) override; void GenTextures(GLsizei n, GLuint* textures) override; +void GenTransformFeedbacks(GLsizei n, GLuint* ids) override; void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, @@ -176,6 +182,12 @@ void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) override; +void GetSamplerParameterfv(GLuint sampler, + GLenum pname, + GLfloat* params) override; +void GetSamplerParameteriv(GLuint sampler, + GLenum pname, + GLint* params) override; void GetShaderiv(GLuint shader, GLenum pname, GLint* params) override; void GetShaderInfoLog(GLuint shader, GLsizei bufsize, @@ -216,10 +228,13 @@ GLboolean IsFramebuffer(GLuint framebuffer) override; GLboolean IsProgram(GLuint program) override; GLboolean IsRenderbuffer(GLuint renderbuffer) override; +GLboolean IsSampler(GLuint sampler) override; GLboolean IsShader(GLuint shader) override; GLboolean IsTexture(GLuint texture) override; +GLboolean IsTransformFeedback(GLuint transformfeedback) override; void LineWidth(GLfloat width) override; void LinkProgram(GLuint program) override; +void PauseTransformFeedback() override; void PixelStorei(GLenum pname, GLint param) override; void PolygonOffset(GLfloat factor, GLfloat units) override; void ReadBuffer(GLenum src) override; @@ -235,7 +250,16 @@ GLenum internalformat, GLsizei width, GLsizei height) override; +void ResumeTransformFeedback() override; void SampleCoverage(GLclampf value, GLboolean invert) override; +void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) override; +void SamplerParameterfv(GLuint sampler, + GLenum pname, + const GLfloat* params) override; +void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) override; +void SamplerParameteriv(GLuint sampler, + GLenum pname, + const GLint* params) override; void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) override; void ShaderBinary(GLsizei n, const GLuint* shaders, @@ -427,7 +451,9 @@ void DeleteQueriesEXT(GLsizei n, const GLuint* queries) override; GLboolean IsQueryEXT(GLuint id) override; void BeginQueryEXT(GLenum target, GLuint id) override; +void BeginTransformFeedback(GLenum primitivemode) override; void EndQueryEXT(GLenum target) override; +void EndTransformFeedback() override; void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) override; void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override; void InsertEventMarkerEXT(GLsizei length, const GLchar* marker) override;
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 c3d2803..fcd196d 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -29,9 +29,14 @@ void GLES2InterfaceStub::BindRenderbuffer(GLenum /* target */, GLuint /* renderbuffer */) { } +void GLES2InterfaceStub::BindSampler(GLuint /* unit */, GLuint /* sampler */) { +} void GLES2InterfaceStub::BindTexture(GLenum /* target */, GLuint /* texture */) { } +void GLES2InterfaceStub::BindTransformFeedback(GLenum /* target */, + GLuint /* transformfeedback */) { +} void GLES2InterfaceStub::BlendColor(GLclampf /* red */, GLclampf /* green */, GLclampf /* blue */, @@ -143,11 +148,17 @@ GLsizei /* n */, const GLuint* /* renderbuffers */) { } +void GLES2InterfaceStub::DeleteSamplers(GLsizei /* n */, + const GLuint* /* samplers */) { +} void GLES2InterfaceStub::DeleteShader(GLuint /* shader */) { } void GLES2InterfaceStub::DeleteTextures(GLsizei /* n */, const GLuint* /* textures */) { } +void GLES2InterfaceStub::DeleteTransformFeedbacks(GLsizei /* n */, + const GLuint* /* ids */) { +} void GLES2InterfaceStub::DepthFunc(GLenum /* func */) { } void GLES2InterfaceStub::DepthMask(GLboolean /* flag */) { @@ -209,8 +220,13 @@ void GLES2InterfaceStub::GenRenderbuffers(GLsizei /* n */, GLuint* /* renderbuffers */) { } +void GLES2InterfaceStub::GenSamplers(GLsizei /* n */, GLuint* /* samplers */) { +} void GLES2InterfaceStub::GenTextures(GLsizei /* n */, GLuint* /* textures */) { } +void GLES2InterfaceStub::GenTransformFeedbacks(GLsizei /* n */, + GLuint* /* ids */) { +} void GLES2InterfaceStub::GetActiveAttrib(GLuint /* program */, GLuint /* index */, GLsizei /* bufsize */, @@ -275,6 +291,14 @@ GLenum /* pname */, GLint* /* params */) { } +void GLES2InterfaceStub::GetSamplerParameterfv(GLuint /* sampler */, + GLenum /* pname */, + GLfloat* /* params */) { +} +void GLES2InterfaceStub::GetSamplerParameteriv(GLuint /* sampler */, + GLenum /* pname */, + GLint* /* params */) { +} void GLES2InterfaceStub::GetShaderiv(GLuint /* shader */, GLenum /* pname */, GLint* /* params */) { @@ -360,16 +384,25 @@ GLboolean GLES2InterfaceStub::IsRenderbuffer(GLuint /* renderbuffer */) { return 0; } +GLboolean GLES2InterfaceStub::IsSampler(GLuint /* sampler */) { + return 0; +} GLboolean GLES2InterfaceStub::IsShader(GLuint /* shader */) { return 0; } GLboolean GLES2InterfaceStub::IsTexture(GLuint /* texture */) { return 0; } +GLboolean GLES2InterfaceStub::IsTransformFeedback( + GLuint /* transformfeedback */) { + return 0; +} void GLES2InterfaceStub::LineWidth(GLfloat /* width */) { } void GLES2InterfaceStub::LinkProgram(GLuint /* program */) { } +void GLES2InterfaceStub::PauseTransformFeedback() { +} void GLES2InterfaceStub::PixelStorei(GLenum /* pname */, GLint /* param */) { } void GLES2InterfaceStub::PolygonOffset(GLfloat /* factor */, @@ -392,9 +425,27 @@ GLsizei /* width */, GLsizei /* height */) { } +void GLES2InterfaceStub::ResumeTransformFeedback() { +} void GLES2InterfaceStub::SampleCoverage(GLclampf /* value */, GLboolean /* invert */) { } +void GLES2InterfaceStub::SamplerParameterf(GLuint /* sampler */, + GLenum /* pname */, + GLfloat /* param */) { +} +void GLES2InterfaceStub::SamplerParameterfv(GLuint /* sampler */, + GLenum /* pname */, + const GLfloat* /* params */) { +} +void GLES2InterfaceStub::SamplerParameteri(GLuint /* sampler */, + GLenum /* pname */, + GLint /* param */) { +} +void GLES2InterfaceStub::SamplerParameteriv(GLuint /* sampler */, + GLenum /* pname */, + const GLint* /* params */) { +} void GLES2InterfaceStub::Scissor(GLint /* x */, GLint /* y */, GLsizei /* width */, @@ -743,8 +794,12 @@ } void GLES2InterfaceStub::BeginQueryEXT(GLenum /* target */, GLuint /* id */) { } +void GLES2InterfaceStub::BeginTransformFeedback(GLenum /* primitivemode */) { +} void GLES2InterfaceStub::EndQueryEXT(GLenum /* target */) { } +void GLES2InterfaceStub::EndTransformFeedback() { +} void GLES2InterfaceStub::GetQueryivEXT(GLenum /* target */, GLenum /* pname */, GLint* /* params */) {
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index f952d58..cd8ad7c 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -20,7 +20,9 @@ void BindBuffer(GLenum target, GLuint buffer) override; void BindFramebuffer(GLenum target, GLuint framebuffer) override; void BindRenderbuffer(GLenum target, GLuint renderbuffer) override; +void BindSampler(GLuint unit, GLuint sampler) override; void BindTexture(GLenum target, GLuint texture) override; +void BindTransformFeedback(GLenum target, GLuint transformfeedback) override; void BlendColor(GLclampf red, GLclampf green, GLclampf blue, @@ -98,8 +100,10 @@ void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) override; void DeleteProgram(GLuint program) override; void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) override; +void DeleteSamplers(GLsizei n, const GLuint* samplers) override; void DeleteShader(GLuint shader) override; void DeleteTextures(GLsizei n, const GLuint* textures) override; +void DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) override; void DepthFunc(GLenum func) override; void DepthMask(GLboolean flag) override; void DepthRangef(GLclampf zNear, GLclampf zFar) override; @@ -134,7 +138,9 @@ void GenerateMipmap(GLenum target) override; void GenFramebuffers(GLsizei n, GLuint* framebuffers) override; void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override; +void GenSamplers(GLsizei n, GLuint* samplers) override; void GenTextures(GLsizei n, GLuint* textures) override; +void GenTransformFeedbacks(GLsizei n, GLuint* ids) override; void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, @@ -176,6 +182,12 @@ void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) override; +void GetSamplerParameterfv(GLuint sampler, + GLenum pname, + GLfloat* params) override; +void GetSamplerParameteriv(GLuint sampler, + GLenum pname, + GLint* params) override; void GetShaderiv(GLuint shader, GLenum pname, GLint* params) override; void GetShaderInfoLog(GLuint shader, GLsizei bufsize, @@ -216,10 +228,13 @@ GLboolean IsFramebuffer(GLuint framebuffer) override; GLboolean IsProgram(GLuint program) override; GLboolean IsRenderbuffer(GLuint renderbuffer) override; +GLboolean IsSampler(GLuint sampler) override; GLboolean IsShader(GLuint shader) override; GLboolean IsTexture(GLuint texture) override; +GLboolean IsTransformFeedback(GLuint transformfeedback) override; void LineWidth(GLfloat width) override; void LinkProgram(GLuint program) override; +void PauseTransformFeedback() override; void PixelStorei(GLenum pname, GLint param) override; void PolygonOffset(GLfloat factor, GLfloat units) override; void ReadBuffer(GLenum src) override; @@ -235,7 +250,16 @@ GLenum internalformat, GLsizei width, GLsizei height) override; +void ResumeTransformFeedback() override; void SampleCoverage(GLclampf value, GLboolean invert) override; +void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) override; +void SamplerParameterfv(GLuint sampler, + GLenum pname, + const GLfloat* params) override; +void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) override; +void SamplerParameteriv(GLuint sampler, + GLenum pname, + const GLint* params) override; void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) override; void ShaderBinary(GLsizei n, const GLuint* shaders, @@ -427,7 +451,9 @@ void DeleteQueriesEXT(GLsizei n, const GLuint* queries) override; GLboolean IsQueryEXT(GLuint id) override; void BeginQueryEXT(GLenum target, GLuint id) override; +void BeginTransformFeedback(GLenum primitivemode) override; void EndQueryEXT(GLenum target) override; +void EndTransformFeedback() override; void GetQueryivEXT(GLenum target, GLenum pname, GLint* params) override; void GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* params) override; void InsertEventMarkerEXT(GLsizei length, const GLchar* marker) override;
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 c9f8b93..567dace 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -46,11 +46,22 @@ gl_->BindRenderbuffer(target, renderbuffer); } +void GLES2TraceImplementation::BindSampler(GLuint unit, GLuint sampler) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindSampler"); + gl_->BindSampler(unit, sampler); +} + void GLES2TraceImplementation::BindTexture(GLenum target, GLuint texture) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindTexture"); gl_->BindTexture(target, texture); } +void GLES2TraceImplementation::BindTransformFeedback(GLenum target, + GLuint transformfeedback) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BindTransformFeedback"); + gl_->BindTransformFeedback(target, transformfeedback); +} + void GLES2TraceImplementation::BlendColor(GLclampf red, GLclampf green, GLclampf blue, @@ -240,6 +251,12 @@ gl_->DeleteRenderbuffers(n, renderbuffers); } +void GLES2TraceImplementation::DeleteSamplers(GLsizei n, + const GLuint* samplers) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DeleteSamplers"); + gl_->DeleteSamplers(n, samplers); +} + void GLES2TraceImplementation::DeleteShader(GLuint shader) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DeleteShader"); gl_->DeleteShader(shader); @@ -251,6 +268,12 @@ gl_->DeleteTextures(n, textures); } +void GLES2TraceImplementation::DeleteTransformFeedbacks(GLsizei n, + const GLuint* ids) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DeleteTransformFeedbacks"); + gl_->DeleteTransformFeedbacks(n, ids); +} + void GLES2TraceImplementation::DepthFunc(GLenum func) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DepthFunc"); gl_->DepthFunc(func); @@ -371,11 +394,21 @@ gl_->GenRenderbuffers(n, renderbuffers); } +void GLES2TraceImplementation::GenSamplers(GLsizei n, GLuint* samplers) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GenSamplers"); + gl_->GenSamplers(n, samplers); +} + void GLES2TraceImplementation::GenTextures(GLsizei n, GLuint* textures) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GenTextures"); gl_->GenTextures(n, textures); } +void GLES2TraceImplementation::GenTransformFeedbacks(GLsizei n, GLuint* ids) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GenTransformFeedbacks"); + gl_->GenTransformFeedbacks(n, ids); +} + void GLES2TraceImplementation::GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, @@ -481,6 +514,20 @@ gl_->GetRenderbufferParameteriv(target, pname, params); } +void GLES2TraceImplementation::GetSamplerParameterfv(GLuint sampler, + GLenum pname, + GLfloat* params) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetSamplerParameterfv"); + gl_->GetSamplerParameterfv(sampler, pname, params); +} + +void GLES2TraceImplementation::GetSamplerParameteriv(GLuint sampler, + GLenum pname, + GLint* params) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetSamplerParameteriv"); + gl_->GetSamplerParameteriv(sampler, pname, params); +} + void GLES2TraceImplementation::GetShaderiv(GLuint shader, GLenum pname, GLint* params) { @@ -623,6 +670,11 @@ return gl_->IsRenderbuffer(renderbuffer); } +GLboolean GLES2TraceImplementation::IsSampler(GLuint sampler) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::IsSampler"); + return gl_->IsSampler(sampler); +} + GLboolean GLES2TraceImplementation::IsShader(GLuint shader) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::IsShader"); return gl_->IsShader(shader); @@ -633,6 +685,12 @@ return gl_->IsTexture(texture); } +GLboolean GLES2TraceImplementation::IsTransformFeedback( + GLuint transformfeedback) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::IsTransformFeedback"); + return gl_->IsTransformFeedback(transformfeedback); +} + void GLES2TraceImplementation::LineWidth(GLfloat width) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::LineWidth"); gl_->LineWidth(width); @@ -643,6 +701,11 @@ gl_->LinkProgram(program); } +void GLES2TraceImplementation::PauseTransformFeedback() { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::PauseTransformFeedback"); + gl_->PauseTransformFeedback(); +} + void GLES2TraceImplementation::PixelStorei(GLenum pname, GLint param) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::PixelStorei"); gl_->PixelStorei(pname, param); @@ -682,12 +745,45 @@ gl_->RenderbufferStorage(target, internalformat, width, height); } +void GLES2TraceImplementation::ResumeTransformFeedback() { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::ResumeTransformFeedback"); + gl_->ResumeTransformFeedback(); +} + void GLES2TraceImplementation::SampleCoverage(GLclampf value, GLboolean invert) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::SampleCoverage"); gl_->SampleCoverage(value, invert); } +void GLES2TraceImplementation::SamplerParameterf(GLuint sampler, + GLenum pname, + GLfloat param) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::SamplerParameterf"); + gl_->SamplerParameterf(sampler, pname, param); +} + +void GLES2TraceImplementation::SamplerParameterfv(GLuint sampler, + GLenum pname, + const GLfloat* params) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::SamplerParameterfv"); + gl_->SamplerParameterfv(sampler, pname, params); +} + +void GLES2TraceImplementation::SamplerParameteri(GLuint sampler, + GLenum pname, + GLint param) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::SamplerParameteri"); + gl_->SamplerParameteri(sampler, pname, param); +} + +void GLES2TraceImplementation::SamplerParameteriv(GLuint sampler, + GLenum pname, + const GLint* params) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::SamplerParameteriv"); + gl_->SamplerParameteriv(sampler, pname, params); +} + void GLES2TraceImplementation::Scissor(GLint x, GLint y, GLsizei width, @@ -1268,11 +1364,21 @@ gl_->BeginQueryEXT(target, id); } +void GLES2TraceImplementation::BeginTransformFeedback(GLenum primitivemode) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::BeginTransformFeedback"); + gl_->BeginTransformFeedback(primitivemode); +} + void GLES2TraceImplementation::EndQueryEXT(GLenum target) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::EndQueryEXT"); gl_->EndQueryEXT(target); } +void GLES2TraceImplementation::EndTransformFeedback() { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::EndTransformFeedback"); + gl_->EndTransformFeedback(); +} + void GLES2TraceImplementation::GetQueryivEXT(GLenum target, GLenum pname, GLint* params) {
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index f0b1627..d046748e 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -10,7 +10,9 @@ GL_APICALL void GL_APIENTRY glBindBuffer (GLenumBufferTarget target, GLidBindBuffer buffer); GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenumFrameBufferTarget target, GLidBindFramebuffer framebuffer); GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenumRenderBufferTarget target, GLidBindRenderbuffer renderbuffer); +GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLidBindSampler sampler); GL_APICALL void GL_APIENTRY glBindTexture (GLenumTextureBindTarget target, GLidBindTexture texture); +GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenumTransformFeedbackBindTarget target, GLidBindTransformFeedback transformfeedback); GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); GL_APICALL void GL_APIENTRY glBlendEquation ( GLenumEquation mode ); GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenumEquation modeRGB, GLenumEquation modeAlpha); @@ -37,8 +39,10 @@ GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizeiNotNegative n, const GLuint* framebuffers); GL_APICALL void GL_APIENTRY glDeleteProgram (GLidProgram program); GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizeiNotNegative n, const GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizeiNotNegative n, const GLuint* samplers); GL_APICALL void GL_APIENTRY glDeleteShader (GLidShader shader); GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizeiNotNegative n, const GLuint* textures); +GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizeiNotNegative n, const GLuint* ids); GL_APICALL void GL_APIENTRY glDepthFunc (GLenumCmpFunction func); GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar); @@ -59,7 +63,9 @@ GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenumTextureBindTarget target); GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizeiNotNegative n, GLuint* framebuffers); GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizeiNotNegative n, GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glGenSamplers (GLsizeiNotNegative n, GLuint* samplers); GL_APICALL void GL_APIENTRY glGenTextures (GLsizeiNotNegative n, GLuint* textures); +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 glGetAttachedShaders (GLidProgram program, GLsizeiNotNegative maxcount, GLsizeiOptional* count, GLuint* shaders); @@ -74,6 +80,8 @@ GL_APICALL void GL_APIENTRY glGetProgramiv (GLidProgram program, GLenumProgramParameter pname, GLint* params); GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLidProgram program, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* infolog); GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenumRenderBufferTarget target, GLenumRenderBufferParameter pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLidSampler sampler, GLenumSamplerParameter pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLidSampler sampler, GLenumSamplerParameter pname, GLint* params); GL_APICALL void GL_APIENTRY glGetShaderiv (GLidShader shader, GLenumShaderParameter pname, GLint* params); GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLidShader shader, GLsizeiNotNegative bufsize, GLsizeiOptional* length, char* infolog); GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenumShaderType shadertype, GLenumShaderPrecision precisiontype, GLint* range, GLint* precision); @@ -95,17 +103,25 @@ GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLidFramebuffer framebuffer); GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLidProgram program); GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLidRenderbuffer renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLidSampler sampler); GL_APICALL GLboolean GL_APIENTRY glIsShader (GLidShader shader); GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLidTexture texture); +GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLidTransformFeedback transformfeedback); GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); GL_APICALL void GL_APIENTRY glLinkProgram (GLidProgram program); +GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); GL_APICALL void GL_APIENTRY glPixelStorei (GLenumPixelStore pname, GLintPixelStoreAlignment param); GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src); GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenumReadPixelFormat format, GLenumPixelType type, void* pixels); GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenumRenderBufferTarget target, GLenumRenderBufferFormat internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); +GL_APICALL void GL_APIENTRY glSamplerParameterf (GLidBindSampler sampler, GLenumSamplerParameter pname, GLfloat param); +GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLidBindSampler sampler, GLenumSamplerParameter pname, const GLfloat* params); +GL_APICALL void GL_APIENTRY glSamplerParameteri (GLidBindSampler sampler, GLenumSamplerParameter pname, GLint param); +GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLidBindSampler sampler, GLenumSamplerParameter pname, const GLint* params); GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glShaderBinary (GLsizeiNotNegative n, const GLuint* shaders, GLenumShaderBinaryFormat binaryformat, const void* binary, GLsizeiNotNegative length); GL_APICALL void GL_APIENTRY glShaderSource (GLidShader shader, GLsizeiNotNegative count, const GLchar* const* str, const GLint* length); @@ -183,7 +199,9 @@ GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizeiNotNegative n, const GLuint* queries); GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLidQuery id); GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenumQueryTarget target, GLidQuery id); +GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenumTransformFeedbackPrimitiveMode primitivemode); GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenumQueryTarget target); +GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenumQueryTarget target, GLenumQueryParameter pname, GLint* params); GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLidQuery id, GLenumQueryObjectParameter pname, GLuint* params); GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar* marker);
diff --git a/gpu/command_buffer/common/gles2_cmd_format.h b/gpu/command_buffer/common/gles2_cmd_format.h index c0bc663..8b22bc6 100644 --- a/gpu/command_buffer/common/gles2_cmd_format.h +++ b/gpu/command_buffer/common/gles2_cmd_format.h
@@ -60,6 +60,8 @@ kQueries, kVertexArrays, kValuebuffers, + kSamplers, + kTransformFeedbacks, kNumIdNamespaces };
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index bdee4e6..c94feaa 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -232,6 +232,42 @@ COMPILE_ASSERT(offsetof(BindRenderbuffer, renderbuffer) == 8, OffsetOf_BindRenderbuffer_renderbuffer_not_8); +struct BindSampler { + typedef BindSampler ValueType; + static const CommandId kCmdId = kBindSampler; + 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 _unit, GLuint _sampler) { + SetHeader(); + unit = _unit; + sampler = _sampler; + } + + void* Set(void* cmd, GLuint _unit, GLuint _sampler) { + static_cast<ValueType*>(cmd)->Init(_unit, _sampler); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t unit; + uint32_t sampler; +}; + +COMPILE_ASSERT(sizeof(BindSampler) == 12, Sizeof_BindSampler_is_not_12); +COMPILE_ASSERT(offsetof(BindSampler, header) == 0, + OffsetOf_BindSampler_header_not_0); +COMPILE_ASSERT(offsetof(BindSampler, unit) == 4, + OffsetOf_BindSampler_unit_not_4); +COMPILE_ASSERT(offsetof(BindSampler, sampler) == 8, + OffsetOf_BindSampler_sampler_not_8); + struct BindTexture { typedef BindTexture ValueType; static const CommandId kCmdId = kBindTexture; @@ -268,6 +304,43 @@ COMPILE_ASSERT(offsetof(BindTexture, texture) == 8, OffsetOf_BindTexture_texture_not_8); +struct BindTransformFeedback { + typedef BindTransformFeedback ValueType; + static const CommandId kCmdId = kBindTransformFeedback; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLenum _target, GLuint _transformfeedback) { + SetHeader(); + target = _target; + transformfeedback = _transformfeedback; + } + + void* Set(void* cmd, GLenum _target, GLuint _transformfeedback) { + static_cast<ValueType*>(cmd)->Init(_target, _transformfeedback); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t target; + uint32_t transformfeedback; +}; + +COMPILE_ASSERT(sizeof(BindTransformFeedback) == 12, + Sizeof_BindTransformFeedback_is_not_12); +COMPILE_ASSERT(offsetof(BindTransformFeedback, header) == 0, + OffsetOf_BindTransformFeedback_header_not_0); +COMPILE_ASSERT(offsetof(BindTransformFeedback, target) == 4, + OffsetOf_BindTransformFeedback_target_not_4); +COMPILE_ASSERT(offsetof(BindTransformFeedback, transformfeedback) == 8, + OffsetOf_BindTransformFeedback_transformfeedback_not_8); + struct BlendColor { typedef BlendColor ValueType; static const CommandId kCmdId = kBlendColor; @@ -1631,6 +1704,48 @@ COMPILE_ASSERT(offsetof(DeleteRenderbuffersImmediate, n) == 4, OffsetOf_DeleteRenderbuffersImmediate_n_not_4); +struct DeleteSamplersImmediate { + typedef DeleteSamplersImmediate ValueType; + static const CommandId kCmdId = kDeleteSamplersImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeDataSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT + } + + static uint32_t ComputeSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(ValueType) + + ComputeDataSize(n)); // NOLINT + } + + void SetHeader(GLsizei n) { + header.SetCmdByTotalSize<ValueType>(ComputeSize(n)); + } + + void Init(GLsizei _n, const GLuint* _samplers) { + SetHeader(_n); + n = _n; + memcpy(ImmediateDataAddress(this), _samplers, ComputeDataSize(_n)); + } + + void* Set(void* cmd, GLsizei _n, const GLuint* _samplers) { + static_cast<ValueType*>(cmd)->Init(_n, _samplers); + const uint32_t size = ComputeSize(_n); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + int32_t n; +}; + +COMPILE_ASSERT(sizeof(DeleteSamplersImmediate) == 8, + Sizeof_DeleteSamplersImmediate_is_not_8); +COMPILE_ASSERT(offsetof(DeleteSamplersImmediate, header) == 0, + OffsetOf_DeleteSamplersImmediate_header_not_0); +COMPILE_ASSERT(offsetof(DeleteSamplersImmediate, n) == 4, + OffsetOf_DeleteSamplersImmediate_n_not_4); + struct DeleteShader { typedef DeleteShader ValueType; static const CommandId kCmdId = kDeleteShader; @@ -1705,6 +1820,48 @@ COMPILE_ASSERT(offsetof(DeleteTexturesImmediate, n) == 4, OffsetOf_DeleteTexturesImmediate_n_not_4); +struct DeleteTransformFeedbacksImmediate { + typedef DeleteTransformFeedbacksImmediate ValueType; + static const CommandId kCmdId = kDeleteTransformFeedbacksImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeDataSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT + } + + static uint32_t ComputeSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(ValueType) + + ComputeDataSize(n)); // NOLINT + } + + void SetHeader(GLsizei n) { + header.SetCmdByTotalSize<ValueType>(ComputeSize(n)); + } + + void Init(GLsizei _n, const GLuint* _ids) { + SetHeader(_n); + n = _n; + memcpy(ImmediateDataAddress(this), _ids, ComputeDataSize(_n)); + } + + void* Set(void* cmd, GLsizei _n, const GLuint* _ids) { + static_cast<ValueType*>(cmd)->Init(_n, _ids); + const uint32_t size = ComputeSize(_n); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + int32_t n; +}; + +COMPILE_ASSERT(sizeof(DeleteTransformFeedbacksImmediate) == 8, + Sizeof_DeleteTransformFeedbacksImmediate_is_not_8); +COMPILE_ASSERT(offsetof(DeleteTransformFeedbacksImmediate, header) == 0, + OffsetOf_DeleteTransformFeedbacksImmediate_header_not_0); +COMPILE_ASSERT(offsetof(DeleteTransformFeedbacksImmediate, n) == 4, + OffsetOf_DeleteTransformFeedbacksImmediate_n_not_4); + struct DepthFunc { typedef DepthFunc ValueType; static const CommandId kCmdId = kDepthFunc; @@ -2457,6 +2614,48 @@ COMPILE_ASSERT(offsetof(GenRenderbuffersImmediate, n) == 4, OffsetOf_GenRenderbuffersImmediate_n_not_4); +struct GenSamplersImmediate { + typedef GenSamplersImmediate ValueType; + static const CommandId kCmdId = kGenSamplersImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeDataSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT + } + + static uint32_t ComputeSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(ValueType) + + ComputeDataSize(n)); // NOLINT + } + + void SetHeader(GLsizei n) { + header.SetCmdByTotalSize<ValueType>(ComputeSize(n)); + } + + void Init(GLsizei _n, GLuint* _samplers) { + SetHeader(_n); + n = _n; + memcpy(ImmediateDataAddress(this), _samplers, ComputeDataSize(_n)); + } + + void* Set(void* cmd, GLsizei _n, GLuint* _samplers) { + static_cast<ValueType*>(cmd)->Init(_n, _samplers); + const uint32_t size = ComputeSize(_n); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + int32_t n; +}; + +COMPILE_ASSERT(sizeof(GenSamplersImmediate) == 8, + Sizeof_GenSamplersImmediate_is_not_8); +COMPILE_ASSERT(offsetof(GenSamplersImmediate, header) == 0, + OffsetOf_GenSamplersImmediate_header_not_0); +COMPILE_ASSERT(offsetof(GenSamplersImmediate, n) == 4, + OffsetOf_GenSamplersImmediate_n_not_4); + struct GenTexturesImmediate { typedef GenTexturesImmediate ValueType; static const CommandId kCmdId = kGenTexturesImmediate; @@ -2499,6 +2698,48 @@ COMPILE_ASSERT(offsetof(GenTexturesImmediate, n) == 4, OffsetOf_GenTexturesImmediate_n_not_4); +struct GenTransformFeedbacksImmediate { + typedef GenTransformFeedbacksImmediate ValueType; + static const CommandId kCmdId = kGenTransformFeedbacksImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeDataSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(GLuint) * n); // NOLINT + } + + static uint32_t ComputeSize(GLsizei n) { + return static_cast<uint32_t>(sizeof(ValueType) + + ComputeDataSize(n)); // NOLINT + } + + void SetHeader(GLsizei n) { + header.SetCmdByTotalSize<ValueType>(ComputeSize(n)); + } + + void Init(GLsizei _n, GLuint* _ids) { + SetHeader(_n); + n = _n; + memcpy(ImmediateDataAddress(this), _ids, ComputeDataSize(_n)); + } + + void* Set(void* cmd, GLsizei _n, GLuint* _ids) { + static_cast<ValueType*>(cmd)->Init(_n, _ids); + const uint32_t size = ComputeSize(_n); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + int32_t n; +}; + +COMPILE_ASSERT(sizeof(GenTransformFeedbacksImmediate) == 8, + Sizeof_GenTransformFeedbacksImmediate_is_not_8); +COMPILE_ASSERT(offsetof(GenTransformFeedbacksImmediate, header) == 0, + OffsetOf_GenTransformFeedbacksImmediate_header_not_0); +COMPILE_ASSERT(offsetof(GenTransformFeedbacksImmediate, n) == 4, + OffsetOf_GenTransformFeedbacksImmediate_n_not_4); + struct GetActiveAttrib { typedef GetActiveAttrib ValueType; static const CommandId kCmdId = kGetActiveAttrib; @@ -3261,6 +3502,116 @@ COMPILE_ASSERT(offsetof(GetRenderbufferParameteriv, params_shm_offset) == 16, OffsetOf_GetRenderbufferParameteriv_params_shm_offset_not_16); +struct GetSamplerParameterfv { + typedef GetSamplerParameterfv ValueType; + static const CommandId kCmdId = kGetSamplerParameterfv; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + typedef SizedResult<GLfloat> Result; + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLuint _sampler, + GLenum _pname, + uint32_t _params_shm_id, + uint32_t _params_shm_offset) { + SetHeader(); + sampler = _sampler; + pname = _pname; + params_shm_id = _params_shm_id; + params_shm_offset = _params_shm_offset; + } + + void* Set(void* cmd, + GLuint _sampler, + GLenum _pname, + uint32_t _params_shm_id, + uint32_t _params_shm_offset) { + static_cast<ValueType*>(cmd) + ->Init(_sampler, _pname, _params_shm_id, _params_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t sampler; + uint32_t pname; + uint32_t params_shm_id; + uint32_t params_shm_offset; +}; + +COMPILE_ASSERT(sizeof(GetSamplerParameterfv) == 20, + Sizeof_GetSamplerParameterfv_is_not_20); +COMPILE_ASSERT(offsetof(GetSamplerParameterfv, header) == 0, + OffsetOf_GetSamplerParameterfv_header_not_0); +COMPILE_ASSERT(offsetof(GetSamplerParameterfv, sampler) == 4, + OffsetOf_GetSamplerParameterfv_sampler_not_4); +COMPILE_ASSERT(offsetof(GetSamplerParameterfv, pname) == 8, + OffsetOf_GetSamplerParameterfv_pname_not_8); +COMPILE_ASSERT(offsetof(GetSamplerParameterfv, params_shm_id) == 12, + OffsetOf_GetSamplerParameterfv_params_shm_id_not_12); +COMPILE_ASSERT(offsetof(GetSamplerParameterfv, params_shm_offset) == 16, + OffsetOf_GetSamplerParameterfv_params_shm_offset_not_16); + +struct GetSamplerParameteriv { + typedef GetSamplerParameteriv ValueType; + static const CommandId kCmdId = kGetSamplerParameteriv; + 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 _sampler, + GLenum _pname, + uint32_t _params_shm_id, + uint32_t _params_shm_offset) { + SetHeader(); + sampler = _sampler; + pname = _pname; + params_shm_id = _params_shm_id; + params_shm_offset = _params_shm_offset; + } + + void* Set(void* cmd, + GLuint _sampler, + GLenum _pname, + uint32_t _params_shm_id, + uint32_t _params_shm_offset) { + static_cast<ValueType*>(cmd) + ->Init(_sampler, _pname, _params_shm_id, _params_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t sampler; + uint32_t pname; + uint32_t params_shm_id; + uint32_t params_shm_offset; +}; + +COMPILE_ASSERT(sizeof(GetSamplerParameteriv) == 20, + Sizeof_GetSamplerParameteriv_is_not_20); +COMPILE_ASSERT(offsetof(GetSamplerParameteriv, header) == 0, + OffsetOf_GetSamplerParameteriv_header_not_0); +COMPILE_ASSERT(offsetof(GetSamplerParameteriv, sampler) == 4, + OffsetOf_GetSamplerParameteriv_sampler_not_4); +COMPILE_ASSERT(offsetof(GetSamplerParameteriv, pname) == 8, + OffsetOf_GetSamplerParameteriv_pname_not_8); +COMPILE_ASSERT(offsetof(GetSamplerParameteriv, params_shm_id) == 12, + OffsetOf_GetSamplerParameteriv_params_shm_id_not_12); +COMPILE_ASSERT(offsetof(GetSamplerParameteriv, params_shm_offset) == 16, + OffsetOf_GetSamplerParameteriv_params_shm_offset_not_16); + struct GetShaderiv { typedef GetShaderiv ValueType; static const CommandId kCmdId = kGetShaderiv; @@ -4322,6 +4673,54 @@ COMPILE_ASSERT(offsetof(IsRenderbuffer, result_shm_offset) == 12, OffsetOf_IsRenderbuffer_result_shm_offset_not_12); +struct IsSampler { + typedef IsSampler ValueType; + static const CommandId kCmdId = kIsSampler; + 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 _sampler, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + SetHeader(); + sampler = _sampler; + result_shm_id = _result_shm_id; + result_shm_offset = _result_shm_offset; + } + + void* Set(void* cmd, + GLuint _sampler, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + static_cast<ValueType*>(cmd) + ->Init(_sampler, _result_shm_id, _result_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t sampler; + uint32_t result_shm_id; + uint32_t result_shm_offset; +}; + +COMPILE_ASSERT(sizeof(IsSampler) == 16, Sizeof_IsSampler_is_not_16); +COMPILE_ASSERT(offsetof(IsSampler, header) == 0, + OffsetOf_IsSampler_header_not_0); +COMPILE_ASSERT(offsetof(IsSampler, sampler) == 4, + OffsetOf_IsSampler_sampler_not_4); +COMPILE_ASSERT(offsetof(IsSampler, result_shm_id) == 8, + OffsetOf_IsSampler_result_shm_id_not_8); +COMPILE_ASSERT(offsetof(IsSampler, result_shm_offset) == 12, + OffsetOf_IsSampler_result_shm_offset_not_12); + struct IsShader { typedef IsShader ValueType; static const CommandId kCmdId = kIsShader; @@ -4416,6 +4815,55 @@ COMPILE_ASSERT(offsetof(IsTexture, result_shm_offset) == 12, OffsetOf_IsTexture_result_shm_offset_not_12); +struct IsTransformFeedback { + typedef IsTransformFeedback ValueType; + static const CommandId kCmdId = kIsTransformFeedback; + 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 _transformfeedback, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + SetHeader(); + transformfeedback = _transformfeedback; + result_shm_id = _result_shm_id; + result_shm_offset = _result_shm_offset; + } + + void* Set(void* cmd, + GLuint _transformfeedback, + uint32_t _result_shm_id, + uint32_t _result_shm_offset) { + static_cast<ValueType*>(cmd) + ->Init(_transformfeedback, _result_shm_id, _result_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t transformfeedback; + uint32_t result_shm_id; + uint32_t result_shm_offset; +}; + +COMPILE_ASSERT(sizeof(IsTransformFeedback) == 16, + Sizeof_IsTransformFeedback_is_not_16); +COMPILE_ASSERT(offsetof(IsTransformFeedback, header) == 0, + OffsetOf_IsTransformFeedback_header_not_0); +COMPILE_ASSERT(offsetof(IsTransformFeedback, transformfeedback) == 4, + OffsetOf_IsTransformFeedback_transformfeedback_not_4); +COMPILE_ASSERT(offsetof(IsTransformFeedback, result_shm_id) == 8, + OffsetOf_IsTransformFeedback_result_shm_id_not_8); +COMPILE_ASSERT(offsetof(IsTransformFeedback, result_shm_offset) == 12, + OffsetOf_IsTransformFeedback_result_shm_offset_not_12); + struct LineWidth { typedef LineWidth ValueType; static const CommandId kCmdId = kLineWidth; @@ -4479,6 +4927,33 @@ COMPILE_ASSERT(offsetof(LinkProgram, program) == 4, OffsetOf_LinkProgram_program_not_4); +struct PauseTransformFeedback { + typedef PauseTransformFeedback ValueType; + static const CommandId kCmdId = kPauseTransformFeedback; + 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() { SetHeader(); } + + void* Set(void* cmd) { + static_cast<ValueType*>(cmd)->Init(); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; +}; + +COMPILE_ASSERT(sizeof(PauseTransformFeedback) == 4, + Sizeof_PauseTransformFeedback_is_not_4); +COMPILE_ASSERT(offsetof(PauseTransformFeedback, header) == 0, + OffsetOf_PauseTransformFeedback_header_not_0); + struct PixelStorei { typedef PixelStorei ValueType; static const CommandId kCmdId = kPixelStorei; @@ -4760,6 +5235,33 @@ COMPILE_ASSERT(offsetof(RenderbufferStorage, height) == 16, OffsetOf_RenderbufferStorage_height_not_16); +struct ResumeTransformFeedback { + typedef ResumeTransformFeedback ValueType; + static const CommandId kCmdId = kResumeTransformFeedback; + 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() { SetHeader(); } + + void* Set(void* cmd) { + static_cast<ValueType*>(cmd)->Init(); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; +}; + +COMPILE_ASSERT(sizeof(ResumeTransformFeedback) == 4, + Sizeof_ResumeTransformFeedback_is_not_4); +COMPILE_ASSERT(offsetof(ResumeTransformFeedback, header) == 0, + OffsetOf_ResumeTransformFeedback_header_not_0); + struct SampleCoverage { typedef SampleCoverage ValueType; static const CommandId kCmdId = kSampleCoverage; @@ -4796,6 +5298,176 @@ COMPILE_ASSERT(offsetof(SampleCoverage, invert) == 8, OffsetOf_SampleCoverage_invert_not_8); +struct SamplerParameterf { + typedef SamplerParameterf ValueType; + static const CommandId kCmdId = kSamplerParameterf; + 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 _sampler, GLenum _pname, GLfloat _param) { + SetHeader(); + sampler = _sampler; + pname = _pname; + param = _param; + } + + void* Set(void* cmd, GLuint _sampler, GLenum _pname, GLfloat _param) { + static_cast<ValueType*>(cmd)->Init(_sampler, _pname, _param); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t sampler; + uint32_t pname; + float param; +}; + +COMPILE_ASSERT(sizeof(SamplerParameterf) == 16, + Sizeof_SamplerParameterf_is_not_16); +COMPILE_ASSERT(offsetof(SamplerParameterf, header) == 0, + OffsetOf_SamplerParameterf_header_not_0); +COMPILE_ASSERT(offsetof(SamplerParameterf, sampler) == 4, + OffsetOf_SamplerParameterf_sampler_not_4); +COMPILE_ASSERT(offsetof(SamplerParameterf, pname) == 8, + OffsetOf_SamplerParameterf_pname_not_8); +COMPILE_ASSERT(offsetof(SamplerParameterf, param) == 12, + OffsetOf_SamplerParameterf_param_not_12); + +struct SamplerParameterfvImmediate { + typedef SamplerParameterfvImmediate ValueType; + static const CommandId kCmdId = kSamplerParameterfvImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeDataSize() { + return static_cast<uint32_t>(sizeof(GLfloat) * 1); // NOLINT + } + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType) + + ComputeDataSize()); // NOLINT + } + + void SetHeader() { header.SetCmdByTotalSize<ValueType>(ComputeSize()); } + + void Init(GLuint _sampler, GLenum _pname, const GLfloat* _params) { + SetHeader(); + sampler = _sampler; + pname = _pname; + memcpy(ImmediateDataAddress(this), _params, ComputeDataSize()); + } + + void* Set(void* cmd, GLuint _sampler, GLenum _pname, const GLfloat* _params) { + static_cast<ValueType*>(cmd)->Init(_sampler, _pname, _params); + const uint32_t size = ComputeSize(); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + uint32_t sampler; + uint32_t pname; +}; + +COMPILE_ASSERT(sizeof(SamplerParameterfvImmediate) == 12, + Sizeof_SamplerParameterfvImmediate_is_not_12); +COMPILE_ASSERT(offsetof(SamplerParameterfvImmediate, header) == 0, + OffsetOf_SamplerParameterfvImmediate_header_not_0); +COMPILE_ASSERT(offsetof(SamplerParameterfvImmediate, sampler) == 4, + OffsetOf_SamplerParameterfvImmediate_sampler_not_4); +COMPILE_ASSERT(offsetof(SamplerParameterfvImmediate, pname) == 8, + OffsetOf_SamplerParameterfvImmediate_pname_not_8); + +struct SamplerParameteri { + typedef SamplerParameteri ValueType; + static const CommandId kCmdId = kSamplerParameteri; + 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 _sampler, GLenum _pname, GLint _param) { + SetHeader(); + sampler = _sampler; + pname = _pname; + param = _param; + } + + void* Set(void* cmd, GLuint _sampler, GLenum _pname, GLint _param) { + static_cast<ValueType*>(cmd)->Init(_sampler, _pname, _param); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t sampler; + uint32_t pname; + int32_t param; +}; + +COMPILE_ASSERT(sizeof(SamplerParameteri) == 16, + Sizeof_SamplerParameteri_is_not_16); +COMPILE_ASSERT(offsetof(SamplerParameteri, header) == 0, + OffsetOf_SamplerParameteri_header_not_0); +COMPILE_ASSERT(offsetof(SamplerParameteri, sampler) == 4, + OffsetOf_SamplerParameteri_sampler_not_4); +COMPILE_ASSERT(offsetof(SamplerParameteri, pname) == 8, + OffsetOf_SamplerParameteri_pname_not_8); +COMPILE_ASSERT(offsetof(SamplerParameteri, param) == 12, + OffsetOf_SamplerParameteri_param_not_12); + +struct SamplerParameterivImmediate { + typedef SamplerParameterivImmediate ValueType; + static const CommandId kCmdId = kSamplerParameterivImmediate; + static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeDataSize() { + return static_cast<uint32_t>(sizeof(GLint) * 1); // NOLINT + } + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType) + + ComputeDataSize()); // NOLINT + } + + void SetHeader() { header.SetCmdByTotalSize<ValueType>(ComputeSize()); } + + void Init(GLuint _sampler, GLenum _pname, const GLint* _params) { + SetHeader(); + sampler = _sampler; + pname = _pname; + memcpy(ImmediateDataAddress(this), _params, ComputeDataSize()); + } + + void* Set(void* cmd, GLuint _sampler, GLenum _pname, const GLint* _params) { + static_cast<ValueType*>(cmd)->Init(_sampler, _pname, _params); + const uint32_t size = ComputeSize(); + return NextImmediateCmdAddressTotalSize<ValueType>(cmd, size); + } + + gpu::CommandHeader header; + uint32_t sampler; + uint32_t pname; +}; + +COMPILE_ASSERT(sizeof(SamplerParameterivImmediate) == 12, + Sizeof_SamplerParameterivImmediate_is_not_12); +COMPILE_ASSERT(offsetof(SamplerParameterivImmediate, header) == 0, + OffsetOf_SamplerParameterivImmediate_header_not_0); +COMPILE_ASSERT(offsetof(SamplerParameterivImmediate, sampler) == 4, + OffsetOf_SamplerParameterivImmediate_sampler_not_4); +COMPILE_ASSERT(offsetof(SamplerParameterivImmediate, pname) == 8, + OffsetOf_SamplerParameterivImmediate_pname_not_8); + struct Scissor { typedef Scissor ValueType; static const CommandId kCmdId = kScissor; @@ -8264,6 +8936,39 @@ COMPILE_ASSERT(offsetof(BeginQueryEXT, sync_data_shm_offset) == 16, OffsetOf_BeginQueryEXT_sync_data_shm_offset_not_16); +struct BeginTransformFeedback { + typedef BeginTransformFeedback ValueType; + static const CommandId kCmdId = kBeginTransformFeedback; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLenum _primitivemode) { + SetHeader(); + primitivemode = _primitivemode; + } + + void* Set(void* cmd, GLenum _primitivemode) { + static_cast<ValueType*>(cmd)->Init(_primitivemode); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t primitivemode; +}; + +COMPILE_ASSERT(sizeof(BeginTransformFeedback) == 8, + Sizeof_BeginTransformFeedback_is_not_8); +COMPILE_ASSERT(offsetof(BeginTransformFeedback, header) == 0, + OffsetOf_BeginTransformFeedback_header_not_0); +COMPILE_ASSERT(offsetof(BeginTransformFeedback, primitivemode) == 4, + OffsetOf_BeginTransformFeedback_primitivemode_not_4); + struct EndQueryEXT { typedef EndQueryEXT ValueType; static const CommandId kCmdId = kEndQueryEXT; @@ -8300,6 +9005,33 @@ COMPILE_ASSERT(offsetof(EndQueryEXT, submit_count) == 8, OffsetOf_EndQueryEXT_submit_count_not_8); +struct EndTransformFeedback { + typedef EndTransformFeedback ValueType; + static const CommandId kCmdId = kEndTransformFeedback; + 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() { SetHeader(); } + + void* Set(void* cmd) { + static_cast<ValueType*>(cmd)->Init(); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; +}; + +COMPILE_ASSERT(sizeof(EndTransformFeedback) == 4, + Sizeof_EndTransformFeedback_is_not_4); +COMPILE_ASSERT(offsetof(EndTransformFeedback, header) == 0, + OffsetOf_EndTransformFeedback_header_not_0); + struct InsertEventMarkerEXT { typedef InsertEventMarkerEXT ValueType; static const CommandId kCmdId = kInsertEventMarkerEXT;
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 49c108c..ca81047 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -86,6 +86,18 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, BindSampler) { + cmds::BindSampler& cmd = *GetBufferAs<cmds::BindSampler>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLuint>(12)); + EXPECT_EQ(static_cast<uint32_t>(cmds::BindSampler::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.unit); + EXPECT_EQ(static_cast<GLuint>(12), cmd.sampler); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, BindTexture) { cmds::BindTexture& cmd = *GetBufferAs<cmds::BindTexture>(); void* next_cmd = @@ -98,6 +110,19 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, BindTransformFeedback) { + cmds::BindTransformFeedback& cmd = + *GetBufferAs<cmds::BindTransformFeedback>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLuint>(12)); + EXPECT_EQ(static_cast<uint32_t>(cmds::BindTransformFeedback::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLuint>(12), cmd.transformfeedback); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, BlendColor) { cmds::BlendColor& cmd = *GetBufferAs<cmds::BlendColor>(); void* next_cmd = @@ -518,6 +543,24 @@ // TODO(gman): Check that ids were inserted; } +TEST_F(GLES2FormatTest, DeleteSamplersImmediate) { + static GLuint ids[] = { + 12, 23, 34, + }; + cmds::DeleteSamplersImmediate& cmd = + *GetBufferAs<cmds::DeleteSamplersImmediate>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLsizei>(arraysize(ids)), ids); + EXPECT_EQ(static_cast<uint32_t>(cmds::DeleteSamplersImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(cmd.n * 4u), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLsizei>(arraysize(ids)), cmd.n); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, + sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u)); + // TODO(gman): Check that ids were inserted; +} + TEST_F(GLES2FormatTest, DeleteShader) { cmds::DeleteShader& cmd = *GetBufferAs<cmds::DeleteShader>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11)); @@ -546,6 +589,25 @@ // TODO(gman): Check that ids were inserted; } +TEST_F(GLES2FormatTest, DeleteTransformFeedbacksImmediate) { + static GLuint ids[] = { + 12, 23, 34, + }; + cmds::DeleteTransformFeedbacksImmediate& cmd = + *GetBufferAs<cmds::DeleteTransformFeedbacksImmediate>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLsizei>(arraysize(ids)), ids); + EXPECT_EQ( + static_cast<uint32_t>(cmds::DeleteTransformFeedbacksImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(cmd.n * 4u), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLsizei>(arraysize(ids)), cmd.n); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, + sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u)); + // TODO(gman): Check that ids were inserted; +} + TEST_F(GLES2FormatTest, DepthFunc) { cmds::DepthFunc& cmd = *GetBufferAs<cmds::DepthFunc>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11)); @@ -792,6 +854,23 @@ // TODO(gman): Check that ids were inserted; } +TEST_F(GLES2FormatTest, GenSamplersImmediate) { + static GLuint ids[] = { + 12, 23, 34, + }; + cmds::GenSamplersImmediate& cmd = *GetBufferAs<cmds::GenSamplersImmediate>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLsizei>(arraysize(ids)), ids); + EXPECT_EQ(static_cast<uint32_t>(cmds::GenSamplersImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(cmd.n * 4u), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLsizei>(arraysize(ids)), cmd.n); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, + sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u)); + // TODO(gman): Check that ids were inserted; +} + TEST_F(GLES2FormatTest, GenTexturesImmediate) { static GLuint ids[] = { 12, 23, 34, @@ -809,6 +888,24 @@ // TODO(gman): Check that ids were inserted; } +TEST_F(GLES2FormatTest, GenTransformFeedbacksImmediate) { + static GLuint ids[] = { + 12, 23, 34, + }; + cmds::GenTransformFeedbacksImmediate& cmd = + *GetBufferAs<cmds::GenTransformFeedbacksImmediate>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLsizei>(arraysize(ids)), ids); + EXPECT_EQ(static_cast<uint32_t>(cmds::GenTransformFeedbacksImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(cmd.n * 4u), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLsizei>(arraysize(ids)), cmd.n); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, + sizeof(cmd) + RoundSizeToMultipleOfEntries(arraysize(ids) * 4u)); + // TODO(gman): Check that ids were inserted; +} + TEST_F(GLES2FormatTest, GetActiveAttrib) { cmds::GetActiveAttrib& cmd = *GetBufferAs<cmds::GetActiveAttrib>(); void* next_cmd = @@ -1020,6 +1117,38 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, GetSamplerParameterfv) { + cmds::GetSamplerParameterfv& cmd = + *GetBufferAs<cmds::GetSamplerParameterfv>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLenum>(12), + static_cast<uint32_t>(13), static_cast<uint32_t>(14)); + EXPECT_EQ(static_cast<uint32_t>(cmds::GetSamplerParameterfv::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.sampler); + EXPECT_EQ(static_cast<GLenum>(12), cmd.pname); + EXPECT_EQ(static_cast<uint32_t>(13), cmd.params_shm_id); + EXPECT_EQ(static_cast<uint32_t>(14), cmd.params_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, GetSamplerParameteriv) { + cmds::GetSamplerParameteriv& cmd = + *GetBufferAs<cmds::GetSamplerParameteriv>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLenum>(12), + static_cast<uint32_t>(13), static_cast<uint32_t>(14)); + EXPECT_EQ(static_cast<uint32_t>(cmds::GetSamplerParameteriv::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.sampler); + EXPECT_EQ(static_cast<GLenum>(12), cmd.pname); + EXPECT_EQ(static_cast<uint32_t>(13), cmd.params_shm_id); + EXPECT_EQ(static_cast<uint32_t>(14), cmd.params_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, GetShaderiv) { cmds::GetShaderiv& cmd = *GetBufferAs<cmds::GetShaderiv>(); void* next_cmd = @@ -1338,6 +1467,19 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, IsSampler) { + cmds::IsSampler& cmd = *GetBufferAs<cmds::IsSampler>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12), + static_cast<uint32_t>(13)); + EXPECT_EQ(static_cast<uint32_t>(cmds::IsSampler::kCmdId), cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.sampler); + EXPECT_EQ(static_cast<uint32_t>(12), cmd.result_shm_id); + EXPECT_EQ(static_cast<uint32_t>(13), cmd.result_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, IsShader) { cmds::IsShader& cmd = *GetBufferAs<cmds::IsShader>(); void* next_cmd = @@ -1364,6 +1506,20 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, IsTransformFeedback) { + cmds::IsTransformFeedback& cmd = *GetBufferAs<cmds::IsTransformFeedback>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12), + static_cast<uint32_t>(13)); + EXPECT_EQ(static_cast<uint32_t>(cmds::IsTransformFeedback::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.transformfeedback); + EXPECT_EQ(static_cast<uint32_t>(12), cmd.result_shm_id); + EXPECT_EQ(static_cast<uint32_t>(13), cmd.result_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, LineWidth) { cmds::LineWidth& cmd = *GetBufferAs<cmds::LineWidth>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLfloat>(11)); @@ -1383,6 +1539,16 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, PauseTransformFeedback) { + cmds::PauseTransformFeedback& cmd = + *GetBufferAs<cmds::PauseTransformFeedback>(); + void* next_cmd = cmd.Set(&cmd); + EXPECT_EQ(static_cast<uint32_t>(cmds::PauseTransformFeedback::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, PixelStorei) { cmds::PixelStorei& cmd = *GetBufferAs<cmds::PixelStorei>(); void* next_cmd = @@ -1467,6 +1633,16 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, ResumeTransformFeedback) { + cmds::ResumeTransformFeedback& cmd = + *GetBufferAs<cmds::ResumeTransformFeedback>(); + void* next_cmd = cmd.Set(&cmd); + EXPECT_EQ(static_cast<uint32_t>(cmds::ResumeTransformFeedback::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, SampleCoverage) { cmds::SampleCoverage& cmd = *GetBufferAs<cmds::SampleCoverage>(); void* next_cmd = @@ -1479,6 +1655,72 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, SamplerParameterf) { + cmds::SamplerParameterf& cmd = *GetBufferAs<cmds::SamplerParameterf>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11), + static_cast<GLenum>(12), static_cast<GLfloat>(13)); + EXPECT_EQ(static_cast<uint32_t>(cmds::SamplerParameterf::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.sampler); + EXPECT_EQ(static_cast<GLenum>(12), cmd.pname); + EXPECT_EQ(static_cast<GLfloat>(13), cmd.param); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, SamplerParameterfvImmediate) { + const int kSomeBaseValueToTestWith = 51; + static GLfloat data[] = { + static_cast<GLfloat>(kSomeBaseValueToTestWith + 0), + }; + cmds::SamplerParameterfvImmediate& cmd = + *GetBufferAs<cmds::SamplerParameterfvImmediate>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLenum>(12), data); + EXPECT_EQ(static_cast<uint32_t>(cmds::SamplerParameterfvImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data)), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.sampler); + EXPECT_EQ(static_cast<GLenum>(12), cmd.pname); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data))); + // TODO(gman): Check that data was inserted; +} + +TEST_F(GLES2FormatTest, SamplerParameteri) { + cmds::SamplerParameteri& cmd = *GetBufferAs<cmds::SamplerParameteri>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11), + static_cast<GLenum>(12), static_cast<GLint>(13)); + EXPECT_EQ(static_cast<uint32_t>(cmds::SamplerParameteri::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.sampler); + EXPECT_EQ(static_cast<GLenum>(12), cmd.pname); + EXPECT_EQ(static_cast<GLint>(13), cmd.param); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, SamplerParameterivImmediate) { + const int kSomeBaseValueToTestWith = 51; + static GLint data[] = { + static_cast<GLint>(kSomeBaseValueToTestWith + 0), + }; + cmds::SamplerParameterivImmediate& cmd = + *GetBufferAs<cmds::SamplerParameterivImmediate>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLenum>(12), data); + EXPECT_EQ(static_cast<uint32_t>(cmds::SamplerParameterivImmediate::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data)), + cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.sampler); + EXPECT_EQ(static_cast<GLenum>(12), cmd.pname); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data))); + // TODO(gman): Check that data was inserted; +} + TEST_F(GLES2FormatTest, Scissor) { cmds::Scissor& cmd = *GetBufferAs<cmds::Scissor>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLint>(11), static_cast<GLint>(12), @@ -2962,6 +3204,17 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, BeginTransformFeedback) { + cmds::BeginTransformFeedback& cmd = + *GetBufferAs<cmds::BeginTransformFeedback>(); + void* next_cmd = cmd.Set(&cmd, static_cast<GLenum>(11)); + EXPECT_EQ(static_cast<uint32_t>(cmds::BeginTransformFeedback::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.primitivemode); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, EndQueryEXT) { cmds::EndQueryEXT& cmd = *GetBufferAs<cmds::EndQueryEXT>(); void* next_cmd = @@ -2974,6 +3227,15 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, EndTransformFeedback) { + cmds::EndTransformFeedback& cmd = *GetBufferAs<cmds::EndTransformFeedback>(); + void* next_cmd = cmd.Set(&cmd); + EXPECT_EQ(static_cast<uint32_t>(cmds::EndTransformFeedback::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, InsertEventMarkerEXT) { cmds::InsertEventMarkerEXT& cmd = *GetBufferAs<cmds::InsertEventMarkerEXT>(); void* next_cmd = cmd.Set(&cmd, static_cast<GLuint>(11));
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 4fe80f8..34957e4 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -18,232 +18,250 @@ OP(BindBuffer) /* 259 */ \ OP(BindFramebuffer) /* 260 */ \ OP(BindRenderbuffer) /* 261 */ \ - OP(BindTexture) /* 262 */ \ - OP(BlendColor) /* 263 */ \ - OP(BlendEquation) /* 264 */ \ - OP(BlendEquationSeparate) /* 265 */ \ - OP(BlendFunc) /* 266 */ \ - OP(BlendFuncSeparate) /* 267 */ \ - OP(BufferData) /* 268 */ \ - OP(BufferSubData) /* 269 */ \ - OP(CheckFramebufferStatus) /* 270 */ \ - OP(Clear) /* 271 */ \ - OP(ClearColor) /* 272 */ \ - OP(ClearDepthf) /* 273 */ \ - OP(ClearStencil) /* 274 */ \ - OP(ColorMask) /* 275 */ \ - OP(CompileShader) /* 276 */ \ - OP(CompressedTexImage2DBucket) /* 277 */ \ - OP(CompressedTexImage2D) /* 278 */ \ - OP(CompressedTexSubImage2DBucket) /* 279 */ \ - OP(CompressedTexSubImage2D) /* 280 */ \ - OP(CopyBufferSubData) /* 281 */ \ - OP(CopyTexImage2D) /* 282 */ \ - OP(CopyTexSubImage2D) /* 283 */ \ - OP(CreateProgram) /* 284 */ \ - OP(CreateShader) /* 285 */ \ - OP(CullFace) /* 286 */ \ - OP(DeleteBuffersImmediate) /* 287 */ \ - OP(DeleteFramebuffersImmediate) /* 288 */ \ - OP(DeleteProgram) /* 289 */ \ - OP(DeleteRenderbuffersImmediate) /* 290 */ \ - OP(DeleteShader) /* 291 */ \ - OP(DeleteTexturesImmediate) /* 292 */ \ - OP(DepthFunc) /* 293 */ \ - OP(DepthMask) /* 294 */ \ - OP(DepthRangef) /* 295 */ \ - OP(DetachShader) /* 296 */ \ - OP(Disable) /* 297 */ \ - OP(DisableVertexAttribArray) /* 298 */ \ - OP(DrawArrays) /* 299 */ \ - OP(DrawElements) /* 300 */ \ - OP(Enable) /* 301 */ \ - OP(EnableVertexAttribArray) /* 302 */ \ - OP(Finish) /* 303 */ \ - OP(Flush) /* 304 */ \ - OP(FramebufferRenderbuffer) /* 305 */ \ - OP(FramebufferTexture2D) /* 306 */ \ - OP(FramebufferTextureLayer) /* 307 */ \ - OP(FrontFace) /* 308 */ \ - OP(GenBuffersImmediate) /* 309 */ \ - OP(GenerateMipmap) /* 310 */ \ - OP(GenFramebuffersImmediate) /* 311 */ \ - OP(GenRenderbuffersImmediate) /* 312 */ \ - OP(GenTexturesImmediate) /* 313 */ \ - OP(GetActiveAttrib) /* 314 */ \ - OP(GetActiveUniform) /* 315 */ \ - OP(GetAttachedShaders) /* 316 */ \ - OP(GetAttribLocation) /* 317 */ \ - OP(GetBooleanv) /* 318 */ \ - OP(GetBufferParameteriv) /* 319 */ \ - OP(GetError) /* 320 */ \ - OP(GetFloatv) /* 321 */ \ - OP(GetFramebufferAttachmentParameteriv) /* 322 */ \ - OP(GetIntegerv) /* 323 */ \ - OP(GetInternalformativ) /* 324 */ \ - OP(GetProgramiv) /* 325 */ \ - OP(GetProgramInfoLog) /* 326 */ \ - OP(GetRenderbufferParameteriv) /* 327 */ \ - OP(GetShaderiv) /* 328 */ \ - OP(GetShaderInfoLog) /* 329 */ \ - OP(GetShaderPrecisionFormat) /* 330 */ \ - OP(GetShaderSource) /* 331 */ \ - OP(GetString) /* 332 */ \ - OP(GetTexParameterfv) /* 333 */ \ - OP(GetTexParameteriv) /* 334 */ \ - OP(GetUniformfv) /* 335 */ \ - OP(GetUniformiv) /* 336 */ \ - OP(GetUniformLocation) /* 337 */ \ - OP(GetVertexAttribfv) /* 338 */ \ - OP(GetVertexAttribiv) /* 339 */ \ - OP(GetVertexAttribPointerv) /* 340 */ \ - OP(Hint) /* 341 */ \ - OP(InvalidateFramebufferImmediate) /* 342 */ \ - OP(InvalidateSubFramebufferImmediate) /* 343 */ \ - OP(IsBuffer) /* 344 */ \ - OP(IsEnabled) /* 345 */ \ - OP(IsFramebuffer) /* 346 */ \ - OP(IsProgram) /* 347 */ \ - OP(IsRenderbuffer) /* 348 */ \ - OP(IsShader) /* 349 */ \ - OP(IsTexture) /* 350 */ \ - OP(LineWidth) /* 351 */ \ - OP(LinkProgram) /* 352 */ \ - OP(PixelStorei) /* 353 */ \ - OP(PolygonOffset) /* 354 */ \ - OP(ReadBuffer) /* 355 */ \ - OP(ReadPixels) /* 356 */ \ - OP(ReleaseShaderCompiler) /* 357 */ \ - OP(RenderbufferStorage) /* 358 */ \ - OP(SampleCoverage) /* 359 */ \ - OP(Scissor) /* 360 */ \ - OP(ShaderBinary) /* 361 */ \ - OP(ShaderSourceBucket) /* 362 */ \ - OP(StencilFunc) /* 363 */ \ - OP(StencilFuncSeparate) /* 364 */ \ - OP(StencilMask) /* 365 */ \ - OP(StencilMaskSeparate) /* 366 */ \ - OP(StencilOp) /* 367 */ \ - OP(StencilOpSeparate) /* 368 */ \ - OP(TexImage2D) /* 369 */ \ - OP(TexParameterf) /* 370 */ \ - OP(TexParameterfvImmediate) /* 371 */ \ - OP(TexParameteri) /* 372 */ \ - OP(TexParameterivImmediate) /* 373 */ \ - OP(TexStorage3D) /* 374 */ \ - OP(TexSubImage2D) /* 375 */ \ - OP(Uniform1f) /* 376 */ \ - OP(Uniform1fvImmediate) /* 377 */ \ - OP(Uniform1i) /* 378 */ \ - OP(Uniform1ivImmediate) /* 379 */ \ - OP(Uniform1ui) /* 380 */ \ - OP(Uniform1uivImmediate) /* 381 */ \ - OP(Uniform2f) /* 382 */ \ - OP(Uniform2fvImmediate) /* 383 */ \ - OP(Uniform2i) /* 384 */ \ - OP(Uniform2ivImmediate) /* 385 */ \ - OP(Uniform2ui) /* 386 */ \ - OP(Uniform2uivImmediate) /* 387 */ \ - OP(Uniform3f) /* 388 */ \ - OP(Uniform3fvImmediate) /* 389 */ \ - OP(Uniform3i) /* 390 */ \ - OP(Uniform3ivImmediate) /* 391 */ \ - OP(Uniform3ui) /* 392 */ \ - OP(Uniform3uivImmediate) /* 393 */ \ - OP(Uniform4f) /* 394 */ \ - OP(Uniform4fvImmediate) /* 395 */ \ - OP(Uniform4i) /* 396 */ \ - OP(Uniform4ivImmediate) /* 397 */ \ - OP(Uniform4ui) /* 398 */ \ - OP(Uniform4uivImmediate) /* 399 */ \ - OP(UniformMatrix2fvImmediate) /* 400 */ \ - OP(UniformMatrix2x3fvImmediate) /* 401 */ \ - OP(UniformMatrix2x4fvImmediate) /* 402 */ \ - OP(UniformMatrix3fvImmediate) /* 403 */ \ - OP(UniformMatrix3x2fvImmediate) /* 404 */ \ - OP(UniformMatrix3x4fvImmediate) /* 405 */ \ - OP(UniformMatrix4fvImmediate) /* 406 */ \ - OP(UniformMatrix4x2fvImmediate) /* 407 */ \ - OP(UniformMatrix4x3fvImmediate) /* 408 */ \ - OP(UseProgram) /* 409 */ \ - OP(ValidateProgram) /* 410 */ \ - OP(VertexAttrib1f) /* 411 */ \ - OP(VertexAttrib1fvImmediate) /* 412 */ \ - OP(VertexAttrib2f) /* 413 */ \ - OP(VertexAttrib2fvImmediate) /* 414 */ \ - OP(VertexAttrib3f) /* 415 */ \ - OP(VertexAttrib3fvImmediate) /* 416 */ \ - OP(VertexAttrib4f) /* 417 */ \ - OP(VertexAttrib4fvImmediate) /* 418 */ \ - OP(VertexAttribI4i) /* 419 */ \ - OP(VertexAttribI4ivImmediate) /* 420 */ \ - OP(VertexAttribI4ui) /* 421 */ \ - OP(VertexAttribI4uivImmediate) /* 422 */ \ - OP(VertexAttribIPointer) /* 423 */ \ - OP(VertexAttribPointer) /* 424 */ \ - OP(Viewport) /* 425 */ \ - OP(BlitFramebufferCHROMIUM) /* 426 */ \ - OP(RenderbufferStorageMultisampleCHROMIUM) /* 427 */ \ - OP(RenderbufferStorageMultisampleEXT) /* 428 */ \ - OP(FramebufferTexture2DMultisampleEXT) /* 429 */ \ - OP(TexStorage2DEXT) /* 430 */ \ - OP(GenQueriesEXTImmediate) /* 431 */ \ - OP(DeleteQueriesEXTImmediate) /* 432 */ \ - OP(BeginQueryEXT) /* 433 */ \ - OP(EndQueryEXT) /* 434 */ \ - OP(InsertEventMarkerEXT) /* 435 */ \ - OP(PushGroupMarkerEXT) /* 436 */ \ - OP(PopGroupMarkerEXT) /* 437 */ \ - OP(GenVertexArraysOESImmediate) /* 438 */ \ - OP(DeleteVertexArraysOESImmediate) /* 439 */ \ - OP(IsVertexArrayOES) /* 440 */ \ - OP(BindVertexArrayOES) /* 441 */ \ - OP(SwapBuffers) /* 442 */ \ - OP(GetMaxValueInBufferCHROMIUM) /* 443 */ \ - OP(EnableFeatureCHROMIUM) /* 444 */ \ - OP(ResizeCHROMIUM) /* 445 */ \ - OP(GetRequestableExtensionsCHROMIUM) /* 446 */ \ - OP(RequestExtensionCHROMIUM) /* 447 */ \ - OP(GetProgramInfoCHROMIUM) /* 448 */ \ - OP(GetTranslatedShaderSourceANGLE) /* 449 */ \ - OP(PostSubBufferCHROMIUM) /* 450 */ \ - OP(TexImageIOSurface2DCHROMIUM) /* 451 */ \ - OP(CopyTextureCHROMIUM) /* 452 */ \ - OP(DrawArraysInstancedANGLE) /* 453 */ \ - OP(DrawElementsInstancedANGLE) /* 454 */ \ - OP(VertexAttribDivisorANGLE) /* 455 */ \ - OP(GenMailboxCHROMIUM) /* 456 */ \ - OP(ProduceTextureCHROMIUMImmediate) /* 457 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 458 */ \ - OP(ConsumeTextureCHROMIUMImmediate) /* 459 */ \ - OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 460 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 461 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 462 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 463 */ \ - OP(IsValuebufferCHROMIUM) /* 464 */ \ - OP(BindValuebufferCHROMIUM) /* 465 */ \ - OP(SubscribeValueCHROMIUM) /* 466 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 467 */ \ - OP(UniformValuebufferCHROMIUM) /* 468 */ \ - OP(BindTexImage2DCHROMIUM) /* 469 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 470 */ \ - OP(TraceBeginCHROMIUM) /* 471 */ \ - OP(TraceEndCHROMIUM) /* 472 */ \ - OP(AsyncTexSubImage2DCHROMIUM) /* 473 */ \ - OP(AsyncTexImage2DCHROMIUM) /* 474 */ \ - OP(WaitAsyncTexImage2DCHROMIUM) /* 475 */ \ - OP(WaitAllAsyncTexImage2DCHROMIUM) /* 476 */ \ - OP(DiscardFramebufferEXTImmediate) /* 477 */ \ - OP(LoseContextCHROMIUM) /* 478 */ \ - OP(InsertSyncPointCHROMIUM) /* 479 */ \ - OP(WaitSyncPointCHROMIUM) /* 480 */ \ - OP(DrawBuffersEXTImmediate) /* 481 */ \ - OP(DiscardBackbufferCHROMIUM) /* 482 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 483 */ \ - OP(SwapInterval) /* 484 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 485 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 486 */ \ - OP(BlendBarrierKHR) /* 487 */ + OP(BindSampler) /* 262 */ \ + OP(BindTexture) /* 263 */ \ + OP(BindTransformFeedback) /* 264 */ \ + OP(BlendColor) /* 265 */ \ + OP(BlendEquation) /* 266 */ \ + OP(BlendEquationSeparate) /* 267 */ \ + OP(BlendFunc) /* 268 */ \ + OP(BlendFuncSeparate) /* 269 */ \ + OP(BufferData) /* 270 */ \ + OP(BufferSubData) /* 271 */ \ + OP(CheckFramebufferStatus) /* 272 */ \ + OP(Clear) /* 273 */ \ + OP(ClearColor) /* 274 */ \ + OP(ClearDepthf) /* 275 */ \ + OP(ClearStencil) /* 276 */ \ + OP(ColorMask) /* 277 */ \ + OP(CompileShader) /* 278 */ \ + OP(CompressedTexImage2DBucket) /* 279 */ \ + OP(CompressedTexImage2D) /* 280 */ \ + OP(CompressedTexSubImage2DBucket) /* 281 */ \ + OP(CompressedTexSubImage2D) /* 282 */ \ + OP(CopyBufferSubData) /* 283 */ \ + OP(CopyTexImage2D) /* 284 */ \ + OP(CopyTexSubImage2D) /* 285 */ \ + OP(CreateProgram) /* 286 */ \ + OP(CreateShader) /* 287 */ \ + OP(CullFace) /* 288 */ \ + OP(DeleteBuffersImmediate) /* 289 */ \ + OP(DeleteFramebuffersImmediate) /* 290 */ \ + OP(DeleteProgram) /* 291 */ \ + OP(DeleteRenderbuffersImmediate) /* 292 */ \ + OP(DeleteSamplersImmediate) /* 293 */ \ + OP(DeleteShader) /* 294 */ \ + OP(DeleteTexturesImmediate) /* 295 */ \ + OP(DeleteTransformFeedbacksImmediate) /* 296 */ \ + OP(DepthFunc) /* 297 */ \ + OP(DepthMask) /* 298 */ \ + OP(DepthRangef) /* 299 */ \ + OP(DetachShader) /* 300 */ \ + OP(Disable) /* 301 */ \ + OP(DisableVertexAttribArray) /* 302 */ \ + OP(DrawArrays) /* 303 */ \ + OP(DrawElements) /* 304 */ \ + OP(Enable) /* 305 */ \ + OP(EnableVertexAttribArray) /* 306 */ \ + OP(Finish) /* 307 */ \ + OP(Flush) /* 308 */ \ + OP(FramebufferRenderbuffer) /* 309 */ \ + OP(FramebufferTexture2D) /* 310 */ \ + OP(FramebufferTextureLayer) /* 311 */ \ + OP(FrontFace) /* 312 */ \ + OP(GenBuffersImmediate) /* 313 */ \ + OP(GenerateMipmap) /* 314 */ \ + OP(GenFramebuffersImmediate) /* 315 */ \ + OP(GenRenderbuffersImmediate) /* 316 */ \ + OP(GenSamplersImmediate) /* 317 */ \ + OP(GenTexturesImmediate) /* 318 */ \ + OP(GenTransformFeedbacksImmediate) /* 319 */ \ + OP(GetActiveAttrib) /* 320 */ \ + OP(GetActiveUniform) /* 321 */ \ + OP(GetAttachedShaders) /* 322 */ \ + OP(GetAttribLocation) /* 323 */ \ + OP(GetBooleanv) /* 324 */ \ + OP(GetBufferParameteriv) /* 325 */ \ + OP(GetError) /* 326 */ \ + OP(GetFloatv) /* 327 */ \ + OP(GetFramebufferAttachmentParameteriv) /* 328 */ \ + OP(GetIntegerv) /* 329 */ \ + OP(GetInternalformativ) /* 330 */ \ + OP(GetProgramiv) /* 331 */ \ + OP(GetProgramInfoLog) /* 332 */ \ + OP(GetRenderbufferParameteriv) /* 333 */ \ + OP(GetSamplerParameterfv) /* 334 */ \ + OP(GetSamplerParameteriv) /* 335 */ \ + OP(GetShaderiv) /* 336 */ \ + OP(GetShaderInfoLog) /* 337 */ \ + OP(GetShaderPrecisionFormat) /* 338 */ \ + OP(GetShaderSource) /* 339 */ \ + OP(GetString) /* 340 */ \ + OP(GetTexParameterfv) /* 341 */ \ + OP(GetTexParameteriv) /* 342 */ \ + OP(GetUniformfv) /* 343 */ \ + OP(GetUniformiv) /* 344 */ \ + OP(GetUniformLocation) /* 345 */ \ + OP(GetVertexAttribfv) /* 346 */ \ + OP(GetVertexAttribiv) /* 347 */ \ + OP(GetVertexAttribPointerv) /* 348 */ \ + OP(Hint) /* 349 */ \ + OP(InvalidateFramebufferImmediate) /* 350 */ \ + OP(InvalidateSubFramebufferImmediate) /* 351 */ \ + OP(IsBuffer) /* 352 */ \ + OP(IsEnabled) /* 353 */ \ + OP(IsFramebuffer) /* 354 */ \ + OP(IsProgram) /* 355 */ \ + OP(IsRenderbuffer) /* 356 */ \ + OP(IsSampler) /* 357 */ \ + OP(IsShader) /* 358 */ \ + OP(IsTexture) /* 359 */ \ + OP(IsTransformFeedback) /* 360 */ \ + OP(LineWidth) /* 361 */ \ + OP(LinkProgram) /* 362 */ \ + OP(PauseTransformFeedback) /* 363 */ \ + OP(PixelStorei) /* 364 */ \ + OP(PolygonOffset) /* 365 */ \ + OP(ReadBuffer) /* 366 */ \ + OP(ReadPixels) /* 367 */ \ + OP(ReleaseShaderCompiler) /* 368 */ \ + OP(RenderbufferStorage) /* 369 */ \ + OP(ResumeTransformFeedback) /* 370 */ \ + OP(SampleCoverage) /* 371 */ \ + OP(SamplerParameterf) /* 372 */ \ + OP(SamplerParameterfvImmediate) /* 373 */ \ + OP(SamplerParameteri) /* 374 */ \ + OP(SamplerParameterivImmediate) /* 375 */ \ + OP(Scissor) /* 376 */ \ + OP(ShaderBinary) /* 377 */ \ + OP(ShaderSourceBucket) /* 378 */ \ + OP(StencilFunc) /* 379 */ \ + OP(StencilFuncSeparate) /* 380 */ \ + OP(StencilMask) /* 381 */ \ + OP(StencilMaskSeparate) /* 382 */ \ + OP(StencilOp) /* 383 */ \ + OP(StencilOpSeparate) /* 384 */ \ + OP(TexImage2D) /* 385 */ \ + OP(TexParameterf) /* 386 */ \ + OP(TexParameterfvImmediate) /* 387 */ \ + OP(TexParameteri) /* 388 */ \ + OP(TexParameterivImmediate) /* 389 */ \ + OP(TexStorage3D) /* 390 */ \ + OP(TexSubImage2D) /* 391 */ \ + OP(Uniform1f) /* 392 */ \ + OP(Uniform1fvImmediate) /* 393 */ \ + OP(Uniform1i) /* 394 */ \ + OP(Uniform1ivImmediate) /* 395 */ \ + OP(Uniform1ui) /* 396 */ \ + OP(Uniform1uivImmediate) /* 397 */ \ + OP(Uniform2f) /* 398 */ \ + OP(Uniform2fvImmediate) /* 399 */ \ + OP(Uniform2i) /* 400 */ \ + OP(Uniform2ivImmediate) /* 401 */ \ + OP(Uniform2ui) /* 402 */ \ + OP(Uniform2uivImmediate) /* 403 */ \ + OP(Uniform3f) /* 404 */ \ + OP(Uniform3fvImmediate) /* 405 */ \ + OP(Uniform3i) /* 406 */ \ + OP(Uniform3ivImmediate) /* 407 */ \ + OP(Uniform3ui) /* 408 */ \ + OP(Uniform3uivImmediate) /* 409 */ \ + OP(Uniform4f) /* 410 */ \ + OP(Uniform4fvImmediate) /* 411 */ \ + OP(Uniform4i) /* 412 */ \ + OP(Uniform4ivImmediate) /* 413 */ \ + OP(Uniform4ui) /* 414 */ \ + OP(Uniform4uivImmediate) /* 415 */ \ + OP(UniformMatrix2fvImmediate) /* 416 */ \ + OP(UniformMatrix2x3fvImmediate) /* 417 */ \ + OP(UniformMatrix2x4fvImmediate) /* 418 */ \ + OP(UniformMatrix3fvImmediate) /* 419 */ \ + OP(UniformMatrix3x2fvImmediate) /* 420 */ \ + OP(UniformMatrix3x4fvImmediate) /* 421 */ \ + OP(UniformMatrix4fvImmediate) /* 422 */ \ + OP(UniformMatrix4x2fvImmediate) /* 423 */ \ + OP(UniformMatrix4x3fvImmediate) /* 424 */ \ + OP(UseProgram) /* 425 */ \ + OP(ValidateProgram) /* 426 */ \ + OP(VertexAttrib1f) /* 427 */ \ + OP(VertexAttrib1fvImmediate) /* 428 */ \ + OP(VertexAttrib2f) /* 429 */ \ + OP(VertexAttrib2fvImmediate) /* 430 */ \ + OP(VertexAttrib3f) /* 431 */ \ + OP(VertexAttrib3fvImmediate) /* 432 */ \ + OP(VertexAttrib4f) /* 433 */ \ + OP(VertexAttrib4fvImmediate) /* 434 */ \ + OP(VertexAttribI4i) /* 435 */ \ + OP(VertexAttribI4ivImmediate) /* 436 */ \ + OP(VertexAttribI4ui) /* 437 */ \ + OP(VertexAttribI4uivImmediate) /* 438 */ \ + OP(VertexAttribIPointer) /* 439 */ \ + OP(VertexAttribPointer) /* 440 */ \ + OP(Viewport) /* 441 */ \ + OP(BlitFramebufferCHROMIUM) /* 442 */ \ + OP(RenderbufferStorageMultisampleCHROMIUM) /* 443 */ \ + OP(RenderbufferStorageMultisampleEXT) /* 444 */ \ + OP(FramebufferTexture2DMultisampleEXT) /* 445 */ \ + OP(TexStorage2DEXT) /* 446 */ \ + OP(GenQueriesEXTImmediate) /* 447 */ \ + OP(DeleteQueriesEXTImmediate) /* 448 */ \ + OP(BeginQueryEXT) /* 449 */ \ + OP(BeginTransformFeedback) /* 450 */ \ + OP(EndQueryEXT) /* 451 */ \ + OP(EndTransformFeedback) /* 452 */ \ + OP(InsertEventMarkerEXT) /* 453 */ \ + OP(PushGroupMarkerEXT) /* 454 */ \ + OP(PopGroupMarkerEXT) /* 455 */ \ + OP(GenVertexArraysOESImmediate) /* 456 */ \ + OP(DeleteVertexArraysOESImmediate) /* 457 */ \ + OP(IsVertexArrayOES) /* 458 */ \ + OP(BindVertexArrayOES) /* 459 */ \ + OP(SwapBuffers) /* 460 */ \ + OP(GetMaxValueInBufferCHROMIUM) /* 461 */ \ + OP(EnableFeatureCHROMIUM) /* 462 */ \ + OP(ResizeCHROMIUM) /* 463 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 464 */ \ + OP(RequestExtensionCHROMIUM) /* 465 */ \ + OP(GetProgramInfoCHROMIUM) /* 466 */ \ + OP(GetTranslatedShaderSourceANGLE) /* 467 */ \ + OP(PostSubBufferCHROMIUM) /* 468 */ \ + OP(TexImageIOSurface2DCHROMIUM) /* 469 */ \ + OP(CopyTextureCHROMIUM) /* 470 */ \ + OP(DrawArraysInstancedANGLE) /* 471 */ \ + OP(DrawElementsInstancedANGLE) /* 472 */ \ + OP(VertexAttribDivisorANGLE) /* 473 */ \ + OP(GenMailboxCHROMIUM) /* 474 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 475 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 476 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 477 */ \ + OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 478 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 479 */ \ + OP(GenValuebuffersCHROMIUMImmediate) /* 480 */ \ + OP(DeleteValuebuffersCHROMIUMImmediate) /* 481 */ \ + OP(IsValuebufferCHROMIUM) /* 482 */ \ + OP(BindValuebufferCHROMIUM) /* 483 */ \ + OP(SubscribeValueCHROMIUM) /* 484 */ \ + OP(PopulateSubscribedValuesCHROMIUM) /* 485 */ \ + OP(UniformValuebufferCHROMIUM) /* 486 */ \ + OP(BindTexImage2DCHROMIUM) /* 487 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 488 */ \ + OP(TraceBeginCHROMIUM) /* 489 */ \ + OP(TraceEndCHROMIUM) /* 490 */ \ + OP(AsyncTexSubImage2DCHROMIUM) /* 491 */ \ + OP(AsyncTexImage2DCHROMIUM) /* 492 */ \ + OP(WaitAsyncTexImage2DCHROMIUM) /* 493 */ \ + OP(WaitAllAsyncTexImage2DCHROMIUM) /* 494 */ \ + OP(DiscardFramebufferEXTImmediate) /* 495 */ \ + OP(LoseContextCHROMIUM) /* 496 */ \ + OP(InsertSyncPointCHROMIUM) /* 497 */ \ + OP(WaitSyncPointCHROMIUM) /* 498 */ \ + OP(DrawBuffersEXTImmediate) /* 499 */ \ + OP(DiscardBackbufferCHROMIUM) /* 500 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 501 */ \ + OP(SwapInterval) /* 502 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 503 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 504 */ \ + OP(BlendBarrierKHR) /* 505 */ 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 bb809fc..e4ccbe7 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -48,6 +48,7 @@ static std::string GetStringRenderBufferParameter(uint32_t value); static std::string GetStringRenderBufferTarget(uint32_t value); static std::string GetStringResetStatus(uint32_t value); +static std::string GetStringSamplerParameter(uint32_t value); static std::string GetStringShaderBinaryFormat(uint32_t value); static std::string GetStringShaderParameter(uint32_t value); static std::string GetStringShaderPrecision(uint32_t value); @@ -68,6 +69,8 @@ static std::string GetStringTextureTarget(uint32_t value); static std::string GetStringTextureUsage(uint32_t value); static std::string GetStringTextureWrapMode(uint32_t value); +static std::string GetStringTransformFeedbackBindTarget(uint32_t value); +static std::string GetStringTransformFeedbackPrimitiveMode(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 b205347..03a6d4d 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -4938,6 +4938,22 @@ arraysize(string_table), value); } +std::string GLES2Util::GetStringSamplerParameter(uint32_t value) { + static const EnumToString string_table[] = { + {GL_TEXTURE_MAG_FILTER, "GL_TEXTURE_MAG_FILTER"}, + {GL_TEXTURE_MIN_FILTER, "GL_TEXTURE_MIN_FILTER"}, + {GL_TEXTURE_MIN_LOD, "GL_TEXTURE_MIN_LOD"}, + {GL_TEXTURE_MAX_LOD, "GL_TEXTURE_MAX_LOD"}, + {GL_TEXTURE_WRAP_S, "GL_TEXTURE_WRAP_S"}, + {GL_TEXTURE_WRAP_T, "GL_TEXTURE_WRAP_T"}, + {GL_TEXTURE_WRAP_R, "GL_TEXTURE_WRAP_R"}, + {GL_TEXTURE_COMPARE_MODE, "GL_TEXTURE_COMPARE_MODE"}, + {GL_TEXTURE_COMPARE_FUNC, "GL_TEXTURE_COMPARE_FUNC"}, + }; + return GLES2Util::GetQualifiedEnumString(string_table, + arraysize(string_table), value); +} + std::string GLES2Util::GetStringShaderBinaryFormat(uint32_t value) { return GLES2Util::GetQualifiedEnumString(NULL, 0, value); } @@ -5168,6 +5184,24 @@ arraysize(string_table), value); } +std::string GLES2Util::GetStringTransformFeedbackBindTarget(uint32_t value) { + static const EnumToString string_table[] = { + {GL_TRANSFORM_FEEDBACK, "GL_TRANSFORM_FEEDBACK"}, + }; + return GLES2Util::GetQualifiedEnumString(string_table, + arraysize(string_table), value); +} + +std::string GLES2Util::GetStringTransformFeedbackPrimitiveMode(uint32_t value) { + static const EnumToString string_table[] = { + {GL_POINTS, "GL_POINTS"}, + {GL_LINES, "GL_LINES"}, + {GL_TRIANGLES, "GL_TRIANGLES"}, + }; + 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/context_group.h b/gpu/command_buffer/service/context_group.h index b6b6483..f695a3e 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h
@@ -5,6 +5,7 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_CONTEXT_GROUP_H_ #define GPU_COMMAND_BUFFER_SERVICE_CONTEXT_GROUP_H_ +#include <map> #include <string> #include <vector> #include "base/basictypes.h" @@ -174,6 +175,43 @@ draw_buffer_ = buf; } + void AddSamplerId(GLuint client_id, GLuint service_id) { + samplers_id_map_[client_id] = service_id; + } + + bool GetSamplerServiceId(GLuint client_id, GLuint* service_id) const { + std::map<GLuint, GLuint>::const_iterator iter = + samplers_id_map_.find(client_id); + if (iter == samplers_id_map_.end()) + return false; + if (service_id) + *service_id = iter->second; + return true; + } + + void RemoveSamplerId(GLuint client_id) { + samplers_id_map_.erase(client_id); + } + + void AddTransformFeedbackId(GLuint client_id, GLuint service_id) { + transformfeedbacks_id_map_[client_id] = service_id; + } + + bool GetTransformFeedbackServiceId( + GLuint client_id, GLuint* service_id) const { + std::map<GLuint, GLuint>::const_iterator iter = + transformfeedbacks_id_map_.find(client_id); + if (iter == transformfeedbacks_id_map_.end()) + return false; + if (service_id) + *service_id = iter->second; + return true; + } + + void RemoveTransformFeedbackId(GLuint client_id) { + transformfeedbacks_id_map_.erase(client_id); + } + private: friend class base::RefCounted<ContextGroup>; ~ContextGroup(); @@ -223,6 +261,10 @@ std::vector<base::WeakPtr<gles2::GLES2Decoder> > decoders_; + // Mappings from client side IDs to service side IDs. + std::map<GLuint, GLuint> samplers_id_map_; + std::map<GLuint, GLuint> transformfeedbacks_id_map_; + GLenum draw_buffer_; DISALLOW_COPY_AND_ASSIGN(ContextGroup);
diff --git a/gpu/command_buffer/service/gl_context_virtual.cc b/gpu/command_buffer/service/gl_context_virtual.cc index a29e540..765dbee 100644 --- a/gpu/command_buffer/service/gl_context_virtual.cc +++ b/gpu/command_buffer/service/gl_context_virtual.cc
@@ -82,7 +82,7 @@ return shared_context_->GetHandle(); } -void GLContextVirtual::SetSwapInterval(int interval) { +void GLContextVirtual::OnSetSwapInterval(int interval) { shared_context_->SetSwapInterval(interval); }
diff --git a/gpu/command_buffer/service/gl_context_virtual.h b/gpu/command_buffer/service/gl_context_virtual.h index ed61016..7a79928 100644 --- a/gpu/command_buffer/service/gl_context_virtual.h +++ b/gpu/command_buffer/service/gl_context_virtual.h
@@ -41,7 +41,7 @@ void ReleaseCurrent(gfx::GLSurface* surface) override; bool IsCurrent(gfx::GLSurface* surface) override; void* GetHandle() override; - void SetSwapInterval(int interval) override; + void OnSetSwapInterval(int interval) override; std::string GetExtensions() override; bool GetTotalGpuMemory(size_t* bytes) override; void SetSafeToForceGpuSwitch() override;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index f97710e..7ea1a06 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1473,6 +1473,11 @@ // Wrapper for glReleaseShaderCompiler. void DoReleaseShaderCompiler() { } + // Wrappers for glSamplerParameter*v functions. + void DoSamplerParameterfv( + GLuint sampler, GLenum pname, const GLfloat* params); + void DoSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* params); + // Wrappers for glTexParameter functions. void DoTexParameterf(GLenum target, GLenum pname, GLfloat param); void DoTexParameteri(GLenum target, GLenum pname, GLint param); @@ -2955,6 +2960,10 @@ if (workarounds().regenerate_struct_names) driver_bug_workarounds |= SH_REGENERATE_STRUCT_NAMES; + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEmulateShaderPrecision)) + resources.WEBGL_debug_shader_precision = true; + vertex_translator_ = shader_translator_cache()->GetTranslator( GL_VERTEX_SHADER, shader_spec, @@ -4269,6 +4278,14 @@ void GLES2DecoderImpl::OnFboChanged() const { if (workarounds().restore_scissor_on_fbo_change) state_.fbo_binding_for_scissor_workaround_dirty_ = true; + + if (workarounds().gl_begin_gl_end_on_fbo_change_to_backbuffer) { + GLint bound_fbo_unsigned = -1; + glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_fbo_unsigned); + GLuint bound_fbo = static_cast<GLuint>(bound_fbo_unsigned); + if (surface_ && surface_->GetBackingFrameBufferObject() == bound_fbo) + surface_->NotifyWasBound(); + } } // Called after the FBO is checked for completeness. @@ -5858,6 +5875,18 @@ ExitCommandProcessingEarly(); }; +void GLES2DecoderImpl::DoSamplerParameterfv( + GLuint sampler, GLenum pname, const GLfloat* params) { + DCHECK(params); + glSamplerParameterf(sampler, pname, params[0]); +} + +void GLES2DecoderImpl::DoSamplerParameteriv( + GLuint sampler, GLenum pname, const GLint* params) { + DCHECK(params); + glSamplerParameteri(sampler, pname, params[0]); +} + void GLES2DecoderImpl::DoTexParameterf( GLenum target, GLenum pname, GLfloat param) { TextureRef* texture = texture_manager()->GetTextureInfoForTarget(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index f81b56a..b7877ff 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -80,6 +80,20 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBindSampler(uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::BindSampler& c = + *static_cast<const gles2::cmds::BindSampler*>(cmd_data); + (void)c; + GLuint unit = static_cast<GLuint>(c.unit); + GLuint sampler = c.sampler; + group_->GetSamplerServiceId(sampler, &sampler); + glBindSampler(unit, sampler); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleBindTexture(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::BindTexture& c = @@ -95,6 +109,21 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBindTransformFeedback( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::BindTransformFeedback& c = + *static_cast<const gles2::cmds::BindTransformFeedback*>(cmd_data); + (void)c; + GLenum target = static_cast<GLenum>(c.target); + GLuint transformfeedback = c.transformfeedback; + group_->GetTransformFeedbackServiceId(transformfeedback, &transformfeedback); + glBindTransformFeedback(target, transformfeedback); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleBlendColor(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::BlendColor& c = @@ -616,6 +645,34 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleDeleteSamplersImmediate( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::DeleteSamplersImmediate& c = + *static_cast<const gles2::cmds::DeleteSamplersImmediate*>(cmd_data); + (void)c; + GLsizei n = static_cast<GLsizei>(c.n); + uint32_t data_size; + if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { + return error::kOutOfBounds; + } + const GLuint* samplers = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); + if (samplers == NULL) { + return error::kOutOfBounds; + } + for (GLsizei ii = 0; ii < n; ++ii) { + GLuint service_id = 0; + if (group_->GetSamplerServiceId(samplers[ii], &service_id)) { + glDeleteSamplers(1, &service_id); + group_->RemoveSamplerId(samplers[ii]); + } + } + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleDeleteTexturesImmediate( uint32_t immediate_data_size, const void* cmd_data) { @@ -636,6 +693,35 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleDeleteTransformFeedbacksImmediate( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::DeleteTransformFeedbacksImmediate& c = + *static_cast<const gles2::cmds::DeleteTransformFeedbacksImmediate*>( + cmd_data); + (void)c; + GLsizei n = static_cast<GLsizei>(c.n); + uint32_t data_size; + if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { + return error::kOutOfBounds; + } + const GLuint* ids = + GetImmediateDataAs<const GLuint*>(c, data_size, immediate_data_size); + if (ids == NULL) { + return error::kOutOfBounds; + } + for (GLsizei ii = 0; ii < n; ++ii) { + GLuint service_id = 0; + if (group_->GetTransformFeedbackServiceId(ids[ii], &service_id)) { + glDeleteTransformFeedbacks(1, &service_id); + group_->RemoveTransformFeedbackId(ids[ii]); + } + } + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleDepthFunc(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::DepthFunc& c = @@ -934,6 +1020,37 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleGenSamplersImmediate( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GenSamplersImmediate& c = + *static_cast<const gles2::cmds::GenSamplersImmediate*>(cmd_data); + (void)c; + GLsizei n = static_cast<GLsizei>(c.n); + uint32_t data_size; + if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { + return error::kOutOfBounds; + } + GLuint* samplers = + GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); + if (samplers == NULL) { + return error::kOutOfBounds; + } + for (GLsizei ii = 0; ii < n; ++ii) { + if (group_->GetSamplerServiceId(samplers[ii], NULL)) { + return error::kInvalidArguments; + } + } + scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + glGenSamplers(n, service_ids.get()); + for (GLsizei ii = 0; ii < n; ++ii) { + group_->AddSamplerId(samplers[ii], service_ids[ii]); + } + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleGenTexturesImmediate( uint32_t immediate_data_size, const void* cmd_data) { @@ -956,6 +1073,37 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleGenTransformFeedbacksImmediate( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GenTransformFeedbacksImmediate& c = + *static_cast<const gles2::cmds::GenTransformFeedbacksImmediate*>( + cmd_data); + (void)c; + GLsizei n = static_cast<GLsizei>(c.n); + uint32_t data_size; + if (!SafeMultiplyUint32(n, sizeof(GLuint), &data_size)) { + return error::kOutOfBounds; + } + GLuint* ids = GetImmediateDataAs<GLuint*>(c, data_size, immediate_data_size); + if (ids == NULL) { + return error::kOutOfBounds; + } + for (GLsizei ii = 0; ii < n; ++ii) { + if (group_->GetTransformFeedbackServiceId(ids[ii], NULL)) { + return error::kInvalidArguments; + } + } + scoped_ptr<GLuint[]> service_ids(new GLuint[n]); + glGenTransformFeedbacks(n, service_ids.get()); + for (GLsizei ii = 0; ii < n; ++ii) { + group_->AddTransformFeedbackId(ids[ii], service_ids[ii]); + } + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleGetBooleanv(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::GetBooleanv& c = @@ -1273,6 +1421,76 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleGetSamplerParameterfv( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GetSamplerParameterfv& c = + *static_cast<const gles2::cmds::GetSamplerParameterfv*>(cmd_data); + (void)c; + GLuint sampler = c.sampler; + GLenum pname = static_cast<GLenum>(c.pname); + typedef cmds::GetSamplerParameterfv::Result Result; + GLsizei num_values = 0; + GetNumValuesReturnedForGLGet(pname, &num_values); + Result* result = GetSharedMemoryAs<Result*>( + c.params_shm_id, c.params_shm_offset, Result::ComputeSize(num_values)); + GLfloat* params = result ? result->GetData() : NULL; + if (params == NULL) { + return error::kOutOfBounds; + } + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetSamplerParameterfv"); + // Check that the client initialized the result. + if (result->size != 0) { + return error::kInvalidArguments; + } + group_->GetSamplerServiceId(sampler, &sampler); + glGetSamplerParameterfv(sampler, pname, params); + GLenum error = glGetError(); + if (error == GL_NO_ERROR) { + result->SetNumResults(num_values); + } else { + LOCAL_SET_GL_ERROR(error, "GetSamplerParameterfv", ""); + } + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleGetSamplerParameteriv( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GetSamplerParameteriv& c = + *static_cast<const gles2::cmds::GetSamplerParameteriv*>(cmd_data); + (void)c; + GLuint sampler = c.sampler; + GLenum pname = static_cast<GLenum>(c.pname); + typedef cmds::GetSamplerParameteriv::Result Result; + GLsizei num_values = 0; + GetNumValuesReturnedForGLGet(pname, &num_values); + 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; + } + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetSamplerParameteriv"); + // Check that the client initialized the result. + if (result->size != 0) { + return error::kInvalidArguments; + } + group_->GetSamplerServiceId(sampler, &sampler); + glGetSamplerParameteriv(sampler, pname, params); + GLenum error = glGetError(); + if (error == GL_NO_ERROR) { + result->SetNumResults(num_values); + } else { + LOCAL_SET_GL_ERROR(error, "GetSamplerParameteriv", ""); + } + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleGetShaderiv(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::GetShaderiv& c = @@ -1646,6 +1864,25 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleIsSampler(uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::IsSampler& c = + *static_cast<const gles2::cmds::IsSampler*>(cmd_data); + (void)c; + GLuint sampler = c.sampler; + typedef cmds::IsSampler::Result Result; + Result* result_dst = GetSharedMemoryAs<Result*>( + c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); + if (!result_dst) { + return error::kOutOfBounds; + } + group_->GetSamplerServiceId(sampler, &sampler); + *result_dst = glIsSampler(sampler); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleIsShader(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::IsShader& c = @@ -1678,6 +1915,26 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleIsTransformFeedback( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::IsTransformFeedback& c = + *static_cast<const gles2::cmds::IsTransformFeedback*>(cmd_data); + (void)c; + GLuint transformfeedback = c.transformfeedback; + typedef cmds::IsTransformFeedback::Result Result; + Result* result_dst = GetSharedMemoryAs<Result*>( + c.result_shm_id, c.result_shm_offset, sizeof(*result_dst)); + if (!result_dst) { + return error::kOutOfBounds; + } + group_->GetTransformFeedbackServiceId(transformfeedback, &transformfeedback); + *result_dst = glIsTransformFeedback(transformfeedback); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleLineWidth(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::LineWidth& c = @@ -1705,6 +1962,18 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandlePauseTransformFeedback( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::PauseTransformFeedback& c = + *static_cast<const gles2::cmds::PauseTransformFeedback*>(cmd_data); + (void)c; + glPauseTransformFeedback(); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandlePolygonOffset(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::PolygonOffset& c = @@ -1774,6 +2043,18 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleResumeTransformFeedback( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::ResumeTransformFeedback& c = + *static_cast<const gles2::cmds::ResumeTransformFeedback*>(cmd_data); + (void)c; + glResumeTransformFeedback(); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleSampleCoverage( uint32_t immediate_data_size, const void* cmd_data) { @@ -1786,6 +2067,91 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleSamplerParameterf( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::SamplerParameterf& c = + *static_cast<const gles2::cmds::SamplerParameterf*>(cmd_data); + (void)c; + GLuint sampler = c.sampler; + GLenum pname = static_cast<GLenum>(c.pname); + GLfloat param = static_cast<GLfloat>(c.param); + group_->GetSamplerServiceId(sampler, &sampler); + glSamplerParameterf(sampler, pname, param); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleSamplerParameterfvImmediate( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::SamplerParameterfvImmediate& c = + *static_cast<const gles2::cmds::SamplerParameterfvImmediate*>(cmd_data); + (void)c; + GLuint sampler = c.sampler; + GLenum pname = static_cast<GLenum>(c.pname); + uint32_t data_size; + if (!ComputeDataSize(1, sizeof(GLfloat), 1, &data_size)) { + return error::kOutOfBounds; + } + if (data_size > immediate_data_size) { + return error::kOutOfBounds; + } + const GLfloat* params = + GetImmediateDataAs<const GLfloat*>(c, data_size, immediate_data_size); + if (params == NULL) { + return error::kOutOfBounds; + } + group_->GetSamplerServiceId(sampler, &sampler); + DoSamplerParameterfv(sampler, pname, params); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleSamplerParameteri( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::SamplerParameteri& c = + *static_cast<const gles2::cmds::SamplerParameteri*>(cmd_data); + (void)c; + GLuint sampler = c.sampler; + GLenum pname = static_cast<GLenum>(c.pname); + GLint param = static_cast<GLint>(c.param); + group_->GetSamplerServiceId(sampler, &sampler); + glSamplerParameteri(sampler, pname, param); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleSamplerParameterivImmediate( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::SamplerParameterivImmediate& c = + *static_cast<const gles2::cmds::SamplerParameterivImmediate*>(cmd_data); + (void)c; + GLuint sampler = c.sampler; + GLenum pname = static_cast<GLenum>(c.pname); + uint32_t data_size; + if (!ComputeDataSize(1, sizeof(GLint), 1, &data_size)) { + return error::kOutOfBounds; + } + if (data_size > immediate_data_size) { + return error::kOutOfBounds; + } + const GLint* params = + GetImmediateDataAs<const GLint*>(c, data_size, immediate_data_size); + if (params == NULL) { + return error::kOutOfBounds; + } + DoSamplerParameteriv(sampler, pname, params); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleScissor(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::Scissor& c = @@ -3416,6 +3782,31 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBeginTransformFeedback( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::BeginTransformFeedback& c = + *static_cast<const gles2::cmds::BeginTransformFeedback*>(cmd_data); + (void)c; + GLenum primitivemode = static_cast<GLenum>(c.primitivemode); + glBeginTransformFeedback(primitivemode); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleEndTransformFeedback( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::EndTransformFeedback& c = + *static_cast<const gles2::cmds::EndTransformFeedback*>(cmd_data); + (void)c; + glEndTransformFeedback(); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleInsertEventMarkerEXT( uint32_t immediate_data_size, const void* cmd_data) {
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 014007a..2bc23a0 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
@@ -124,6 +124,18 @@ EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } +TEST_P(GLES2DecoderTest1, BindSamplerValidArgs) { + EXPECT_CALL(*gl_, BindSampler(1, kServiceSamplerId)); + SpecializedSetup<cmds::BindSampler, 0>(true); + cmds::BindSampler cmd; + cmd.Init(1, client_sampler_id_); + 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(GLES2DecoderTest1, BindTextureValidArgs) { EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId)); SpecializedSetup<cmds::BindTexture, 0>(true); @@ -163,6 +175,19 @@ EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } +TEST_P(GLES2DecoderTest1, BindTransformFeedbackValidArgs) { + EXPECT_CALL(*gl_, BindTransformFeedback(GL_TRANSFORM_FEEDBACK, + kServiceTransformFeedbackId)); + SpecializedSetup<cmds::BindTransformFeedback, 0>(true); + cmds::BindTransformFeedback cmd; + cmd.Init(GL_TRANSFORM_FEEDBACK, client_transformfeedback_id_); + 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(GLES2DecoderTest1, BlendColorValidArgs) { EXPECT_CALL(*gl_, BlendColor(1, 2, 3, 4)); SpecializedSetup<cmds::BlendColor, 0>(true); @@ -515,6 +540,34 @@ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } +TEST_P(GLES2DecoderTest1, DeleteSamplersImmediateValidArgs) { + EXPECT_CALL(*gl_, DeleteSamplers(1, Pointee(kServiceSamplerId))).Times(1); + cmds::DeleteSamplersImmediate& cmd = + *GetImmediateAs<cmds::DeleteSamplersImmediate>(); + SpecializedSetup<cmds::DeleteSamplersImmediate, 0>(true); + cmd.Init(1, &client_sampler_id_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(client_sampler_id_))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_FALSE(GetSamplerServiceId(client_sampler_id_, NULL)); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, + ExecuteImmediateCmd(cmd, sizeof(client_sampler_id_))); +} + +TEST_P(GLES2DecoderTest1, DeleteSamplersImmediateInvalidArgs) { + cmds::DeleteSamplersImmediate& cmd = + *GetImmediateAs<cmds::DeleteSamplersImmediate>(); + SpecializedSetup<cmds::DeleteSamplersImmediate, 0>(false); + GLuint temp = kInvalidClientId; + cmd.Init(1, &temp); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp))); +} + TEST_P(GLES2DecoderTest1, DeleteShaderValidArgs) { EXPECT_CALL(*gl_, DeleteShader(kServiceShaderId)); SpecializedSetup<cmds::DeleteShader, 0>(true); @@ -545,6 +598,36 @@ EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); } +TEST_P(GLES2DecoderTest1, DeleteTransformFeedbacksImmediateValidArgs) { + EXPECT_CALL(*gl_, DeleteTransformFeedbacks( + 1, Pointee(kServiceTransformFeedbackId))).Times(1); + cmds::DeleteTransformFeedbacksImmediate& cmd = + *GetImmediateAs<cmds::DeleteTransformFeedbacksImmediate>(); + SpecializedSetup<cmds::DeleteTransformFeedbacksImmediate, 0>(true); + cmd.Init(1, &client_transformfeedback_id_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, + ExecuteImmediateCmd(cmd, sizeof(client_transformfeedback_id_))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_FALSE( + GetTransformFeedbackServiceId(client_transformfeedback_id_, NULL)); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, + ExecuteImmediateCmd(cmd, sizeof(client_transformfeedback_id_))); +} + +TEST_P(GLES2DecoderTest1, DeleteTransformFeedbacksImmediateInvalidArgs) { + cmds::DeleteTransformFeedbacksImmediate& cmd = + *GetImmediateAs<cmds::DeleteTransformFeedbacksImmediate>(); + SpecializedSetup<cmds::DeleteTransformFeedbacksImmediate, 0>(false); + GLuint temp = kInvalidClientId; + cmd.Init(1, &temp); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp))); +} + TEST_P(GLES2DecoderTest1, DepthFuncValidArgs) { EXPECT_CALL(*gl_, DepthFunc(GL_NEVER)); SpecializedSetup<cmds::DepthFunc, 0>(true); @@ -874,6 +957,36 @@ ExecuteImmediateCmd(*cmd, sizeof(&client_renderbuffer_id_))); } +TEST_P(GLES2DecoderTest1, GenSamplersImmediateValidArgs) { + EXPECT_CALL(*gl_, GenSamplers(1, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + cmds::GenSamplersImmediate* cmd = + GetImmediateAs<cmds::GenSamplersImmediate>(); + GLuint temp = kNewClientId; + SpecializedSetup<cmds::GenSamplersImmediate, 0>(true); + decoder_->set_unsafe_es3_apis_enabled(true); + cmd->Init(1, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + GLuint service_id; + EXPECT_TRUE(GetSamplerServiceId(kNewClientId, &service_id)); + EXPECT_EQ(kNewServiceId, service_id); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(*cmd, sizeof(temp))); +} + +TEST_P(GLES2DecoderTest1, GenSamplersImmediateInvalidArgs) { + EXPECT_CALL(*gl_, GenSamplers(_, _)).Times(0); + cmds::GenSamplersImmediate* cmd = + GetImmediateAs<cmds::GenSamplersImmediate>(); + SpecializedSetup<cmds::GenSamplersImmediate, 0>(false); + cmd->Init(1, &client_sampler_id_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kInvalidArguments, + ExecuteImmediateCmd(*cmd, sizeof(&client_sampler_id_))); + decoder_->set_unsafe_es3_apis_enabled(false); +} + TEST_P(GLES2DecoderTest1, GenTexturesImmediateValidArgs) { EXPECT_CALL(*gl_, GenTextures(1, _)) .WillOnce(SetArgumentPointee<1>(kNewServiceId)); @@ -896,6 +1009,36 @@ EXPECT_EQ(error::kInvalidArguments, ExecuteImmediateCmd(*cmd, sizeof(&client_texture_id_))); } + +TEST_P(GLES2DecoderTest1, GenTransformFeedbacksImmediateValidArgs) { + EXPECT_CALL(*gl_, GenTransformFeedbacks(1, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + cmds::GenTransformFeedbacksImmediate* cmd = + GetImmediateAs<cmds::GenTransformFeedbacksImmediate>(); + GLuint temp = kNewClientId; + SpecializedSetup<cmds::GenTransformFeedbacksImmediate, 0>(true); + decoder_->set_unsafe_es3_apis_enabled(true); + cmd->Init(1, &temp); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + GLuint service_id; + EXPECT_TRUE(GetTransformFeedbackServiceId(kNewClientId, &service_id)); + EXPECT_EQ(kNewServiceId, service_id); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(*cmd, sizeof(temp))); +} + +TEST_P(GLES2DecoderTest1, GenTransformFeedbacksImmediateInvalidArgs) { + EXPECT_CALL(*gl_, GenTransformFeedbacks(_, _)).Times(0); + cmds::GenTransformFeedbacksImmediate* cmd = + GetImmediateAs<cmds::GenTransformFeedbacksImmediate>(); + SpecializedSetup<cmds::GenTransformFeedbacksImmediate, 0>(false); + cmd->Init(1, &client_transformfeedback_id_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kInvalidArguments, + ExecuteImmediateCmd(*cmd, sizeof(&client_transformfeedback_id_))); + decoder_->set_unsafe_es3_apis_enabled(false); +} // TODO(gman): GetActiveAttrib // TODO(gman): GetActiveUniform @@ -1397,6 +1540,56 @@ EXPECT_EQ(0u, result->size); } +TEST_P(GLES2DecoderTest1, GetSamplerParameterfvValidArgs) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + SpecializedSetup<cmds::GetSamplerParameterfv, 0>(true); + typedef cmds::GetSamplerParameterfv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, + GetSamplerParameterfv(kServiceSamplerId, GL_TEXTURE_MAG_FILTER, + result->GetData())); + result->size = 0; + cmds::GetSamplerParameterfv cmd; + cmd.Init(client_sampler_id_, GL_TEXTURE_MAG_FILTER, shared_memory_id_, + shared_memory_offset_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest1, GetSamplerParameterivValidArgs) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + SpecializedSetup<cmds::GetSamplerParameteriv, 0>(true); + typedef cmds::GetSamplerParameteriv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, + GetSamplerParameteriv(kServiceSamplerId, GL_TEXTURE_MAG_FILTER, + result->GetData())); + result->size = 0; + cmds::GetSamplerParameteriv cmd; + cmd.Init(client_sampler_id_, GL_TEXTURE_MAG_FILTER, shared_memory_id_, + shared_memory_offset_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ( + decoder_->GetGLES2Util()->GLGetNumValuesReturned(GL_TEXTURE_MAG_FILTER), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + TEST_P(GLES2DecoderTest1, GetShaderivValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -1752,129 +1945,4 @@ cmd.Init(GL_BLEND, shared_memory_id_, kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } - -TEST_P(GLES2DecoderTest1, IsFramebufferValidArgs) { - SpecializedSetup<cmds::IsFramebuffer, 0>(true); - cmds::IsFramebuffer cmd; - cmd.Init(client_framebuffer_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, IsFramebufferInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsFramebuffer, 0>(false); - cmds::IsFramebuffer cmd; - cmd.Init(client_framebuffer_id_, kInvalidSharedMemoryId, - shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_framebuffer_id_, shared_memory_id_, - kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest1, IsProgramValidArgs) { - SpecializedSetup<cmds::IsProgram, 0>(true); - cmds::IsProgram cmd; - cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, IsProgramInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsProgram, 0>(false); - cmds::IsProgram cmd; - cmd.Init(client_program_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_program_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest1, IsRenderbufferValidArgs) { - SpecializedSetup<cmds::IsRenderbuffer, 0>(true); - cmds::IsRenderbuffer cmd; - cmd.Init(client_renderbuffer_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, IsRenderbufferInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsRenderbuffer, 0>(false); - cmds::IsRenderbuffer cmd; - cmd.Init(client_renderbuffer_id_, kInvalidSharedMemoryId, - shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_renderbuffer_id_, shared_memory_id_, - kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest1, IsShaderValidArgs) { - SpecializedSetup<cmds::IsShader, 0>(true); - cmds::IsShader cmd; - cmd.Init(client_shader_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, IsShaderInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsShader, 0>(false); - cmds::IsShader cmd; - cmd.Init(client_shader_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_shader_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest1, IsTextureValidArgs) { - SpecializedSetup<cmds::IsTexture, 0>(true); - cmds::IsTexture cmd; - cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, IsTextureInvalidArgsBadSharedMemoryId) { - SpecializedSetup<cmds::IsTexture, 0>(false); - cmds::IsTexture cmd; - cmd.Init(client_texture_id_, kInvalidSharedMemoryId, shared_memory_offset_); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); - cmd.Init(client_texture_id_, shared_memory_id_, kInvalidSharedMemoryOffset); - EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); -} - -TEST_P(GLES2DecoderTest1, LineWidthValidArgs) { - EXPECT_CALL(*gl_, LineWidth(0.5f)); - SpecializedSetup<cmds::LineWidth, 0>(true); - cmds::LineWidth cmd; - cmd.Init(0.5f); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, LineWidthInvalidValue0_0) { - SpecializedSetup<cmds::LineWidth, 0>(false); - cmds::LineWidth cmd; - cmd.Init(0.0f); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, LineWidthNaNValue0) { - SpecializedSetup<cmds::LineWidth, 0>(false); - cmds::LineWidth cmd; - cmd.Init(nanf("")); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -} - -TEST_P(GLES2DecoderTest1, LinkProgramValidArgs) { - EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)); - SpecializedSetup<cmds::LinkProgram, 0>(true); - cmds::LinkProgram cmd; - cmd.Init(client_program_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} -// TODO(gman): PixelStorei - #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 602be42..6f8b706 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,6 +12,193 @@ #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, IsFramebufferValidArgs) { + SpecializedSetup<cmds::IsFramebuffer, 0>(true); + cmds::IsFramebuffer cmd; + cmd.Init(client_framebuffer_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, IsFramebufferInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsFramebuffer, 0>(false); + cmds::IsFramebuffer cmd; + cmd.Init(client_framebuffer_id_, kInvalidSharedMemoryId, + shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_framebuffer_id_, shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest2, IsProgramValidArgs) { + SpecializedSetup<cmds::IsProgram, 0>(true); + cmds::IsProgram cmd; + cmd.Init(client_program_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, IsProgramInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsProgram, 0>(false); + cmds::IsProgram cmd; + cmd.Init(client_program_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest2, IsRenderbufferValidArgs) { + SpecializedSetup<cmds::IsRenderbuffer, 0>(true); + cmds::IsRenderbuffer cmd; + cmd.Init(client_renderbuffer_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, IsRenderbufferInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsRenderbuffer, 0>(false); + cmds::IsRenderbuffer cmd; + cmd.Init(client_renderbuffer_id_, kInvalidSharedMemoryId, + shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_renderbuffer_id_, shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest2, IsSamplerValidArgs) { + EXPECT_CALL(*gl_, IsSampler(kServiceSamplerId)); + SpecializedSetup<cmds::IsSampler, 0>(true); + cmds::IsSampler cmd; + cmd.Init(client_sampler_id_, shared_memory_id_, shared_memory_offset_); + 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(GLES2DecoderTest2, IsSamplerInvalidArgsBadSharedMemoryId) { + EXPECT_CALL(*gl_, IsSampler(kServiceSamplerId)).Times(0); + SpecializedSetup<cmds::IsSampler, 0>(false); + decoder_->set_unsafe_es3_apis_enabled(true); + cmds::IsSampler cmd; + cmd.Init(client_sampler_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_sampler_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + decoder_->set_unsafe_es3_apis_enabled(true); +} + +TEST_P(GLES2DecoderTest2, IsShaderValidArgs) { + SpecializedSetup<cmds::IsShader, 0>(true); + cmds::IsShader cmd; + cmd.Init(client_shader_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, IsShaderInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsShader, 0>(false); + cmds::IsShader cmd; + cmd.Init(client_shader_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_shader_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest2, IsTextureValidArgs) { + SpecializedSetup<cmds::IsTexture, 0>(true); + cmds::IsTexture cmd; + cmd.Init(client_texture_id_, shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, IsTextureInvalidArgsBadSharedMemoryId) { + SpecializedSetup<cmds::IsTexture, 0>(false); + cmds::IsTexture cmd; + cmd.Init(client_texture_id_, kInvalidSharedMemoryId, shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_texture_id_, shared_memory_id_, kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest2, IsTransformFeedbackValidArgs) { + EXPECT_CALL(*gl_, IsTransformFeedback(kServiceTransformFeedbackId)); + SpecializedSetup<cmds::IsTransformFeedback, 0>(true); + cmds::IsTransformFeedback cmd; + cmd.Init(client_transformfeedback_id_, shared_memory_id_, + shared_memory_offset_); + 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(GLES2DecoderTest2, IsTransformFeedbackInvalidArgsBadSharedMemoryId) { + EXPECT_CALL(*gl_, IsTransformFeedback(kServiceTransformFeedbackId)).Times(0); + SpecializedSetup<cmds::IsTransformFeedback, 0>(false); + decoder_->set_unsafe_es3_apis_enabled(true); + cmds::IsTransformFeedback cmd; + cmd.Init(client_transformfeedback_id_, kInvalidSharedMemoryId, + shared_memory_offset_); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + cmd.Init(client_transformfeedback_id_, shared_memory_id_, + kInvalidSharedMemoryOffset); + EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); + decoder_->set_unsafe_es3_apis_enabled(true); +} + +TEST_P(GLES2DecoderTest2, LineWidthValidArgs) { + EXPECT_CALL(*gl_, LineWidth(0.5f)); + SpecializedSetup<cmds::LineWidth, 0>(true); + cmds::LineWidth cmd; + cmd.Init(0.5f); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, LineWidthInvalidValue0_0) { + SpecializedSetup<cmds::LineWidth, 0>(false); + cmds::LineWidth cmd; + cmd.Init(0.0f); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, LineWidthNaNValue0) { + SpecializedSetup<cmds::LineWidth, 0>(false); + cmds::LineWidth cmd; + cmd.Init(nanf("")); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, LinkProgramValidArgs) { + EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)); + SpecializedSetup<cmds::LinkProgram, 0>(true); + cmds::LinkProgram cmd; + cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, PauseTransformFeedbackValidArgs) { + EXPECT_CALL(*gl_, PauseTransformFeedback()); + SpecializedSetup<cmds::PauseTransformFeedback, 0>(true); + cmds::PauseTransformFeedback cmd; + cmd.Init(); + 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)); +} +// TODO(gman): PixelStorei + TEST_P(GLES2DecoderTest2, PolygonOffsetValidArgs) { EXPECT_CALL(*gl_, PolygonOffset(1, 2)); SpecializedSetup<cmds::PolygonOffset, 0>(true); @@ -71,6 +258,18 @@ EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } +TEST_P(GLES2DecoderTest2, ResumeTransformFeedbackValidArgs) { + EXPECT_CALL(*gl_, ResumeTransformFeedback()); + SpecializedSetup<cmds::ResumeTransformFeedback, 0>(true); + cmds::ResumeTransformFeedback cmd; + cmd.Init(); + 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(GLES2DecoderTest2, SampleCoverageValidArgs) { EXPECT_CALL(*gl_, SampleCoverage(1, true)); SpecializedSetup<cmds::SampleCoverage, 0>(true); @@ -80,6 +279,68 @@ EXPECT_EQ(GL_NO_ERROR, GetGLError()); } +TEST_P(GLES2DecoderTest2, SamplerParameterfValidArgs) { + EXPECT_CALL(*gl_, SamplerParameterf(kServiceSamplerId, GL_TEXTURE_MAG_FILTER, + GL_NEAREST)); + SpecializedSetup<cmds::SamplerParameterf, 0>(true); + cmds::SamplerParameterf cmd; + cmd.Init(client_sampler_id_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + 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(GLES2DecoderTest2, SamplerParameterfvImmediateValidArgs) { + cmds::SamplerParameterfvImmediate& cmd = + *GetImmediateAs<cmds::SamplerParameterfvImmediate>(); + SpecializedSetup<cmds::SamplerParameterfvImmediate, 0>(true); + GLfloat temp[1] = { + GL_NEAREST, + }; + cmd.Init(kServiceSamplerId, GL_TEXTURE_MAG_FILTER, &temp[0]); + EXPECT_CALL(*gl_, SamplerParameterf(kServiceSamplerId, GL_TEXTURE_MAG_FILTER, + *reinterpret_cast<GLfloat*>( + ImmediateDataAddress(&cmd)))); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp))); +} + +TEST_P(GLES2DecoderTest2, SamplerParameteriValidArgs) { + EXPECT_CALL(*gl_, SamplerParameteri(kServiceSamplerId, GL_TEXTURE_MAG_FILTER, + GL_NEAREST)); + SpecializedSetup<cmds::SamplerParameteri, 0>(true); + cmds::SamplerParameteri cmd; + cmd.Init(client_sampler_id_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + 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(GLES2DecoderTest2, SamplerParameterivImmediateValidArgs) { + cmds::SamplerParameterivImmediate& cmd = + *GetImmediateAs<cmds::SamplerParameterivImmediate>(); + SpecializedSetup<cmds::SamplerParameterivImmediate, 0>(true); + GLint temp[1] = { + GL_NEAREST, + }; + cmd.Init(kServiceSamplerId, GL_TEXTURE_MAG_FILTER, &temp[0]); + EXPECT_CALL(*gl_, SamplerParameteri( + kServiceSamplerId, GL_TEXTURE_MAG_FILTER, + *reinterpret_cast<GLint*>(ImmediateDataAddress(&cmd)))); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteImmediateCmd(cmd, sizeof(temp))); +} + TEST_P(GLES2DecoderTest2, ScissorValidArgs) { EXPECT_CALL(*gl_, Scissor(1, 2, 3, 4)); SpecializedSetup<cmds::Scissor, 0>(true); @@ -220,12 +481,14 @@ cmds::TexParameterfvImmediate& cmd = *GetImmediateAs<cmds::TexParameterfvImmediate>(); EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); + SpecializedSetup<cmds::TexParameterfvImmediate, 0>(false); GLfloat temp[1] = { GL_NEAREST, }; cmd.Init(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, &temp[0]); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -233,12 +496,14 @@ cmds::TexParameterfvImmediate& cmd = *GetImmediateAs<cmds::TexParameterfvImmediate>(); EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); + SpecializedSetup<cmds::TexParameterfvImmediate, 0>(false); GLfloat temp[1] = { GL_NEAREST, }; cmd.Init(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, &temp[0]); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -246,12 +511,14 @@ cmds::TexParameterfvImmediate& cmd = *GetImmediateAs<cmds::TexParameterfvImmediate>(); EXPECT_CALL(*gl_, TexParameterf(_, _, _)).Times(0); + SpecializedSetup<cmds::TexParameterfvImmediate, 0>(false); GLfloat temp[1] = { GL_NEAREST, }; cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, &temp[0]); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -311,12 +578,14 @@ cmds::TexParameterivImmediate& cmd = *GetImmediateAs<cmds::TexParameterivImmediate>(); EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); + SpecializedSetup<cmds::TexParameterivImmediate, 0>(false); GLint temp[1] = { GL_NEAREST, }; cmd.Init(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, &temp[0]); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -324,12 +593,14 @@ cmds::TexParameterivImmediate& cmd = *GetImmediateAs<cmds::TexParameterivImmediate>(); EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); + SpecializedSetup<cmds::TexParameterivImmediate, 0>(false); GLint temp[1] = { GL_NEAREST, }; cmd.Init(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, &temp[0]); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -337,12 +608,14 @@ cmds::TexParameterivImmediate& cmd = *GetImmediateAs<cmds::TexParameterivImmediate>(); EXPECT_CALL(*gl_, TexParameteri(_, _, _)).Times(0); + SpecializedSetup<cmds::TexParameterivImmediate, 0>(false); GLint temp[1] = { GL_NEAREST, }; cmd.Init(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, &temp[0]); EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp))); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -1006,35 +1279,17 @@ // TODO(gman): DeleteQueriesEXTImmediate // TODO(gman): BeginQueryEXT -// TODO(gman): EndQueryEXT - -// TODO(gman): InsertEventMarkerEXT - -// TODO(gman): PushGroupMarkerEXT - -TEST_P(GLES2DecoderTest2, PopGroupMarkerEXTValidArgs) { - SpecializedSetup<cmds::PopGroupMarkerEXT, 0>(true); - cmds::PopGroupMarkerEXT cmd; - cmd.Init(); +TEST_P(GLES2DecoderTest2, BeginTransformFeedbackValidArgs) { + EXPECT_CALL(*gl_, BeginTransformFeedback(GL_POINTS)); + SpecializedSetup<cmds::BeginTransformFeedback, 0>(true); + cmds::BeginTransformFeedback cmd; + cmd.Init(GL_POINTS); + 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)); } -// TODO(gman): GenVertexArraysOESImmediate -// TODO(gman): DeleteVertexArraysOESImmediate -// TODO(gman): IsVertexArrayOES -// TODO(gman): BindVertexArrayOES -// TODO(gman): SwapBuffers -// TODO(gman): GetMaxValueInBufferCHROMIUM -// TODO(gman): EnableFeatureCHROMIUM +// TODO(gman): EndQueryEXT -// TODO(gman): ResizeCHROMIUM -// TODO(gman): GetRequestableExtensionsCHROMIUM - -// TODO(gman): RequestExtensionCHROMIUM - -// TODO(gman): GetProgramInfoCHROMIUM - -// TODO(gman): GetTranslatedShaderSourceANGLE -// TODO(gman): PostSubBufferCHROMIUM -// TODO(gman): TexImageIOSurface2DCHROMIUM #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 6de18e0..506e045 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,46 @@ #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, EndTransformFeedbackValidArgs) { + EXPECT_CALL(*gl_, EndTransformFeedback()); + SpecializedSetup<cmds::EndTransformFeedback, 0>(true); + cmds::EndTransformFeedback cmd; + cmd.Init(); + 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)); +} +// TODO(gman): InsertEventMarkerEXT + +// TODO(gman): PushGroupMarkerEXT + +TEST_P(GLES2DecoderTest3, PopGroupMarkerEXTValidArgs) { + SpecializedSetup<cmds::PopGroupMarkerEXT, 0>(true); + cmds::PopGroupMarkerEXT cmd; + cmd.Init(); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} +// TODO(gman): GenVertexArraysOESImmediate +// TODO(gman): DeleteVertexArraysOESImmediate +// TODO(gman): IsVertexArrayOES +// TODO(gman): BindVertexArrayOES +// TODO(gman): SwapBuffers +// TODO(gman): GetMaxValueInBufferCHROMIUM +// TODO(gman): EnableFeatureCHROMIUM + +// TODO(gman): ResizeCHROMIUM +// TODO(gman): GetRequestableExtensionsCHROMIUM + +// TODO(gman): RequestExtensionCHROMIUM + +// TODO(gman): GetProgramInfoCHROMIUM + +// TODO(gman): GetTranslatedShaderSourceANGLE +// TODO(gman): PostSubBufferCHROMIUM +// TODO(gman): TexImageIOSurface2DCHROMIUM // TODO(gman): CopyTextureCHROMIUM // TODO(gman): DrawArraysInstancedANGLE // TODO(gman): DrawElementsInstancedANGLE
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 017f36c..aeb4477 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -90,7 +90,8 @@ client_framebuffer_id_(101), client_program_id_(102), client_renderbuffer_id_(103), - client_shader_id_(104), + client_sampler_id_(104), + client_shader_id_(105), client_texture_id_(106), client_element_buffer_id_(107), client_vertex_shader_id_(121), @@ -98,6 +99,7 @@ client_query_id_(123), client_vertexarray_id_(124), client_valuebuffer_id_(125), + client_transformfeedback_id_(126), service_renderbuffer_id_(0), service_renderbuffer_valid_(false), ignore_cached_state_for_test_(GetParam()), @@ -413,6 +415,24 @@ DoCreateProgram(client_program_id_, kServiceProgramId); DoCreateShader(GL_VERTEX_SHADER, client_shader_id_, kServiceShaderId); + // Unsafe commands. + bool reset_unsafe_es3_apis_enabled = false; + if (!decoder_->unsafe_es3_apis_enabled()) { + decoder_->set_unsafe_es3_apis_enabled(true); + reset_unsafe_es3_apis_enabled = true; + } + EXPECT_CALL(*gl_, GenSamplers(_, _)) + .WillOnce(SetArgumentPointee<1>(kServiceSamplerId)) + .RetiresOnSaturation(); + GenHelper<cmds::GenSamplersImmediate>(client_sampler_id_); + EXPECT_CALL(*gl_, GenTransformFeedbacks(_, _)) + .WillOnce(SetArgumentPointee<1>(kServiceTransformFeedbackId)) + .RetiresOnSaturation(); + GenHelper<cmds::GenTransformFeedbacksImmediate>(client_transformfeedback_id_); + if (reset_unsafe_es3_apis_enabled) { + decoder_->set_unsafe_es3_apis_enabled(false); + } + EXPECT_EQ(GL_NO_ERROR, GetGLError()); } @@ -1245,12 +1265,14 @@ const GLuint GLES2DecoderTestBase::kServiceBufferId; const GLuint GLES2DecoderTestBase::kServiceFramebufferId; const GLuint GLES2DecoderTestBase::kServiceRenderbufferId; +const GLuint GLES2DecoderTestBase::kServiceSamplerId; const GLuint GLES2DecoderTestBase::kServiceTextureId; const GLuint GLES2DecoderTestBase::kServiceProgramId; const GLuint GLES2DecoderTestBase::kServiceShaderId; const GLuint GLES2DecoderTestBase::kServiceElementBufferId; const GLuint GLES2DecoderTestBase::kServiceQueryId; const GLuint GLES2DecoderTestBase::kServiceVertexArrayId; +const GLuint GLES2DecoderTestBase::kServiceTransformFeedbackId; const int32 GLES2DecoderTestBase::kSharedMemoryId; const size_t GLES2DecoderTestBase::kSharedBufferSize;
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 459f1e0..6d6ddd2 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -131,6 +131,15 @@ return decoder_->GetQueryManager()->GetQuery(client_id); } + bool GetSamplerServiceId(GLuint client_id, GLuint* service_id) const { + return group_->GetSamplerServiceId(client_id, service_id); + } + + bool GetTransformFeedbackServiceId( + GLuint client_id, GLuint* service_id) const { + return group_->GetTransformFeedbackServiceId(client_id, service_id); + } + // This name doesn't match the underlying function, but doing it this way // prevents the need to special-case the unit test generation VertexAttribManager* GetVertexArrayInfo(GLuint client_id) { @@ -427,10 +436,12 @@ static const GLuint kServiceRenderbufferId = 303; static const GLuint kServiceTextureId = 304; static const GLuint kServiceProgramId = 305; - static const GLuint kServiceShaderId = 306; + static const GLuint kServiceSamplerId = 306; + static const GLuint kServiceShaderId = 307; static const GLuint kServiceElementBufferId = 308; static const GLuint kServiceQueryId = 309; static const GLuint kServiceVertexArrayId = 310; + static const GLuint kServiceTransformFeedbackId = 311; static const int32 kSharedMemoryId = 401; static const size_t kSharedBufferSize = 2048; @@ -520,6 +531,7 @@ GLuint client_framebuffer_id_; GLuint client_program_id_; GLuint client_renderbuffer_id_; + GLuint client_sampler_id_; GLuint client_shader_id_; GLuint client_texture_id_; GLuint client_element_buffer_id_; @@ -528,6 +540,7 @@ GLuint client_query_id_; GLuint client_vertexarray_id_; GLuint client_valuebuffer_id_; + GLuint client_transformfeedback_id_; uint32 shared_memory_id_; uint32 shared_memory_offset_;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index 3436e96..fc650d2 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -49,6 +49,7 @@ ValueValidator<GLenum> render_buffer_parameter; ValueValidator<GLenum> render_buffer_target; ValueValidator<GLenum> reset_status; +ValueValidator<GLenum> sampler_parameter; ValueValidator<GLenum> shader_binary_format; ValueValidator<GLenum> shader_parameter; ValueValidator<GLenum> shader_precision; @@ -69,6 +70,8 @@ ValueValidator<GLenum> texture_target; ValueValidator<GLenum> texture_usage; ValueValidator<GLenum> texture_wrap_mode; +ValueValidator<GLenum> transform_feedback_bind_target; +ValueValidator<GLenum> transform_feedback_primitive_mode; 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 d718391..a1e5c74 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -353,6 +353,18 @@ GL_UNKNOWN_CONTEXT_RESET_ARB, }; +static const GLenum valid_sampler_parameter_table[] = { + GL_TEXTURE_MAG_FILTER, + GL_TEXTURE_MIN_FILTER, + GL_TEXTURE_MIN_LOD, + GL_TEXTURE_MAX_LOD, + GL_TEXTURE_WRAP_S, + GL_TEXTURE_WRAP_T, + GL_TEXTURE_WRAP_R, + GL_TEXTURE_COMPARE_MODE, + GL_TEXTURE_COMPARE_FUNC, +}; + static const GLenum valid_shader_parameter_table[] = { GL_SHADER_TYPE, GL_DELETE_STATUS, @@ -502,6 +514,16 @@ GL_REPEAT, }; +static const GLenum valid_transform_feedback_bind_target_table[] = { + GL_TRANSFORM_FEEDBACK, +}; + +static const GLenum valid_transform_feedback_primitive_mode_table[] = { + GL_POINTS, + GL_LINES, + GL_TRIANGLES, +}; + static const GLenum valid_value_buffer_target_table[] = { GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, }; @@ -596,6 +618,8 @@ arraysize(valid_render_buffer_target_table)), reset_status(valid_reset_status_table, arraysize(valid_reset_status_table)), + sampler_parameter(valid_sampler_parameter_table, + arraysize(valid_sampler_parameter_table)), shader_binary_format(), shader_parameter(valid_shader_parameter_table, arraysize(valid_shader_parameter_table)), @@ -633,6 +657,12 @@ arraysize(valid_texture_usage_table)), texture_wrap_mode(valid_texture_wrap_mode_table, arraysize(valid_texture_wrap_mode_table)), + transform_feedback_bind_target( + valid_transform_feedback_bind_target_table, + arraysize(valid_transform_feedback_bind_target_table)), + transform_feedback_primitive_mode( + valid_transform_feedback_primitive_mode_table, + arraysize(valid_transform_feedback_primitive_mode_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_switches.cc b/gpu/command_buffer/service/gpu_switches.cc index 7298140..a2d43e9 100644 --- a/gpu/command_buffer/service/gpu_switches.cc +++ b/gpu/command_buffer/service/gpu_switches.cc
@@ -68,6 +68,14 @@ // Enable OpenGL ES 3 APIs without proper service side validation. const char kEnableUnsafeES3APIs[] = "enable-unsafe-es3-apis"; +// Include ANGLE's intermediate representation (AST) output in shader +// compilation info logs. +const char kGLShaderIntermOutput[] = "gl-shader-interm-output"; + +// Emulate ESSL lowp and mediump float precisions by mutating the shaders to +// round intermediate values in ANGLE. +const char kEmulateShaderPrecision[] = "emulate-shader-precision"; + const char* kGpuSwitches[] = { kCompileShaderAlwaysSucceeds, kDisableGLErrorLimit, @@ -86,6 +94,8 @@ kEnableShareGroupAsyncTextureUpload, kEnableUnsafeES3APIs, kEnableSubscribeUniformExtension, + kGLShaderIntermOutput, + kEmulateShaderPrecision, }; const int kNumGpuSwitches = arraysize(kGpuSwitches);
diff --git a/gpu/command_buffer/service/gpu_switches.h b/gpu/command_buffer/service/gpu_switches.h index c7a34f6..5ed2861 100644 --- a/gpu/command_buffer/service/gpu_switches.h +++ b/gpu/command_buffer/service/gpu_switches.h
@@ -29,6 +29,8 @@ GPU_EXPORT extern const char kEnableSubscribeUniformExtension[]; GPU_EXPORT extern const char kEnableThreadedTextureMailboxes[]; GPU_EXPORT extern const char kEnableUnsafeES3APIs[]; +GPU_EXPORT extern const char kGLShaderIntermOutput[]; +GPU_EXPORT extern const char kEmulateShaderPrecision[]; GPU_EXPORT extern const char* kGpuSwitches[]; GPU_EXPORT extern const int kNumGpuSwitches;
diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc index 576c7c8..d7def00 100644 --- a/gpu/command_buffer/service/shader_translator.cc +++ b/gpu/command_buffer/service/shader_translator.cc
@@ -14,7 +14,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" -#include "ui/gl/gl_switches.h" +#include "gpu/command_buffer/service/gpu_switches.h" namespace gpu { namespace gles2 {
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index b447c1a..8014746 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.11", + "version": "7.12", "entries": [ { "id": 1, @@ -1081,6 +1081,17 @@ "features": [ "gl_clear_broken" ] + }, + { + "id": 96, + "description": "glBindFramebuffer sometimes requires a glBegin/End to take effect", + "cr_bugs": [435786], + "os": { + "type": "macosx" + }, + "features": [ + "gl_begin_gl_end_on_fbo_change_to_backbuffer" + ] } ] }
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h index 841a470..77d721b 100644 --- a/gpu/config/gpu_driver_bug_workaround_type.h +++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -54,6 +54,8 @@ force_gl_finish_after_compositing) \ GPU_OP(FORCE_INTEGRATED_GPU, \ force_integrated_gpu) \ + GPU_OP(GL_BEGIN_GL_END_ON_FBO_CHANGE_TO_BACKBUFFER, \ + gl_begin_gl_end_on_fbo_change_to_backbuffer) \ GPU_OP(GL_CLEAR_BROKEN, \ gl_clear_broken) \ GPU_OP(INIT_GL_POSITION_IN_VERTEX_SHADER, \
diff --git a/gpu/tools/compositor_model_bench/compositor_model_bench.cc b/gpu/tools/compositor_model_bench/compositor_model_bench.cc index 5108a87..375bce2 100644 --- a/gpu/tools/compositor_model_bench/compositor_model_bench.cc +++ b/gpu/tools/compositor_model_bench/compositor_model_bench.cc
@@ -61,12 +61,12 @@ : current_sim_(NULL), output_path_(output_path), seconds_per_test_(seconds_per_test), - weak_factory_(this), display_(NULL), window_(0), gl_context_(NULL), window_width_(WINDOW_WIDTH), - window_height_(WINDOW_HEIGHT) { + window_height_(WINDOW_HEIGHT), + weak_factory_(this) { } ~Simulator() { @@ -344,12 +344,12 @@ // Amount of time to run each simulation int seconds_per_test_; // GUI data - base::WeakPtrFactory<Simulator> weak_factory_; Display* display_; Window window_; GLXContext gl_context_; int window_width_; int window_height_; + base::WeakPtrFactory<Simulator> weak_factory_; }; int main(int argc, char* argv[]) {
diff --git a/mojo/converters/surfaces/surfaces_type_converters.cc b/mojo/converters/surfaces/surfaces_type_converters.cc index 1a6ab99..4d563e1 100644 --- a/mojo/converters/surfaces/surfaces_type_converters.cc +++ b/mojo/converters/surfaces/surfaces_type_converters.cc
@@ -158,7 +158,8 @@ tile_state->resource_id, tile_state->tex_coord_rect.To<gfx::RectF>(), tile_state->texture_size.To<gfx::Size>(), - tile_state->swizzle_contents); + tile_state->swizzle_contents, + tile_state->nearest_neighbor); break; } case MATERIAL_YUV_VIDEO_CONTENT: {
diff --git a/mojo/public/python/BUILD.gn b/mojo/public/python/BUILD.gn index 51bd6eb..70c2dca 100644 --- a/mojo/public/python/BUILD.gn +++ b/mojo/public/python/BUILD.gn
@@ -16,44 +16,40 @@ # GYP version: mojo.gyp:mojo_python_system python_binary_module("system") { python_base_module = "mojo" - sources = [ + cython_sources = [ "mojo/c_core.pxd", "mojo/system.pyx", ] - configs = [ "../build/config:mojo_sdk" ] deps = [ ":base", "../c/environment", - "../c/system", + "../c/system:for_shared_library", "../cpp/environment:standalone", "../cpp/system", "../cpp/utility", "../cpp/bindings:callback", - "../platform/native:system", ] } python_binary_module("system_impl") { python_base_module = "mojo" - sources = [ + cython_sources = [ "mojo/c_core.pxd", "mojo/c_environment.pxd", "mojo/system_impl.pyx", ] - additional_sources = [ + sources = [ "src/python_system_helper.cc", "src/python_system_helper.h", ] - configs = [ "../build/config:mojo_sdk" ] deps = [ ":base", "../c/environment", - "../c/system", + "../c/system:for_shared_library", "../cpp/environment:standalone", "../cpp/system", "../cpp/utility", "../cpp/bindings:callback", - "../platform/native:system", ] }
diff --git a/mojo/python/BUILD.gn b/mojo/python/BUILD.gn index f96c2cc..8cbb5fa 100644 --- a/mojo/python/BUILD.gn +++ b/mojo/python/BUILD.gn
@@ -16,7 +16,7 @@ # GYP version: mojo/mojo.gyp:mojo_python_embedder python_binary_module("embedder") { python_base_module = "mojo" - sources = [ + cython_sources = [ "system/mojo/embedder.pyx", ] deps = [ @@ -38,7 +38,7 @@ python_binary_module("validation_util") { python_base_module = "mojo/tests" - sources = [ + cython_sources = [ "system/mojo/tests/validation_util.pyx", ] deps = [
diff --git a/mojo/services/surfaces/public/interfaces/quads.mojom b/mojo/services/surfaces/public/interfaces/quads.mojom index 88006f7..52a667d 100644 --- a/mojo/services/surfaces/public/interfaces/quads.mojom +++ b/mojo/services/surfaces/public/interfaces/quads.mojom
@@ -72,6 +72,7 @@ Size texture_size; bool swizzle_contents; uint32 resource_id; + bool nearest_neighbor; }; struct StreamVideoQuadState {};
diff --git a/mojo/tools/roll/cc_strip_video.patch b/mojo/tools/roll/cc_strip_video.patch index df14109..aefb753 100644 --- a/mojo/tools/roll/cc_strip_video.patch +++ b/mojo/tools/roll/cc_strip_video.patch
@@ -1,8 +1,8 @@ diff --git a/cc/BUILD.gn b/cc/BUILD.gn -index c744c5b..16a1589 100644 +index 826e12c..13e974d 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn -@@ -212,13 +212,6 @@ component("cc") { +@@ -213,13 +213,6 @@ component("cc") { "layers/ui_resource_layer.h", "layers/ui_resource_layer_impl.cc", "layers/ui_resource_layer_impl.h", @@ -16,7 +16,7 @@ "output/begin_frame_args.cc", "output/begin_frame_args.h", "output/bsp_tree.cc", -@@ -453,8 +446,6 @@ component("cc") { +@@ -456,8 +449,6 @@ component("cc") { "resources/ui_resource_client.h", "resources/ui_resource_request.cc", "resources/ui_resource_request.h", @@ -25,16 +25,16 @@ "resources/zero_copy_tile_task_worker_pool.cc", "resources/zero_copy_tile_task_worker_pool.h", "scheduler/begin_frame_source.cc", -@@ -588,8 +579,6 @@ source_set("test_support") { +@@ -590,8 +581,6 @@ source_set("test_support") { "test/fake_tile_manager_client.h", "test/fake_ui_resource_layer_tree_host_impl.cc", "test/fake_ui_resource_layer_tree_host_impl.h", - "test/fake_video_frame_provider.cc", - "test/fake_video_frame_provider.h", + "test/failure_output_surface.cc", + "test/failure_output_surface.h", "test/geometry_test_utils.cc", - "test/geometry_test_utils.h", - "test/test_in_process_context_provider.cc", -@@ -744,7 +733,6 @@ test("cc_unittests") { +@@ -747,7 +736,6 @@ test("cc_unittests") { "layers/tiled_layer_unittest.cc", "layers/ui_resource_layer_impl_unittest.cc", "layers/ui_resource_layer_unittest.cc", @@ -42,7 +42,7 @@ "output/begin_frame_args_unittest.cc", "output/delegating_renderer_unittest.cc", "output/filter_operations_unittest.cc", -@@ -775,7 +763,6 @@ test("cc_unittests") { +@@ -778,7 +766,6 @@ test("cc_unittests") { "resources/texture_uploader_unittest.cc", "resources/tile_manager_unittest.cc", "resources/tile_priority_unittest.cc", @@ -50,7 +50,7 @@ "scheduler/begin_frame_source_unittest.cc", "scheduler/delay_based_time_source_unittest.cc", "scheduler/scheduler_state_machine_unittest.cc", -@@ -804,7 +791,6 @@ test("cc_unittests") { +@@ -807,7 +794,6 @@ test("cc_unittests") { "trees/layer_tree_host_unittest_picture.cc", "trees/layer_tree_host_unittest_proxy.cc", "trees/layer_tree_host_unittest_scroll.cc", @@ -229,7 +229,7 @@ - -} // namespace cc diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc -index 27f40eb..49af1c3 100644 +index ee94a4c..7896bb8 100644 --- a/cc/output/gl_renderer.cc +++ b/cc/output/gl_renderer.cc @@ -13,7 +13,6 @@ @@ -241,7 +241,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 0c2bc3d..d112ed1 100644 +index b51aef6..58205a9 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc @@ -12,7 +12,6 @@ @@ -252,7 +252,7 @@ #include "third_party/skia/include/core/SkColorPriv.h" #include "third_party/skia/include/core/SkImageFilter.h" #include "third_party/skia/include/core/SkMatrix.h" -@@ -385,346 +384,6 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) { +@@ -386,346 +385,6 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) { FuzzyPixelOffByOneComparator(true))); } @@ -624,7 +624,7 @@ #include "third_party/skia/include/core/SkMatrix.h" #include "third_party/skia/include/core/SkPicture.h" diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc -index f31cde0..4e070e2 100644 +index fc4780f..61bda89 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -27,7 +27,6 @@ @@ -667,7 +667,7 @@ } LayerTreeSettings DefaultSettings() { -@@ -5247,18 +5242,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { +@@ -5248,18 +5243,6 @@ TEST_F(LayerTreeHostImplTest, LayersFreeTextures) { LayerImpl::Create(host_impl_->active_tree(), 1); root_layer->SetBounds(gfx::Size(10, 10)); @@ -686,7 +686,7 @@ scoped_ptr<IOSurfaceLayerImpl> io_surface_layer = IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5); io_surface_layer->SetBounds(gfx::Size(10, 10)); -@@ -6321,16 +6304,6 @@ TEST_F(LayerTreeHostImplTest, +@@ -6322,16 +6305,6 @@ TEST_F(LayerTreeHostImplTest, scoped_ptr<SolidColorLayerImpl> root_layer = SolidColorLayerImpl::Create(host_impl_->active_tree(), 1); @@ -704,7 +704,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 712909f..51c5d7e 100644 +index a343466..eee6275 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc @@ -18,7 +18,6 @@ @@ -723,7 +723,7 @@ #include "cc/test/geometry_test_utils.h" #include "cc/test/layer_tree_test.h" #include "cc/test/test_shared_bitmap_manager.h" -@@ -4189,28 +4187,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest { +@@ -4183,28 +4181,6 @@ class LayerInvalidateCausesDraw : public LayerTreeHostTest { int num_draws_; }; @@ -753,7 +753,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 2d23d75..b646e6a 100644 +index 24ffcd4..cc4f28f 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc @@ -15,8 +15,6 @@ @@ -764,8 +764,8 @@ -#include "cc/layers/video_layer_impl.h" #include "cc/output/filter_operations.h" #include "cc/resources/single_release_callback.h" - #include "cc/test/fake_content_layer.h" -@@ -32,7 +30,6 @@ + #include "cc/test/failure_output_surface.h" +@@ -33,7 +31,6 @@ #include "cc/test/fake_picture_layer_impl.h" #include "cc/test/fake_scoped_ui_resource.h" #include "cc/test/fake_scrollbar.h" @@ -773,7 +773,7 @@ #include "cc/test/layer_tree_test.h" #include "cc/test/render_pass_test_common.h" #include "cc/test/test_context_provider.h" -@@ -42,9 +39,6 @@ +@@ -43,9 +40,6 @@ #include "cc/trees/layer_tree_impl.h" #include "cc/trees/single_thread_proxy.h" #include "gpu/GLES2/gl2extchromium.h" @@ -783,7 +783,7 @@ namespace cc { namespace { -@@ -65,7 +59,6 @@ class LayerTreeHostContextTest : public LayerTreeTest { +@@ -66,7 +60,6 @@ class LayerTreeHostContextTest : public LayerTreeTest { context_should_support_io_surface_(false), fallback_context_works_(false), async_output_surface_creation_(false) { @@ -791,7 +791,7 @@ } void LoseContext() { -@@ -1083,49 +1076,6 @@ class LayerTreeHostContextTestDontUseLostResources +@@ -1041,49 +1034,6 @@ class LayerTreeHostContextTestDontUseLostResources layer_with_mask->SetMaskLayer(mask.get()); root->AddChild(layer_with_mask); @@ -841,7 +841,7 @@ if (!delegating_renderer()) { // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335 scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create(); -@@ -1155,14 +1105,6 @@ class LayerTreeHostContextTestDontUseLostResources +@@ -1113,14 +1063,6 @@ class LayerTreeHostContextTestDontUseLostResources void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { LayerTreeHostContextTest::CommitCompleteOnThread(host_impl); @@ -856,7 +856,7 @@ } DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, -@@ -1212,14 +1154,6 @@ class LayerTreeHostContextTestDontUseLostResources +@@ -1169,14 +1111,6 @@ class LayerTreeHostContextTestDontUseLostResources scoped_refptr<DelegatedFrameResourceCollection> delegated_resource_collection_; scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
diff --git a/net/BUILD.gn b/net/BUILD.gn index 4cecaef..c4c928e 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -566,6 +566,8 @@ "server/http_server_response_info.h", "server/web_socket.cc", "server/web_socket.h", + "server/web_socket_encoder.cc", + "server/web_socket_encoder.h", ] configs += [ "//build/config/compiler:wexit_time_destructors", @@ -677,6 +679,8 @@ "test/spawned_test_server/spawner_communicator.h", "test/url_request/url_request_failed_job.cc", "test/url_request/url_request_failed_job.h", + "test/url_request/url_request_mock_data_job.cc", + "test/url_request/url_request_mock_data_job.h", "test/url_request/url_request_mock_http_job.cc", "test/url_request/url_request_mock_http_job.h", "url_request/test_url_fetcher_factory.cc", @@ -1247,6 +1251,10 @@ if (!enable_websockets) { sources -= [ + "server/http_connection_unittest.cc", + "server/http_server_response_info_unittest.cc", + "server/http_server_unittest.cc", + "server/web_socket_encoder_unittest.cc", "websockets/websocket_basic_stream_test.cc", "websockets/websocket_channel_test.cc", "websockets/websocket_deflate_predictor_impl_test.cc", @@ -1263,6 +1271,7 @@ "websockets/websocket_test_util.cc", "websockets/websocket_test_util.h", ] + deps -= [ ":http_server" ] } if (disable_file_support) {
diff --git a/net/base/filename_util_unittest.cc b/net/base/filename_util_unittest.cc index 391baeb..0e7d504 100644 --- a/net/base/filename_util_unittest.cc +++ b/net/base/filename_util_unittest.cc
@@ -48,6 +48,25 @@ #endif } +std::string GetLocaleWarningString() { +#if defined(OS_POSIX) && !defined(OS_ANDROID) + // The generate filename tests can fail on certain OS_POSIX platforms when + // LC_CTYPE is not "utf8" or "utf-8" because some of the string conversions + // fail. + // This warning text is appended to any test failures to save people time if + // this happens to be the cause of failure :) + // Note: some platforms (MACOSX, Chromecast) don't have this problem: + // setlocale returns "c" but it functions as utf8. And Android doesn't + // have setlocale at all. + std::string locale = setlocale(LC_CTYPE, NULL); + return " this test may have failed because the current LC_CTYPE locale is " + "not utf8 (currently set to " + + locale + ")"; +#else + return ""; +#endif +} + void RunGenerateFileNameTestCase(const GenerateFilenameCase* test_case) { std::string default_filename(base::WideToUTF8(test_case->default_filename)); base::FilePath file_path = GenerateFileName( @@ -55,7 +74,8 @@ test_case->referrer_charset, test_case->suggested_filename, test_case->mime_type, default_filename); EXPECT_EQ(test_case->expected_filename, FilePathAsWString(file_path)) - << "test case at line number: " << test_case->lineno; + << "test case at line number: " << test_case->lineno << "; " + << GetLocaleWarningString(); } } // namespace @@ -418,18 +438,6 @@ } TEST(FilenameUtilTest, GenerateFileName) { -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) - // This test doesn't run when the locale is not UTF-8 because some of the - // string conversions fail. This is OK (we have the default value) but they - // don't match our expectations. - std::string locale = setlocale(LC_CTYPE, NULL); - base::StringToLowerASCII(&locale); - EXPECT_TRUE(locale.find("utf-8") != std::string::npos || - locale.find("utf8") != std::string::npos) - << "Your locale (" << locale << ") must be set to UTF-8 " - << "for this test to pass!"; -#endif - // Tests whether the correct filename is selected from the the given // parameters and that Content-Disposition headers are properly // handled including failovers when the header is malformed.
diff --git a/net/base/net_log_util.cc b/net/base/net_log_util.cc index 3b437aa..75be128 100644 --- a/net/base/net_log_util.cc +++ b/net/base/net_log_util.cc
@@ -33,6 +33,7 @@ #include "net/proxy/proxy_service.h" #include "net/quic/quic_protocol.h" #include "net/quic/quic_utils.h" +#include "net/socket/ssl_client_socket.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" @@ -447,10 +448,17 @@ "force_spdy_always", http_network_session->params().force_spdy_always); - std::vector<std::string> next_protos; + NextProtoVector next_protos; http_network_session->GetNextProtos(&next_protos); - std::string next_protos_string = JoinString(next_protos, ','); - status_dict->SetString("next_protos", next_protos_string); + if (!next_protos.empty()) { + std::string next_protos_string; + for (const NextProto proto : next_protos) { + if (!next_protos_string.empty()) + next_protos_string.append(","); + next_protos_string.append(SSLClientSocket::NextProtoToString(proto)); + } + status_dict->SetString("next_protos", next_protos_string); + } net_info_dict->Set(NetInfoSourceToString(NET_INFO_SPDY_STATUS), status_dict);
diff --git a/net/data/proxy_resolver_v8_unittest/pac_library_unittest.js b/net/data/proxy_resolver_v8_unittest/pac_library_unittest.js index 0c0a4a9..58de402 100644 --- a/net/data/proxy_resolver_v8_unittest/pac_library_unittest.js +++ b/net/data/proxy_resolver_v8_unittest/pac_library_unittest.js
@@ -1,3 +1,7 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // This should output "PROXY success:80" if all the tests pass. // Otherwise it will output "PROXY failure:<num-failures>". // @@ -61,6 +65,56 @@ Tests.testIsPlainHostName = function(t) { t.expectTrue(isPlainHostName("google")); t.expectFalse(isPlainHostName("google.com")); + t.expectFalse(isPlainHostName("192.168.1.1")); + t.expectFalse(isPlainHostName(".")); + t.expectFalse(isPlainHostName(".:")); + + // Valid IPv6 address + t.expectFalse(isPlainHostName("::1")); + + // Not a valid IPv6 address + t.expectTrue(isPlainHostName("foopy::1")); + t.expectTrue(isPlainHostName("foo:112")); + t.expectTrue(isPlainHostName(":")); + t.expectTrue(isPlainHostName("[:]")); + + // Not considered a valid IPv6 address because of surrounding brackets. + t.expectTrue(isPlainHostName("[::1]")); + + // Calling with more than 1 argument is allowed. + t.expectTrue(isPlainHostName("foo", "foo", "foo")); + + // Calling with no arguments is an error. + try { + isPlainHostName(); + t.expectTrue(false); // Not reached. + } catch (e) { + t.expectEquals('TypeError: Requires 1 string parameter', e.toString()); + } + + // Calling with the wrong argument type is an error. + try { + isPlainHostName(null); + t.expectTrue(false); // Not reached. + } catch (e) { + t.expectEquals('TypeError: Requires 1 string parameter', e.toString()); + } + + // Calling with the wrong argument type is an error. + try { + isPlainHostName(1); + t.expectTrue(false); // Not reached. + } catch (e) { + t.expectEquals('TypeError: Requires 1 string parameter', e.toString()); + } + + // Calling with the wrong argument type is an error. + try { + isPlainHostName(function() {}); + t.expectTrue(false); // Not reached. + } catch (e) { + t.expectEquals('TypeError: Requires 1 string parameter', e.toString()); + } }; Tests.testLocalHostOrDomainIs = function(t) {
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc index 843a619..3b1f669 100644 --- a/net/disk_cache/backend_unittest.cc +++ b/net/disk_cache/backend_unittest.cc
@@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/metrics/field_trial.h" #include "base/port.h" +#include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" @@ -3282,6 +3283,10 @@ entry->Close(); entry = NULL; + // The entry is being closed on the Simple Cache worker pool + disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting(); + base::RunLoop().RunUntilIdle(); + // Write an invalid header for stream 0 and stream 1. base::FilePath entry_file1_path = cache_path_.AppendASCII( disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, 0));
diff --git a/net/disk_cache/blockfile/stress_cache.cc b/net/disk_cache/blockfile/stress_cache.cc index f28e8af..d43cb74 100644 --- a/net/disk_cache/blockfile/stress_cache.cc +++ b/net/disk_cache/blockfile/stress_cache.cc
@@ -27,7 +27,6 @@ #include "base/path_service.h" #include "base/process/kill.h" #include "base/process/launch.h" -#include "base/process/process_handle.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -59,14 +58,14 @@ base::CommandLine cmdline(exe); cmdline.AppendArg(base::IntToString(iteration)); - base::ProcessHandle handle; - if (!base::LaunchProcess(cmdline, base::LaunchOptions(), &handle)) { + base::Process process = base::LaunchProcess(cmdline, base::LaunchOptions()); + if (!process.IsValid()) { printf("Unable to run test\n"); return kError; } int exit_code; - if (!base::WaitForExitCode(handle, &exit_code)) { + if (!process.WaitForExit(&exit_code)) { printf("Unable to get return code\n"); return kError; }
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 656db54..405c88c 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -26,6 +26,7 @@ #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_pool_manager_impl.h" #include "net/socket/next_proto.h" +#include "net/socket/ssl_client_socket.h" #include "net/spdy/hpack_huffman_aggregator.h" #include "net/spdy/spdy_session_pool.h" @@ -166,7 +167,7 @@ // Add the protocol to the TLS next protocol list, except for QUIC // since it uses UDP. if (proto != kProtoQUIC1SPDY3) { - next_protos_.push_back(SSLClientSocket::NextProtoToString(proto)); + next_protos_.push_back(proto); } // Enable the corresponding alternate protocol, except for HTTP @@ -284,8 +285,7 @@ protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION]; } -void HttpNetworkSession::GetNextProtos( - std::vector<std::string>* next_protos) const { +void HttpNetworkSession::GetNextProtos(NextProtoVector* next_protos) const { if (HttpStreamFactory::spdy_enabled()) { *next_protos = next_protos_; } else {
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index bf93c83..c9704a4 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -205,7 +205,8 @@ bool IsProtocolEnabled(AlternateProtocol protocol) const; - void GetNextProtos(std::vector<std::string>* next_protos) const; + // Populates |*next_protos| with protocols. + void GetNextProtos(NextProtoVector* next_protos) const; // Convenience function for searching through |params_| for // |forced_spdy_exclusions|. @@ -242,7 +243,7 @@ // TODO(jgraettinger): Remove when Huffman collection is complete. scoped_ptr<HpackHuffmanAggregator> huffman_aggregator_; - std::vector<std::string> next_protos_; + NextProtoVector next_protos_; bool enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS]; Params params_;
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h index 4c09bec..3c59a75 100644 --- a/net/http/transport_security_state_static.h +++ b/net/http/transport_security_state_static.h
@@ -2060,297 +2060,296 @@ 0x15, 0xcf, 0xf7, 0x1d, 0xd6, 0x29, 0xba, 0x86, 0x8a, 0xe2, 0x1c, 0x7f, 0x5a, 0x6b, 0x3d, 0x79, 0xdc, 0x1d, 0x3f, 0xaf, 0xc3, 0xff, 0xfd, 0xd0, - 0xe9, 0x37, 0x40, 0x7a, 0xb4, 0x20, 0x9f, 0xfb, - 0x7c, 0xff, 0x06, 0x3b, 0xc8, 0xd9, 0xd3, 0xeb, - 0xf7, 0x23, 0x67, 0x4e, 0xc5, 0x3d, 0x93, 0xe9, - 0xc2, 0x1c, 0xf8, 0x53, 0x75, 0x0d, 0x14, 0xf4, - 0xfd, 0x74, 0xe0, 0x1a, 0xf3, 0xa3, 0x8d, 0x4c, - 0x99, 0x61, 0x2b, 0x66, 0x80, 0x61, 0x3f, 0xfb, - 0x5e, 0xee, 0x43, 0x7e, 0xa5, 0x17, 0xf3, 0xa1, - 0xc8, 0x90, 0xe5, 0x16, 0x73, 0xb9, 0xb3, 0xa7, - 0xca, 0xff, 0xfb, 0x79, 0xd3, 0xc9, 0xba, 0x86, - 0x8a, 0xce, 0x1a, 0x3d, 0x41, 0x29, 0x9f, 0xaa, - 0x62, 0x83, 0xe8, 0x74, 0xe5, 0xab, 0xc7, 0x4f, - 0xb1, 0xff, 0x50, 0x79, 0xd3, 0xbb, 0xda, 0x1d, - 0x3e, 0xb6, 0xaa, 0xef, 0xf3, 0xa4, 0xeb, 0x46, - 0xe0, 0x91, 0x64, 0xb7, 0x47, 0x00, 0xab, 0xa8, - 0xe4, 0xff, 0xce, 0xd7, 0xba, 0xc5, 0x37, 0x50, - 0xd1, 0x22, 0xcf, 0xe7, 0x58, 0xa6, 0xea, 0x1a, - 0x2c, 0x99, 0xfc, 0xeb, 0x14, 0xdd, 0x43, 0x45, - 0xb1, 0x3a, 0xe9, 0x67, 0x4f, 0x85, 0x37, 0x50, - 0xd1, 0x6d, 0xc9, 0xcf, 0x3c, 0xab, 0x1a, 0x9d, - 0x56, 0x7c, 0x74, 0xff, 0xb8, 0xde, 0x35, 0xb8, - 0x63, 0x36, 0x0b, 0xf9, 0xd3, 0xf2, 0x83, 0xf9, - 0xed, 0x87, 0x4f, 0x85, 0x37, 0x50, 0xd1, 0x78, - 0x4f, 0x63, 0x8a, 0xf2, 0x74, 0xff, 0xcb, 0xd5, - 0x95, 0xbf, 0x16, 0x18, 0xa1, 0xd3, 0xeb, 0x0f, - 0xdb, 0xd4, 0xe9, 0xf2, 0xf5, 0xef, 0x68, 0x74, - 0xec, 0x2f, 0xe7, 0x49, 0xdc, 0x6a, 0x74, 0x2d, - 0xc6, 0x8e, 0xd4, 0x9d, 0x65, 0xd5, 0x98, 0x64, - 0x93, 0xf4, 0x60, 0x29, 0xc1, 0x4c, 0xef, 0x5d, - 0x67, 0x4f, 0x85, 0x37, 0x50, 0xd1, 0x7a, 0x4f, - 0xf8, 0x37, 0x0f, 0x5e, 0x98, 0xf5, 0x47, 0x4f, - 0xad, 0x99, 0xde, 0x4e, 0x93, 0xb9, 0x45, 0x9d, - 0x8e, 0x75, 0x30, 0x6f, 0x40, 0x85, 0x64, 0x87, - 0xd5, 0x0b, 0x5b, 0x94, 0x58, 0x84, 0x9e, 0x8d, - 0x30, 0x56, 0xd8, 0x99, 0xf9, 0xd8, 0x42, 0x17, - 0xb8, 0xf2, 0x3e, 0x8d, 0x1e, 0x6e, 0xf2, 0x74, - 0xf5, 0xe7, 0x70, 0x74, 0xfe, 0xbf, 0x0f, 0xff, - 0xf7, 0x43, 0xa4, 0xdd, 0x01, 0xea, 0xd0, 0x82, - 0x7d, 0xec, 0x2d, 0x75, 0x1d, 0x3e, 0x14, 0xdd, - 0x43, 0x44, 0x47, 0x3f, 0xfd, 0x9e, 0xe9, 0x4b, - 0x60, 0x5b, 0x6e, 0x0a, 0xdd, 0x8e, 0x9f, 0xf3, - 0xd6, 0xa1, 0xbc, 0x63, 0xd8, 0x3a, 0x7f, 0xff, - 0x97, 0x3b, 0xec, 0x2e, 0x42, 0xf1, 0x9f, 0x66, - 0xfd, 0xf1, 0xd3, 0x54, 0xc2, 0xa6, 0xfb, 0xe2, - 0xa7, 0xfe, 0x7b, 0x93, 0x3e, 0x6b, 0x2b, 0x53, - 0xbf, 0x35, 0xff, 0x0b, 0xcf, 0xeb, 0xe3, 0x85, - 0xe7, 0x70, 0x74, 0xff, 0xfc, 0x8e, 0x1d, 0x0f, - 0x61, 0xc2, 0xb8, 0x0d, 0xfc, 0xe8, 0xe3, 0x15, - 0x83, 0x71, 0xad, 0x8a, 0x59, 0x65, 0x28, 0x61, - 0x5a, 0xc8, 0x9f, 0x6c, 0x25, 0x30, 0xbe, 0xd8, - 0xd2, 0x7c, 0x29, 0xba, 0x86, 0x88, 0xba, 0x7d, - 0x8f, 0xfa, 0x83, 0xcb, 0x67, 0xb2, 0x4e, 0xb3, - 0xe8, 0xd3, 0x08, 0x72, 0x65, 0x0f, 0x8c, 0x0a, - 0x7f, 0xe6, 0x6b, 0xdd, 0x62, 0x9b, 0xa8, 0x68, - 0x99, 0xa7, 0x56, 0xb4, 0x3a, 0x72, 0x79, 0x87, - 0x4d, 0xc4, 0xdd, 0xce, 0x9f, 0xb1, 0x75, 0x5f, - 0xed, 0x1d, 0x0d, 0xdc, 0xf3, 0x9a, 0x1f, 0x9f, - 0x26, 0xe7, 0xcd, 0x1d, 0x3f, 0xf3, 0x7f, 0xb1, - 0xe4, 0xf7, 0x38, 0xb4, 0x3a, 0x7f, 0xff, 0xbb, - 0xd0, 0x40, 0xbe, 0x73, 0xdf, 0x0c, 0xab, 0xc5, - 0x6a, 0x3a, 0x2d, 0x15, 0xf9, 0x47, 0x9f, 0xff, - 0x73, 0xe0, 0xaa, 0xe9, 0xed, 0xcb, 0xbe, 0xfb, - 0xe2, 0xa7, 0x93, 0x75, 0x0d, 0x16, 0x7c, 0xff, - 0xbd, 0x95, 0x7f, 0xb0, 0xb8, 0xa1, 0xd3, 0xff, - 0xde, 0x1c, 0xef, 0x0b, 0x6c, 0x17, 0x4b, 0x03, - 0xa7, 0x7d, 0xf7, 0xc5, 0x4f, 0xfb, 0x5f, 0x40, - 0xb4, 0xe6, 0xc4, 0xa7, 0x17, 0xf3, 0xfc, 0xb9, - 0xf7, 0x21, 0xba, 0xd1, 0xd3, 0xfd, 0xe0, 0xe7, - 0xaf, 0x3d, 0xe2, 0x87, 0x42, 0x27, 0xe2, 0x2b, - 0x4c, 0x2b, 0xc9, 0xf7, 0xed, 0xd8, 0x4a, 0x6c, - 0x71, 0x3f, 0xc3, 0xbf, 0x67, 0xca, 0x2a, 0x74, - 0xff, 0xff, 0xfd, 0x77, 0xfd, 0x2e, 0xc3, 0xa7, - 0x51, 0x05, 0xbc, 0xba, 0x81, 0x75, 0x32, 0xd8, - 0x74, 0xea, 0x2d, 0x47, 0x4e, 0xe2, 0xbc, 0x9d, - 0x0f, 0x46, 0x15, 0x21, 0x11, 0x81, 0xc9, 0xea, - 0xff, 0xed, 0x0e, 0x9f, 0x64, 0x16, 0xc4, 0xc9, - 0xff, 0x78, 0x5f, 0x63, 0x57, 0x7b, 0xc9, 0xa2, - 0x0d, 0x71, 0xa4, 0x9f, 0x6a, 0x79, 0x8a, 0x74, - 0xfc, 0xfc, 0x86, 0xd7, 0x83, 0xa5, 0x68, 0x7a, - 0x40, 0x4b, 0x3f, 0xff, 0xed, 0xfb, 0x17, 0x9c, - 0x2d, 0x85, 0x78, 0xb1, 0xf5, 0x5a, 0xc3, 0xa1, - 0xe9, 0x9f, 0x5c, 0x2b, 0x80, 0x96, 0x7e, 0x1b, - 0xe6, 0x99, 0x53, 0xa7, 0xff, 0xf7, 0x61, 0xbd, - 0x38, 0x75, 0x0d, 0xc5, 0x3d, 0x5e, 0x7d, 0xf1, - 0xd3, 0xff, 0xfd, 0x4a, 0x28, 0xe1, 0x5c, 0xcb, - 0xc5, 0x3a, 0xd3, 0x5f, 0x67, 0x4f, 0x66, 0xfc, - 0xd8, 0xe8, 0xf2, 0x22, 0x72, 0xcd, 0x33, 0x1b, - 0xa3, 0x45, 0xf9, 0x3f, 0xf3, 0xf1, 0xdb, 0xde, - 0xcc, 0x61, 0x58, 0x74, 0xff, 0xde, 0xb0, 0xbb, - 0xa7, 0x07, 0xd1, 0x87, 0x45, 0x68, 0x8a, 0xa2, - 0x34, 0xde, 0x68, 0xe9, 0xd8, 0xf5, 0x47, 0x4e, - 0x05, 0x43, 0xa3, 0x81, 0xe6, 0xb0, 0x5c, 0x07, - 0x61, 0x53, 0x76, 0xe4, 0x8e, 0xe1, 0x65, 0xae, - 0x33, 0xff, 0xff, 0x37, 0xae, 0x7c, 0xc7, 0x34, - 0xfd, 0x1e, 0xb9, 0xf5, 0x74, 0x4f, 0x54, 0x74, - 0xf7, 0xdb, 0x74, 0x3a, 0x7f, 0x9e, 0xcd, 0x7e, - 0x28, 0xbd, 0x0e, 0x85, 0x3d, 0xbd, 0x21, 0x9e, - 0xba, 0x78, 0x0e, 0x80, 0x3c, 0x0e, 0xc8, 0x27, - 0xba, 0xf7, 0xb4, 0x3a, 0x7f, 0xd8, 0xa7, 0xfe, - 0xae, 0xb7, 0xde, 0x0e, 0x85, 0x3e, 0x6b, 0x24, - 0x99, 0xae, 0xce, 0x93, 0x0e, 0x8a, 0xcd, 0x43, - 0x72, 0x31, 0x3f, 0xb7, 0x6b, 0x78, 0x2f, 0x27, - 0x4f, 0xff, 0xfb, 0x3e, 0xaf, 0x17, 0x5e, 0x04, - 0x57, 0x1f, 0xf5, 0x07, 0xe6, 0xce, 0x9d, 0xf7, - 0xdf, 0x15, 0x3d, 0xcf, 0x3a, 0x05, 0x38, 0xbf, - 0x9f, 0xf6, 0xe5, 0x3d, 0xbc, 0x29, 0xb9, 0x3a, - 0x15, 0x35, 0x6e, 0x49, 0xd0, 0xcb, 0xd0, 0x8e, - 0xc9, 0x8c, 0xff, 0xd6, 0x15, 0xe2, 0xc7, 0xd5, - 0x6b, 0x0e, 0x9f, 0x5e, 0x1e, 0xcc, 0x9d, 0x3e, - 0xae, 0x80, 0xac, 0x3a, 0x15, 0x12, 0x34, 0x43, - 0xec, 0x9e, 0x6f, 0xf2, 0x74, 0xfd, 0x53, 0x4f, - 0xe3, 0x46, 0xa3, 0xa7, 0xf7, 0x4c, 0xde, 0x33, - 0xec, 0x1d, 0x37, 0x84, 0xe8, 0x6e, 0xe7, 0xff, - 0xe3, 0x5c, 0x9a, 0xcf, 0xfd, 0xca, 0xf2, 0x2b, - 0x8f, 0x27, 0xb9, 0x3a, 0x7e, 0xcf, 0x75, 0x35, - 0x9f, 0x1d, 0x1c, 0x9f, 0xb6, 0x51, 0x64, 0xee, - 0x31, 0x9e, 0xd0, 0xdc, 0x07, 0x15, 0xa6, 0xa2, - 0x9e, 0x61, 0xad, 0x72, 0x84, 0xfa, 0x33, 0x57, - 0x0f, 0x8f, 0x1a, 0xb5, 0x1c, 0x30, 0x9a, 0x30, - 0xb3, 0x32, 0x9a, 0x35, 0x07, 0xf8, 0xc5, 0x42, - 0x11, 0x14, 0x8e, 0x7b, 0x10, 0xe0, 0xf8, 0xc3, - 0x8a, 0x12, 0xdd, 0x61, 0x57, 0x0e, 0x6c, 0x4a, - 0x73, 0x4f, 0xb4, 0x9f, 0xfc, 0xe6, 0x6b, 0xdd, - 0x62, 0x9b, 0xa8, 0x68, 0x9b, 0x27, 0xf3, 0xac, - 0x53, 0x75, 0x0d, 0x15, 0x6c, 0xfe, 0x7b, 0xfb, - 0xc0, 0x2b, 0xce, 0x9e, 0xbc, 0xee, 0x0e, 0x93, - 0x75, 0x67, 0xa6, 0x06, 0x73, 0xe1, 0x4d, 0xd4, - 0x34, 0x56, 0x93, 0xff, 0xc8, 0xa3, 0x7f, 0xeb, - 0x35, 0xeb, 0xe4, 0x3a, 0x7f, 0xf9, 0xf4, 0xb0, - 0x56, 0x6d, 0xe3, 0x0a, 0xc3, 0xa6, 0xc6, 0x15, - 0x12, 0xfa, 0x97, 0x3f, 0x95, 0xb7, 0x5c, 0x02, - 0xfe, 0x74, 0xfd, 0x55, 0xe7, 0xd6, 0xc3, 0xa7, - 0xfa, 0xdb, 0xc1, 0x7e, 0xad, 0xf4, 0x3a, 0x7f, - 0x3e, 0xf1, 0xa1, 0xff, 0x67, 0x49, 0xdc, 0x6a, - 0x7e, 0x36, 0x57, 0xe8, 0x63, 0xe4, 0xb7, 0x4d, - 0x80, 0xb7, 0x07, 0x93, 0xf9, 0xd6, 0x29, 0xba, - 0x86, 0x8b, 0x02, 0x7c, 0x29, 0xba, 0x86, 0x89, - 0xd6, 0x7f, 0xff, 0x65, 0x6a, 0xe6, 0xd8, 0xea, - 0x52, 0xf3, 0xea, 0x77, 0x51, 0xd3, 0xe7, 0x33, - 0x5e, 0xeb, 0x44, 0xab, 0x46, 0x13, 0xe1, 0x4d, - 0xd4, 0x34, 0x5b, 0x33, 0xfe, 0xfd, 0x68, 0xec, - 0xf9, 0x34, 0x4e, 0x93, 0xac, 0xfb, 0x74, 0xc2, - 0x79, 0x37, 0x50, 0xd1, 0x73, 0x49, 0x87, 0x4c, - 0xeb, 0x13, 0x77, 0xf1, 0x5c, 0xfe, 0x75, 0x8a, - 0x6e, 0xa1, 0xa2, 0xef, 0x9e, 0x77, 0x4e, 0x7f, - 0x3a, 0x15, 0xb7, 0x32, 0xba, 0xc5, 0x4d, 0x0c, - 0x6b, 0x52, 0xf4, 0xa7, 0xf1, 0x72, 0x64, 0x34, - 0x3f, 0x85, 0x6d, 0x18, 0x70, 0x59, 0xd4, 0xee, - 0x7f, 0xc1, 0xae, 0x5a, 0x51, 0x9a, 0xf3, 0xa7, - 0xf0, 0x55, 0x6d, 0xf8, 0x5e, 0x87, 0x4f, 0x85, - 0x37, 0x50, 0xd1, 0x2b, 0xcf, 0xf8, 0x37, 0xee, - 0x72, 0xb5, 0x5f, 0xc7, 0x4f, 0x77, 0xa2, 0xf3, - 0xa7, 0xff, 0xf7, 0xb1, 0xac, 0xd0, 0xff, 0x3f, - 0x68, 0x54, 0x9e, 0xa8, 0xe8, 0xe5, 0x10, 0x7a, - 0x43, 0x1c, 0xa3, 0x9b, 0x30, 0xc3, 0x9d, 0xaf, - 0x72, 0xa6, 0xed, 0x66, 0xf4, 0x8c, 0x5a, 0x76, - 0x17, 0x92, 0xa7, 0xff, 0x67, 0x7d, 0x85, 0x7f, - 0x86, 0xae, 0xff, 0x2a, 0x7f, 0x6a, 0x3b, 0x91, - 0x6e, 0x5c, 0xa7, 0xd1, 0x41, 0xc9, 0x39, 0x15, - 0x57, 0x32, 0x3b, 0x26, 0xd0, 0xae, 0x9f, 0xfc, - 0xe6, 0x6b, 0xdd, 0x62, 0x9b, 0xa8, 0x68, 0x98, - 0x67, 0xff, 0xeb, 0x77, 0x51, 0xdf, 0xdd, 0xd3, - 0x0f, 0xf9, 0x68, 0xf3, 0xa7, 0xfe, 0x6e, 0xae, - 0xb7, 0xf7, 0xb8, 0x05, 0x79, 0xd3, 0xf9, 0x76, - 0xac, 0x74, 0xd1, 0x3a, 0x7d, 0xa2, 0xfd, 0x61, - 0xd0, 0x07, 0xb1, 0xd9, 0x9c, 0xfc, 0xc5, 0xb0, - 0xc7, 0x11, 0xd3, 0xe5, 0xb0, 0xc7, 0x11, 0xd3, - 0xf6, 0x7d, 0x8a, 0x6d, 0x7c, 0x0f, 0x59, 0x85, - 0xd3, 0xff, 0xfe, 0x0b, 0xf9, 0xbf, 0x17, 0x9e, - 0x01, 0x75, 0x7a, 0xc2, 0xb7, 0xd0, 0xe9, 0xf9, - 0xb7, 0x5c, 0x02, 0xfe, 0x74, 0xff, 0xe5, 0xc7, - 0xea, 0xfb, 0xaf, 0x15, 0x77, 0xf1, 0xd0, 0xa7, - 0xff, 0xe3, 0x19, 0xfa, 0x9e, 0xe8, 0xcd, 0xc1, - 0xd3, 0xff, 0xfe, 0x1b, 0x6c, 0xa1, 0x8e, 0x1d, - 0x41, 0x73, 0xbe, 0xc2, 0xe2, 0x87, 0x4a, 0xeb, - 0x44, 0xe8, 0x97, 0xcf, 0xff, 0xb2, 0x17, 0x8c, - 0xfa, 0xeb, 0xc5, 0xb6, 0x5a, 0x1d, 0x39, 0x7f, - 0xea, 0x74, 0x59, 0xfa, 0x02, 0xb4, 0xf6, 0xf5, - 0xe6, 0xce, 0x93, 0xb8, 0xd5, 0x7d, 0xdc, 0xc2, - 0x85, 0x1e, 0x1a, 0x48, 0xcc, 0x3c, 0x02, 0x17, - 0xd8, 0x84, 0xe7, 0x64, 0x13, 0xe1, 0x4d, 0xd4, - 0x34, 0x55, 0xd3, 0xfc, 0xf7, 0x58, 0xa6, 0xea, - 0x1a, 0x23, 0xc9, 0x3a, 0xcf, 0xc7, 0x4c, 0x27, - 0xf3, 0xac, 0x53, 0x75, 0x0d, 0x16, 0x0c, 0xfe, - 0x75, 0x8a, 0x6e, 0xa1, 0xa2, 0xca, 0x9f, 0xce, - 0xb1, 0x4d, 0xd4, 0x34, 0x5a, 0x73, 0xc9, 0xba, - 0x86, 0x8b, 0x72, 0x7f, 0xe5, 0xb1, 0xb0, 0xe1, - 0x9b, 0xaf, 0xe3, 0xa0, 0x4f, 0xbe, 0x85, 0x73, - 0xfc, 0xa1, 0xdb, 0x16, 0x98, 0xf1, 0xd3, 0xfe, - 0xd7, 0xba, 0xc5, 0x37, 0x50, 0xd1, 0x43, 0xcf, - 0xfc, 0xcd, 0xe5, 0x79, 0xcf, 0x83, 0xcc, 0x3a, - 0x7f, 0xdd, 0x8f, 0xe3, 0xa1, 0x8b, 0xfc, 0xe9, - 0xfa, 0x9b, 0x5d, 0x31, 0xe3, 0xa7, 0xe0, 0xe3, - 0x6c, 0x56, 0x87, 0x4f, 0xff, 0xd7, 0xce, 0x57, - 0xab, 0xb0, 0x1b, 0xfd, 0x28, 0xbf, 0x95, 0x27, - 0x5a, 0x7b, 0xbe, 0x21, 0x61, 0xc6, 0xa3, 0x51, - 0x17, 0x07, 0xdd, 0x97, 0x71, 0x17, 0xcf, 0xe7, - 0x58, 0xa6, 0xea, 0x1a, 0x2f, 0x38, 0x56, 0x4e, - 0x03, 0xd1, 0x39, 0x52, 0xb9, 0xc4, 0xea, 0xe3, - 0x04, 0x12, 0x66, 0x1d, 0xe4, 0xec, 0x25, 0x43, - 0xb6, 0x7a, 0x9f, 0xce, 0xb1, 0x4d, 0xd4, 0x34, - 0x52, 0xd3, 0xf9, 0xd6, 0x29, 0xba, 0x86, 0x8b, - 0x0a, 0x7f, 0x3a, 0xc5, 0x37, 0x50, 0xd1, 0x65, - 0xcf, 0x3b, 0xa3, 0x71, 0xdb, 0xb1, 0xd3, 0x9d, - 0xd5, 0x87, 0x4f, 0x23, 0x96, 0x88, 0x7a, 0x1d, - 0x99, 0x4f, 0xfe, 0x73, 0x35, 0xee, 0xb1, 0x4d, - 0xd4, 0x34, 0x51, 0x93, 0xf9, 0xca, 0xd9, 0x45, - 0x7f, 0x3a, 0x1e, 0x9d, 0xf0, 0x9d, 0xb0, 0xef, - 0x61, 0x17, 0x43, 0x8c, 0x29, 0x4f, 0xfc, 0xed, - 0x7b, 0xac, 0x53, 0x75, 0x0d, 0x11, 0xcc, 0xff, - 0xe7, 0x33, 0x5e, 0xeb, 0x14, 0xdd, 0x43, 0x44, - 0xe5, 0x3f, 0x9d, 0x62, 0x9b, 0xa8, 0x68, 0xb3, - 0x27, 0xfe, 0x72, 0xfe, 0x2b, 0x8c, 0xed, 0x6f, - 0x3a, 0x7f, 0x3a, 0xc5, 0x37, 0x50, 0xd1, 0x6e, - 0xcf, 0xfe, 0x73, 0x35, 0xee, 0xb1, 0x4d, 0xd4, - 0x34, 0x52, 0x13, 0xff, 0x3b, 0x5e, 0xeb, 0x14, - 0xdd, 0x43, 0x44, 0xa5, 0x15, 0x27, 0xec, 0xd2, - 0x63, 0x14, 0xbf, 0x3b, 0x04, 0x4c, 0x1d, 0xb7, - 0xa9, 0x4f, 0xfb, 0x5e, 0xeb, 0x14, 0xdd, 0x43, - 0x44, 0xed, 0x3f, 0xfe, 0xf7, 0x3d, 0xb1, 0x5b, - 0xf7, 0x90, 0x50, 0xb4, 0x3a, 0x4e, 0x62, 0x27, - 0x75, 0x1a, 0x7f, 0xed, 0x66, 0x6d, 0x37, 0x2b, - 0xd5, 0xe7, 0x4f, 0xfc, 0x17, 0x9d, 0xaa, 0xe8, - 0x1b, 0x59, 0xd3, 0x71, 0x3b, 0x94, 0x42, 0xd1, - 0x0e, 0x18, 0x8e, 0x0e, 0x28, 0x56, 0xcf, 0x85, - 0x37, 0x50, 0xd1, 0x16, 0x4f, 0xfb, 0x5e, 0xeb, - 0x14, 0xdd, 0x43, 0x44, 0xbb, 0x3f, 0xff, 0x5f, - 0x39, 0x5e, 0xae, 0xc0, 0x6f, 0xf4, 0xa2, 0xfe, - 0x54, 0x9d, 0x68, 0xd4, 0x61, 0x87, 0x12, 0x34, - 0xff, 0xe7, 0x33, 0x5e, 0xeb, 0x14, 0xdd, 0x43, - 0x44, 0xc5, 0x3f, 0x58, 0xa6, 0xea, 0x1a, 0x2a, - 0x99, 0xff, 0xff, 0xc3, 0xb9, 0xad, 0xf7, 0x87, - 0x67, 0x68, 0x3e, 0xfb, 0x19, 0xf0, 0xbc, 0xe8, - 0x72, 0x2b, 0x74, 0xd6, 0x7f, 0xf3, 0x99, 0xaf, - 0x75, 0x8a, 0x6e, 0xa1, 0xa2, 0x74, 0x9f, 0xde, - 0xd1, 0x57, 0xeb, 0x63, 0xa7, 0xcd, 0x2b, 0x4b, - 0x43, 0xa7, 0xef, 0xaf, 0xcd, 0xac, 0x0e, 0x9e, - 0xf6, 0x55, 0xde, 0x3d, 0x6a, 0x14, 0x4f, 0xfd, - 0xdd, 0x30, 0xb5, 0xbb, 0xb6, 0xbc, 0xc3, 0xa1, - 0x88, 0x82, 0xc9, 0xcc, 0xff, 0xb5, 0xee, 0xb1, - 0x4d, 0xd4, 0x34, 0x4e, 0xf3, 0xec, 0x77, 0xac, - 0xf1, 0x52, 0x77, 0x29, 0xcd, 0xdc, 0x61, 0x4c, - 0x23, 0xd4, 0x69, 0xff, 0xce, 0x66, 0xbd, 0xd6, - 0x29, 0xba, 0x86, 0x8a, 0x16, 0x7f, 0xf3, 0x99, - 0xaf, 0x75, 0x8a, 0x6e, 0xa1, 0xa2, 0x92, 0x9f, - 0xff, 0xd7, 0x47, 0x75, 0xb6, 0xb3, 0xac, 0xc6, - 0x57, 0x1d, 0xb0, 0xe8, 0xa9, 0x72, 0x5d, 0xe7, - 0x09, 0x0f, 0xf1, 0x22, 0x64, 0x7d, 0xbf, 0xa4, - 0xf6, 0xa5, 0xc4, 0xa5, 0x3f, 0x9d, 0x62, 0x9b, - 0xa8, 0x68, 0x89, 0x27, 0xff, 0x39, 0x9a, 0xf7, - 0x58, 0xa6, 0xea, 0x1a, 0x25, 0xe9, 0xf0, 0xfe, - 0xcf, 0x50, 0xe9, 0xdf, 0xae, 0x0e, 0x9f, 0xfb, - 0x5a, 0xa2, 0xb6, 0xdc, 0xad, 0x6d, 0x1d, 0x1e, - 0x44, 0x5b, 0x45, 0x02, 0x39, 0x3f, 0xde, 0xd0, - 0xef, 0x0d, 0x2f, 0x43, 0xa7, 0xc2, 0x9b, 0xa8, - 0x68, 0xa5, 0xe7, 0xff, 0x5b, 0xd7, 0xfa, 0x0a, - 0xd6, 0xff, 0x30, 0xe9, 0xf3, 0x7f, 0x98, 0xb4, - 0x3a, 0x7d, 0xad, 0xac, 0x68, 0x74, 0x97, 0x93, - 0xd1, 0x61, 0x54, 0x9c, 0xa9, 0xaf, 0x72, 0x61, - 0x67, 0x6d, 0x18, 0x62, 0x13, 0x73, 0xf9, 0xd6, - 0x29, 0xba, 0x86, 0x8a, 0x72, 0x7f, 0xde, 0x1d, - 0xa6, 0x6e, 0xc1, 0x0e, 0x9f, 0xf5, 0xe5, 0x46, - 0xdd, 0xf7, 0xdf, 0x15, 0x37, 0xbe, 0x3a, 0x6a, - 0x9d, 0xca, 0x24, 0x38, 0x8e, 0x9b, 0xcf, 0xe7, - 0xc2, 0x9b, 0xa8, 0x68, 0xaf, 0x27, 0xff, 0xeb, - 0xe7, 0x2b, 0xd5, 0xd8, 0x0d, 0xfe, 0x94, 0x5f, - 0xca, 0x93, 0xad, 0x11, 0xdc, 0x46, 0x13, 0xff, - 0x3b, 0x5e, 0xeb, 0x14, 0xdd, 0x43, 0x44, 0x8f, - 0x3b, 0xdf, 0xa9, 0xd3, 0x92, 0xd8, 0x53, 0x8b, - 0xc9, 0xf0, 0xa6, 0xea, 0x1a, 0x24, 0x89, 0xe7, - 0x6b, 0xdc, 0xa7, 0xb3, 0x65, 0x33, 0xff, 0x3b, - 0x5e, 0xeb, 0x14, 0xdd, 0x43, 0x44, 0x95, 0x3e, - 0x14, 0xdd, 0x43, 0x45, 0xe3, 0x3f, 0x76, 0x15, - 0xed, 0x74, 0x3a, 0x7d, 0x4a, 0x62, 0xd0, 0xe9, - 0xfe, 0x7b, 0xac, 0x53, 0x75, 0x0d, 0x12, 0x6c, - 0x9d, 0x68, 0xc6, 0xac, 0xc0, 0x4b, 0xf4, 0x9a, - 0x15, 0x7b, 0x7e, 0xa3, 0xb7, 0xca, 0x3b, 0xe5, - 0x5b, 0xd0, 0xcb, 0x6a, 0x1a, 0x4c, 0x2b, 0xcc, - 0x30, 0x70, 0x6f, 0xdc, 0x62, 0x50, 0xb1, 0xc7, - 0x36, 0xd5, 0x1d, 0x83, 0xe5, 0x05, 0x73, 0x28, - 0x6a, 0xed, 0xe8, 0x9f, 0x49, 0x4b, 0x49, 0x68, - 0x6f, 0x2b, 0x9e, 0xd3, 0xf4, 0xe9, 0x7f, 0x1e, - 0x3b, 0x66, 0xab, 0x05, 0x41, 0xa5, 0x2a, 0xb3, - 0x12, 0x76, 0x39, 0x9d, 0xfe, 0xda, 0xc7, 0x9b, - 0xf9, 0x62, 0xed, 0xcc, 0x2c, 0x42, 0x90, 0xcd, - 0x4a, 0x4e, 0x4e, 0x2b, 0xc1, 0xee, 0xe9, 0xa4, - 0xcd, 0xa5, 0x31, 0x7d, 0x29, 0x47, 0x8a, 0x3e, - 0x7e, 0xb3, 0xb2, 0xcd, 0xf3, 0xec, 0x50, + 0xe9, 0x37, 0x40, 0x7a, 0xb4, 0x20, 0x9f, 0xff, + 0xb1, 0x4f, 0x67, 0x7c, 0xff, 0x06, 0x3b, 0xc8, + 0xd9, 0xd3, 0xe1, 0x4d, 0xd4, 0x34, 0x53, 0xd3, + 0xf5, 0xd3, 0x80, 0x6b, 0xce, 0x8e, 0x35, 0x1c, + 0x8a, 0x59, 0x6b, 0x60, 0x61, 0x3f, 0xfb, 0x5e, + 0xee, 0x43, 0x7e, 0xa5, 0x17, 0xf3, 0xa1, 0xc8, + 0x8a, 0xe4, 0xfe, 0x73, 0xb9, 0xb3, 0xa7, 0xca, + 0xff, 0xfb, 0x79, 0xd3, 0xc9, 0xba, 0x86, 0x8a, + 0xce, 0x1a, 0x3d, 0x41, 0x29, 0x9f, 0xaa, 0x62, + 0x83, 0xe8, 0x74, 0xe5, 0xab, 0xc7, 0x4f, 0xb1, + 0xff, 0x50, 0x79, 0xd3, 0xbb, 0xda, 0x1d, 0x3e, + 0xb6, 0xaa, 0xef, 0xf3, 0xa4, 0xeb, 0x46, 0xe0, + 0x91, 0x64, 0xb7, 0x47, 0x00, 0xab, 0xa8, 0xe4, + 0xff, 0xce, 0xd7, 0xba, 0xc5, 0x37, 0x50, 0xd1, + 0x22, 0xcf, 0xe7, 0x58, 0xa6, 0xea, 0x1a, 0x2c, + 0x99, 0xfc, 0xeb, 0x14, 0xdd, 0x43, 0x45, 0xb1, + 0x3a, 0xe9, 0x67, 0x4f, 0x85, 0x37, 0x50, 0xd1, + 0x6d, 0xc9, 0xcf, 0x3c, 0xab, 0x1a, 0x9d, 0x56, + 0x7c, 0x74, 0xff, 0xb8, 0xde, 0x35, 0xb8, 0x63, + 0x36, 0x0b, 0xf9, 0xd3, 0xf2, 0x83, 0xf9, 0xed, + 0x87, 0x4f, 0x85, 0x37, 0x50, 0xd1, 0x78, 0x4f, + 0x63, 0x8a, 0xf2, 0x74, 0xff, 0xcb, 0xd5, 0x95, + 0xbf, 0x16, 0x18, 0xa1, 0xd3, 0xeb, 0x0f, 0xdb, + 0xd4, 0xe9, 0xf2, 0xf5, 0xef, 0x68, 0x74, 0xec, + 0x2f, 0xe7, 0x49, 0xdc, 0x6a, 0x74, 0x2d, 0xc6, + 0x8e, 0xd4, 0x9d, 0x65, 0xd5, 0x98, 0x64, 0x93, + 0xf4, 0x60, 0x29, 0xc1, 0x4c, 0xef, 0x5d, 0x67, + 0x4f, 0x85, 0x37, 0x50, 0xd1, 0x7a, 0x4f, 0xf8, + 0x37, 0x0f, 0x5e, 0x98, 0xf5, 0x47, 0x4f, 0xad, + 0x99, 0xde, 0x4e, 0x93, 0xb9, 0x45, 0x9d, 0x8e, + 0x75, 0x30, 0x6f, 0x40, 0x85, 0x64, 0x63, 0xd5, + 0x0b, 0x5b, 0x8f, 0x91, 0x09, 0x3d, 0x1a, 0x60, + 0xad, 0xb1, 0x33, 0xf3, 0xb0, 0x84, 0x2f, 0x71, + 0xe4, 0x7d, 0x1a, 0x3c, 0xdd, 0xe4, 0xe9, 0xeb, + 0xce, 0xe0, 0xe9, 0xfd, 0x7e, 0x1f, 0xff, 0xee, + 0x87, 0x49, 0xba, 0x03, 0xd5, 0xa1, 0x04, 0xfb, + 0xd8, 0x5a, 0xea, 0x3a, 0x7c, 0x29, 0xba, 0x86, + 0x88, 0x8e, 0x7f, 0xfb, 0x3d, 0xd2, 0x96, 0xc0, + 0xb6, 0xdc, 0x15, 0xbb, 0x1d, 0x3f, 0xe7, 0xad, + 0x43, 0x78, 0xc7, 0xb0, 0x74, 0xff, 0xff, 0x2e, + 0x77, 0xd8, 0x5c, 0x85, 0xe3, 0x3e, 0xcd, 0xfb, + 0xe3, 0xa6, 0xa9, 0x85, 0x4d, 0xf7, 0xc5, 0x4f, + 0xfc, 0xf7, 0x26, 0x7c, 0xd6, 0x56, 0xa7, 0x7e, + 0x6b, 0xfe, 0x17, 0x9f, 0xd7, 0xc7, 0x0b, 0xce, + 0xe0, 0xe9, 0xff, 0xf9, 0x1c, 0x3a, 0x1e, 0xc3, + 0x85, 0x70, 0x1b, 0xf9, 0xd1, 0xc6, 0x2b, 0x06, + 0xe3, 0x5b, 0x14, 0xb2, 0xca, 0x50, 0xc2, 0xb5, + 0x91, 0x3e, 0xd8, 0x4a, 0x61, 0x7d, 0xb1, 0xa4, + 0xf8, 0x53, 0x75, 0x0d, 0x11, 0x74, 0xfb, 0x1f, + 0xf5, 0x07, 0x96, 0xcf, 0x64, 0x9d, 0x67, 0xd1, + 0xa6, 0x10, 0xe4, 0xca, 0x1f, 0x18, 0x14, 0xff, + 0xcc, 0xd7, 0xba, 0xc5, 0x37, 0x50, 0xd1, 0x33, + 0x4e, 0xad, 0x68, 0x74, 0xe4, 0xf3, 0x0e, 0x9b, + 0x89, 0xbb, 0x9d, 0x3f, 0x62, 0xea, 0xbf, 0xda, + 0x3a, 0x1b, 0xb9, 0xe7, 0x34, 0x3f, 0x3e, 0x4d, + 0xcf, 0x9a, 0x3a, 0x7f, 0xe6, 0xff, 0x63, 0xc9, + 0xee, 0x71, 0x68, 0x74, 0xff, 0xff, 0x77, 0xa0, + 0x81, 0x7c, 0xe7, 0xbe, 0x19, 0x57, 0x8a, 0xd4, + 0x74, 0x5a, 0x2b, 0xf2, 0x8f, 0x3f, 0xfe, 0xe7, + 0xc1, 0x55, 0xd3, 0xdb, 0x97, 0x7d, 0xf7, 0xc5, + 0x4f, 0x26, 0xea, 0x1a, 0x2c, 0xf9, 0xff, 0x7b, + 0x2a, 0xff, 0x61, 0x71, 0x43, 0xa7, 0xff, 0xbc, + 0x39, 0xde, 0x16, 0xd8, 0x2e, 0x96, 0x07, 0x4e, + 0xfb, 0xef, 0x8a, 0x9f, 0xf6, 0xbe, 0x81, 0x69, + 0xcd, 0x89, 0x4e, 0x2f, 0xe7, 0xf9, 0x73, 0xee, + 0x43, 0x75, 0xa3, 0xa7, 0xfb, 0xc1, 0xcf, 0x5e, + 0x7b, 0xc5, 0x0e, 0x84, 0x4f, 0xc4, 0x56, 0x98, + 0x57, 0x93, 0xef, 0xdb, 0xb0, 0x94, 0xd8, 0xe2, + 0x7f, 0x87, 0x7e, 0xcf, 0x94, 0x54, 0xe9, 0xff, + 0xff, 0xfa, 0xef, 0xfa, 0x5d, 0x87, 0x4e, 0xa2, + 0x0b, 0x79, 0x75, 0x02, 0xea, 0x65, 0xb0, 0xe9, + 0xd4, 0x5a, 0x8e, 0x9d, 0xc5, 0x79, 0x3a, 0x1e, + 0x8c, 0x2a, 0x42, 0x23, 0x03, 0x93, 0xd5, 0xff, + 0xda, 0x1d, 0x3e, 0xc8, 0x2d, 0x89, 0x93, 0xfe, + 0xf0, 0xbe, 0xc6, 0xae, 0xf7, 0x93, 0x44, 0x1a, + 0xe3, 0x49, 0x3e, 0xd4, 0xf3, 0x14, 0xe9, 0xf9, + 0xf9, 0x0d, 0xaf, 0x07, 0x4a, 0xd0, 0xf4, 0x80, + 0x96, 0x7f, 0xff, 0xdb, 0xf6, 0x2f, 0x38, 0x5b, + 0x0a, 0xf1, 0x63, 0xea, 0xb5, 0x87, 0x43, 0xd3, + 0x3e, 0xb8, 0x57, 0x01, 0x2c, 0xfc, 0x37, 0xcd, + 0x32, 0xa7, 0x4f, 0xff, 0xee, 0xc3, 0x7a, 0x70, + 0xea, 0x1b, 0x8a, 0x7a, 0xbc, 0xfb, 0xe3, 0xa7, + 0xff, 0xfa, 0x94, 0x51, 0xc2, 0xb9, 0x97, 0x8a, + 0x75, 0xa6, 0xbe, 0xce, 0x9e, 0xcd, 0xf9, 0xb1, + 0xd1, 0xe4, 0x44, 0xe5, 0x9a, 0x66, 0x37, 0x46, + 0x8b, 0xf2, 0x7f, 0xe7, 0xe3, 0xb7, 0xbd, 0x98, + 0xc2, 0xb0, 0xe9, 0xff, 0xbd, 0x61, 0x77, 0x4e, + 0x0f, 0xa3, 0x0e, 0x8a, 0xd1, 0x15, 0x44, 0x69, + 0xbc, 0xd1, 0xd3, 0xb1, 0xea, 0x8e, 0x9c, 0x0a, + 0x87, 0x47, 0x03, 0xcd, 0x60, 0xb8, 0x0e, 0xc2, + 0xa6, 0xed, 0xc9, 0x1d, 0xc2, 0xcb, 0x5c, 0x67, + 0xff, 0xfe, 0x6f, 0x5c, 0xf9, 0x8e, 0x69, 0xfa, + 0x3d, 0x73, 0xea, 0xe8, 0x9e, 0xa8, 0xe9, 0xef, + 0xb6, 0xe8, 0x74, 0xff, 0x3d, 0x9a, 0xfc, 0x51, + 0x7a, 0x1d, 0x0a, 0x7b, 0x7a, 0x43, 0x3d, 0x74, + 0xf0, 0x1d, 0x00, 0x78, 0x1d, 0x90, 0x4f, 0x75, + 0xef, 0x68, 0x74, 0xff, 0xb1, 0x4f, 0xfd, 0x5d, + 0x6f, 0xbc, 0x1d, 0x0a, 0x7c, 0xd6, 0x49, 0x33, + 0x5d, 0x9d, 0x26, 0x1d, 0x15, 0x9a, 0x86, 0xe4, + 0x62, 0x7f, 0x6e, 0xd6, 0xf0, 0x5e, 0x4e, 0x9f, + 0xff, 0xf6, 0x7d, 0x5e, 0x2e, 0xbc, 0x08, 0xae, + 0x3f, 0xea, 0x0f, 0xcd, 0x9d, 0x3b, 0xef, 0xbe, + 0x2a, 0x7b, 0x9e, 0x74, 0x0a, 0x71, 0x7f, 0x3f, + 0xed, 0xca, 0x7b, 0x78, 0x53, 0x72, 0x74, 0x2a, + 0x6a, 0xdc, 0x93, 0xa1, 0x97, 0xa1, 0x1d, 0x93, + 0x19, 0xff, 0xac, 0x2b, 0xc5, 0x8f, 0xaa, 0xd6, + 0x1d, 0x3e, 0xbc, 0x3d, 0x99, 0x3a, 0x7d, 0x5d, + 0x01, 0x58, 0x74, 0x2a, 0x24, 0x68, 0x87, 0xd9, + 0x3c, 0xdf, 0xe4, 0xe9, 0xfa, 0xa6, 0x9f, 0xc6, + 0x8d, 0x47, 0x4f, 0xee, 0x99, 0xbc, 0x67, 0xd8, + 0x3a, 0x6f, 0x09, 0xd0, 0xdd, 0xcf, 0xff, 0xc6, + 0xb9, 0x35, 0x9f, 0xfb, 0x95, 0xe4, 0x57, 0x1e, + 0x4f, 0x72, 0x74, 0xfd, 0x9e, 0xea, 0x6b, 0x3e, + 0x3a, 0x39, 0x3f, 0x6c, 0xa2, 0xc9, 0xdc, 0x63, + 0x3d, 0xa1, 0xb8, 0x0e, 0x2b, 0x4d, 0x45, 0x3c, + 0xc3, 0x5a, 0xe5, 0x09, 0xf4, 0x66, 0xae, 0x1f, + 0x1e, 0x35, 0x6a, 0x38, 0x61, 0x34, 0x61, 0x66, + 0x65, 0x34, 0x6a, 0x0f, 0xf1, 0x8a, 0x84, 0x22, + 0x29, 0x1c, 0xf6, 0x21, 0xc1, 0xf1, 0x87, 0x14, + 0x25, 0xba, 0xc2, 0xae, 0x1c, 0xd8, 0x94, 0xe6, + 0x9f, 0x69, 0x3f, 0xf9, 0xcc, 0xd7, 0xba, 0xc5, + 0x37, 0x50, 0xd1, 0x36, 0x4f, 0xe7, 0x58, 0xa6, + 0xea, 0x1a, 0x2a, 0xd9, 0xfc, 0xf7, 0xf7, 0x80, + 0x57, 0x9d, 0x3d, 0x79, 0xdc, 0x1d, 0x26, 0xea, + 0xcf, 0x4c, 0x0c, 0xe7, 0xc2, 0x9b, 0xa8, 0x68, + 0xad, 0x27, 0xff, 0x91, 0x46, 0xff, 0xd6, 0x6b, + 0xd7, 0xc8, 0x74, 0xff, 0xf3, 0xe9, 0x60, 0xac, + 0xdb, 0xc6, 0x15, 0x87, 0x4d, 0x8c, 0x2a, 0x25, + 0xf5, 0x2e, 0x7f, 0x2b, 0x6e, 0xb8, 0x05, 0xfc, + 0xe9, 0xfa, 0xab, 0xcf, 0xad, 0x87, 0x4f, 0xf5, + 0xb7, 0x82, 0xfd, 0x5b, 0xe8, 0x74, 0xfe, 0x7d, + 0xe3, 0x43, 0xfe, 0xce, 0x93, 0xb8, 0xd4, 0xfc, + 0x6c, 0xaf, 0xd0, 0xc7, 0xc9, 0x6e, 0x9b, 0x01, + 0x6e, 0x0f, 0x27, 0xf3, 0xac, 0x53, 0x75, 0x0d, + 0x16, 0x04, 0xf8, 0x53, 0x75, 0x0d, 0x13, 0xac, + 0xff, 0xfe, 0xca, 0xd5, 0xcd, 0xb1, 0xd4, 0xa5, + 0xe7, 0xd4, 0xee, 0xa3, 0xa7, 0xce, 0x66, 0xbd, + 0xd6, 0x89, 0x56, 0x8c, 0x27, 0xc2, 0x9b, 0xa8, + 0x68, 0xb6, 0x67, 0xfd, 0xfa, 0xd1, 0xd9, 0xf2, + 0x68, 0x9d, 0x27, 0x59, 0xf6, 0xe9, 0x84, 0xf2, + 0x6e, 0xa1, 0xa2, 0xe6, 0x93, 0x0e, 0x99, 0xd6, + 0x26, 0xef, 0xe2, 0xb9, 0xfc, 0xeb, 0x14, 0xdd, + 0x43, 0x45, 0xdf, 0x3c, 0xee, 0x9c, 0xfe, 0x74, + 0x2b, 0x6e, 0x65, 0x75, 0x8a, 0x9a, 0x18, 0xd6, + 0xa5, 0xe9, 0x4f, 0xe2, 0xe4, 0xc8, 0x68, 0x7f, + 0x0a, 0xda, 0x30, 0xe0, 0xb3, 0xa9, 0xdc, 0xff, + 0x83, 0x5c, 0xb4, 0xa3, 0x35, 0xe7, 0x4f, 0xe0, + 0xaa, 0xdb, 0xf0, 0xbd, 0x0e, 0x9f, 0x0a, 0x6e, + 0xa1, 0xa2, 0x57, 0x9f, 0xf0, 0x6f, 0xdc, 0xe5, + 0x6a, 0xbf, 0x8e, 0x9e, 0xef, 0x45, 0xe7, 0x4f, + 0xff, 0xef, 0x63, 0x59, 0xa1, 0xfe, 0x7e, 0xd0, + 0xa9, 0x3d, 0x51, 0xd1, 0xca, 0x20, 0xf4, 0x86, + 0x39, 0x47, 0x36, 0x61, 0x87, 0x3b, 0x5e, 0xe5, + 0x4d, 0xda, 0xcd, 0xe9, 0x18, 0xb4, 0xec, 0x2f, + 0x25, 0x4f, 0xfe, 0xce, 0xfb, 0x0a, 0xff, 0x0d, + 0x5d, 0xfe, 0x54, 0xfe, 0xd4, 0x77, 0x22, 0xdc, + 0xb9, 0x4f, 0xa2, 0x83, 0x92, 0x72, 0x2a, 0xae, + 0x64, 0x76, 0x4d, 0xa1, 0x5d, 0x3f, 0xf9, 0xcc, + 0xd7, 0xba, 0xc5, 0x37, 0x50, 0xd1, 0x30, 0xcf, + 0xff, 0xd6, 0xee, 0xa3, 0xbf, 0xbb, 0xa6, 0x1f, + 0xf2, 0xd1, 0xe7, 0x4f, 0xfc, 0xdd, 0x5d, 0x6f, + 0xef, 0x70, 0x0a, 0xf3, 0xa7, 0xf2, 0xed, 0x58, + 0xe9, 0xa2, 0x74, 0xfb, 0x45, 0xfa, 0xc3, 0xa0, + 0x0f, 0x63, 0xb3, 0x39, 0xf9, 0x8b, 0x61, 0x8e, + 0x23, 0xa7, 0xcb, 0x61, 0x8e, 0x23, 0xa7, 0xec, + 0xfb, 0x14, 0xda, 0xf8, 0x1e, 0xb3, 0x0b, 0xa7, + 0xff, 0xfc, 0x17, 0xf3, 0x7e, 0x2f, 0x3c, 0x02, + 0xea, 0xf5, 0x85, 0x6f, 0xa1, 0xd3, 0xf3, 0x6e, + 0xb8, 0x05, 0xfc, 0xe9, 0xff, 0xcb, 0x8f, 0xd5, + 0xf7, 0x5e, 0x2a, 0xef, 0xe3, 0xa1, 0x4f, 0xff, + 0xc6, 0x33, 0xf5, 0x3d, 0xd1, 0x9b, 0x83, 0xa7, + 0xff, 0xfc, 0x36, 0xd9, 0x43, 0x1c, 0x3a, 0x82, + 0xe7, 0x7d, 0x85, 0xc5, 0x0e, 0x95, 0xd6, 0x89, + 0xd1, 0x2f, 0x9f, 0xff, 0x64, 0x2f, 0x19, 0xf5, + 0xd7, 0x8b, 0x6c, 0xb4, 0x3a, 0x72, 0xff, 0xd4, + 0xe8, 0xb3, 0xf4, 0x05, 0x69, 0xed, 0xeb, 0xcd, + 0x9d, 0x27, 0x71, 0xaa, 0xfb, 0xb9, 0x85, 0x0a, + 0x3c, 0x34, 0x91, 0x98, 0x78, 0x04, 0x2f, 0xb1, + 0x09, 0xce, 0xc8, 0x27, 0xc2, 0x9b, 0xa8, 0x68, + 0xab, 0xa7, 0xf9, 0xee, 0xb1, 0x4d, 0xd4, 0x34, + 0x47, 0x92, 0x75, 0x9f, 0x8e, 0x98, 0x4f, 0xe7, + 0x58, 0xa6, 0xea, 0x1a, 0x2c, 0x19, 0xfc, 0xeb, + 0x14, 0xdd, 0x43, 0x45, 0x95, 0x3f, 0x9d, 0x62, + 0x9b, 0xa8, 0x68, 0xb4, 0xe7, 0x93, 0x75, 0x0d, + 0x16, 0xe4, 0xff, 0xcb, 0x63, 0x61, 0xc3, 0x37, + 0x5f, 0xc7, 0x40, 0x9f, 0x7d, 0x0a, 0xe7, 0xf9, + 0x43, 0xb6, 0x2d, 0x31, 0xe3, 0xa7, 0xfd, 0xaf, + 0x75, 0x8a, 0x6e, 0xa1, 0xa2, 0x87, 0x9f, 0xf9, + 0x9b, 0xca, 0xf3, 0x9f, 0x07, 0x98, 0x74, 0xff, + 0xbb, 0x1f, 0xc7, 0x43, 0x17, 0xf9, 0xd3, 0xf5, + 0x36, 0xba, 0x63, 0xc7, 0x4f, 0xc1, 0xc6, 0xd8, + 0xad, 0x0e, 0x9f, 0xff, 0xaf, 0x9c, 0xaf, 0x57, + 0x60, 0x37, 0xfa, 0x51, 0x7f, 0x2a, 0x4e, 0xb4, + 0xf7, 0x7c, 0x42, 0xc3, 0x8d, 0x46, 0xa2, 0x2e, + 0x0f, 0xbb, 0x2e, 0xe2, 0x2f, 0x9f, 0xce, 0xb1, + 0x4d, 0xd4, 0x34, 0x5e, 0x70, 0xac, 0x9c, 0x07, + 0xa2, 0x72, 0xa5, 0x73, 0x89, 0xd5, 0xc6, 0x08, + 0x24, 0xcc, 0x3b, 0xc9, 0xd8, 0x4a, 0x87, 0x6c, + 0xf5, 0x3f, 0x9d, 0x62, 0x9b, 0xa8, 0x68, 0xa5, + 0xa7, 0xf3, 0xac, 0x53, 0x75, 0x0d, 0x16, 0x14, + 0xfe, 0x75, 0x8a, 0x6e, 0xa1, 0xa2, 0xcb, 0x9e, + 0x77, 0x46, 0xe3, 0xb7, 0x63, 0xa7, 0x3b, 0xab, + 0x0e, 0x9e, 0x47, 0x2d, 0x10, 0xf4, 0x3b, 0x32, + 0x9f, 0xfc, 0xe6, 0x6b, 0xdd, 0x62, 0x9b, 0xa8, + 0x68, 0xa3, 0x27, 0xf3, 0x95, 0xb2, 0x8a, 0xfe, + 0x74, 0x3d, 0x3b, 0xe1, 0x3b, 0x61, 0xde, 0xc2, + 0x2e, 0x87, 0x18, 0x52, 0x9f, 0xf9, 0xda, 0xf7, + 0x58, 0xa6, 0xea, 0x1a, 0x23, 0x99, 0xff, 0xce, + 0x66, 0xbd, 0xd6, 0x29, 0xba, 0x86, 0x89, 0xca, + 0x7f, 0x3a, 0xc5, 0x37, 0x50, 0xd1, 0x66, 0x4f, + 0xfc, 0xe5, 0xfc, 0x57, 0x19, 0xda, 0xde, 0x74, + 0xfe, 0x75, 0x8a, 0x6e, 0xa1, 0xa2, 0xdd, 0x9f, + 0xfc, 0xe6, 0x6b, 0xdd, 0x62, 0x9b, 0xa8, 0x68, + 0xa4, 0x27, 0xfe, 0x76, 0xbd, 0xd6, 0x29, 0xba, + 0x86, 0x89, 0x4a, 0x2a, 0x4f, 0xd9, 0xa4, 0xc6, + 0x29, 0x7e, 0x76, 0x08, 0x98, 0x3b, 0x6f, 0x52, + 0x9f, 0xf6, 0xbd, 0xd6, 0x29, 0xba, 0x86, 0x89, + 0xda, 0x7f, 0xfd, 0xee, 0x7b, 0x62, 0xb7, 0xef, + 0x20, 0xa1, 0x68, 0x74, 0x9c, 0xc4, 0x4e, 0xea, + 0x34, 0xff, 0xda, 0xcc, 0xda, 0x6e, 0x57, 0xab, + 0xce, 0x9f, 0xf8, 0x2f, 0x3b, 0x55, 0xd0, 0x36, + 0xb3, 0xa6, 0xe2, 0x77, 0x28, 0x85, 0xa2, 0x1c, + 0x31, 0x1c, 0x1c, 0x50, 0xad, 0x9f, 0x0a, 0x6e, + 0xa1, 0xa2, 0x2c, 0x9f, 0xf6, 0xbd, 0xd6, 0x29, + 0xba, 0x86, 0x89, 0x76, 0x7f, 0xfe, 0xbe, 0x72, + 0xbd, 0x5d, 0x80, 0xdf, 0xe9, 0x45, 0xfc, 0xa9, + 0x3a, 0xd1, 0xa8, 0xc3, 0x0e, 0x24, 0x69, 0xff, + 0xce, 0x66, 0xbd, 0xd6, 0x29, 0xba, 0x86, 0x89, + 0x8a, 0x7e, 0xb1, 0x4d, 0xd4, 0x34, 0x55, 0x33, + 0xff, 0xff, 0x87, 0x73, 0x5b, 0xef, 0x0e, 0xce, + 0xd0, 0x7d, 0xf6, 0x33, 0xe1, 0x79, 0xd0, 0xe4, + 0x56, 0xe9, 0xac, 0xff, 0xe7, 0x33, 0x5e, 0xeb, + 0x14, 0xdd, 0x43, 0x44, 0xe9, 0x3f, 0xbd, 0xa2, + 0xaf, 0xd6, 0xc7, 0x4f, 0x9a, 0x56, 0x96, 0x87, + 0x4f, 0xdf, 0x5f, 0x9b, 0x58, 0x1d, 0x3d, 0xec, + 0xab, 0xbc, 0x7a, 0xd4, 0x28, 0x9f, 0xfb, 0xba, + 0x61, 0x6b, 0x77, 0x6d, 0x79, 0x87, 0x43, 0x11, + 0x05, 0x93, 0x99, 0xff, 0x6b, 0xdd, 0x62, 0x9b, + 0xa8, 0x68, 0x9d, 0xe7, 0xd8, 0xef, 0x59, 0xe2, + 0xa4, 0xee, 0x53, 0x9b, 0xb8, 0xc2, 0x98, 0x47, + 0xa8, 0xd3, 0xff, 0x9c, 0xcd, 0x7b, 0xac, 0x53, + 0x75, 0x0d, 0x14, 0x2c, 0xff, 0xe7, 0x33, 0x5e, + 0xeb, 0x14, 0xdd, 0x43, 0x45, 0x25, 0x3f, 0xff, + 0xae, 0x8e, 0xeb, 0x6d, 0x67, 0x59, 0x8c, 0xae, + 0x3b, 0x61, 0xd1, 0x52, 0xe4, 0xbb, 0xce, 0x12, + 0x1f, 0xe2, 0x44, 0xc8, 0xfb, 0x7f, 0x49, 0xed, + 0x4b, 0x89, 0x4a, 0x7f, 0x3a, 0xc5, 0x37, 0x50, + 0xd1, 0x12, 0x4f, 0xfe, 0x73, 0x35, 0xee, 0xb1, + 0x4d, 0xd4, 0x34, 0x4b, 0xd3, 0xe1, 0xfd, 0x9e, + 0xa1, 0xd3, 0xbf, 0x5c, 0x1d, 0x3f, 0xf6, 0xb5, + 0x45, 0x6d, 0xb9, 0x5a, 0xda, 0x3a, 0x3c, 0x88, + 0xb6, 0x8a, 0x04, 0x72, 0x7f, 0xbd, 0xa1, 0xde, + 0x1a, 0x5e, 0x87, 0x4f, 0x85, 0x37, 0x50, 0xd1, + 0x4b, 0xcf, 0xfe, 0xb7, 0xaf, 0xf4, 0x15, 0xad, + 0xfe, 0x61, 0xd3, 0xe6, 0xff, 0x31, 0x68, 0x74, + 0xfb, 0x5b, 0x58, 0xd0, 0xe9, 0x2f, 0x27, 0xa2, + 0xc2, 0xa9, 0x39, 0x53, 0x5e, 0xe4, 0xc2, 0xce, + 0xda, 0x30, 0xc4, 0x26, 0xe7, 0xf3, 0xac, 0x53, + 0x75, 0x0d, 0x14, 0xe4, 0xff, 0xbc, 0x3b, 0x4c, + 0xdd, 0x82, 0x1d, 0x3f, 0xeb, 0xca, 0x8d, 0xbb, + 0xef, 0xbe, 0x2a, 0x6f, 0x7c, 0x74, 0xd5, 0x3b, + 0x94, 0x48, 0x71, 0x1d, 0x37, 0x9f, 0xcf, 0x85, + 0x37, 0x50, 0xd1, 0x5e, 0x4f, 0xff, 0xd7, 0xce, + 0x57, 0xab, 0xb0, 0x1b, 0xfd, 0x28, 0xbf, 0x95, + 0x27, 0x5a, 0x23, 0xb8, 0x8c, 0x27, 0xfe, 0x76, + 0xbd, 0xd6, 0x29, 0xba, 0x86, 0x89, 0x1e, 0x77, + 0xbf, 0x53, 0xa7, 0x25, 0xb0, 0xa7, 0x17, 0x93, + 0xe1, 0x4d, 0xd4, 0x34, 0x49, 0x13, 0xce, 0xd7, + 0xb9, 0x4f, 0x66, 0xca, 0x67, 0xfe, 0x76, 0xbd, + 0xd6, 0x29, 0xba, 0x86, 0x89, 0x2a, 0x7c, 0x29, + 0xba, 0x86, 0x8b, 0xc6, 0x7e, 0xec, 0x2b, 0xda, + 0xe8, 0x74, 0xfa, 0x94, 0xc5, 0xa1, 0xd3, 0xfc, + 0xf7, 0x58, 0xa6, 0xea, 0x1a, 0x24, 0xd9, 0x3a, + 0xd1, 0x8d, 0x59, 0x80, 0x97, 0xe9, 0x34, 0x2a, + 0xf6, 0xfd, 0x47, 0x6f, 0x94, 0x77, 0xca, 0xb7, + 0xa1, 0x96, 0xd4, 0x34, 0x98, 0x57, 0x98, 0x60, + 0xe0, 0xdf, 0xb8, 0xc4, 0xa1, 0x63, 0x8e, 0x24, + 0xaa, 0x3b, 0x07, 0xca, 0x0a, 0xe6, 0x50, 0xd5, + 0xdb, 0xd1, 0x3e, 0x92, 0x96, 0x92, 0xd0, 0xde, + 0x57, 0x3d, 0xa7, 0xe9, 0xd2, 0xfe, 0x3c, 0x76, + 0xcd, 0x56, 0x0a, 0x83, 0x4a, 0x55, 0x66, 0x24, + 0xec, 0x73, 0x3b, 0xfd, 0xb5, 0x8f, 0x37, 0xf2, + 0xc5, 0xdb, 0x98, 0x58, 0x85, 0x21, 0x9a, 0x94, + 0x98, 0x1c, 0x57, 0x83, 0xbd, 0xd3, 0x49, 0x9b, + 0x4a, 0x62, 0xfa, 0x52, 0x8f, 0x14, 0x7c, 0xfd, + 0x67, 0x65, 0x9b, 0xe7, 0xd8, 0xa0, }; -static const unsigned kPreloadedHSTSBits = 103990; +static const unsigned kPreloadedHSTSBits = 103917; -static const unsigned kHSTSRootPosition = 103406; +static const unsigned kHSTSRootPosition = 103333; #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 a8a5bf1..ff5d79a 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -1217,7 +1217,6 @@ { "name": "cloudstoragemaus.com", "include_subdomains": true, "mode": "force-https" }, { "name": "comdurav.com", "include_subdomains": true, "mode": "force-https" }, { "name": "digitaldaddy.net", "include_subdomains": true, "mode": "force-https" }, - { "name": "eldietista.es", "include_subdomains": true, "mode": "force-https" }, { "name": "elnutricionista.es", "include_subdomains": true, "mode": "force-https" }, { "name": "fronteers.nl", "include_subdomains": true, "mode": "force-https" }, { "name": "getssl.uz", "include_subdomains": true, "mode": "force-https" },
diff --git a/net/net.gyp b/net/net.gyp index 8bfcc7b..c1338bf 100644 --- a/net/net.gyp +++ b/net/net.gyp
@@ -665,6 +665,10 @@ [ 'enable_websockets != 1', { 'sources/': [ ['exclude', '^websockets/'], + ['exclude', '^server/'], + ], + 'dependencies!': [ + 'http_server', ], }], ['disable_file_support==1', { @@ -959,6 +963,8 @@ 'test/spawned_test_server/spawner_communicator.h', 'test/url_request/url_request_failed_job.cc', 'test/url_request/url_request_failed_job.h', + 'test/url_request/url_request_mock_data_job.cc', + 'test/url_request/url_request_mock_data_job.h', 'test/url_request/url_request_mock_http_job.cc', 'test/url_request/url_request_mock_http_job.h', 'url_request/test_url_fetcher_factory.cc', @@ -1075,6 +1081,8 @@ 'server/http_server_response_info.h', 'server/web_socket.cc', 'server/web_socket.h', + 'server/web_socket_encoder.cc', + 'server/web_socket_encoder.h', ], # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. 'msvs_disabled_warnings': [4267, ],
diff --git a/net/net.gypi b/net/net.gypi index 7d7d2f0..5ca70f7 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -153,6 +153,8 @@ 'ssl/signed_certificate_timestamp_and_status.h', 'ssl/ssl_cert_request_info.cc', 'ssl/ssl_cert_request_info.h', + 'ssl/ssl_cipher_suite_names.cc', + 'ssl/ssl_cipher_suite_names.h', 'ssl/ssl_client_auth_cache.cc', 'ssl/ssl_client_auth_cache.h', 'ssl/ssl_client_cert_type.h', @@ -1107,8 +1109,6 @@ 'ssl/client_cert_store_nss.h', 'ssl/client_cert_store_win.cc', 'ssl/client_cert_store_win.h', - 'ssl/ssl_cipher_suite_names.cc', - 'ssl/ssl_cipher_suite_names.h', 'ssl/ssl_config_service_defaults.cc', 'ssl/ssl_config_service_defaults.h', 'third_party/mozilla_security_manager/nsKeygenHandler.cpp', @@ -1587,6 +1587,7 @@ 'server/http_connection_unittest.cc', 'server/http_server_response_info_unittest.cc', 'server/http_server_unittest.cc', + 'server/web_socket_encoder_unittest.cc', 'socket/client_socket_pool_base_unittest.cc', 'socket/deterministic_socket_data_unittest.cc', 'socket/mock_client_socket_pool_manager.cc',
diff --git a/net/proxy/proxy_config_service_android.cc b/net/proxy/proxy_config_service_android.cc index 50407fe..80e3b92 100644 --- a/net/proxy/proxy_config_service_android.cc +++ b/net/proxy/proxy_config_service_android.cc
@@ -98,6 +98,12 @@ // by | and that use * as a wildcard. For example, setting the // http.nonProxyHosts property to *.android.com|*.kernel.org will cause // requests to http://developer.android.com to be made without a proxy. + + // Force localhost to be on the proxy exclusion list; + // otherwise all localhost traffic is routed through + // the proxy which is not desired. + bypass_rules->AddRuleToBypassLocal(); + std::string non_proxy_hosts = get_property.Run(scheme + ".nonProxyHosts"); if (non_proxy_hosts.empty())
diff --git a/net/proxy/proxy_resolver_script.h b/net/proxy/proxy_resolver_script.h index 283eff9..e838bed 100644 --- a/net/proxy/proxy_resolver_script.h +++ b/net/proxy/proxy_resolver_script.h
@@ -1,3 +1,10 @@ +// Copyright (c) 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 NET_PROXY_PROXY_RESOLVER_SCRIPT_H_ +#define NET_PROXY_PROXY_RESOLVER_SCRIPT_H_ + /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -37,9 +44,6 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef NET_PROXY_PROXY_RESOLVER_SCRIPT_H_ -#define NET_PROXY_PROXY_RESOLVER_SCRIPT_H_ - // The following code was formatted from: // 'mozilla/netwerk/base/src/nsProxyAutoConfig.js' (1.55) // @@ -51,6 +55,8 @@ // sed -e 's/"$/" \\/g' | // sed -e 's/\/(ipaddr);/\/.exec(ipaddr);/g' | // grep -v '^var pacUtils =' +// +// isPlainHost() was removed. #define PROXY_RESOLVER_SCRIPT \ "function dnsDomainIs(host, domain) {\n" \ " return (host.length >= domain.length &&\n" \ @@ -87,10 +93,6 @@ " \n" \ "}\n" \ "" \ - "function isPlainHostName(host) {\n" \ - " return (host.search('\\\\.') == -1);\n" \ - "}\n" \ - "" \ "function isResolvable(host) {\n" \ " var ip = dnsResolve(host);\n" \ " return (ip != null);\n" \
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc index 963153d..57ee714 100644 --- a/net/proxy/proxy_resolver_v8.cc +++ b/net/proxy/proxy_resolver_v8.cc
@@ -334,6 +334,17 @@ return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); } +// Consider only single component domains like 'foo' as plain host names. +bool IsPlainHostName(const std::string& hostname_utf8) { + if (hostname_utf8.find('.') != std::string::npos) + return false; + + // IPv6 addresses may not contain periods, however are not be considered a + // plain host name. + IPAddressNumber unused; + return !ParseIPLiteralToNumber(hostname_utf8, &unused); +} + } // namespace // ProxyResolverV8::Context --------------------------------------------------- @@ -439,6 +450,11 @@ global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolve"), dns_resolve_template); + v8::Local<v8::FunctionTemplate> is_plain_host_name_template = + v8::FunctionTemplate::New(isolate_, &IsPlainHostNameCallback, v8_this); + global_template->Set(ASCIILiteralToV8String(isolate_, "isPlainHostName"), + is_plain_host_name_template); + // Microsoft's PAC extensions: v8::Local<v8::FunctionTemplate> dns_resolve_ex_template = @@ -698,6 +714,22 @@ args.GetReturnValue().Set(IsInNetEx(ip_address, ip_prefix)); } + // V8 callback for when "isPlainHostName()" is invoked by the PAC script. + static void IsPlainHostNameCallback( + const v8::FunctionCallbackInfo<v8::Value>& args) { + // Need at least 1 string arguments. + if (args.Length() < 1 || args[0].IsEmpty() || !args[0]->IsString()) { + args.GetIsolate()->ThrowException( + v8::Exception::TypeError(ASCIIStringToV8String( + args.GetIsolate(), "Requires 1 string parameter"))); + return; + } + + std::string hostname_utf8 = + V8StringToUTF8(v8::Local<v8::String>::Cast(args[0])); + args.GetReturnValue().Set(IsPlainHostName(hostname_utf8)); + } + mutable base::Lock lock_; ProxyResolverV8* parent_; v8::Isolate* isolate_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 738326a..ecd338a 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -292,13 +292,17 @@ } void QuicStreamFactory::Job::OnIOComplete(int rv) { - // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. - tracked_objects::ScopedTracker tracking_profile( + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile1( FROM_HERE_WITH_EXPLICIT_FUNCTION( - "436634 QuicStreamFactory::Job::OnIOComplete")); + "422516 QuicStreamFactory::Job::OnIOComplete1")); rv = DoLoop(rv); + tracked_objects::ScopedTracker tracking_profile2( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicStreamFactory::Job::OnIOComplete2")); + if (rv != ERR_IO_PENDING && !callback_.is_null()) { callback_.Run(rv); } @@ -647,6 +651,11 @@ void QuicStreamFactory::OnJobComplete(Job* job, int rv) { if (rv == OK) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile1( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicStreamFactory::OnJobComplete1")); + if (!always_require_handshake_confirmation_) set_require_confirmation(false); @@ -658,6 +667,12 @@ (*it)->net_log())); } } + + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile2( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicStreamFactory::OnJobComplete2")); + while (!job_requests_map_[job].empty()) { RequestSet::iterator it = job_requests_map_[job].begin(); QuicStreamRequest* request = *it; @@ -668,6 +683,12 @@ // profile which can not be deleted via callbacks. request->OnRequestComplete(rv); } + + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile3( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicStreamFactory::OnJobComplete3")); + active_jobs_.erase(job->server_id()); job_requests_map_.erase(job); delete job;
diff --git a/net/server/web_socket.cc b/net/server/web_socket.cc index d67ecb6..e5d1cb7 100644 --- a/net/server/web_socket.cc +++ b/net/server/web_socket.cc
@@ -4,10 +4,7 @@ #include "net/server/web_socket.h" -#include <limits> - #include "base/base64.h" -#include "base/rand_util.h" #include "base/logging.h" #include "base/md5.h" #include "base/sha1.h" @@ -18,6 +15,7 @@ #include "net/server/http_server.h" #include "net/server/http_server_request_info.h" #include "net/server/http_server_response_info.h" +#include "net/server/web_socket_encoder.h" namespace net { @@ -152,31 +150,6 @@ const int WebSocketHixie76::kWebSocketHandshakeBodyLen = 8; - -// Constants for hybi-10 frame format. - -typedef int OpCode; - -const OpCode kOpCodeContinuation = 0x0; -const OpCode kOpCodeText = 0x1; -const OpCode kOpCodeBinary = 0x2; -const OpCode kOpCodeClose = 0x8; -const OpCode kOpCodePing = 0x9; -const OpCode kOpCodePong = 0xA; - -const unsigned char kFinalBit = 0x80; -const unsigned char kReserved1Bit = 0x40; -const unsigned char kReserved2Bit = 0x20; -const unsigned char kReserved3Bit = 0x10; -const unsigned char kOpCodeMask = 0xF; -const unsigned char kMaskBit = 0x80; -const unsigned char kPayloadLengthMask = 0x7F; - -const size_t kMaxSingleBytePayloadLength = 125; -const size_t kTwoBytePayloadLengthField = 126; -const size_t kEightBytePayloadLengthField = 127; -const size_t kMaskingKeyWidthInBytes = 4; - class WebSocketHybi17 : public WebSocket { public: static WebSocket* Create(HttpServer* server, @@ -207,22 +180,22 @@ std::string encoded_hash; base::Base64Encode(base::SHA1HashString(data), &encoded_hash); - server_->SendRaw( - connection_->id(), - base::StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" - "Upgrade: WebSocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: %s\r\n" - "\r\n", - encoded_hash.c_str())); + server_->SendRaw(connection_->id(), + base::StringPrintf( + "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" + "Upgrade: WebSocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: %s\r\n" + "%s" + "\r\n", + encoded_hash.c_str(), response_extensions_.c_str())); } ParseResult Read(std::string* message) override { HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf(); base::StringPiece frame(read_buf->StartOfBuffer(), read_buf->GetSize()); int bytes_consumed = 0; - ParseResult result = - WebSocket::DecodeFrameHybi17(frame, true, &bytes_consumed, message); + ParseResult result = encoder_->DecodeFrame(frame, &bytes_consumed, message); if (result == FRAME_OK) read_buf->DidConsume(bytes_consumed); if (result == FRAME_CLOSE) @@ -233,8 +206,9 @@ void Send(const std::string& message) override { if (closed_) return; - server_->SendRaw(connection_->id(), - WebSocket::EncodeFrameHybi17(message, 0)); + std::string encoded; + encoder_->EncodeFrame(message, 0, &encoded); + server_->SendRaw(connection_->id(), encoded); } private: @@ -243,27 +217,19 @@ const HttpServerRequestInfo& request, size_t* pos) : WebSocket(server, connection), - op_code_(0), - final_(false), - reserved1_(false), - reserved2_(false), - reserved3_(false), - masked_(false), - payload_(0), - payload_length_(0), - frame_end_(0), closed_(false) { + std::string request_extensions = + request.GetHeaderValue("sec-websocket-extensions"); + encoder_.reset(WebSocketEncoder::CreateServer(request_extensions, + &response_extensions_)); + if (!response_extensions_.empty()) { + response_extensions_ = + "Sec-WebSocket-Extensions: " + response_extensions_ + "\r\n"; + } } - OpCode op_code_; - bool final_; - bool reserved1_; - bool reserved2_; - bool reserved3_; - bool masked_; - const char* payload_; - size_t payload_length_; - const char* frame_end_; + scoped_ptr<WebSocketEncoder> encoder_; + std::string response_extensions_; bool closed_; DISALLOW_COPY_AND_ASSIGN(WebSocketHybi17); @@ -282,142 +248,12 @@ return WebSocketHixie76::Create(server, connection, request, pos); } -// static -WebSocket::ParseResult WebSocket::DecodeFrameHybi17( - const base::StringPiece& frame, - bool client_frame, - int* bytes_consumed, - std::string* output) { - size_t data_length = frame.length(); - if (data_length < 2) - return FRAME_INCOMPLETE; - - const char* buffer_begin = const_cast<char*>(frame.data()); - const char* p = buffer_begin; - const char* buffer_end = p + data_length; - - unsigned char first_byte = *p++; - unsigned char second_byte = *p++; - - bool final = (first_byte & kFinalBit) != 0; - bool reserved1 = (first_byte & kReserved1Bit) != 0; - bool reserved2 = (first_byte & kReserved2Bit) != 0; - bool reserved3 = (first_byte & kReserved3Bit) != 0; - int op_code = first_byte & kOpCodeMask; - bool masked = (second_byte & kMaskBit) != 0; - if (!final || reserved1 || reserved2 || reserved3) - return FRAME_ERROR; // Extensions and not supported. - - bool closed = false; - switch (op_code) { - case kOpCodeClose: - closed = true; - break; - case kOpCodeText: - break; - case kOpCodeBinary: // We don't support binary frames yet. - case kOpCodeContinuation: // We don't support binary frames yet. - case kOpCodePing: // We don't support binary frames yet. - case kOpCodePong: // We don't support binary frames yet. - default: - return FRAME_ERROR; - } - - if (client_frame && !masked) // In Hybi-17 spec client MUST mask his frame. - return FRAME_ERROR; - - uint64 payload_length64 = second_byte & kPayloadLengthMask; - if (payload_length64 > kMaxSingleBytePayloadLength) { - int extended_payload_length_size; - if (payload_length64 == kTwoBytePayloadLengthField) - extended_payload_length_size = 2; - else { - DCHECK(payload_length64 == kEightBytePayloadLengthField); - extended_payload_length_size = 8; - } - if (buffer_end - p < extended_payload_length_size) - return FRAME_INCOMPLETE; - payload_length64 = 0; - for (int i = 0; i < extended_payload_length_size; ++i) { - payload_length64 <<= 8; - payload_length64 |= static_cast<unsigned char>(*p++); - } - } - - size_t actual_masking_key_length = masked ? kMaskingKeyWidthInBytes : 0; - static const uint64 max_payload_length = 0x7FFFFFFFFFFFFFFFull; - static size_t max_length = std::numeric_limits<size_t>::max(); - if (payload_length64 > max_payload_length || - payload_length64 + actual_masking_key_length > max_length) { - // WebSocket frame length too large. - return FRAME_ERROR; - } - size_t payload_length = static_cast<size_t>(payload_length64); - - size_t total_length = actual_masking_key_length + payload_length; - if (static_cast<size_t>(buffer_end - p) < total_length) - return FRAME_INCOMPLETE; - - if (masked) { - output->resize(payload_length); - const char* masking_key = p; - char* payload = const_cast<char*>(p + kMaskingKeyWidthInBytes); - for (size_t i = 0; i < payload_length; ++i) // Unmask the payload. - (*output)[i] = payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]; - } else { - output->assign(p, p + payload_length); - } - - size_t pos = p + actual_masking_key_length + payload_length - buffer_begin; - *bytes_consumed = pos; - return closed ? FRAME_CLOSE : FRAME_OK; -} - -// static -std::string WebSocket::EncodeFrameHybi17(const std::string& message, - int masking_key) { - std::vector<char> frame; - OpCode op_code = kOpCodeText; - size_t data_length = message.length(); - - frame.push_back(kFinalBit | op_code); - char mask_key_bit = masking_key != 0 ? kMaskBit : 0; - if (data_length <= kMaxSingleBytePayloadLength) - frame.push_back(data_length | mask_key_bit); - else if (data_length <= 0xFFFF) { - frame.push_back(kTwoBytePayloadLengthField | mask_key_bit); - frame.push_back((data_length & 0xFF00) >> 8); - frame.push_back(data_length & 0xFF); - } else { - frame.push_back(kEightBytePayloadLengthField | mask_key_bit); - char extended_payload_length[8]; - size_t remaining = data_length; - // Fill the length into extended_payload_length in the network byte order. - for (int i = 0; i < 8; ++i) { - extended_payload_length[7 - i] = remaining & 0xFF; - remaining >>= 8; - } - frame.insert(frame.end(), - extended_payload_length, - extended_payload_length + 8); - DCHECK(!remaining); - } - - const char* data = const_cast<char*>(message.data()); - if (masking_key != 0) { - const char* mask_bytes = reinterpret_cast<char*>(&masking_key); - frame.insert(frame.end(), mask_bytes, mask_bytes + 4); - for (size_t i = 0; i < data_length; ++i) // Mask the payload. - frame.push_back(data[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]); - } else { - frame.insert(frame.end(), data, data + data_length); - } - return std::string(&frame[0], frame.size()); -} - WebSocket::WebSocket(HttpServer* server, HttpConnection* connection) : server_(server), connection_(connection) { } +WebSocket::~WebSocket() { +} + } // namespace net
diff --git a/net/server/web_socket.h b/net/server/web_socket.h index 9b3a794..3f2c1d8 100644 --- a/net/server/web_socket.h +++ b/net/server/web_socket.h
@@ -30,18 +30,10 @@ const HttpServerRequestInfo& request, size_t* pos); - static ParseResult DecodeFrameHybi17(const base::StringPiece& frame, - bool client_frame, - int* bytes_consumed, - std::string* output); - - static std::string EncodeFrameHybi17(const std::string& data, - int masking_key); - virtual void Accept(const HttpServerRequestInfo& request) = 0; virtual ParseResult Read(std::string* message) = 0; virtual void Send(const std::string& message) = 0; - virtual ~WebSocket() {} + virtual ~WebSocket(); protected: WebSocket(HttpServer* server, HttpConnection* connection);
diff --git a/net/server/web_socket_encoder.cc b/net/server/web_socket_encoder.cc new file mode 100644 index 0000000..cb23326 --- /dev/null +++ b/net/server/web_socket_encoder.cc
@@ -0,0 +1,364 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/server/web_socket_encoder.h" + +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "net/base/io_buffer.h" +#include "net/websockets/websocket_extension_parser.h" + +namespace net { + +const char WebSocketEncoder::kClientExtensions[] = + "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits"; + +namespace { + +const int kInflaterChunkSize = 16 * 1024; + +// Constants for hybi-10 frame format. + +typedef int OpCode; + +const OpCode kOpCodeContinuation = 0x0; +const OpCode kOpCodeText = 0x1; +const OpCode kOpCodeBinary = 0x2; +const OpCode kOpCodeClose = 0x8; +const OpCode kOpCodePing = 0x9; +const OpCode kOpCodePong = 0xA; + +const unsigned char kFinalBit = 0x80; +const unsigned char kReserved1Bit = 0x40; +const unsigned char kReserved2Bit = 0x20; +const unsigned char kReserved3Bit = 0x10; +const unsigned char kOpCodeMask = 0xF; +const unsigned char kMaskBit = 0x80; +const unsigned char kPayloadLengthMask = 0x7F; + +const size_t kMaxSingleBytePayloadLength = 125; +const size_t kTwoBytePayloadLengthField = 126; +const size_t kEightBytePayloadLengthField = 127; +const size_t kMaskingKeyWidthInBytes = 4; + +WebSocket::ParseResult DecodeFrameHybi17(const base::StringPiece& frame, + bool client_frame, + int* bytes_consumed, + std::string* output, + bool* compressed) { + size_t data_length = frame.length(); + if (data_length < 2) + return WebSocket::FRAME_INCOMPLETE; + + const char* buffer_begin = const_cast<char*>(frame.data()); + const char* p = buffer_begin; + const char* buffer_end = p + data_length; + + unsigned char first_byte = *p++; + unsigned char second_byte = *p++; + + bool final = (first_byte & kFinalBit) != 0; + bool reserved1 = (first_byte & kReserved1Bit) != 0; + bool reserved2 = (first_byte & kReserved2Bit) != 0; + bool reserved3 = (first_byte & kReserved3Bit) != 0; + int op_code = first_byte & kOpCodeMask; + bool masked = (second_byte & kMaskBit) != 0; + *compressed = reserved1; + if (!final || reserved2 || reserved3) + return WebSocket::FRAME_ERROR; // Only compression extension is supported. + + bool closed = false; + switch (op_code) { + case kOpCodeClose: + closed = true; + break; + case kOpCodeText: + break; + case kOpCodeBinary: // We don't support binary frames yet. + case kOpCodeContinuation: // We don't support binary frames yet. + case kOpCodePing: // We don't support binary frames yet. + case kOpCodePong: // We don't support binary frames yet. + default: + return WebSocket::FRAME_ERROR; + } + + if (client_frame && !masked) // In Hybi-17 spec client MUST mask his frame. + return WebSocket::FRAME_ERROR; + + uint64 payload_length64 = second_byte & kPayloadLengthMask; + if (payload_length64 > kMaxSingleBytePayloadLength) { + int extended_payload_length_size; + if (payload_length64 == kTwoBytePayloadLengthField) + extended_payload_length_size = 2; + else { + DCHECK(payload_length64 == kEightBytePayloadLengthField); + extended_payload_length_size = 8; + } + if (buffer_end - p < extended_payload_length_size) + return WebSocket::FRAME_INCOMPLETE; + payload_length64 = 0; + for (int i = 0; i < extended_payload_length_size; ++i) { + payload_length64 <<= 8; + payload_length64 |= static_cast<unsigned char>(*p++); + } + } + + size_t actual_masking_key_length = masked ? kMaskingKeyWidthInBytes : 0; + static const uint64 max_payload_length = 0x7FFFFFFFFFFFFFFFull; + static size_t max_length = std::numeric_limits<size_t>::max(); + if (payload_length64 > max_payload_length || + payload_length64 + actual_masking_key_length > max_length) { + // WebSocket frame length too large. + return WebSocket::FRAME_ERROR; + } + size_t payload_length = static_cast<size_t>(payload_length64); + + size_t total_length = actual_masking_key_length + payload_length; + if (static_cast<size_t>(buffer_end - p) < total_length) + return WebSocket::FRAME_INCOMPLETE; + + if (masked) { + output->resize(payload_length); + const char* masking_key = p; + char* payload = const_cast<char*>(p + kMaskingKeyWidthInBytes); + for (size_t i = 0; i < payload_length; ++i) // Unmask the payload. + (*output)[i] = payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]; + } else { + output->assign(p, p + payload_length); + } + + size_t pos = p + actual_masking_key_length + payload_length - buffer_begin; + *bytes_consumed = pos; + return closed ? WebSocket::FRAME_CLOSE : WebSocket::FRAME_OK; +} + +void EncodeFrameHybi17(const std::string& message, + int masking_key, + bool compressed, + std::string* output) { + std::vector<char> frame; + OpCode op_code = kOpCodeText; + size_t data_length = message.length(); + + int reserved1 = compressed ? kReserved1Bit : 0; + frame.push_back(kFinalBit | op_code | reserved1); + char mask_key_bit = masking_key != 0 ? kMaskBit : 0; + if (data_length <= kMaxSingleBytePayloadLength) + frame.push_back(data_length | mask_key_bit); + else if (data_length <= 0xFFFF) { + frame.push_back(kTwoBytePayloadLengthField | mask_key_bit); + frame.push_back((data_length & 0xFF00) >> 8); + frame.push_back(data_length & 0xFF); + } else { + frame.push_back(kEightBytePayloadLengthField | mask_key_bit); + char extended_payload_length[8]; + size_t remaining = data_length; + // Fill the length into extended_payload_length in the network byte order. + for (int i = 0; i < 8; ++i) { + extended_payload_length[7 - i] = remaining & 0xFF; + remaining >>= 8; + } + frame.insert(frame.end(), extended_payload_length, + extended_payload_length + 8); + DCHECK(!remaining); + } + + const char* data = const_cast<char*>(message.data()); + if (masking_key != 0) { + const char* mask_bytes = reinterpret_cast<char*>(&masking_key); + frame.insert(frame.end(), mask_bytes, mask_bytes + 4); + for (size_t i = 0; i < data_length; ++i) // Mask the payload. + frame.push_back(data[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]); + } else { + frame.insert(frame.end(), data, data + data_length); + } + *output = std::string(&frame[0], frame.size()); +} + +} // anonymous namespace + +// static +WebSocketEncoder* WebSocketEncoder::CreateServer( + const std::string& request_extensions, + std::string* response_extensions) { + bool deflate; + int client_window_bits; + int server_window_bits; + bool client_no_context_takeover; + bool server_no_context_takeover; + ParseExtensions(request_extensions, &deflate, &client_window_bits, + &server_window_bits, &client_no_context_takeover, + &server_no_context_takeover); + + if (deflate) { + *response_extensions = base::StringPrintf( + "permessage-deflate; server_max_window_bits=%d; " + "client_max_window_bits=%d%s", + server_window_bits, client_window_bits, + server_no_context_takeover ? "; server_no_context_takeover" : ""); + return new WebSocketEncoder(true /* is_server */, server_window_bits, + client_window_bits, server_no_context_takeover); + } else { + *response_extensions = std::string(); + return new WebSocketEncoder(true /* is_server */); + } +} + +// static +WebSocketEncoder* WebSocketEncoder::CreateClient( + const std::string& response_extensions) { + bool deflate; + int client_window_bits; + int server_window_bits; + bool client_no_context_takeover; + bool server_no_context_takeover; + ParseExtensions(response_extensions, &deflate, &client_window_bits, + &server_window_bits, &client_no_context_takeover, + &server_no_context_takeover); + + if (deflate) { + return new WebSocketEncoder(false /* is_server */, client_window_bits, + server_window_bits, client_no_context_takeover); + } else { + return new WebSocketEncoder(false /* is_server */); + } +} + +// static +void WebSocketEncoder::ParseExtensions(const std::string& extensions, + bool* deflate, + int* client_window_bits, + int* server_window_bits, + bool* client_no_context_takeover, + bool* server_no_context_takeover) { + *deflate = false; + *client_window_bits = 15; + *server_window_bits = 15; + *client_no_context_takeover = false; + *server_no_context_takeover = false; + + if (extensions.empty()) + return; + + // TODO(dgozman): split extensions header if another extension is introduced. + WebSocketExtensionParser parser; + parser.Parse(extensions); + if (parser.has_error()) + return; + if (parser.extension().name() != "permessage-deflate") + return; + + const std::vector<WebSocketExtension::Parameter>& parameters = + parser.extension().parameters(); + for (const auto& param : parameters) { + const std::string& name = param.name(); + if (name == "client_max_window_bits" && param.HasValue()) { + int bits = 0; + if (base::StringToInt(param.value(), &bits) && bits >= 8 && bits <= 15) + *client_window_bits = bits; + } + if (name == "server_max_window_bits" && param.HasValue()) { + int bits = 0; + if (base::StringToInt(param.value(), &bits) && bits >= 8 && bits <= 15) + *server_window_bits = bits; + } + if (name == "client_no_context_takeover") + *client_no_context_takeover = true; + if (name == "server_no_context_takeover") + *server_no_context_takeover = true; + } + *deflate = true; +} + +WebSocketEncoder::WebSocketEncoder(bool is_server) : is_server_(is_server) { +} + +WebSocketEncoder::WebSocketEncoder(bool is_server, + int deflate_bits, + int inflate_bits, + bool no_context_takeover) + : is_server_(is_server) { + deflater_.reset(new WebSocketDeflater( + no_context_takeover ? WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT + : WebSocketDeflater::TAKE_OVER_CONTEXT)); + inflater_.reset( + new WebSocketInflater(kInflaterChunkSize, kInflaterChunkSize)); + + if (!deflater_->Initialize(deflate_bits) || + !inflater_->Initialize(inflate_bits)) { + // Disable deflate support. + deflater_.reset(); + inflater_.reset(); + } +} + +WebSocketEncoder::~WebSocketEncoder() { +} + +WebSocket::ParseResult WebSocketEncoder::DecodeFrame( + const base::StringPiece& frame, + int* bytes_consumed, + std::string* output) { + bool compressed; + WebSocket::ParseResult result = + DecodeFrameHybi17(frame, is_server_, bytes_consumed, output, &compressed); + if (result == WebSocket::FRAME_OK && compressed) { + if (!Inflate(output)) + result = WebSocket::FRAME_ERROR; + } + return result; +} + +void WebSocketEncoder::EncodeFrame(const std::string& frame, + int masking_key, + std::string* output) { + std::string compressed; + if (Deflate(frame, &compressed)) + EncodeFrameHybi17(compressed, masking_key, true, output); + else + EncodeFrameHybi17(frame, masking_key, false, output); +} + +bool WebSocketEncoder::Inflate(std::string* message) { + if (!inflater_) + return false; + if (!inflater_->AddBytes(message->data(), message->length())) + return false; + if (!inflater_->Finish()) + return false; + + std::vector<char> output; + while (inflater_->CurrentOutputSize() > 0) { + scoped_refptr<IOBufferWithSize> chunk = + inflater_->GetOutput(inflater_->CurrentOutputSize()); + if (!chunk.get()) + return false; + output.insert(output.end(), chunk->data(), chunk->data() + chunk->size()); + } + + *message = + output.size() ? std::string(&output[0], output.size()) : std::string(); + return true; +} + +bool WebSocketEncoder::Deflate(const std::string& message, + std::string* output) { + if (!deflater_) + return false; + if (!deflater_->AddBytes(message.data(), message.length())) { + deflater_->Finish(); + return false; + } + if (!deflater_->Finish()) + return false; + scoped_refptr<IOBufferWithSize> buffer = + deflater_->GetOutput(deflater_->CurrentOutputSize()); + if (!buffer.get()) + return false; + *output = std::string(buffer->data(), buffer->size()); + return true; +} + +} // namespace net
diff --git a/net/server/web_socket_encoder.h b/net/server/web_socket_encoder.h new file mode 100644 index 0000000..c534c2f --- /dev/null +++ b/net/server/web_socket_encoder.h
@@ -0,0 +1,63 @@ +// 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 NET_SERVER_WEB_SOCKET_ENCODER_H_ +#define NET_SERVER_WEB_SOCKET_ENCODER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_piece.h" +#include "net/server/web_socket.h" +#include "net/websockets/websocket_deflater.h" +#include "net/websockets/websocket_inflater.h" + +namespace net { + +class WebSocketEncoder { + public: + ~WebSocketEncoder(); + + static WebSocketEncoder* CreateServer(const std::string& request_extensions, + std::string* response_extensions); + + static const char kClientExtensions[]; + static WebSocketEncoder* CreateClient(const std::string& response_extensions); + + WebSocket::ParseResult DecodeFrame(const base::StringPiece& frame, + int* bytes_consumed, + std::string* output); + + void EncodeFrame(const std::string& frame, + int masking_key, + std::string* output); + + private: + explicit WebSocketEncoder(bool is_server); + WebSocketEncoder(bool is_server, + int deflate_bits, + int inflate_bits, + bool no_context_takeover); + + static void ParseExtensions(const std::string& extensions, + bool* deflate, + int* client_window_bits, + int* server_window_bits, + bool* client_no_context_takeover, + bool* server_no_context_takeover); + + bool Inflate(std::string* message); + bool Deflate(const std::string& message, std::string* output); + + scoped_ptr<WebSocketDeflater> deflater_; + scoped_ptr<WebSocketInflater> inflater_; + bool is_server_; + + DISALLOW_COPY_AND_ASSIGN(WebSocketEncoder); +}; + +} // namespace net + +#endif // NET_SERVER_WEB_SOCKET_ENCODER_H_
diff --git a/net/server/web_socket_encoder_unittest.cc b/net/server/web_socket_encoder_unittest.cc new file mode 100644 index 0000000..b52939a --- /dev/null +++ b/net/server/web_socket_encoder_unittest.cc
@@ -0,0 +1,155 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/server/web_socket_encoder.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +class WebSocketEncoderTest : public testing::Test { + public: + WebSocketEncoderTest() {} + + void SetUp() override { + std::string response_extensions; + server_.reset(WebSocketEncoder::CreateServer("", &response_extensions)); + EXPECT_EQ(std::string(), response_extensions); + client_.reset(WebSocketEncoder::CreateClient("")); + } + + protected: + scoped_ptr<WebSocketEncoder> server_; + scoped_ptr<WebSocketEncoder> client_; +}; + +class WebSocketEncoderCompressionTest : public WebSocketEncoderTest { + public: + WebSocketEncoderCompressionTest() : WebSocketEncoderTest() {} + + void SetUp() override { + std::string response_extensions; + server_.reset(WebSocketEncoder::CreateServer( + "permessage-deflate; client_max_window_bits", &response_extensions)); + EXPECT_EQ( + "permessage-deflate; server_max_window_bits=15; " + "client_max_window_bits=15", + response_extensions); + client_.reset(WebSocketEncoder::CreateClient(response_extensions)); + } +}; + +TEST_F(WebSocketEncoderTest, ClientToServer) { + std::string frame("ClientToServer"); + int mask = 123456; + std::string encoded; + int bytes_consumed; + std::string decoded; + + client_->EncodeFrame(frame, mask, &encoded); + EXPECT_EQ(WebSocket::FRAME_OK, + server_->DecodeFrame(encoded, &bytes_consumed, &decoded)); + EXPECT_EQ(frame, decoded); + EXPECT_EQ((int)encoded.length(), bytes_consumed); + + std::string partial = encoded.substr(0, encoded.length() - 2); + EXPECT_EQ(WebSocket::FRAME_INCOMPLETE, + server_->DecodeFrame(partial, &bytes_consumed, &decoded)); + + std::string extra = encoded + "more stuff"; + EXPECT_EQ(WebSocket::FRAME_OK, + server_->DecodeFrame(extra, &bytes_consumed, &decoded)); + EXPECT_EQ(frame, decoded); + EXPECT_EQ((int)encoded.length(), bytes_consumed); + + EXPECT_EQ( + WebSocket::FRAME_ERROR, + server_->DecodeFrame(std::string("abcde"), &bytes_consumed, &decoded)); +} + +TEST_F(WebSocketEncoderTest, ServerToClient) { + std::string frame("ServerToClient"); + int mask = 0; + std::string encoded; + int bytes_consumed; + std::string decoded; + + server_->EncodeFrame(frame, mask, &encoded); + EXPECT_EQ(WebSocket::FRAME_OK, + client_->DecodeFrame(encoded, &bytes_consumed, &decoded)); + EXPECT_EQ(frame, decoded); + EXPECT_EQ((int)encoded.length(), bytes_consumed); + + std::string partial = encoded.substr(0, encoded.length() - 2); + EXPECT_EQ(WebSocket::FRAME_INCOMPLETE, + client_->DecodeFrame(partial, &bytes_consumed, &decoded)); + + std::string extra = encoded + "more stuff"; + EXPECT_EQ(WebSocket::FRAME_OK, + client_->DecodeFrame(extra, &bytes_consumed, &decoded)); + EXPECT_EQ(frame, decoded); + EXPECT_EQ((int)encoded.length(), bytes_consumed); + + EXPECT_EQ( + WebSocket::FRAME_ERROR, + client_->DecodeFrame(std::string("abcde"), &bytes_consumed, &decoded)); +} + +TEST_F(WebSocketEncoderCompressionTest, ClientToServer) { + std::string frame("CompressionCompressionCompressionCompression"); + int mask = 654321; + std::string encoded; + int bytes_consumed; + std::string decoded; + + client_->EncodeFrame(frame, mask, &encoded); + EXPECT_LT(encoded.length(), frame.length()); + EXPECT_EQ(WebSocket::FRAME_OK, + server_->DecodeFrame(encoded, &bytes_consumed, &decoded)); + EXPECT_EQ(frame, decoded); + EXPECT_EQ((int)encoded.length(), bytes_consumed); +} + +TEST_F(WebSocketEncoderCompressionTest, ServerToClient) { + std::string frame("CompressionCompressionCompressionCompression"); + int mask = 0; + std::string encoded; + int bytes_consumed; + std::string decoded; + + server_->EncodeFrame(frame, mask, &encoded); + EXPECT_LT(encoded.length(), frame.length()); + EXPECT_EQ(WebSocket::FRAME_OK, + client_->DecodeFrame(encoded, &bytes_consumed, &decoded)); + EXPECT_EQ(frame, decoded); + EXPECT_EQ((int)encoded.length(), bytes_consumed); +} + +TEST_F(WebSocketEncoderCompressionTest, LongFrame) { + int length = 1000000; + std::string temp; + temp.reserve(length); + for (int i = 0; i < length; ++i) + temp += (char)('a' + (i % 26)); + + std::string frame; + frame.reserve(length); + for (int i = 0; i < length; ++i) { + int64 j = i; + frame += temp.data()[(j * j) % length]; + } + + int mask = 0; + std::string encoded; + int bytes_consumed; + std::string decoded; + + server_->EncodeFrame(frame, mask, &encoded); + EXPECT_LT(encoded.length(), frame.length()); + EXPECT_EQ(WebSocket::FRAME_OK, + client_->DecodeFrame(encoded, &bytes_consumed, &decoded)); + EXPECT_EQ(frame, decoded); + EXPECT_EQ((int)encoded.length(), bytes_consumed); +} + +} // namespace net
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc index 9e1abf4..4092365 100644 --- a/net/socket/client_socket_pool_base.cc +++ b/net/socket/client_socket_pool_base.cc
@@ -9,6 +9,7 @@ #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" #include "base/time/time.h" @@ -865,6 +866,11 @@ void ClientSocketPoolBaseHelper::OnConnectJobComplete( int result, ConnectJob* job) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "436634 ClientSocketPoolBaseHelper::OnConnectJobComplete")); + DCHECK_NE(ERR_IO_PENDING, result); const std::string group_name = job->group_name(); GroupMap::iterator group_it = group_map_.find(group_name);
diff --git a/net/socket/next_proto.cc b/net/socket/next_proto.cc index 0e59ce7..0d1b400 100644 --- a/net/socket/next_proto.cc +++ b/net/socket/next_proto.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "next_proto.h" +#include "net/socket/next_proto.h" namespace net { @@ -16,6 +16,8 @@ NextProtoVector next_protos; next_protos.push_back(kProtoHTTP11); next_protos.push_back(kProtoSPDY31); + next_protos.push_back(kProtoSPDY4_14); + next_protos.push_back(kProtoSPDY4_15); return next_protos; } @@ -27,6 +29,8 @@ next_protos.push_back(kProtoQUIC1SPDY3); if (spdy_enabled) { next_protos.push_back(kProtoSPDY31); + next_protos.push_back(kProtoSPDY4_14); + next_protos.push_back(kProtoSPDY4_15); } return next_protos; }
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc index a52e6a3..2ea403f 100644 --- a/net/socket/ssl_client_socket.cc +++ b/net/socket/ssl_client_socket.cc
@@ -11,6 +11,7 @@ #include "net/base/connection_type_histograms.h" #include "net/base/host_port_pair.h" #include "net/ssl/channel_id_service.h" +#include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_config_service.h" #include "net/ssl/ssl_connection_status_flags.h" @@ -234,38 +235,46 @@ } // static +bool SSLClientSocket::HasCipherAdequateForHTTP2( + const std::vector<uint16>& cipher_suites) { + for (uint16 cipher : cipher_suites) { + if (IsSecureTLSCipherSuite(cipher)) + return true; + } + return false; +} + +// static +bool SSLClientSocket::IsTLSVersionAdequateForHTTP2( + const SSLConfig& ssl_config) { + return ssl_config.version_max >= SSL_PROTOCOL_VERSION_TLS1_2; +} + +// static std::vector<uint8_t> SSLClientSocket::SerializeNextProtos( - const std::vector<std::string>& next_protos) { - // Do a first pass to determine the total length. - size_t wire_length = 0; - for (std::vector<std::string>::const_iterator i = next_protos.begin(); - i != next_protos.end(); ++i) { - if (i->size() > 255) { - LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << *i; + const NextProtoVector& next_protos, + bool can_advertise_http2) { + std::vector<uint8_t> wire_protos; + for (const NextProto next_proto : next_protos) { + if (!can_advertise_http2 && kProtoSPDY4MinimumVersion <= next_proto && + next_proto <= kProtoSPDY4MaximumVersion) { continue; } - if (i->size() == 0) { + const std::string proto = NextProtoToString(next_proto); + if (proto.size() > 255) { + LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << proto; + continue; + } + if (proto.size() == 0) { LOG(WARNING) << "Ignoring empty NPN/ALPN protocol"; continue; } - wire_length += i->size(); - wire_length++; + wire_protos.push_back(proto.size()); + for (const char ch : proto) { + wire_protos.push_back(static_cast<uint8_t>(ch)); + } } - // Allocate memory for the result and fill it in. - std::vector<uint8_t> wire_protos; - wire_protos.reserve(wire_length); - for (std::vector<std::string>::const_iterator i = next_protos.begin(); - i != next_protos.end(); i++) { - if (i->size() == 0 || i->size() > 255) - continue; - wire_protos.push_back(i->size()); - wire_protos.resize(wire_protos.size() + i->size()); - memcpy(&wire_protos[wire_protos.size() - i->size()], - i->data(), i->size()); - } - DCHECK_EQ(wire_protos.size(), wire_length); - return wire_protos; }
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index 11b19a1..46461df 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h
@@ -209,10 +209,23 @@ const SSLConfig& ssl_config, ChannelIDService* channel_id_service); + // Determine if there is at least one enabled cipher suite that satisfies + // Section 9.2 of the HTTP/2 specification. Note that the server might still + // pick an inadequate cipher suite. + static bool HasCipherAdequateForHTTP2( + const std::vector<uint16>& cipher_suites); + + // Determine if the TLS version required by Section 9.2 of the HTTP/2 + // specification is enabled. Note that the server might still pick an + // inadequate TLS version. + static bool IsTLSVersionAdequateForHTTP2(const SSLConfig& ssl_config); + // Serializes |next_protos| in the wire format for ALPN: protocols are listed - // in order, each prefixed by a one-byte length. + // in order, each prefixed by a one-byte length. Any HTTP/2 protocols in + // |next_protos| are ignored if |can_advertise_http2| is false. static std::vector<uint8_t> SerializeNextProtos( - const std::vector<std::string>& next_protos); + const NextProtoVector& next_protos, + bool can_advertise_http2); // For unit testing only. // Returns the unverified certificate chain as presented by server. @@ -222,6 +235,7 @@ const = 0; private: + FRIEND_TEST_ALL_PREFIXES(SSLClientSocket, SerializeNextProtos); // For signed_cert_timestamps_received_ and stapled_ocsp_response_received_. FRIEND_TEST_ALL_PREFIXES(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension);
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 3651e8d..5e33e12 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc
@@ -149,6 +149,14 @@ } while (0) #endif +#if !defined(CKM_AES_GCM) +#define CKM_AES_GCM 0x00001087 +#endif + +#if !defined(CKM_NSS_CHACHA20_POLY1305) +#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 26) +#endif + namespace { // SSL plaintext fragments are shorter than 16KB. Although the record layer @@ -973,8 +981,16 @@ SECStatus rv = SECSuccess; if (!ssl_config_.next_protos.empty()) { + // TODO(bnc): Check ssl_config_.disabled_cipher_suites. + const bool adequate_encryption = + PK11_TokenExists(CKM_AES_GCM) || + PK11_TokenExists(CKM_NSS_CHACHA20_POLY1305); + const bool adequate_key_agreement = PK11_TokenExists(CKM_DH_PKCS_DERIVE) || + PK11_TokenExists(CKM_ECDH1_DERIVE); std::vector<uint8_t> wire_protos = - SerializeNextProtos(ssl_config_.next_protos); + SerializeNextProtos(ssl_config_.next_protos, + adequate_encryption && adequate_key_agreement && + IsTLSVersionAdequateForHTTP2(ssl_config_)); rv = SSL_SetNextProtoNego( nss_fd_, wire_protos.empty() ? NULL : &wire_protos[0], wire_protos.size());
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index 4e86c05..c78a974 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc
@@ -788,8 +788,8 @@ // disabled by default. Note that !SHA256 and !SHA384 only remove HMAC-SHA256 // and HMAC-SHA384 cipher suites, not GCM cipher suites with SHA256 or SHA384 // as the handshake hash. - std::string command("DEFAULT:!NULL:!aNULL:!IDEA:!FZA:!SRP:!SHA256:!SHA384:" - "!aECDH:!AESGCM+AES256"); + std::string command( + "DEFAULT:!NULL:!aNULL:!SHA256:!SHA384:!aECDH:!AESGCM+AES256:!aPSK"); // Walk through all the installed ciphers, seeing if any need to be // appended to the cipher removal |command|. for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) { @@ -838,8 +838,20 @@ } if (!ssl_config_.next_protos.empty()) { + // Get list of ciphers that are enabled. + STACK_OF(SSL_CIPHER)* enabled_ciphers = SSL_get_ciphers(ssl_); + DCHECK(enabled_ciphers); + std::vector<uint16> enabled_ciphers_vector; + for (size_t i = 0; i < sk_SSL_CIPHER_num(enabled_ciphers); ++i) { + const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(enabled_ciphers, i); + const uint16 id = static_cast<uint16>(SSL_CIPHER_get_id(cipher)); + enabled_ciphers_vector.push_back(id); + } + std::vector<uint8_t> wire_protos = - SerializeNextProtos(ssl_config_.next_protos); + SerializeNextProtos(ssl_config_.next_protos, + HasCipherAdequateForHTTP2(enabled_ciphers_vector) && + IsTLSVersionAdequateForHTTP2(ssl_config_)); SSL_set_alpn_protos(ssl_, wire_protos.empty() ? NULL : &wire_protos[0], wire_protos.size()); } @@ -1131,9 +1143,18 @@ } } - if (result == OK) + if (result == OK) { RecordConnectionTypeMetrics(GetNetSSLVersion(ssl_)); + if (SSL_session_reused(ssl_)) { + // Record whether or not the server tried to resume a session for a + // different version. See https://crbug.com/441456. + UMA_HISTOGRAM_BOOLEAN( + "Net.SSLSessionVersionMatch", + SSL_version(ssl_) == SSL_get_session(ssl_)->ssl_version); + } + } + const CertStatus cert_status = server_cert_verify_result_.cert_status; if (transport_security_state_ && (result == OK || @@ -1782,11 +1803,10 @@ // For each protocol in server preference order, see if we support it. for (unsigned int i = 0; i < inlen; i += in[i] + 1) { - for (std::vector<std::string>::const_iterator - j = ssl_config_.next_protos.begin(); - j != ssl_config_.next_protos.end(); ++j) { - if (in[i] == j->size() && - memcmp(&in[i + 1], j->data(), in[i]) == 0) { + for (NextProto next_proto : ssl_config_.next_protos) { + const std::string proto = NextProtoToString(next_proto); + if (in[i] == proto.size() && + memcmp(&in[i + 1], proto.data(), in[i]) == 0) { // We found a match. *out = const_cast<unsigned char*>(in) + i + 1; *outlen = in[i]; @@ -1800,9 +1820,9 @@ // If we didn't find a protocol, we select the first one from our list. if (npn_status_ == kNextProtoNoOverlap) { - *out = reinterpret_cast<uint8*>(const_cast<char*>( - ssl_config_.next_protos[0].data())); - *outlen = ssl_config_.next_protos[0].size(); + const std::string proto = NextProtoToString(ssl_config_.next_protos[0]); + *out = reinterpret_cast<uint8*>(const_cast<char*>(proto.data())); + *outlen = proto.size(); } npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 16e03f7..d14f1fd 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2351,6 +2351,33 @@ SSLClientSocket::ClearSessionCache(); } +TEST(SSLClientSocket, SerializeNextProtos) { + NextProtoVector next_protos; + next_protos.push_back(kProtoHTTP11); + next_protos.push_back(kProtoSPDY31); + static std::vector<uint8_t> serialized = + SSLClientSocket::SerializeNextProtos(next_protos, true); + ASSERT_EQ(18u, serialized.size()); + EXPECT_EQ(8, serialized[0]); // length("http/1.1") + EXPECT_EQ('h', serialized[1]); + EXPECT_EQ('t', serialized[2]); + EXPECT_EQ('t', serialized[3]); + EXPECT_EQ('p', serialized[4]); + EXPECT_EQ('/', serialized[5]); + EXPECT_EQ('1', serialized[6]); + EXPECT_EQ('.', serialized[7]); + EXPECT_EQ('1', serialized[8]); + EXPECT_EQ(8, serialized[9]); // length("spdy/3.1") + EXPECT_EQ('s', serialized[10]); + EXPECT_EQ('p', serialized[11]); + EXPECT_EQ('d', serialized[12]); + EXPECT_EQ('y', serialized[13]); + EXPECT_EQ('/', serialized[14]); + EXPECT_EQ('3', serialized[15]); + EXPECT_EQ('.', serialized[16]); + EXPECT_EQ('1', serialized[17]); +} + // Test that the server certificates are properly retrieved from the underlying // SSL stack. TEST_F(SSLClientSocketTest, VerifyServerChainProperlyOrdered) { @@ -2889,7 +2916,7 @@ SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; server_options.enable_npn = true; SSLConfig client_config; - client_config.next_protos.push_back("http/1.1"); + client_config.next_protos.push_back(kProtoHTTP11); monitor_handshake_callback_ = true; fail_handshake_after_false_start_ = true; ASSERT_NO_FATAL_FAILURE(TestFalseStart(server_options, client_config, true)); @@ -2904,7 +2931,7 @@ SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; server_options.enable_npn = true; SSLConfig client_config; - client_config.next_protos.push_back("http/1.1"); + client_config.next_protos.push_back(kProtoHTTP11); monitor_handshake_callback_ = true; ASSERT_NO_FATAL_FAILURE(TestFalseStart(server_options, client_config, true)); ASSERT_TRUE(ran_handshake_completion_callback_); @@ -2918,7 +2945,7 @@ SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; server_options.enable_npn = true; SSLConfig client_config; - client_config.next_protos.push_back("http/1.1"); + client_config.next_protos.push_back(kProtoHTTP11); ASSERT_NO_FATAL_FAILURE( TestFalseStart(server_options, client_config, true)); } @@ -2941,7 +2968,7 @@ SpawnedTestServer::SSLOptions::KEY_EXCHANGE_RSA; server_options.enable_npn = true; SSLConfig client_config; - client_config.next_protos.push_back("http/1.1"); + client_config.next_protos.push_back(kProtoHTTP11); ASSERT_NO_FATAL_FAILURE( TestFalseStart(server_options, client_config, false)); } @@ -2954,7 +2981,7 @@ SpawnedTestServer::SSLOptions::KEY_EXCHANGE_DHE_RSA; server_options.enable_npn = true; SSLConfig client_config; - client_config.next_protos.push_back("http/1.1"); + client_config.next_protos.push_back(kProtoHTTP11); // Let a full handshake complete with False Start. ASSERT_NO_FATAL_FAILURE( @@ -2987,7 +3014,7 @@ ASSERT_TRUE(StartTestServer(server_options)); SSLConfig client_config; - client_config.next_protos.push_back("http/1.1"); + client_config.next_protos.push_back(kProtoHTTP11); // Start a handshake up to the server Finished message. TestCompletionCallback callback;
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h index bcc369f..2deb947 100644 --- a/net/socket/transport_client_socket_pool.h +++ b/net/socket/transport_client_socket_pool.h
@@ -326,6 +326,12 @@ "436634 TransportConnectJobHelper::OnIOComplete")); result = this->DoLoop(job, result); + + // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. + tracked_objects::ScopedTracker tracking_profile1( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "436634 TransportConnectJobHelper::OnIOComplete1")); + if (result != ERR_IO_PENDING) job->NotifyDelegateOfCompletion(result); // Deletes |job| and |this| }
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc index 15ec028..ec83529 100644 --- a/net/socket/websocket_transport_client_socket_pool.cc +++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" +#include "base/profiler/scoped_tracker.h" #include "base/strings/string_util.h" #include "base/time/time.h" #include "base/values.h" @@ -630,6 +631,11 @@ WebSocketTransportClientSocketPool::ConnectJobDelegate::OnConnectJobComplete( int result, ConnectJob* job) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "436634 WebSocket...::ConnectJobDelegate::OnConnectJobComplete")); + owner_->OnConnectJobComplete(result, static_cast<WebSocketTransportConnectJob*>(job)); }
diff --git a/net/ssl/client_cert_store.h b/net/ssl/client_cert_store.h index fe050e5..b1172de 100644 --- a/net/ssl/client_cert_store.h +++ b/net/ssl/client_cert_store.h
@@ -14,8 +14,10 @@ class SSLCertRequestInfo; -// The caller is expected to keep the ClientCertStore alive until the callback -// supplied to GetClientCerts has been run. +// A handle to a client certificate store to query matching certificates when a +// server requests client auth. Note that there may be multiple ClientCertStore +// objects corresponding to the same platform certificate store; each request +// gets its own uniquely owned handle. class NET_EXPORT ClientCertStore { public: virtual ~ClientCertStore() {} @@ -23,8 +25,8 @@ // Get client certs matching the |cert_request_info|. On completion, the // results will be stored in |selected_certs| and the |callback| will be run. // The |callback| may be called sychronously. The caller must ensure the - // ClientCertStore and the |selected_certs| object remain alive until the - // callback has been run. + // ClientCertStore, |cert_request_info|, and |selected_certs| remain alive + // until the callback has been run. virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info, CertificateList* selected_certs, const base::Closure& callback) = 0;
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h index 5a0c0fa..2cbc995 100644 --- a/net/ssl/ssl_config.h +++ b/net/ssl/ssl_config.h
@@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "net/base/net_export.h" #include "net/cert/x509_certificate.h" +#include "net/socket/next_proto.h" namespace net { @@ -155,7 +156,7 @@ // Protocol Negotiation, but there is no overlap between the server's and // client's protocol sets, then the first protocol in this list will be // requested by the client. - std::vector<std::string> next_protos; + NextProtoVector next_protos; scoped_refptr<X509Certificate> client_cert; };
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc index 97b5d84..ac7d3bc 100644 --- a/net/test/embedded_test_server/embedded_test_server.cc +++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -49,8 +49,15 @@ // This is a test-only server. Ignore I/O thread restrictions. base::ThreadRestrictions::ScopedAllowIO allow_io; + std::string relative_url(request.relative_url); + // A proxy request will have an absolute path. Simulate the proxy by stripping + // the scheme, host, and port. + GURL relative_gurl(relative_url); + if (relative_gurl.is_valid()) + relative_url = relative_gurl.PathForRequest(); + // Trim the first byte ('/'). - std::string request_path(request.relative_url.substr(1)); + std::string request_path = relative_url.substr(1); // Remove the query string if present. size_t query_pos = request_path.find('?');
diff --git a/net/test/spawned_test_server/local_test_server.cc b/net/test/spawned_test_server/local_test_server.cc index c85e05a..309c69c 100644 --- a/net/test/spawned_test_server/local_test_server.cc +++ b/net/test/spawned_test_server/local_test_server.cc
@@ -121,18 +121,17 @@ bool LocalTestServer::Stop() { CleanUpWhenStoppingServer(); - if (!process_handle_) + if (!process_.IsValid()) return true; // First check if the process has already terminated. - bool ret = base::WaitForSingleProcess(process_handle_, base::TimeDelta()); + bool ret = base::WaitForSingleProcess(process_.Handle(), base::TimeDelta()); if (!ret) { - ret = base::KillProcess(process_handle_, 1, true); + ret = base::KillProcess(process_.Handle(), 1, true); } if (ret) { - base::CloseProcessHandle(process_handle_); - process_handle_ = base::kNullProcessHandle; + process_.Close(); } else { VLOG(1) << "Kill failed?"; } @@ -149,7 +148,6 @@ // number out over a pipe that this TestServer object will read from. Once // that is complete, the host port pair will contain the actual port. DCHECK(!GetPort()); - process_handle_ = base::kNullProcessHandle; base::FilePath src_dir; if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_dir))
diff --git a/net/test/spawned_test_server/local_test_server.h b/net/test/spawned_test_server/local_test_server.h index 37b1185..785d726 100644 --- a/net/test/spawned_test_server/local_test_server.h +++ b/net/test/spawned_test_server/local_test_server.h
@@ -9,7 +9,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_file.h" -#include "base/process/process_handle.h" +#include "base/process/process.h" #include "net/test/spawned_test_server/base_test_server.h" #if defined(OS_WIN) @@ -92,8 +92,8 @@ // Waits for the server to start. Returns true on success. bool WaitToStart() WARN_UNUSED_RESULT; - // Handle of the Python process running the test server. - base::ProcessHandle process_handle_; + // The Python process running the test server. + base::Process process_; #if defined(OS_WIN) // The pipe file handle we read from.
diff --git a/net/test/spawned_test_server/local_test_server_posix.cc b/net/test/spawned_test_server/local_test_server_posix.cc index 0edbedf..c770152 100644 --- a/net/test/spawned_test_server/local_test_server_posix.cc +++ b/net/test/spawned_test_server/local_test_server_posix.cc
@@ -139,7 +139,8 @@ base::LaunchOptions options; options.fds_to_remap = &map_write_fd; - if (!base::LaunchProcess(python_command, options, &process_handle_)) { + process_ = base::LaunchProcess(python_command, options); + if (!process_.IsValid()) { LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString(); return false; }
diff --git a/net/test/spawned_test_server/local_test_server_win.cc b/net/test/spawned_test_server/local_test_server_win.cc index 412e4e1..5eb5aaf 100644 --- a/net/test/spawned_test_server/local_test_server_win.cc +++ b/net/test/spawned_test_server/local_test_server_win.cc
@@ -176,7 +176,8 @@ base::LaunchOptions launch_options; launch_options.inherit_handles = true; - if (!base::LaunchProcess(python_command, launch_options, &process_handle_)) { + process_ = base::LaunchProcess(python_command, launch_options); + if (!process_.IsValid()) { LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString(); return false; }
diff --git a/net/test/url_request/url_request_mock_data_job.cc b/net/test/url_request/url_request_mock_data_job.cc new file mode 100644 index 0000000..54c174c --- /dev/null +++ b/net/test/url_request/url_request_mock_data_job.cc
@@ -0,0 +1,165 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/test/url_request/url_request_mock_data_job.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/string_number_conversions.h" +#include "net/base/io_buffer.h" +#include "net/base/url_util.h" +#include "net/http/http_request_headers.h" +#include "net/url_request/url_request_filter.h" + +namespace net { +namespace { + +const char kMockHostname[] = "mock.data"; + +// Gets the data from URL of the form: +// scheme://kMockHostname/?data=abc&repeat_count=nnn. +std::string GetDataFromRequest(const net::URLRequest& request) { + std::string value; + if (!GetValueForKeyInQuery(request.url(), "data", &value)) + return "default_data"; + return value; +} + +// Gets the numeric repeat count from URL of the form: +// scheme://kMockHostname/?data=abc&repeat_count=nnn. +int GetRepeatCountFromRequest(const net::URLRequest& request) { + std::string value; + if (!GetValueForKeyInQuery(request.url(), "repeat", &value)) + return 1; + + int repeat_count; + if (!base::StringToInt(value, &repeat_count)) + return 1; + + DCHECK_GT(repeat_count, 0); + + return repeat_count; +} + +GURL GetMockUrl(const std::string& scheme, + const std::string& hostname, + const std::string& data, + int data_repeat_count) { + DCHECK_GT(data_repeat_count, 0); + std::string url(scheme + "://" + hostname + "/"); + url.append("?data="); + url.append(data); + url.append("&repeat="); + url.append(base::IntToString(data_repeat_count)); + return GURL(url); +} + +class MockJobInterceptor : public net::URLRequestInterceptor { + public: + MockJobInterceptor() {} + ~MockJobInterceptor() override {} + + // net::URLRequestInterceptor implementation + net::URLRequestJob* MaybeInterceptRequest( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const override { + return new URLRequestMockDataJob(request, network_delegate, + GetDataFromRequest(*request), + GetRepeatCountFromRequest(*request)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(MockJobInterceptor); +}; + +} // namespace + +URLRequestMockDataJob::URLRequestMockDataJob(URLRequest* request, + NetworkDelegate* network_delegate, + const std::string& data, + int data_repeat_count) + : URLRequestJob(request, network_delegate), + data_offset_(0), + weak_factory_(this) { + DCHECK_GT(data_repeat_count, 0); + for (int i = 0; i < data_repeat_count; ++i) { + data_.append(data); + } +} + +void URLRequestMockDataJob::Start() { + // Start reading asynchronously so that all error reporting and data + // callbacks happen as they would for network requests. + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&URLRequestMockDataJob::StartAsync, + weak_factory_.GetWeakPtr())); +} + +URLRequestMockDataJob::~URLRequestMockDataJob() { +} + +bool URLRequestMockDataJob::ReadRawData(IOBuffer* buf, + int buf_size, + int* bytes_read) { + DCHECK(bytes_read); + *bytes_read = static_cast<int>( + std::min(static_cast<size_t>(buf_size), data_.length() - data_offset_)); + memcpy(buf->data(), data_.c_str() + data_offset_, *bytes_read); + data_offset_ += *bytes_read; + return true; +} + +void URLRequestMockDataJob::StartAsync() { + if (!request_) + return; + + set_expected_content_size(data_.length()); + NotifyHeadersComplete(); +} + +// static +void URLRequestMockDataJob::AddUrlHandler() { + return AddUrlHandlerForHostname(kMockHostname); +} + +// static +void URLRequestMockDataJob::AddUrlHandlerForHostname( + const std::string& hostname) { + // Add |hostname| to net::URLRequestFilter for HTTP and HTTPS. + net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); + filter->AddHostnameInterceptor("http", hostname, + make_scoped_ptr(new MockJobInterceptor())); + filter->AddHostnameInterceptor("https", hostname, + make_scoped_ptr(new MockJobInterceptor())); +} + +// static +GURL URLRequestMockDataJob::GetMockHttpUrl(const std::string& data, + int repeat_count) { + return GetMockHttpUrlForHostname(kMockHostname, data, repeat_count); +} + +// static +GURL URLRequestMockDataJob::GetMockHttpsUrl(const std::string& data, + int repeat_count) { + return GetMockHttpsUrlForHostname(kMockHostname, data, repeat_count); +} + +// static +GURL URLRequestMockDataJob::GetMockHttpUrlForHostname( + const std::string& hostname, + const std::string& data, + int repeat_count) { + return GetMockUrl("http", hostname, data, repeat_count); +} + +// static +GURL URLRequestMockDataJob::GetMockHttpsUrlForHostname( + const std::string& hostname, + const std::string& data, + int repeat_count) { + return GetMockUrl("https", hostname, data, repeat_count); +} + +} // namespace net
diff --git a/net/test/url_request/url_request_mock_data_job.h b/net/test/url_request/url_request_mock_data_job.h new file mode 100644 index 0000000..5bdfa23 --- /dev/null +++ b/net/test/url_request/url_request_mock_data_job.h
@@ -0,0 +1,60 @@ +// 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 NET_URL_REQUEST_URL_REQUEST_MOCK_DATA_JOB_H_ +#define NET_URL_REQUEST_URL_REQUEST_MOCK_DATA_JOB_H_ + +#include <string> + +#include "base/memory/weak_ptr.h" +#include "net/base/net_export.h" +#include "net/url_request/url_request_job.h" + +namespace net { + +class URLRequest; + +// Mock data job, which synchronously returns data repeated multiple times. +class URLRequestMockDataJob : public URLRequestJob { + public: + URLRequestMockDataJob(URLRequest* request, + NetworkDelegate* network_delegate, + const std::string& data, + int data_repeat_count); + + void Start() override; + bool ReadRawData(IOBuffer* buf, int buf_size, int* bytes_read) override; + + // Adds the testing URLs to the URLRequestFilter. + static void AddUrlHandler(); + static void AddUrlHandlerForHostname(const std::string& hostname); + + // Given data and repeat cound, constructs a mock URL that will return that + // data repeated |repeat_count| times when started. |data| must be safe for + // URL. + static GURL GetMockHttpUrl(const std::string& data, int repeat_count); + static GURL GetMockHttpsUrl(const std::string& data, int repeat_count); + + // URLRequestFailedJob must be added as a handler for |hostname| for + // the returned URL to return |net_error|. + static GURL GetMockHttpUrlForHostname(const std::string& hostname, + const std::string& data, + int repeat_count); + static GURL GetMockHttpsUrlForHostname(const std::string& hostname, + const std::string& data, + int repeat_count); + + private: + ~URLRequestMockDataJob() override; + + void StartAsync(); + + std::string data_; + size_t data_offset_; + base::WeakPtrFactory<URLRequestMockDataJob> weak_factory_; +}; + +} // namespace net + +#endif // NET_URL_REQUEST_URL_REQUEST_SIMPLE_JOB_H_
diff --git a/net/tools/crash_cache/crash_cache.cc b/net/tools/crash_cache/crash_cache.cc index d548c79..9ec15bb 100644 --- a/net/tools/crash_cache/crash_cache.cc +++ b/net/tools/crash_cache/crash_cache.cc
@@ -17,7 +17,6 @@ #include "base/path_service.h" #include "base/process/kill.h" #include "base/process/launch.h" -#include "base/process/process_handle.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -50,15 +49,15 @@ base::CommandLine cmdline(exe); cmdline.AppendArg(base::IntToString(action)); - base::ProcessHandle handle; - if (!base::LaunchProcess(cmdline, base::LaunchOptions(), &handle)) { + base::Process process = base::LaunchProcess(cmdline, base::LaunchOptions()); + if (!process.IsValid()) { printf("Unable to run test %d\n", action); return GENERIC; } int exit_code; - if (!base::WaitForExitCode(handle, &exit_code)) { + if (!process.WaitForExit(&exit_code)) { printf("Unable to get return code, test %d\n", action); return GENERIC; }
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 3cd8cf4..2deb0f5 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -97,18 +97,32 @@ filtered_read_buffer_ = buf; filtered_read_buffer_len_ = buf_size; + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile2( + FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 URLRequestJob::Read2")); + if (ReadFilteredData(bytes_read)) { rv = true; // We have data to return. // It is fine to call DoneReading even if ReadFilteredData receives 0 // bytes from the net, but we avoid making that call if we know for // sure that's the case (ReadRawDataHelper path). + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is + // fixed. + tracked_objects::ScopedTracker tracking_profile3( + FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 URLRequestJob::Read3")); + if (*bytes_read == 0) DoneReading(); } else { rv = false; // Error, or a new IO is pending. } } + + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile4( + FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 URLRequestJob::Read4")); + if (rv && *bytes_read == 0) NotifyDone(URLRequestStatus()); return rv; @@ -487,6 +501,10 @@ } void URLRequestJob::NotifyReadComplete(int bytes_read) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("URLRequestJob::NotifyReadComplete")); + if (!request_ || !request_->has_delegate()) return; // The request was destroyed, so there is no more work to do. @@ -801,6 +819,11 @@ bool URLRequestJob::ReadRawDataHelper(IOBuffer* buf, int buf_size, int* bytes_read) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "423948 URLRequestJob::ReadRawDataHelper")); + DCHECK(!request_->status().is_io_pending()); DCHECK(raw_read_buffer_.get() == NULL);
diff --git a/services/surfaces/surfaces_impl.cc b/services/surfaces/surfaces_impl.cc index df91bf8..eccdd75 100644 --- a/services/surfaces/surfaces_impl.cc +++ b/services/surfaces/surfaces_impl.cc
@@ -19,7 +19,7 @@ namespace surfaces { namespace { -void CallCallback(const mojo::Closure& callback) { +void CallCallback(const mojo::Closure& callback, bool frame_drawn) { callback.Run(); } }
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index bd039e3..07b47d2 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -257,10 +257,6 @@ # define SK_SUPPORT_LEGACY_PUBLIC_IMAGEINFO_FIELDS #endif -#ifndef SK_SUPPORT_LEGACY_PICTURE_CLONE -# define SK_SUPPORT_LEGACY_PICTURE_CLONE -#endif - #ifndef SK_IGNORE_ETC1_SUPPORT # define SK_IGNORE_ETC1_SUPPORT #endif @@ -269,24 +265,14 @@ # define SK_IGNORE_GPU_DITHER #endif -#ifndef SK_LEGACY_PICTURE_SIZE_API -# define SK_LEGACY_PICTURE_SIZE_API -#endif - #ifndef SK_LEGACY_PICTURE_DRAW_API # define SK_LEGACY_PICTURE_DRAW_API #endif - -// Turns SkPicture::clone() into a simple "return SkRef(this);" as a way to -// test the threadsafety of SkPicture playback. -#define SK_PICTURE_CLONE_NOOP 1 - -// Turns on new (nicer, hopefully faster) SkPicture backend. -#define SK_PICTURE_USE_SK_RECORD 1 - -// Run a few optimization passes over the SkRecord after recording. -#define SK_PICTURE_OPTIMIZE_SK_RECORD 1 +// If this goes well, we can have Skia respect DYNAMIC_ANNOTATIONS_ENABLED directly. +#if DYNAMIC_ANNOTATIONS_ENABLED +# define SK_DYNAMIC_ANNOTATIONS_ENABLED 1 +#endif // ===== End Chrome-specific definitions =====
diff --git a/skia/ext/pixel_ref_utils.cc b/skia/ext/pixel_ref_utils.cc index 324adbd..777c253 100644 --- a/skia/ext/pixel_ref_utils.cc +++ b/skia/ext/pixel_ref_utils.cc
@@ -351,15 +351,17 @@ pixel_refs->clear(); DiscardablePixelRefSet pixel_ref_set(pixel_refs); + SkRect picture_bounds = picture->cullRect(); + SkIRect picture_ibounds = picture_bounds.roundOut(); SkBitmap empty_bitmap; - empty_bitmap.setInfo(SkImageInfo::MakeUnknown(picture->width(), picture->height())); + empty_bitmap.setInfo(SkImageInfo::MakeUnknown(picture_ibounds.width(), + picture_ibounds.height())); GatherPixelRefDevice device(empty_bitmap, &pixel_ref_set); SkNoSaveLayerCanvas canvas(&device); - canvas.clipRect(SkRect::MakeWH(picture->width(), picture->height()), - SkRegion::kIntersect_Op, - false); + // Draw the picture pinned against our top/left corner. + canvas.translate(-picture_bounds.left(), -picture_bounds.top()); canvas.drawPicture(picture); }
diff --git a/skia/ext/skia_utils_mac.mm b/skia/ext/skia_utils_mac.mm index dd8f560..9e552eb 100644 --- a/skia/ext/skia_utils_mac.mm +++ b/skia/ext/skia_utils_mac.mm
@@ -376,16 +376,9 @@ if (!bitmap_.extractSubset(&subset, bounds)) { return; } - // Neutralize the global matrix by concatenating the inverse. In the - // future, Skia may provide some mechanism to set the device portion of - // the matrix to identity without clobbering any hosting matrix (e.g., the - // picture's matrix). - const SkMatrix& skMatrix = canvas_->getTotalMatrix(); - SkMatrix inverse; - if (!skMatrix.invert(&inverse)) - return; + subset.setImmutable(); // Prevents a defensive copy inside Skia. canvas_->save(); - canvas_->concat(inverse); + canvas_->setMatrix(SkMatrix::I()); // Reset back to device space. canvas_->translate(bounds.x() + bitmapOffset_.x(), bounds.y() + bitmapOffset_.y()); canvas_->scale(1.f / bitmapScaleFactor_, 1.f / bitmapScaleFactor_);
diff --git a/sky/engine/core/rendering/RenderBlock.cpp b/sky/engine/core/rendering/RenderBlock.cpp index e4f0aef..1c66659 100644 --- a/sky/engine/core/rendering/RenderBlock.cpp +++ b/sky/engine/core/rendering/RenderBlock.cpp
@@ -49,7 +49,6 @@ #include "sky/engine/core/rendering/style/RenderStyle.h" #include "sky/engine/platform/geometry/FloatQuad.h" #include "sky/engine/platform/geometry/TransformState.h" -#include "sky/engine/platform/graphics/GraphicsContextCullSaver.h" #include "sky/engine/platform/graphics/GraphicsContextStateSaver.h" #include "sky/engine/wtf/StdLibExtras.h" #include "sky/engine/wtf/TemporaryChange.h" @@ -597,13 +596,6 @@ bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset, contentsClipBehavior); { - GraphicsContextCullSaver cullSaver(*paintInfo.context); - // Cull if we have more than one child and we didn't already clip. - bool shouldCull = document().settings()->containerCullingEnabled() && !pushedClip && !isDocumentElement() - && firstChild() && lastChild() && firstChild() != lastChild(); - if (shouldCull) - cullSaver.cull(overflowBox); - paintObject(paintInfo, adjustedPaintOffset); } if (pushedClip)
diff --git a/sky/engine/platform/graphics/GraphicsContext.cpp b/sky/engine/platform/graphics/GraphicsContext.cpp index 8f17728..2a7fb35 100644 --- a/sky/engine/platform/graphics/GraphicsContext.cpp +++ b/sky/engine/platform/graphics/GraphicsContext.cpp
@@ -1471,25 +1471,6 @@ m_canvas->clipRRect(rect, op, aa == AntiAliased); } -void GraphicsContext::beginCull(const FloatRect& rect) -{ - if (contextDisabled()) - return; - - realizeCanvasSave(); - m_canvas->pushCull(rect); -} - -void GraphicsContext::endCull() -{ - if (contextDisabled()) - return; - - realizeCanvasSave(); - - m_canvas->popCull(); -} - void GraphicsContext::rotate(float angleInRadians) { if (contextDisabled())
diff --git a/sky/engine/platform/graphics/GraphicsContext.h b/sky/engine/platform/graphics/GraphicsContext.h index 6f59a2f..782fa23 100644 --- a/sky/engine/platform/graphics/GraphicsContext.h +++ b/sky/engine/platform/graphics/GraphicsContext.h
@@ -325,9 +325,6 @@ void beginLayer(float opacity, CompositeOperator, const FloatRect* = 0, ColorFilter = ColorFilterNone, ImageFilter* = 0); void endLayer(); - void beginCull(const FloatRect&); - void endCull(); - // Instead of being dispatched to the active canvas, draw commands following beginRecording() // are stored in a display list that can be replayed at a later time. void beginRecording(const FloatRect& bounds);
diff --git a/sky/engine/platform/graphics/GraphicsContextCullSaver.h b/sky/engine/platform/graphics/GraphicsContextCullSaver.h deleted file mode 100644 index 7ea99f4..0000000 --- a/sky/engine/platform/graphics/GraphicsContextCullSaver.h +++ /dev/null
@@ -1,46 +0,0 @@ -#ifndef GraphicsContextCullSaver_h -#define GraphicsContextCullSaver_h - -#include "sky/engine/platform/graphics/GraphicsContext.h" - -namespace blink { - -class FloatRect; - -class GraphicsContextCullSaver { - WTF_MAKE_FAST_ALLOCATED; -public: - GraphicsContextCullSaver(GraphicsContext& context) - : m_context(context) - , m_cullApplied(false) - { - } - - GraphicsContextCullSaver(GraphicsContext& context, const FloatRect& rect) - : m_context(context) - , m_cullApplied(true) - { - context.beginCull(rect); - } - - ~GraphicsContextCullSaver() - { - if (m_cullApplied) - m_context.endCull(); - } - - void cull(const FloatRect& rect) - { - ASSERT(!m_cullApplied); - m_context.beginCull(rect); - m_cullApplied = true; - } - -private: - GraphicsContext& m_context; - bool m_cullApplied; -}; - -} // namespace blink - -#endif // GraphicsContextCullSaver_h
diff --git a/sky/engine/platform/graphics/GraphicsContextRecorder.cpp b/sky/engine/platform/graphics/GraphicsContextRecorder.cpp index 6b8851b..05d82f6 100644 --- a/sky/engine/platform/graphics/GraphicsContextRecorder.cpp +++ b/sky/engine/platform/graphics/GraphicsContextRecorder.cpp
@@ -100,10 +100,9 @@ PassOwnPtr<Vector<char> > GraphicsContextSnapshot::replay(unsigned fromStep, unsigned toStep, double scale) const { - int width = ceil(scale * m_picture->width()); - int height = ceil(scale * m_picture->height()); + const SkIRect bounds = m_picture->cullRect().roundOut(); SkBitmap bitmap; - bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height)); + bitmap.allocPixels(SkImageInfo::MakeN32Premul(bounds.width(), bounds.height())); { ReplayingCanvas canvas(bitmap, fromStep, toStep); canvas.scale(scale, scale); @@ -122,8 +121,9 @@ { OwnPtr<GraphicsContextSnapshot::Timings> timings = adoptPtr(new GraphicsContextSnapshot::Timings()); timings->reserveCapacity(minRepeatCount); + const SkIRect bounds = m_picture->cullRect().roundOut(); SkBitmap bitmap; - bitmap.allocPixels(SkImageInfo::MakeN32Premul(m_picture->width(), m_picture->height())); + bitmap.allocPixels(SkImageInfo::MakeN32Premul(bounds.width(), bounds.height())); OwnPtr<ProfilingCanvas> canvas = adoptPtr(new ProfilingCanvas(bitmap)); double now = WTF::monotonicallyIncreasingTime(); @@ -144,7 +144,8 @@ PassRefPtr<JSONArray> GraphicsContextSnapshot::snapshotCommandLog() const { - LoggingCanvas canvas(m_picture->width(), m_picture->height()); + const SkIRect bounds = m_picture->cullRect().roundOut(); + LoggingCanvas canvas(bounds.width(), bounds.height()); m_picture->draw(&canvas); return canvas.log(); }
diff --git a/sky/engine/platform/graphics/InterceptingCanvas.h b/sky/engine/platform/graphics/InterceptingCanvas.h index a3e9ba5..32e50a4 100644 --- a/sky/engine/platform/graphics/InterceptingCanvas.h +++ b/sky/engine/platform/graphics/InterceptingCanvas.h
@@ -48,7 +48,6 @@ virtual void drawPath(const SkPath&, const SkPaint&) override = 0; virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint* = 0) override = 0; virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*, DrawBitmapRectFlags) override = 0; - virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, const SkPaint* = 0) override = 0; virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override = 0; virtual void drawSprite(const SkBitmap&, int left, int top, const SkPaint* = 0) override = 0; virtual void drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], @@ -63,8 +62,6 @@ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint&) override = 0; virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint&) override = 0; virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath&, const SkMatrix*, const SkPaint&) override = 0; - virtual void onPushCull(const SkRect& cullRect) override = 0; - virtual void onPopCull() override = 0; virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override = 0; virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override = 0; virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override = 0;
diff --git a/sky/engine/platform/graphics/LoggingCanvas.cpp b/sky/engine/platform/graphics/LoggingCanvas.cpp index 18adab9..8cb941f 100644 --- a/sky/engine/platform/graphics/LoggingCanvas.cpp +++ b/sky/engine/platform/graphics/LoggingCanvas.cpp
@@ -160,16 +160,6 @@ this->SkCanvas::drawBitmapRectToRect(bitmap, src, dst, paint, flags); } -void LoggingCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) -{ - AutoLogger logger(this); - RefPtr<JSONObject> params = logger.logItemWithParams("drawBitmapMatrix"); - params->setObject("bitmap", objectForSkBitmap(bitmap)); - params->setArray("matrix", arrayForSkMatrix(m)); - params->setObject("paint", objectForSkPaint(*paint)); - this->SkCanvas::drawBitmapMatrix(bitmap, m, paint); -} - void LoggingCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { AutoLogger logger(this); @@ -288,21 +278,6 @@ this->SkCanvas::onDrawTextOnPath(text, byteLength, path, matrix, paint); } -void LoggingCanvas::onPushCull(const SkRect& cullRect) -{ - AutoLogger logger(this); - RefPtr<JSONObject> params = logger.logItemWithParams("pushCull"); - params->setObject("cullRect", objectForSkRect(cullRect)); - this->SkCanvas::onPushCull(cullRect); -} - -void LoggingCanvas::onPopCull() -{ - AutoLogger logger(this); - logger.logItem("popCull"); - this->SkCanvas::onPopCull(); -} - void LoggingCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle style) { AutoLogger logger(this); @@ -461,9 +436,10 @@ PassRefPtr<JSONObject> LoggingCanvas::objectForSkPicture(const SkPicture& picture) { + const SkIRect bounds = picture.cullRect().roundOut(); RefPtr<JSONObject> pictureItem = JSONObject::create(); - pictureItem->setNumber("width", picture.width()); - pictureItem->setNumber("height", picture.height()); + pictureItem->setNumber("width", bounds.width()); + pictureItem->setNumber("height", bounds.height()); return pictureItem.release(); }
diff --git a/sky/engine/platform/graphics/LoggingCanvas.h b/sky/engine/platform/graphics/LoggingCanvas.h index 3483015..6abb7a3 100644 --- a/sky/engine/platform/graphics/LoggingCanvas.h +++ b/sky/engine/platform/graphics/LoggingCanvas.h
@@ -49,7 +49,6 @@ virtual void drawPath(const SkPath&, const SkPaint&) override; virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint* = 0) override; virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*, DrawBitmapRectFlags) override; - virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, const SkPaint* = 0) override; virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; virtual void drawSprite(const SkBitmap&, int left, int top, const SkPaint* = 0) override; virtual void drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], @@ -64,8 +63,6 @@ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint&) override; virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint&) override; virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath&, const SkMatrix*, const SkPaint&) override; - virtual void onPushCull(const SkRect& cullRect) override; - virtual void onPopCull() override; virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override; virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override; virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
diff --git a/sky/engine/platform/graphics/ProfilingCanvas.cpp b/sky/engine/platform/graphics/ProfilingCanvas.cpp index 2940339..728a5c0 100644 --- a/sky/engine/platform/graphics/ProfilingCanvas.cpp +++ b/sky/engine/platform/graphics/ProfilingCanvas.cpp
@@ -118,12 +118,6 @@ this->SkCanvas::drawBitmapRectToRect(bitmap, src, dst, paint, flags); } -void ProfilingCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) -{ - AutoStamper stamper(this); - this->SkCanvas::drawBitmapMatrix(bitmap, m, paint); -} - void ProfilingCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { AutoStamper stamper(this); @@ -197,18 +191,6 @@ this->SkCanvas::onDrawTextOnPath(text, byteLength, path, matrix, paint); } -void ProfilingCanvas::onPushCull(const SkRect& cullRect) -{ - AutoStamper stamper(this); - this->SkCanvas::onPushCull(cullRect); -} - -void ProfilingCanvas::onPopCull() -{ - AutoStamper stamper(this); - this->SkCanvas::onPopCull(); -} - void ProfilingCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { AutoStamper stamper(this);
diff --git a/sky/engine/platform/graphics/ProfilingCanvas.h b/sky/engine/platform/graphics/ProfilingCanvas.h index b390ab4..4ec11f2 100644 --- a/sky/engine/platform/graphics/ProfilingCanvas.h +++ b/sky/engine/platform/graphics/ProfilingCanvas.h
@@ -49,7 +49,6 @@ virtual void drawPath(const SkPath&, const SkPaint&) override; virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint* = 0) override; virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*, DrawBitmapRectFlags) override; - virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, const SkPaint* = 0) override; virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; virtual void drawSprite(const SkBitmap&, int left, int top, const SkPaint* = 0) override; virtual void drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], @@ -64,8 +63,6 @@ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint&) override; virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint&) override; virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath&, const SkMatrix*, const SkPaint&) override; - virtual void onPushCull(const SkRect& cullRect) override; - virtual void onPopCull() override; virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override; virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override; virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
diff --git a/sky/engine/platform/graphics/ReplayingCanvas.cpp b/sky/engine/platform/graphics/ReplayingCanvas.cpp index 3c13a10..dbb2d19 100644 --- a/sky/engine/platform/graphics/ReplayingCanvas.cpp +++ b/sky/engine/platform/graphics/ReplayingCanvas.cpp
@@ -132,12 +132,6 @@ this->SkCanvas::drawBitmapRectToRect(bitmap, src, dst, paint, flags); } -void ReplayingCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) -{ - AutoReplayer replayer(this); - this->SkCanvas::drawBitmapMatrix(bitmap, m, paint); -} - void ReplayingCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) { AutoReplayer replayer(this); @@ -211,18 +205,6 @@ this->SkCanvas::onDrawTextOnPath(text, byteLength, path, matrix, paint); } -void ReplayingCanvas::onPushCull(const SkRect& cullRect) -{ - AutoReplayer replayer(this); - this->SkCanvas::onPushCull(cullRect); -} - -void ReplayingCanvas::onPopCull() -{ - AutoReplayer replayer(this); - this->SkCanvas::onPopCull(); -} - void ReplayingCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { AutoReplayer replayer(this);
diff --git a/sky/engine/platform/graphics/ReplayingCanvas.h b/sky/engine/platform/graphics/ReplayingCanvas.h index a8e9541..4939db6 100644 --- a/sky/engine/platform/graphics/ReplayingCanvas.h +++ b/sky/engine/platform/graphics/ReplayingCanvas.h
@@ -51,7 +51,6 @@ virtual void drawPath(const SkPath&, const SkPaint&) override; virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint* = 0) override; virtual void drawBitmapRectToRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*, DrawBitmapRectFlags) override; - virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&, const SkPaint* = 0) override; virtual void drawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; virtual void drawSprite(const SkBitmap&, int left, int top, const SkPaint* = 0) override; virtual void drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], const SkPoint texs[], @@ -66,8 +65,6 @@ virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], const SkPaint&) override; virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint&) override; virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath&, const SkMatrix*, const SkPaint&) override; - virtual void onPushCull(const SkRect& cullRect) override; - virtual void onPopCull() override; virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override; virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override; virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 0927e93..42cc7c7 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -362,71 +362,5 @@ { "test": "content_unittests", "args": ["--enable-browser-side-navigation"] }, { "test": "content_browsertests", "args": ["--enable-browser-side-navigation"] } ] - }, - "Linux ChromeOS MSan Tests": { - "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", - "app_shell_browsertests", - "aura_unittests", - "base_unittests", - "cacheinvalidation_unittests", - "cast_unittests", - "cc_unittests", - "chromedriver_unittests", - "components_unittests", - "content_browsertests", - "content_unittests", - "crypto_unittests", - "dbus_unittests", - "device_unittests", - "display_unittests", - "events_unittests", - "extensions_unittests", - "gcm_unit_tests", - "gfx_unittests", - "google_apis_unittests", - "gpu_unittests", - "interactive_ui_tests", - "ipc_mojo_unittests", - "ipc_tests", - "jingle_unittests", - "media_unittests", - "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", - "net_unittests", - "ppapi_unittests", - "printing_unittests", - "remoting_unittests", - "sandbox_linux_unittests", - "sql_unittests", - "sync_unit_tests", - "ui_base_unittests", - "ui_touch_selection_unittests", - "unit_tests", - "url_unittests", - "views_unittests", - "wm_unittests" - ] - }, - "Linux ChromeOS MSan Browser (1)": { - "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} - ] } }
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 39bfb16..d9f5f96 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1,8 +1,18 @@ { "Linux Tests": { "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "app_shell_browsertests", "app_shell_unittests", "aura_unittests", @@ -41,10 +51,20 @@ "dbus_unittests", "device_unittests", "display_unittests", - "events_unittests", + { + "test": "events_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "google_apis_unittests", "gpu_unittests", { @@ -75,7 +95,12 @@ "remoting_unittests", "sandbox_linux_unittests", "sql_unittests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "ui_touch_selection_unittests", { "test": "sync_integration_tests", @@ -111,8 +136,18 @@ }, "Linux Tests (dbg)(1)(32)": { "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "app_shell_browsertests", "app_shell_unittests", "aura_unittests", @@ -151,10 +186,20 @@ "dbus_unittests", "device_unittests", "display_unittests", - "events_unittests", + { + "test": "events_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "google_apis_unittests", "gpu_unittests", { @@ -185,7 +230,12 @@ "remoting_unittests", "sandbox_linux_unittests", "sql_unittests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "ui_touch_selection_unittests", { "test": "sync_integration_tests", @@ -213,8 +263,18 @@ }, "Linux Tests (dbg)(1)": { "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "app_shell_browsertests", "app_shell_unittests", "aura_unittests", @@ -253,10 +313,20 @@ "dbus_unittests", "device_unittests", "display_unittests", - "events_unittests", + { + "test": "events_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "google_apis_unittests", "gpu_unittests", { @@ -291,7 +361,12 @@ "args": ["--test-launcher-print-test-stdio=always"] }, "sql_unittests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "ui_touch_selection_unittests", { "test": "sync_integration_tests",
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 0ea46e9..8a20416 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -1,8 +1,18 @@ { "Mac10.6 Tests": { "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "base_unittests", "swarming": { @@ -36,7 +46,12 @@ "crypto_unittests", "extensions_unittests", "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "gpu_unittests", "google_apis_unittests", { @@ -48,7 +63,12 @@ "ipc_tests", "jingle_unittests", "media_unittests", - "message_center_unittests", + { + "test": "message_center_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "mojo_common_unittests", "mojo_public_bindings_unittests", "mojo_public_environment_unittests", @@ -73,7 +93,12 @@ } }, "sync_unit_tests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "unit_tests", "swarming": { @@ -99,8 +124,18 @@ }, "Mac10.8 Tests": { "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "base_unittests", "swarming": { @@ -134,7 +169,12 @@ "crypto_unittests", "extensions_unittests", "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "gpu_unittests", "google_apis_unittests", { @@ -146,7 +186,12 @@ "ipc_tests", "jingle_unittests", "media_unittests", - "message_center_unittests", + { + "test": "message_center_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "mojo_common_unittests", "mojo_public_bindings_unittests", "mojo_public_environment_unittests", @@ -171,7 +216,12 @@ } }, "sync_unit_tests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "unit_tests", "swarming": { @@ -197,8 +247,18 @@ }, "Mac10.9 Tests": { "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "base_unittests", "swarming": { @@ -232,7 +292,12 @@ "crypto_unittests", "extensions_unittests", "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "gpu_unittests", "google_apis_unittests", { @@ -244,7 +309,12 @@ "ipc_tests", "jingle_unittests", "media_unittests", - "message_center_unittests", + { + "test": "message_center_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "mojo_common_unittests", "mojo_public_bindings_unittests", "mojo_public_environment_unittests", @@ -269,7 +339,12 @@ } }, "sync_unit_tests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "unit_tests", "swarming": { @@ -295,8 +370,18 @@ }, "Mac10.9 Tests (dbg)": { "gtest_tests": [ - "accessibility_unittests", - "app_list_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "base_unittests", "swarming": { @@ -330,7 +415,12 @@ "crypto_unittests", "extensions_unittests", "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "gpu_unittests", "google_apis_unittests", { @@ -343,7 +433,12 @@ "ipc_tests", "jingle_unittests", "media_unittests", - "message_center_unittests", + { + "test": "message_center_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "mojo_common_unittests", "mojo_public_bindings_unittests", "mojo_public_environment_unittests", @@ -368,7 +463,12 @@ } }, "sync_unit_tests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "unit_tests", "swarming": {
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json index 1db2fb5..3852f7a 100644 --- a/testing/buildbot/chromium.memory.fyi.json +++ b/testing/buildbot/chromium.memory.fyi.json
@@ -64,5 +64,70 @@ "gtest_tests": [ {"test": "browser_tests", "shard_index": 2, "total_shards": 3} ] + }, + "Linux ChromeOS MSan Tests": { + "gtest_tests": [ + "accessibility_unittests", + "app_list_unittests", + "app_shell_browsertests", + "aura_unittests", + "base_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "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", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" + ] + }, + "Linux ChromeOS MSan Browser (1)": { + "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} + ] } }
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json index 9a0e4af..7925d5d 100644 --- a/testing/buildbot/chromium_trybot.json +++ b/testing/buildbot/chromium_trybot.json
@@ -3,12 +3,22 @@ "all" ], "gtest_tests": [ - "accessibility_unittests", + { + "test": "accessibility_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "app_installer_unittests", "platforms": ["win"] }, - "app_list_unittests", + { + "test": "app_list_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "ash_unittests", "chromium_configs": [ @@ -84,13 +94,23 @@ "platforms": ["linux"] }, "device_unittests", - "events_unittests", + { + "test": "events_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "extensions_unittests", "platforms": ["win", "mac", "linux"] }, "gcm_unit_tests", - "gfx_unittests", + { + "test": "gfx_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "google_apis_unittests", "gpu_unittests", { @@ -116,7 +136,12 @@ }, "media_perftests", "media_unittests", - "message_center_unittests", + { + "test": "message_center_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "mojo_common_unittests", "mojo_public_bindings_unittests", "mojo_public_environment_unittests", @@ -157,7 +182,12 @@ } }, "sync_unit_tests", - "ui_base_unittests", + { + "test": "ui_base_unittests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "ui_touch_selection_unittests", { "test": "unit_tests",
diff --git a/third_party/cython/rules.gni b/third_party/cython/rules.gni index 53125fe..5cfea1a 100644 --- a/third_party/cython/rules.gni +++ b/third_party/cython/rules.gni
@@ -2,34 +2,37 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -template("python_binary_module_sources") { +template("python_binary_source_set") { # Only available on linux for now. assert(is_linux) - assert(defined(invoker.sources)) + assert(defined(invoker.cython_sources) || defined(invoker.sources)) - cython_root = "//third_party/cython" - cython_script = "$cython_root/src/cython.py" - cython_output = "${target_out_dir}/${target_name}.cc" - - generator_target_name = target_name + "_cython_compiler" config_name = target_name + "_python_config" target_visibility = [ ":$target_name" ] - action(generator_target_name) { - visibility = target_visibility - script = cython_script - sources = invoker.sources - outputs = [ - cython_output, - ] - args = [ - "--cplus", - "-I", - rebase_path("//", root_build_dir), - "-o", - rebase_path(cython_output, root_build_dir), - ] + rebase_path(sources, root_build_dir) + if (defined(invoker.cython_sources)) { + generator_target_name = target_name + "_cython_compiler" + + cython_root = "//third_party/cython" + cython_script = "$cython_root/src/cython.py" + cython_output = "${target_out_dir}/${target_name}.cc" + + action(generator_target_name) { + visibility = target_visibility + script = cython_script + sources = invoker.cython_sources + outputs = [ + cython_output, + ] + args = [ + "--cplus", + "-I", + rebase_path("//", root_build_dir), + "-o", + rebase_path(cython_output, root_build_dir), + ] + rebase_path(sources, root_build_dir) + } } config(config_name) { @@ -45,35 +48,40 @@ } source_set(target_name) { - deps = [ - ":$generator_target_name", - ] if (defined(invoker.visibility)) { visibility = invoker.visibility } + sources = [] + if (defined(invoker.cython_sources)) { + sources += [ cython_output ] + } + if (defined(invoker.sources)) { + sources += invoker.sources + } + if (defined(invoker.configs)) { + configs += invoker.configs + } + all_dependent_configs = [ ":$config_name" ] + deps = [] + if (defined(invoker.cython_sources)) { + deps += [ ":$generator_target_name" ] + } if (defined(invoker.deps)) { deps += invoker.deps } if (defined(invoker.datadeps)) { datadeps = invoker.datadeps } - sources = [ - cython_output, - ] - if (defined(invoker.additional_sources)) { - sources += invoker.additional_sources - } - if (defined(invoker.configs)) { - configs += invoker.configs - } - all_dependent_configs = [ ":$config_name" ] } } template("python_binary_module") { # Only available on linux for now. assert(is_linux) - assert(defined(invoker.sources)) + + has_sources = defined(invoker.cython_sources) || defined(invoker.sources) + + assert(has_sources || defined(invoker.deps)) assert(defined(invoker.python_base_module)) sources_target_name = target_name + "_cython_sources" @@ -91,31 +99,42 @@ ":$target_name", ] - python_binary_module_sources(sources_target_name) { - visibility = target_visibility - sources = invoker.sources - if (defined(invoker.configs)) { - configs = invoker.configs + if (has_sources) { + python_binary_source_set(sources_target_name) { + visibility = target_visibility + if (defined(invoker.cython_sources)) { + cython_sources = invoker.cython_sources + } + if (defined(invoker.sources)) { + sources = invoker.sources + } + if (defined(invoker.configs)) { + configs = invoker.configs + } + if (defined(invoker.deps)) { + deps = invoker.deps + } + if (defined(invoker.datadeps)) { + datadeps = invoker.datadeps + } } } shared_library(shared_library_name) { visibility = target_visibility - deps = [ - ":$sources_target_name", - ] + if (defined(invoker.configs)) { + configs += invoker.configs + } + deps = [] + if (has_sources) { + deps += [ ":$sources_target_name" ] + } if (defined(invoker.deps)) { deps += invoker.deps } if (defined(invoker.datadeps)) { datadeps = invoker.datadeps } - if (defined(invoker.additional_sources)) { - sources = invoker.additional_sources - } - if (defined(invoker.configs)) { - configs += invoker.configs - } } copy(target_name) {
diff --git a/third_party/mesa/mesa.gyp b/third_party/mesa/mesa.gyp index 056eb40..3db0d4c 100644 --- a/third_party/mesa/mesa.gyp +++ b/third_party/mesa/mesa.gyp
@@ -132,6 +132,7 @@ 'variables': { 'clang_warning_flags': [ '-Wno-tautological-constant-out-of-range-compare', + '-Wno-mismatched-tags', # Fixed upstream. ], 'clang_warning_flags_unset': [ # Don't warn about string->bool used in asserts. @@ -269,6 +270,8 @@ 'variables': { 'clang_warning_flags': [ '-Wno-tautological-constant-out-of-range-compare', + '-Wno-absolute-value', # Fires on st_atom_array.c, might be a bug + '-Wno-mismatched-tags', # Fixed upstream. ], 'clang_warning_flags_unset': [ # Don't warn about string->bool used in asserts.
diff --git a/tools/clang/blink_gc_plugin/CMakeLists.txt b/tools/clang/blink_gc_plugin/CMakeLists.txt index 85ce4a9..c511edf 100644 --- a/tools/clang/blink_gc_plugin/CMakeLists.txt +++ b/tools/clang/blink_gc_plugin/CMakeLists.txt
@@ -1,6 +1,6 @@ # This line is read by update.sh and other scripts in tools/clang/scripts # Note: The spaces are significant. -set(LIBRARYNAME BlinkGCPlugin_12) +set(LIBRARYNAME BlinkGCPlugin_14) add_llvm_loadable_module("lib${LIBRARYNAME}" BlinkGCPlugin.cpp
diff --git a/tools/clang/plugins/tests/overridden_methods.txt b/tools/clang/plugins/tests/overridden_methods.txt index 199876b..3ee0333 100644 --- a/tools/clang/plugins/tests/overridden_methods.txt +++ b/tools/clang/plugins/tests/overridden_methods.txt
@@ -11,14 +11,14 @@ virtual void SomeConstMethod() const {} ^ override -./overridden_methods.h:58:53: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. +./overridden_methods.h:58:55: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. virtual void SomeMethodWithExceptionSpec() throw() {} - ^ - override -./overridden_methods.h:61:67: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. + ^ + override +./overridden_methods.h:61:69: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. virtual void SomeConstMethodWithExceptionSpec() const throw(int) {} - ^ - override + ^ + override ./overridden_methods.h:63:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. virtual void SomeNonPureBaseMethod() {} ^ @@ -43,14 +43,14 @@ virtual void SomeConstMethod() const {} ^ override -overridden_methods.cpp:34:53: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. +overridden_methods.cpp:34:55: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. virtual void SomeMethodWithExceptionSpec() throw() {} - ^ - override -overridden_methods.cpp:37:67: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. + ^ + override +overridden_methods.cpp:37:69: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. virtual void SomeConstMethodWithExceptionSpec() const throw(int) {} - ^ - override + ^ + override overridden_methods.cpp:39:39: warning: [chromium-style] Overriding method must be marked with 'override' or 'final'. virtual void SomeNonPureBaseMethod() {} ^
diff --git a/tools/clang/plugins/tests/test.sh b/tools/clang/plugins/tests/test.sh index 9f63f7a..63aa872 100755 --- a/tools/clang/plugins/tests/test.sh +++ b/tools/clang/plugins/tests/test.sh
@@ -34,6 +34,7 @@ fi local output="$("${CLANG_PATH}" -fsyntax-only -Wno-c++11-extensions \ + -Wno-inconsistent-missing-override \ -Xclang -load -Xclang "${PLUGIN_PATH}" \ -Xclang -add-plugin -Xclang find-bad-constructs ${flags} ${1} 2>&1)" local diffout="$(echo "${output}" | diff - "${2}")"
diff --git a/tools/clang/scripts/package.sh b/tools/clang/scripts/package.sh index f00abb4..e0c0fcc 100755 --- a/tools/clang/scripts/package.sh +++ b/tools/clang/scripts/package.sh
@@ -87,7 +87,7 @@ ${extra_flags} 2>&1 | tee -a buildlog.txt R=$("${LLVM_BIN_DIR}/clang" --version | \ - sed -ne 's/clang version .*(\([0-9]*\))/\1/p') + sed -ne 's/clang version .*(trunk \([0-9]*\))/\1/p') PDIR=clang-$R rm -rf $PDIR
diff --git a/tools/clang/scripts/repackage.sh b/tools/clang/scripts/repackage.sh index c92447a..e19ab7e 100755 --- a/tools/clang/scripts/repackage.sh +++ b/tools/clang/scripts/repackage.sh
@@ -30,7 +30,7 @@ "$THIS_DIR"/package.sh $@ R=$("${LLVM_BIN_DIR}/clang" --version | \ - sed -ne 's/clang version .*(\([0-9]*\))/\1/p') + sed -ne 's/clang version .*(trunk \([0-9]*\))/\1/p') PDIR=clang-$R if [ ! -f "$PDIR.tgz" ]; then
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh index ad534ad..b585440 100755 --- a/tools/clang/scripts/update.sh +++ b/tools/clang/scripts/update.sh
@@ -8,7 +8,7 @@ # Do NOT CHANGE this if you don't know what you're doing -- see # https://code.google.com/p/chromium/wiki/UpdatingClang # Reverting problematic clang rolls is safe, though. -CLANG_REVISION=218707 +CLANG_REVISION=223109 THIS_DIR="$(dirname "${0}")" LLVM_DIR="${THIS_DIR}/../../../third_party/llvm" @@ -238,8 +238,15 @@ "${LLVM_DIR}/test/DebugInfo/gmlt.ll" \ "${LLVM_DIR}/lib/CodeGen/SpillPlacement.cpp" \ "${LLVM_DIR}/lib/CodeGen/SpillPlacement.h" \ + "${LLVM_DIR}/lib/Transforms/Instrumentation/MemorySanitizer.cpp" \ + "${CLANG_DIR}/test/Driver/env.c" \ + "${CLANG_DIR}/lib/Frontend/InitPreprocessor.cpp" \ + "${CLANG_DIR}/test/Frontend/exceptions.c" \ + "${CLANG_DIR}/test/Preprocessor/predefined-exceptions.m" \ + "${LLVM_DIR}/test/Bindings/Go/go.test" \ ; do if [[ -e "${i}" ]]; then + rm -f "${i}" # For unversioned files. svn revert "${i}" fi; done @@ -317,179 +324,143 @@ patch -p0 popd -# Apply r218742: test: XFAIL the non-darwin gmlt test on darwin -# Back-ported becase the test was renamed. +# Apply r223211: "Revert r222997." pushd "${LLVM_DIR}" cat << 'EOF' | ---- a/test/DebugInfo/gmlt.ll -+++ b/test/DebugInfo/gmlt.ll -@@ -1,2 +1,5 @@ - ; REQUIRES: object-emission - ; RUN: %llc_dwarf -O0 -filetype=obj < %S/Inputs/gmlt.ll | llvm-dwarfdump - | FileCheck %S/Inputs/gmlt.ll -+ -+; There's a darwin specific test in X86/gmlt, so it's okay to XFAIL this here. -+; XFAIL: darwin +--- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp ++++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp +@@ -921,8 +921,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { + Value *OriginPtr = + getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset); + setOrigin(A, EntryIRB.CreateLoad(OriginPtr)); +- } else { +- setOrigin(A, getCleanOrigin()); + } + } + ArgOffset += RoundUpToAlignment(Size, kShadowTLSAlignment); +@@ -942,13 +940,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { + /// \brief Get the origin for a value. + Value *getOrigin(Value *V) { + if (!MS.TrackOrigins) return nullptr; +- if (!PropagateShadow) return getCleanOrigin(); +- if (isa<Constant>(V)) return getCleanOrigin(); +- assert((isa<Instruction>(V) || isa<Argument>(V)) && +- "Unexpected value type in getOrigin()"); +- Value *Origin = OriginMap[V]; +- assert(Origin && "Missing origin"); +- return Origin; ++ if (isa<Instruction>(V) || isa<Argument>(V)) { ++ Value *Origin = OriginMap[V]; ++ if (!Origin) { ++ DEBUG(dbgs() << "NO ORIGIN: " << *V << "\n"); ++ Origin = getCleanOrigin(); ++ } ++ return Origin; ++ } ++ return getCleanOrigin(); + } + + /// \brief Get the origin for i-th argument of the instruction I. +@@ -1088,7 +1088,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { + IRB.CreateStore(getCleanShadow(&I), ShadowPtr); + + setShadow(&I, getCleanShadow(&I)); +- setOrigin(&I, getCleanOrigin()); + } + + void visitAtomicRMWInst(AtomicRMWInst &I) { EOF patch -p1 popd -# Apply r218921; fixes spill placement compile-time regression. -pushd "${LLVM_DIR}" +# Apply r223219: "Preserve LD_LIBRARY_PATH when using the 'env' command" +pushd "${CLANG_DIR}" cat << 'EOF' | ---- a/lib/CodeGen/SpillPlacement.cpp -+++ b/lib/CodeGen/SpillPlacement.cpp -@@ -61,27 +61,6 @@ void SpillPlacement::getAnalysisUsage(AnalysisUsage &AU) const { - MachineFunctionPass::getAnalysisUsage(AU); - } - --namespace { --static ManagedStatic<BlockFrequency> Threshold; --} -- --/// Decision threshold. A node gets the output value 0 if the weighted sum of --/// its inputs falls in the open interval (-Threshold;Threshold). --static BlockFrequency getThreshold() { return *Threshold; } -- --/// \brief Set the threshold for a given entry frequency. --/// --/// Set the threshold relative to \c Entry. Since the threshold is used as a --/// bound on the open interval (-Threshold;Threshold), 1 is the minimum --/// threshold. --static void setThreshold(const BlockFrequency &Entry) { -- // Apparently 2 is a good threshold when Entry==2^14, but we need to scale -- // it. Divide by 2^13, rounding as appropriate. -- uint64_t Freq = Entry.getFrequency(); -- uint64_t Scaled = (Freq >> 13) + bool(Freq & (1 << 12)); -- *Threshold = std::max(UINT64_C(1), Scaled); --} -- - /// Node - Each edge bundle corresponds to a Hopfield node. - /// - /// The node contains precomputed frequency data that only depends on the CFG, -@@ -127,9 +106,9 @@ struct SpillPlacement::Node { - - /// clear - Reset per-query data, but preserve frequencies that only depend on - // the CFG. -- void clear() { -+ void clear(const BlockFrequency &Threshold) { - BiasN = BiasP = Value = 0; -- SumLinkWeights = getThreshold(); -+ SumLinkWeights = Threshold; - Links.clear(); - } - -@@ -167,7 +146,7 @@ struct SpillPlacement::Node { - - /// update - Recompute Value from Bias and Links. Return true when node - /// preference changes. -- bool update(const Node nodes[]) { -+ bool update(const Node nodes[], const BlockFrequency &Threshold) { - // Compute the weighted sum of inputs. - BlockFrequency SumN = BiasN; - BlockFrequency SumP = BiasP; -@@ -187,9 +166,9 @@ struct SpillPlacement::Node { - // 2. It helps tame rounding errors when the links nominally sum to 0. - // - bool Before = preferReg(); -- if (SumN >= SumP + getThreshold()) -+ if (SumN >= SumP + Threshold) - Value = -1; -- else if (SumP >= SumN + getThreshold()) -+ else if (SumP >= SumN + Threshold) - Value = 1; - else - Value = 0; -@@ -228,7 +207,7 @@ void SpillPlacement::activate(unsigned n) { - if (ActiveNodes->test(n)) - return; - ActiveNodes->set(n); -- nodes[n].clear(); -+ nodes[n].clear(Threshold); - - // Very large bundles usually come from big switches, indirect branches, - // landing pads, or loops with many 'continue' statements. It is difficult to -@@ -245,6 +224,18 @@ void SpillPlacement::activate(unsigned n) { - } - } - -+/// \brief Set the threshold for a given entry frequency. -+/// -+/// Set the threshold relative to \c Entry. Since the threshold is used as a -+/// bound on the open interval (-Threshold;Threshold), 1 is the minimum -+/// threshold. -+void SpillPlacement::setThreshold(const BlockFrequency &Entry) { -+ // Apparently 2 is a good threshold when Entry==2^14, but we need to scale -+ // it. Divide by 2^13, rounding as appropriate. -+ uint64_t Freq = Entry.getFrequency(); -+ uint64_t Scaled = (Freq >> 13) + bool(Freq & (1 << 12)); -+ Threshold = std::max(UINT64_C(1), Scaled); -+} - - /// addConstraints - Compute node biases and weights from a set of constraints. - /// Set a bit in NodeMask for each active node. -@@ -311,7 +302,7 @@ bool SpillPlacement::scanActiveBundles() { - Linked.clear(); - RecentPositive.clear(); - for (int n = ActiveNodes->find_first(); n>=0; n = ActiveNodes->find_next(n)) { -- nodes[n].update(nodes); -+ nodes[n].update(nodes, Threshold); - // A node that must spill, or a node without any links is not going to - // change its value ever again, so exclude it from iterations. - if (nodes[n].mustSpill()) -@@ -331,7 +322,7 @@ void SpillPlacement::iterate() { - // First update the recently positive nodes. They have likely received new - // negative bias that will turn them off. - while (!RecentPositive.empty()) -- nodes[RecentPositive.pop_back_val()].update(nodes); -+ nodes[RecentPositive.pop_back_val()].update(nodes, Threshold); - - if (Linked.empty()) - return; -@@ -350,7 +341,7 @@ void SpillPlacement::iterate() { - iteration == 0 ? Linked.rbegin() : std::next(Linked.rbegin()), - E = Linked.rend(); I != E; ++I) { - unsigned n = *I; -- if (nodes[n].update(nodes)) { -+ if (nodes[n].update(nodes, Threshold)) { - Changed = true; - if (nodes[n].preferReg()) - RecentPositive.push_back(n); -@@ -364,7 +355,7 @@ void SpillPlacement::iterate() { - for (SmallVectorImpl<unsigned>::const_iterator I = - std::next(Linked.begin()), E = Linked.end(); I != E; ++I) { - unsigned n = *I; -- if (nodes[n].update(nodes)) { -+ if (nodes[n].update(nodes, Threshold)) { - Changed = true; - if (nodes[n].preferReg()) - RecentPositive.push_back(n); -diff --git a/lib/CodeGen/SpillPlacement.h b/lib/CodeGen/SpillPlacement.h -index 03cf5cd..622361e 100644 ---- a/lib/CodeGen/SpillPlacement.h -+++ b/lib/CodeGen/SpillPlacement.h -@@ -62,6 +62,10 @@ class SpillPlacement : public MachineFunctionPass { - // Block frequencies are computed once. Indexed by block number. - SmallVector<BlockFrequency, 8> BlockFrequencies; - -+ /// Decision threshold. A node gets the output value 0 if the weighted sum of -+ /// its inputs falls in the open interval (-Threshold;Threshold). -+ BlockFrequency Threshold; -+ - public: - static char ID; // Pass identification, replacement for typeid. - -@@ -152,6 +156,7 @@ private: - void releaseMemory() override; - - void activate(unsigned); -+ void setThreshold(const BlockFrequency &Entry); - }; - - } // end namespace llvm +--- a/test/Driver/env.c ++++ b/test/Driver/env.c +@@ -5,12 +5,14 @@ + // REQUIRES: shell + // + // The PATH variable is heavily used when trying to find a linker. +-// RUN: env -i LC_ALL=C %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ ++// RUN: env -i LC_ALL=C LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \ ++// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ + // RUN: --target=i386-unknown-linux \ + // RUN: --sysroot=%S/Inputs/basic_linux_tree \ + // RUN: | FileCheck --check-prefix=CHECK-LD-32 %s + // +-// RUN: env -i LC_ALL=C PATH="" %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ ++// RUN: env -i LC_ALL=C PATH="" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \ ++// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ + // RUN: --target=i386-unknown-linux \ + // RUN: --sysroot=%S/Inputs/basic_linux_tree \ + // RUN: | FileCheck --check-prefix=CHECK-LD-32 %s EOF patch -p1 popd +# 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, + Builder.defineMacro("__BLOCKS__"); + } + +- if (!LangOpts.MSVCCompat && LangOpts.Exceptions) ++ if (!LangOpts.MSVCCompat && LangOpts.CXXExceptions) + Builder.defineMacro("__EXCEPTIONS"); + if (!LangOpts.MSVCCompat && LangOpts.RTTI) + Builder.defineMacro("__GXX_RTTI"); +diff --git a/test/Frontend/exceptions.c b/test/Frontend/exceptions.c +index 981b5b9..4bbaaa3 100644 +--- a/test/Frontend/exceptions.c ++++ b/test/Frontend/exceptions.c +@@ -1,9 +1,6 @@ +-// RUN: %clang_cc1 -fms-compatibility -fexceptions -fcxx-exceptions -DMS_MODE -verify %s ++// RUN: %clang_cc1 -fms-compatibility -fexceptions -fcxx-exceptions -verify %s + // expected-no-diagnostics + +-// RUN: %clang_cc1 -fms-compatibility -fexceptions -verify %s +-// expected-no-diagnostics +- +-#if defined(MS_MODE) && defined(__EXCEPTIONS) ++#if defined(__EXCEPTIONS) + #error __EXCEPTIONS should not be defined. + #endif +diff --git a/test/Preprocessor/predefined-exceptions.m b/test/Preprocessor/predefined-exceptions.m +index 0791075..c13f429 100644 +--- a/test/Preprocessor/predefined-exceptions.m ++++ b/test/Preprocessor/predefined-exceptions.m +@@ -1,6 +1,6 @@ + // RUN: %clang_cc1 -x objective-c -fobjc-exceptions -fexceptions -E -dM %s | FileCheck -check-prefix=CHECK-OBJC-NOCXX %s + // CHECK-OBJC-NOCXX: #define OBJC_ZEROCOST_EXCEPTIONS 1 +-// CHECK-OBJC-NOCXX: #define __EXCEPTIONS 1 ++// CHECK-OBJC-NOCXX-NOT: #define __EXCEPTIONS 1 + + // 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 + +# 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) ++++ test/Bindings/Go/go.test (working copy) +@@ -1,3 +1,3 @@ +-; RUN: llvm-go test llvm.org/llvm/bindings/go/llvm ++; RUN: true + + ; REQUIRES: shell +EOF +patch -p0 +popd + # Echo all commands. set -x
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py index 677cb63..e43c605 100755 --- a/tools/valgrind/chrome_tests.py +++ b/tools/valgrind/chrome_tests.py
@@ -362,9 +362,6 @@ def TestExtensions(self): return self.SimpleTest("extensions", "extensions_unittests") - def TestFFmpeg(self): - return self.SimpleTest("chrome", "ffmpeg_unittests") - def TestFFmpegRegressions(self): return self.SimpleTest("chrome", "ffmpeg_regression_tests") @@ -678,7 +675,6 @@ "display": TestDisplay, "display_unittests": TestDisplay, "events": TestEvents, "events_unittests": TestEvents, "extensions": TestExtensions, "extensions_unittests": TestExtensions, - "ffmpeg": TestFFmpeg, "ffmpeg_unittests": TestFFmpeg, "ffmpeg_regression_tests": TestFFmpegRegressions, "gcm": TestGCM, "gcm_unit_tests": TestGCM, "gin": TestGin, "gin_unittests": TestGin,
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt index 4310d8a..4a6b5a9 100644 --- a/tools/valgrind/drmemory/suppressions.txt +++ b/tools/valgrind/drmemory/suppressions.txt
@@ -669,3 +669,15 @@ content.dll!content::RenderFrameProxy::OnDeleteProxy content.dll!content::RenderFrameProxy::OnMessageReceived content.dll!content::MessageRouter::RouteMessage + +HANDLE LEAK +name=http://crbug.com/441785 +system call NtCreateSection +*!CreateFileMappingW +*!base::SharedMemory::Create +*!base::SharedMemory::CreateAnonymous +*!content::ChildThread::AllocateSharedMemory +*!content::ChildSharedBitmapManager::AllocateSharedMemoryBitmap +*!content::ChildSharedBitmapManager::AllocateSharedBitmap +*!cc::ResourceProvider::CreateBitmap +*!cc::ResourceProvider::Create*Resource
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt index 14cbe8b..3fd0cf4 100644 --- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt +++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
@@ -17,6 +17,7 @@ RenderViewImplTest.ReloadWhileSwappedOut RenderViewImplTest.SendSwapOutACK RenderViewImplTest.StaleNavigationsIgnored +RenderFrameHostManagerTest.RestoreFileAccessForHistoryNavigation ResourceFetcherTests.ResourceFetcher404 ResourceFetcherTests.ResourceFetcherDidFail ResourceFetcherTests.ResourceFetcherDownload
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt index 3f1ea1b..ad58793 100644 --- a/tools/valgrind/memcheck/suppressions.txt +++ b/tools/valgrind/memcheck/suppressions.txt
@@ -3533,3 +3533,11 @@ ... fun:_ZN3gpu22InProcessCommandBuffer21InitializeOnGpuThreadERKNS0_27InitializeOnGpuThreadParamsE } +{ + bug_441333 + Memcheck:Uninitialized + fun:av_packet_unpack_dictionary + fun:add_metadata_from_side_data + fun:avcodec_decode_* + fun:avcodec_decode_* +}
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 58297e6..7fd7fe9 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -108,7 +108,7 @@ draw_on_compositing_end_(false), swap_state_(SWAP_NONE), layer_animator_collection_(this), - schedule_draw_factory_(this) { + weak_ptr_factory_(this) { root_web_layer_ = cc::Layer::Create(); CommandLine* command_line = CommandLine::ForCurrentProcess(); @@ -210,10 +210,27 @@ defer_draw_scheduling_ = true; task_runner_->PostTask( FROM_HERE, - base::Bind(&Compositor::Draw, schedule_draw_factory_.GetWeakPtr())); + base::Bind(&Compositor::Draw, weak_ptr_factory_.GetWeakPtr())); } } +void Compositor::DidInitializeOutputSurface() { + num_failed_recreate_attempts_ = 0; +} + +void Compositor::DidFailToInitializeOutputSurface() { + num_failed_recreate_attempts_++; + + // Tolerate a certain number of recreation failures to work around races + // in the output-surface-lost machinery. + if (num_failed_recreate_attempts_ >= MAX_OUTPUT_SURFACE_RETRIES) + LOG(FATAL) << "Failed to create a fallback OutputSurface."; + + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&Compositor::RequestNewOutputSurface, + weak_ptr_factory_.GetWeakPtr())); +} + void Compositor::SetRootLayer(Layer* root_layer) { if (root_layer_ == root_layer) return; @@ -367,9 +384,11 @@ disable_schedule_composite_ = false; } -void Compositor::RequestNewOutputSurface(bool fallback) { - host_->SetOutputSurface( - context_factory_->CreateOutputSurface(this, fallback)); +void Compositor::RequestNewOutputSurface() { + bool fallback = + num_failed_recreate_attempts_ >= OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK; + context_factory_->CreateOutputSurface(weak_ptr_factory_.GetWeakPtr().get(), + fallback); } void Compositor::DidCommit() {
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index a937886..d679551 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -73,7 +73,7 @@ Compositor* compositor, bool software_fallback) = 0; // Creates a reflector that copies the content of the |mirrored_compositor| - // onto |mirroing_layer|. + // onto |mirroring_layer|. virtual scoped_refptr<Reflector> CreateReflector( Compositor* mirrored_compositor, Layer* mirroring_layer) = 0; @@ -249,8 +249,9 @@ void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta, float page_scale, float top_controls_delta) override {} - void RequestNewOutputSurface(bool fallback) override; - void DidInitializeOutputSurface() override {} + void RequestNewOutputSurface() override; + void DidInitializeOutputSurface() override; + void DidFailToInitializeOutputSurface() override; void WillCommit() override {} void DidCommit() override; void DidCommitAndDrawFrame() override; @@ -286,6 +287,10 @@ friend class base::RefCounted<Compositor>; friend class CompositorLock; + enum { + OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK = 4, + MAX_OUTPUT_SURFACE_RETRIES = 5, + }; // Called by CompositorLock. void UnlockCompositor(); @@ -323,6 +328,8 @@ int last_started_frame_; int last_ended_frame_; + int num_failed_recreate_attempts_; + bool disable_schedule_composite_; CompositorLock* compositor_lock_; @@ -338,7 +345,7 @@ LayerAnimatorCollection layer_animator_collection_; - base::WeakPtrFactory<Compositor> schedule_draw_factory_; + base::WeakPtrFactory<Compositor> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(Compositor); };
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc index e358069..4cfcf73 100644 --- a/ui/gl/gl_context.cc +++ b/ui/gl/gl_context.cc
@@ -52,7 +52,10 @@ return flag_.IsSet(); } -GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) { +GLContext::GLContext(GLShareGroup* share_group) : + share_group_(share_group), + swap_interval_(1), + force_swap_interval_zero_(false) { if (!share_group_.get()) share_group_ = new GLShareGroup; @@ -178,6 +181,16 @@ state_restorer_ = make_scoped_ptr(state_restorer); } +void GLContext::SetSwapInterval(int interval) { + swap_interval_ = interval; + OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_); +} + +void GLContext::ForceSwapIntervalZero(bool force) { + force_swap_interval_zero_ = force; + OnSetSwapInterval(force_swap_interval_zero_ ? 0 : swap_interval_); +} + bool GLContext::WasAllocatedUsingRobustnessExtension() { return false; }
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h index cdebd68..62cabcd 100644 --- a/ui/gl/gl_context.h +++ b/ui/gl/gl_context.h
@@ -76,7 +76,11 @@ void SetGLStateRestorer(GLStateRestorer* state_restorer); // Set swap interval. This context must be current. - virtual void SetSwapInterval(int interval) = 0; + void SetSwapInterval(int interval); + + // Forces the swap interval to zero (no vsync) regardless of any future values + // passed to SetSwapInterval. + void ForceSwapIntervalZero(bool force); // Returns space separated list of extensions. The context must be current. virtual std::string GetExtensions(); @@ -169,6 +173,8 @@ // Returns the last real (non-virtual) GLContext made current. static GLContext* GetRealCurrent(); + virtual void OnSetSwapInterval(int interval) = 0; + private: friend class base::RefCounted<GLContext>; @@ -182,6 +188,9 @@ std::vector<scoped_refptr<FlushEvent> > flush_events_; + int swap_interval_; + bool force_swap_interval_zero_; + DISALLOW_COPY_AND_ASSIGN(GLContext); };
diff --git a/ui/gl/gl_context_android.cc b/ui/gl/gl_context_android.cc index 7f9cf2d..76b9238 100644 --- a/ui/gl/gl_context_android.cc +++ b/ui/gl/gl_context_android.cc
@@ -33,7 +33,7 @@ virtual void ReleaseCurrent(GLSurface* surface) override {} virtual bool IsCurrent(GLSurface* surface) override { return true; } virtual void* GetHandle() override { return NULL; } - virtual void SetSwapInterval(int interval) override {} + virtual void OnSetSwapInterval(int interval) override {} virtual std::string GetExtensions() override; protected:
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc index 277780a..723e97e 100644 --- a/ui/gl/gl_context_cgl.cc +++ b/ui/gl/gl_context_cgl.cc
@@ -238,7 +238,7 @@ return context_; } -void GLContextCGL::SetSwapInterval(int interval) { +void GLContextCGL::OnSetSwapInterval(int interval) { DCHECK(IsCurrent(NULL)); }
diff --git a/ui/gl/gl_context_cgl.h b/ui/gl/gl_context_cgl.h index 456ea08..88813b3 100644 --- a/ui/gl/gl_context_cgl.h +++ b/ui/gl/gl_context_cgl.h
@@ -26,7 +26,7 @@ void ReleaseCurrent(GLSurface* surface) override; bool IsCurrent(GLSurface* surface) override; void* GetHandle() override; - void SetSwapInterval(int interval) override; + void OnSetSwapInterval(int interval) override; bool GetTotalGpuMemory(size_t* bytes) override; void SetSafeToForceGpuSwitch() override; bool ForceGpuSwitchIfNeeded() override;
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc index 733ad8d..5dd1aaf 100644 --- a/ui/gl/gl_context_egl.cc +++ b/ui/gl/gl_context_egl.cc
@@ -172,7 +172,7 @@ return context_; } -void GLContextEGL::SetSwapInterval(int interval) { +void GLContextEGL::OnSetSwapInterval(int interval) { DCHECK(IsCurrent(NULL) && GLSurface::GetCurrent()); // This is a surfaceless context. eglSwapInterval doesn't take any effect in
diff --git a/ui/gl/gl_context_egl.h b/ui/gl/gl_context_egl.h index 9f071e2..99a4481 100644 --- a/ui/gl/gl_context_egl.h +++ b/ui/gl/gl_context_egl.h
@@ -31,7 +31,7 @@ void ReleaseCurrent(GLSurface* surface) override; bool IsCurrent(GLSurface* surface) override; void* GetHandle() override; - void SetSwapInterval(int interval) override; + void OnSetSwapInterval(int interval) override; std::string GetExtensions() override; bool WasAllocatedUsingRobustnessExtension() override; bool GetTotalGpuMemory(size_t* bytes) override;
diff --git a/ui/gl/gl_context_glx.cc b/ui/gl/gl_context_glx.cc index 9b6cfb4..a16daf3 100644 --- a/ui/gl/gl_context_glx.cc +++ b/ui/gl/gl_context_glx.cc
@@ -163,7 +163,7 @@ return context_; } -void GLContextGLX::SetSwapInterval(int interval) { +void GLContextGLX::OnSetSwapInterval(int interval) { DCHECK(IsCurrent(NULL)); if (HasExtension("GLX_EXT_swap_control") && g_driver_glx.fn.glXSwapIntervalEXTFn) {
diff --git a/ui/gl/gl_context_glx.h b/ui/gl/gl_context_glx.h index fe3d754..6973542 100644 --- a/ui/gl/gl_context_glx.h +++ b/ui/gl/gl_context_glx.h
@@ -31,7 +31,7 @@ void ReleaseCurrent(GLSurface* surface) override; bool IsCurrent(GLSurface* surface) override; void* GetHandle() override; - void SetSwapInterval(int interval) override; + void OnSetSwapInterval(int interval) override; std::string GetExtensions() override; bool GetTotalGpuMemory(size_t* bytes) override; bool WasAllocatedUsingRobustnessExtension() override;
diff --git a/ui/gl/gl_context_osmesa.cc b/ui/gl/gl_context_osmesa.cc index 524fe42..d41a493 100644 --- a/ui/gl/gl_context_osmesa.cc +++ b/ui/gl/gl_context_osmesa.cc
@@ -123,7 +123,7 @@ return context_; } -void GLContextOSMesa::SetSwapInterval(int interval) { +void GLContextOSMesa::OnSetSwapInterval(int interval) { DCHECK(IsCurrent(NULL)); }
diff --git a/ui/gl/gl_context_osmesa.h b/ui/gl/gl_context_osmesa.h index 0ae32db..9ce37d7 100644 --- a/ui/gl/gl_context_osmesa.h +++ b/ui/gl/gl_context_osmesa.h
@@ -29,7 +29,7 @@ void ReleaseCurrent(GLSurface* surface) override; bool IsCurrent(GLSurface* surface) override; void* GetHandle() override; - void SetSwapInterval(int interval) override; + void OnSetSwapInterval(int interval) override; protected: ~GLContextOSMesa() override;
diff --git a/ui/gl/gl_context_stub.cc b/ui/gl/gl_context_stub.cc index faf957b..ff3a85d 100644 --- a/ui/gl/gl_context_stub.cc +++ b/ui/gl/gl_context_stub.cc
@@ -33,7 +33,7 @@ return NULL; } -void GLContextStub::SetSwapInterval(int interval) { +void GLContextStub::OnSetSwapInterval(int interval) { } std::string GLContextStub::GetExtensions() {
diff --git a/ui/gl/gl_context_stub.h b/ui/gl/gl_context_stub.h index 1a7eb24..b4eef93 100644 --- a/ui/gl/gl_context_stub.h +++ b/ui/gl/gl_context_stub.h
@@ -22,7 +22,7 @@ void ReleaseCurrent(GLSurface* surface) override; bool IsCurrent(GLSurface* surface) override; void* GetHandle() override; - void SetSwapInterval(int interval) override; + void OnSetSwapInterval(int interval) override; std::string GetExtensions() override; std::string GetGLRenderer() override;
diff --git a/ui/gl/gl_context_wgl.cc b/ui/gl/gl_context_wgl.cc index abe47e4..2f34cd3 100644 --- a/ui/gl/gl_context_wgl.cc +++ b/ui/gl/gl_context_wgl.cc
@@ -131,7 +131,7 @@ return context_; } -void GLContextWGL::SetSwapInterval(int interval) { +void GLContextWGL::OnSetSwapInterval(int interval) { DCHECK(IsCurrent(NULL)); if (gfx::g_driver_wgl.ext.b_WGL_EXT_swap_control) { wglSwapIntervalEXT(interval);
diff --git a/ui/gl/gl_context_wgl.h b/ui/gl/gl_context_wgl.h index 13a274b..d97e568 100644 --- a/ui/gl/gl_context_wgl.h +++ b/ui/gl/gl_context_wgl.h
@@ -28,7 +28,7 @@ virtual void ReleaseCurrent(GLSurface* surface); virtual bool IsCurrent(GLSurface* surface); virtual void* GetHandle(); - virtual void SetSwapInterval(int interval); + virtual void OnSetSwapInterval(int interval); virtual std::string GetExtensions(); private:
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc index 00e224d..1d5598e 100644 --- a/ui/gl/gl_surface.cc +++ b/ui/gl/gl_surface.cc
@@ -200,6 +200,9 @@ return true; } +void GLSurface::NotifyWasBound() { +} + bool GLSurface::SetBackbufferAllocation(bool allocated) { return true; }
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h index 1351638..c218267 100644 --- a/ui/gl/gl_surface.h +++ b/ui/gl/gl_surface.h
@@ -88,6 +88,10 @@ // on error. virtual bool OnMakeCurrent(GLContext* context); + // Called when the surface is bound as the current framebuffer for the + // current context. + virtual void NotifyWasBound(); + // Used for explicit buffer management. virtual bool SetBackbufferAllocation(bool allocated); virtual void SetFrontbufferAllocation(bool allocated);
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index 936daf6..479ff69 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -58,10 +58,6 @@ // On Windows only: use the WARP software rasterizer in the GPU process. const char kUseWarp[] = "use-warp"; -// Include ANGLE's intermediate representation (AST) output in shader -// compilation info logs. -const char kGLShaderIntermOutput[] = "gl-shader-interm-output"; - // Disables GL drawing operations which produce pixel output. With this // the GL output will not be correct but tests will run faster. const char kDisableGLDrawingForTests[] = "disable-gl-drawing-for-tests"; @@ -82,7 +78,6 @@ kDisableGLDrawingForTests, kOverrideUseGLWithOSMesaForTests, kUseWarp, - kGLShaderIntermOutput }; const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches = arraysize(kGLSwitchesCopiedFromGpuProcessHost);
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h index 115ee36..ce27df0 100644 --- a/ui/gl/gl_switches.h +++ b/ui/gl/gl_switches.h
@@ -37,8 +37,6 @@ GL_EXPORT extern const char kUseGpuInTests[]; GL_EXPORT extern const char kUseWarp[]; -GL_EXPORT extern const char kGLShaderIntermOutput[]; - // These flags are used by the test harness code, not passed in by users. GL_EXPORT extern const char kDisableGLDrawingForTests[]; GL_EXPORT extern const char kOverrideUseGLWithOSMesaForTests[];