Import Cobalt 12.81256
diff --git a/src/base/base.gyp b/src/base/base.gyp
index e7e004c..d9c7764 100644
--- a/src/base/base.gyp
+++ b/src/base/base.gyp
@@ -325,7 +325,10 @@
},
],
'msvs_disabled_warnings': [
- 4800, # forcing value to bool 'true' or 'false' (performance warning)
+ # forcing value to bool 'true' or 'false' (performance warning)
+ 4800,
+ # Destructor is explicitly deleted.
+ 4624,
],
},
{
diff --git a/src/base/base.gypi b/src/base/base.gypi
index 8f39243..dc08b0c 100644
--- a/src/base/base.gypi
+++ b/src/base/base.gypi
@@ -329,9 +329,6 @@
'include_dirs': [
'<(DEPTH)',
],
- 'msvs_disabled_warnings': [
- 4018,
- ],
}],
],
},
diff --git a/src/base/file_path_unittest.cc b/src/base/file_path_unittest.cc
index b61d5d2..42f1dcb 100644
--- a/src/base/file_path_unittest.cc
+++ b/src/base/file_path_unittest.cc
@@ -1110,7 +1110,7 @@
TEST_F(FilePathTest, FromUTF8Unsafe_And_AsUTF8Unsafe) {
const struct UTF8TestData cases[] = {
{ FPL("foo.txt"), "foo.txt" },
-#if !defined(__LB_SHELL__)
+#if !defined(STARBOARD)
// "aeo" with accents. Use http://0xcc.net/jsescape/ to decode them.
{ FPL("\u00E0\u00E8\u00F2.txt"), "\xC3\xA0\xC3\xA8\xC3\xB2.txt" },
// Full-width "ABC".
diff --git a/src/base/observer_list_unittest.cc b/src/base/observer_list_unittest.cc
index baa8f3a..7e16b47 100644
--- a/src/base/observer_list_unittest.cc
+++ b/src/base/observer_list_unittest.cc
@@ -122,7 +122,7 @@
//LOG(ERROR) << "Loop 0x" << std::hex << loop_ << " done. " <<
// count_observes_ << ", " << count_addtask_;
delete loop_;
- loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
+ loop_ = reinterpret_cast<MessageLoop*>(static_cast<size_t>(0xdeadbeef));
delete this;
}
diff --git a/src/base/string_number_conversions_unittest.cc b/src/base/string_number_conversions_unittest.cc
index 0bb33b5..cec6c7c 100644
--- a/src/base/string_number_conversions_unittest.cc
+++ b/src/base/string_number_conversions_unittest.cc
@@ -36,8 +36,9 @@
#define DEFINE_INTEGRAL_TO_STRING_TEST(Name, CppType) \
{ \
static const CppType kValuesToTest[] = { \
- 0, static_cast<CppType>(-1), 42, std::numeric_limits<CppType>::min(), \
- std::numeric_limits<CppType>::max()}; \
+ 0, 1, 42, \
+ static_cast<CppType>(std::numeric_limits<CppType>::min()), \
+ static_cast<CppType>(std::numeric_limits<CppType>::max())}; \
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValuesToTest); ++i) { \
CppType value = static_cast<CppType>(kValuesToTest[i]); \
std::ostringstream oss; \
@@ -112,7 +113,7 @@
{"blah42", 0}, \
{"42blah", 42}, \
{"blah42blah", 0}, \
- {"-73.15", -73}, \
+ {"-73.15", static_cast<CppType>(-73)}, \
{"+98.6", 98}, \
{"--123", 0}, \
{"++123", 0}, \
@@ -206,14 +207,14 @@
{"7fffffff", INT_MAX, true},
{"80000000", INT_MIN, true},
{"ffffffff", -1, true},
- {"DeadBeef", 0xdeadbeef, true},
+ {"DeadBeef", static_cast<int>(0xdeadbeef), true},
{"0x42", 66, true},
{"-0x42", -66, true},
{"+0x42", 66, true},
{"0x7fffffff", INT_MAX, true},
{"0x80000000", INT_MIN, true},
{"0xffffffff", -1, true},
- {"0XDeadBeef", 0xdeadbeef, true},
+ {"0XDeadBeef", static_cast<int>(0xdeadbeef), true},
{"0x0f", 15, true},
{"0f", 15, true},
{" 45", 0x45, false},
diff --git a/src/base/third_party/nspr/prcpucfg_starboard.h b/src/base/third_party/nspr/prcpucfg_starboard.h
index 2113b0f..f443065 100644
--- a/src/base/third_party/nspr/prcpucfg_starboard.h
+++ b/src/base/third_party/nspr/prcpucfg_starboard.h
@@ -97,11 +97,24 @@
#define PR_BYTES_PER_DWORD_LOG2 3
#elif SB_IS(ARCH_X86) && SB_IS(64_BIT)
+
+#if defined(_WIN32)
+// WIN32 defines long as 4 bytes.
+#define PR_BYTES_PER_LONG 4
+#define PR_BITS_PER_LONG 32
+#define PR_BITS_PER_LONG_LOG2 5
+#define PR_ALIGN_OF_LONG 4
+#else
+#define PR_BYTES_PER_LONG 8
+#define PR_BITS_PER_LONG 64
+#define PR_BITS_PER_LONG_LOG2 6
+#define PR_ALIGN_OF_LONG 8
+#endif // defined(_WIN32)
+
#define PR_BYTES_PER_BYTE 1
#define PR_BYTES_PER_SHORT 2
#define PR_BYTES_PER_INT 4
#define PR_BYTES_PER_INT64 8
-#define PR_BYTES_PER_LONG 8
#define PR_BYTES_PER_FLOAT 4
#define PR_BYTES_PER_DOUBLE 8
#define PR_BYTES_PER_WORD 8
@@ -111,7 +124,6 @@
#define PR_BITS_PER_SHORT 16
#define PR_BITS_PER_INT 32
#define PR_BITS_PER_INT64 64
-#define PR_BITS_PER_LONG 64
#define PR_BITS_PER_FLOAT 32
#define PR_BITS_PER_DOUBLE 64
#define PR_BITS_PER_WORD 64
@@ -120,14 +132,12 @@
#define PR_BITS_PER_SHORT_LOG2 4
#define PR_BITS_PER_INT_LOG2 5
#define PR_BITS_PER_INT64_LOG2 6
-#define PR_BITS_PER_LONG_LOG2 6
#define PR_BITS_PER_FLOAT_LOG2 5
#define PR_BITS_PER_DOUBLE_LOG2 6
#define PR_BITS_PER_WORD_LOG2 6
#define PR_ALIGN_OF_SHORT 2
#define PR_ALIGN_OF_INT 4
-#define PR_ALIGN_OF_LONG 8
#define PR_ALIGN_OF_INT64 8
#define PR_ALIGN_OF_FLOAT 4
#define PR_ALIGN_OF_DOUBLE 8
diff --git a/src/build/common.gypi b/src/build/common.gypi
index c72e66b..e41bd74 100644
--- a/src/build/common.gypi
+++ b/src/build/common.gypi
@@ -53,9 +53,6 @@
# The system root for cross-compiles. Default: none.
'sysroot%': '',
- # Use libjpeg-turbo as the JPEG codec used by Chromium.
- 'use_libjpeg_turbo%': 1,
-
# Use system libjpeg. Note that the system's libjepg will be used even if
# use_libjpeg_turbo is set.
'use_system_libjpeg%': 0,
@@ -120,17 +117,12 @@
'tsan%': '<(tsan)',
'clang_type_profiler%': '<(clang_type_profiler)',
'order_profiling%': '<(order_profiling)',
- 'use_libjpeg_turbo%': '<(use_libjpeg_turbo)',
'use_system_libjpeg%': '<(use_system_libjpeg)',
'android_build_type%': '<(android_build_type)',
# Use system protobuf instead of bundled one.
'use_system_protobuf%': 0,
- # Whether proprietary audio/video codecs are assumed to be included with
- # this build (only meaningful if branding!=Chrome).
- 'proprietary_codecs%': 0,
-
# TODO(sgk): eliminate this if possible.
# It would be nicer to support this via a setting in 'target_defaults'
# in chrome/app/locales/locales.gypi overriding the setting in the
@@ -229,8 +221,6 @@
# to specify the output directory for Ant in the Android build.
'ant_build_out': '`cd <(PRODUCT_DIR) && pwd -P`',
- 'proprietary_codecs%': '<(proprietary_codecs)',
-
# Disable Native Client.
'disable_nacl%': 1,
@@ -245,13 +235,6 @@
'android_build_type%': '<(android_build_type)',
}], # target_arch=="android"
- ['use_system_libjpeg==1 or use_libjpeg_turbo==0', {
- # Configuration for using the system libjeg is here.
- 'libjpeg_gyp_path': '../third_party/libjpeg/libjpeg.gyp',
- }, {
- 'libjpeg_gyp_path': '../third_party/libjpeg_turbo/libjpeg.gyp',
- }],
-
['asan==1 and OS!="win"', {
'clang%': 1,
}],
@@ -399,9 +382,6 @@
['profiling==1', {
'defines': ['ENABLE_PROFILING=1'],
}],
- ['proprietary_codecs==1', {
- 'defines': ['USE_PROPRIETARY_CODECS'],
- }],
['dcheck_always_on!=0', {
'defines': ['DCHECK_ALWAYS_ON=1'],
}], # dcheck_always_on!=0
diff --git a/src/build/filename_rules.gypi b/src/build/filename_rules.gypi
index 6ae44dc..13b4735 100644
--- a/src/build/filename_rules.gypi
+++ b/src/build/filename_rules.gypi
@@ -41,16 +41,6 @@
['exclude', '(^|/)android/'],
],
}],
- ['OS=="lb_shell"', {
- 'sources/': [
- # Re-include things in media/audio and media/filters
- ['include', 'audio/shell_.*<(target_arch)'],
- ['include', 'filters/shell_.*<(target_arch)'],
- # Re-include things in lbshell
- ['include', 'lbshell/src/platform/<(target_arch)'],
- ['include', 'lbshell/src/platform/<(actual_target_arch)'],
- ],
- }],
['(OS=="win" and >(nacl_untrusted_build)==0) or OS=="lb_shell" or OS=="starboard"', {
'sources/': [
['exclude', '_posix(_unittest)?\\.(h|cc)$'],
diff --git a/src/cobalt/CHANGELOG.md b/src/cobalt/CHANGELOG.md
index 57b1de8..1cbd099 100644
--- a/src/cobalt/CHANGELOG.md
+++ b/src/cobalt/CHANGELOG.md
@@ -49,7 +49,9 @@
Cobalt now supports the page visibility API, and will signal visibility and
focus changes to the web app as the process transitions between Starboard
- lifecycle states.
+ lifecycle states. See the
+ new [Application Lifecycle Integration](doc/lifecycle.md) document for more
+ details.
- **Opus Support**
@@ -81,4 +83,10 @@
Decode targets with the format `kSbDecodeTargetFormat1PlaneUYVY` will now
be rendered by Cobalt. This will allow decoders that produce YUV 422 UYVY
- video frames to now efficiently support 360 video.
\ No newline at end of file
+ video frames to now efficiently support 360 video.
+
+ - **Preload Support**
+
+ Support for preloading an application with no graphics resources. See the
+ new [Application Lifecycle Integration](doc/lifecycle.md) guide for more
+ details.
diff --git a/src/cobalt/audio/audio_node_input_output_test.cc b/src/cobalt/audio/audio_node_input_output_test.cc
index 8a69ac3..d167bd9 100644
--- a/src/cobalt/audio/audio_node_input_output_test.cc
+++ b/src/cobalt/audio/audio_node_input_output_test.cc
@@ -39,6 +39,8 @@
public:
explicit AudioDestinationNodeMock(AudioContext* context)
: AudioNode(context) {
+ AudioLock::AutoLock lock(audio_lock());
+
AddInput(new AudioNodeInput(this));
}
@@ -51,6 +53,8 @@
// From AudioDevice::RenderCallback.
void FillAudioBus(ShellAudioBus* audio_bus, bool* silence) OVERRIDE {
+ AudioLock::AutoLock lock(audio_lock());
+
// Destination node only has one input.
Input(0)->FillAudioBus(audio_bus, silence);
}
@@ -61,15 +65,17 @@
scoped_array<uint8> src_data,
const AudioNodeChannelInterpretation& interpretation,
ShellAudioBus* audio_bus, bool* silence) {
- scoped_refptr<AudioBufferSourceNode> source(new AudioBufferSourceNode(NULL));
+ scoped_refptr<AudioContext> audio_context(new AudioContext());
+ scoped_refptr<AudioBufferSourceNode> source(
+ audio_context->CreateBufferSource());
scoped_refptr<AudioBuffer> buffer(
new AudioBuffer(NULL, 44100, static_cast<int32>(num_of_frames),
static_cast<int32>(num_of_src_channel), src_data.Pass(),
- GetPreferredOutputSampleType()));
+ kSampleTypeFloat32));
source->set_buffer(buffer);
scoped_refptr<AudioDestinationNodeMock> destination(
- new AudioDestinationNodeMock(NULL));
+ new AudioDestinationNodeMock(audio_context.get()));
destination->set_channel_interpretation(interpretation);
source->Connect(destination, 0, 0, NULL);
source->Start(0, 0, NULL);
@@ -77,7 +83,12 @@
destination->FillAudioBus(audio_bus, silence);
}
-TEST(AudioNodeInputOutputTest, StereoToStereoSpeakersLayoutTest) {
+class AudioNodeInputOutputTest : public ::testing::Test {
+ protected:
+ MessageLoop message_loop_;
+};
+
+TEST_F(AudioNodeInputOutputTest, StereoToStereoSpeakersLayoutTest) {
size_t num_of_src_channel = 2;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 25;
@@ -119,7 +130,7 @@
}
}
-TEST(AudioNodeInputOutputTest, StereoToStereoDiscreteLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, StereoToStereoDiscreteLayoutTest) {
size_t num_of_src_channel = 2;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 25;
@@ -161,7 +172,7 @@
}
}
-TEST(AudioNodeInputOutputTest, MonoToStereoSpeakersLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, MonoToStereoSpeakersLayoutTest) {
size_t num_of_src_channel = 1;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 25;
@@ -197,7 +208,7 @@
}
}
-TEST(AudioNodeInputOutputTest, MonoToStereoDiscreteLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, MonoToStereoDiscreteLayoutTest) {
size_t num_of_src_channel = 1;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 25;
@@ -233,7 +244,7 @@
}
}
-TEST(AudioNodeInputOutputTest, QuadToStereoSpeakersLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, QuadToStereoSpeakersLayoutTest) {
size_t num_of_src_channel = 4;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 25;
@@ -275,7 +286,7 @@
}
}
-TEST(AudioNodeInputOutputTest, QuadToStereoDiscreteLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, QuadToStereoDiscreteLayoutTest) {
size_t num_of_src_channel = 4;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 25;
@@ -317,7 +328,7 @@
}
}
-TEST(AudioNodeInputOutputTest, FivePointOneToStereoSpeakersLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, FivePointOneToStereoSpeakersLayoutTest) {
size_t num_of_src_channel = 6;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 10;
@@ -359,7 +370,7 @@
}
}
-TEST(AudioNodeInputOutputTest, FivePointOneToStereoDiscreteLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, FivePointOneToStereoDiscreteLayoutTest) {
size_t num_of_src_channel = 6;
size_t num_of_dest_channel = 2;
size_t num_of_frames = 10;
@@ -401,7 +412,7 @@
}
}
-TEST(AudioNodeInputOutputTest, StereoToMonoSpeakersLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, StereoToMonoSpeakersLayoutTest) {
size_t num_of_src_channel = 2;
size_t num_of_dest_channel = 1;
size_t num_of_frames = 25;
@@ -439,7 +450,7 @@
}
}
-TEST(AudioNodeInputOutputTest, StereoToMonoDiscreteLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, StereoToMonoDiscreteLayoutTest) {
size_t num_of_src_channel = 2;
size_t num_of_dest_channel = 1;
size_t num_of_frames = 25;
@@ -477,7 +488,7 @@
}
}
-TEST(AudioNodeInputOutputTest, QuadToMonoSpeakersLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, QuadToMonoSpeakersLayoutTest) {
size_t num_of_src_channel = 4;
size_t num_of_dest_channel = 1;
size_t num_of_frames = 25;
@@ -515,7 +526,7 @@
}
}
-TEST(AudioNodeInputOutputTest, QuadToMonoDiscreteLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, QuadToMonoDiscreteLayoutTest) {
size_t num_of_src_channel = 4;
size_t num_of_dest_channel = 1;
size_t num_of_frames = 25;
@@ -553,7 +564,7 @@
}
}
-TEST(AudioNodeInputOutputTest, FivePointOneToMonoSpeakersLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, FivePointOneToMonoSpeakersLayoutTest) {
size_t num_of_src_channel = 6;
size_t num_of_dest_channel = 1;
size_t num_of_frames = 10;
@@ -591,7 +602,7 @@
}
}
-TEST(AudioNodeInputOutputTest, FivePointOneToMonoDiscreteLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, FivePointOneToMonoDiscreteLayoutTest) {
size_t num_of_src_channel = 6;
size_t num_of_dest_channel = 1;
size_t num_of_frames = 10;
@@ -629,7 +640,9 @@
}
}
-TEST(AudioNodeInputOutputTest, MultipleInputNodesLayoutTest) {
+TEST_F(AudioNodeInputOutputTest, MultipleInputNodesLayoutTest) {
+ scoped_refptr<AudioContext> audio_context(new AudioContext());
+
size_t num_of_src_channel = 2;
size_t num_of_dest_channel = 2;
AudioNodeChannelInterpretation interpretation =
@@ -646,11 +659,11 @@
uint8* src_buffer_1 = src_data_1.get();
memcpy(src_buffer_1, src_data_in_float_1, 200 * sizeof(uint8));
scoped_refptr<AudioBufferSourceNode> source_1(
- new AudioBufferSourceNode(NULL));
+ audio_context->CreateBufferSource());
scoped_refptr<AudioBuffer> buffer_1(
new AudioBuffer(NULL, 44100, static_cast<int32>(num_of_frames_1),
static_cast<int32>(num_of_src_channel), src_data_1.Pass(),
- GetPreferredOutputSampleType()));
+ kSampleTypeFloat32));
source_1->set_buffer(buffer_1);
size_t num_of_frames_2 = 50;
@@ -664,15 +677,15 @@
uint8* src_buffer_2 = src_data_2.get();
memcpy(src_buffer_2, src_data_in_float_2, 400 * sizeof(uint8));
scoped_refptr<AudioBufferSourceNode> source_2(
- new AudioBufferSourceNode(NULL));
+ audio_context->CreateBufferSource());
scoped_refptr<AudioBuffer> buffer_2(
new AudioBuffer(NULL, 44100, static_cast<int32>(num_of_frames_2),
static_cast<int32>(num_of_src_channel), src_data_2.Pass(),
- GetPreferredOutputSampleType()));
+ kSampleTypeFloat32));
source_2->set_buffer(buffer_2);
scoped_refptr<AudioDestinationNodeMock> destination(
- new AudioDestinationNodeMock(NULL));
+ new AudioDestinationNodeMock(audio_context.get()));
destination->set_channel_interpretation(interpretation);
source_1->Connect(destination, 0, 0, NULL);
source_2->Connect(destination, 0, 0, NULL);
diff --git a/src/cobalt/base/application_state.h b/src/cobalt/base/application_state.h
index a7fbc19..b1a0a21 100644
--- a/src/cobalt/base/application_state.h
+++ b/src/cobalt/base/application_state.h
@@ -17,6 +17,8 @@
#ifndef COBALT_BASE_APPLICATION_STATE_H_
#define COBALT_BASE_APPLICATION_STATE_H_
+#include "base/logging.h"
+
namespace base {
// Application states that Cobalt can be in, as derived from Starboard lifecycle
@@ -49,6 +51,25 @@
kApplicationStateSuspended,
};
+// Returns a human-readable string for the given |state|.
+static inline const char *GetApplicationStateString(ApplicationState state) {
+ switch (state) {
+ case kApplicationStatePaused:
+ return "kApplicationStatePaused";
+ case kApplicationStatePreloading:
+ return "kApplicationStatePreloading";
+ case kApplicationStateStarted:
+ return "kApplicationStateStarted";
+ case kApplicationStateStopped:
+ return "kApplicationStateStopped";
+ case kApplicationStateSuspended:
+ return "kApplicationStateSuspended";
+ }
+
+ NOTREACHED() << "state = " << state;
+ return "INVALID_APPLICATION_STATE";
+}
+
} // namespace base
#endif // COBALT_BASE_APPLICATION_STATE_H_
diff --git a/src/cobalt/base/event_dispatcher.h b/src/cobalt/base/event_dispatcher.h
index 45179e4..a131042 100644
--- a/src/cobalt/base/event_dispatcher.h
+++ b/src/cobalt/base/event_dispatcher.h
@@ -40,11 +40,11 @@
void DispatchEvent(scoped_ptr<Event> event) const;
// Register a callback to be notified about Events of the given type.
- // May be called from any thread.
+ // May be called from any thread, but not from a dispatched event.
void AddEventCallback(TypeId type, const EventCallback& cb);
// De-register the given callback from subsequent notifications.
- // May be called from any thread.
+ // May be called from any thread, but not from a dispatched event.
void RemoveEventCallback(TypeId type, const EventCallback& cb);
private:
diff --git a/src/cobalt/base/tokens.h b/src/cobalt/base/tokens.h
index 079661b..35d8e57 100644
--- a/src/cobalt/base/tokens.h
+++ b/src/cobalt/base/tokens.h
@@ -99,6 +99,7 @@
MacroOpWithNameOnly(removals) \
MacroOpWithNameOnly(removesourcebuffer) \
MacroOpWithNameOnly(removetrack) \
+ MacroOpWithNameOnly(resize) \
MacroOpWithNameOnly(result) \
MacroOpWithNameOnly(resume) \
MacroOpWithNameOnly(securitypolicyviolation) \
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc
index 4fedd30..6f7ac05 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_indexed_getter_interface.cc
@@ -275,6 +275,11 @@
bool get_length(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsAnonymousIndexedGetterInterface::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc
index e2bbf8b..9afcce7 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_anonymous_named_indexed_getter_interface.cc
@@ -372,6 +372,11 @@
bool get_length(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc
index 34b1625..de68231 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_arbitrary_interface.cc
@@ -181,6 +181,11 @@
bool get_arbitraryProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsArbitraryInterface::PrototypeClass(context);
@@ -224,6 +229,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc
index ae10c81..954072a 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_base_interface.cc
@@ -181,6 +181,11 @@
bool get_baseAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsBaseInterface::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc
index 9eef1ad..64e9741 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_boolean_type_test_interface.cc
@@ -180,6 +180,11 @@
bool get_booleanProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsBooleanTypeTestInterface::PrototypeClass(context);
@@ -223,6 +228,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc
index d4dd89a..3cf816e 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_function_interface.cc
@@ -184,6 +184,11 @@
bool get_callbackAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsCallbackFunctionInterface::PrototypeClass(context);
@@ -227,6 +232,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -274,6 +284,11 @@
bool get_nullableCallbackAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsCallbackFunctionInterface::PrototypeClass(context);
@@ -317,6 +332,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc
index 19ff19e..c5622f7 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_callback_interface_interface.cc
@@ -184,6 +184,11 @@
bool get_callbackAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsCallbackInterfaceInterface::PrototypeClass(context);
@@ -227,6 +232,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc
index 7d8ae8d..ae18a41 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_conditional_interface.cc
@@ -183,6 +183,11 @@
bool get_enabledAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsConditionalInterface::PrototypeClass(context);
@@ -226,6 +231,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -275,6 +285,11 @@
bool get_disabledAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsConditionalInterface::PrototypeClass(context);
@@ -318,6 +333,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc
index 12749e6..cd9cc40 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constants_interface.cc
@@ -124,6 +124,11 @@
COMPILE_ASSERT(ConstantsInterface::kIntegerConstant == 5,
ValueForConstantsInterface_kIntegerConstantDoesNotMatchIDL);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
MozjsExceptionState exception_state(context);
JS::RootedValue result_value(context);
@@ -140,6 +145,11 @@
"The value for ConstantsInterface::kDoubleConstant does not match "
"the value in the interface definition.";
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
MozjsExceptionState exception_state(context);
JS::RootedValue result_value(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc
index a309c05..416a407 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_constructor_with_arguments_interface.cc
@@ -181,6 +181,11 @@
bool get_longArg(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsConstructorWithArgumentsInterface::PrototypeClass(context);
@@ -224,6 +229,11 @@
bool get_booleanArg(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsConstructorWithArgumentsInterface::PrototypeClass(context);
@@ -267,6 +277,11 @@
bool get_stringArg(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsConstructorWithArgumentsInterface::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc
index 0574f01..f855b8d 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_getter_setter_interface.cc
@@ -376,6 +376,11 @@
bool get_length(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDerivedGetterSetterInterface::PrototypeClass(context);
@@ -419,6 +424,11 @@
bool get_propertyOnDerivedClass(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDerivedGetterSetterInterface::PrototypeClass(context);
@@ -462,6 +472,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc
index 82deddc..e04680b 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_derived_interface.cc
@@ -185,6 +185,11 @@
bool get_derivedAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDerivedInterface::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc
index ac2592b..1b865a6 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dictionary_interface.cc
@@ -184,6 +184,11 @@
bool get_dictionarySequence(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDictionaryInterface::PrototypeClass(context);
@@ -227,6 +232,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc
index dba9f4e..f08fc6a 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_disabled_interface.cc
@@ -182,6 +182,11 @@
bool get_disabledProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDisabledInterface::PrototypeClass(context);
@@ -225,6 +230,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc
index f26ffc4..2f4b7f8 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_dom_string_test_interface.cc
@@ -180,6 +180,11 @@
bool get_property(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDOMStringTestInterface::PrototypeClass(context);
@@ -223,6 +228,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -270,6 +280,11 @@
bool get_readOnlyProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDOMStringTestInterface::PrototypeClass(context);
@@ -313,6 +328,11 @@
bool get_readOnlyTokenProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDOMStringTestInterface::PrototypeClass(context);
@@ -356,6 +376,11 @@
bool get_nullIsEmptyProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDOMStringTestInterface::PrototypeClass(context);
@@ -399,6 +424,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -446,6 +476,11 @@
bool get_undefinedIsEmptyProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDOMStringTestInterface::PrototypeClass(context);
@@ -489,6 +524,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -536,6 +576,11 @@
bool get_nullableUndefinedIsEmptyProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsDOMStringTestInterface::PrototypeClass(context);
@@ -579,6 +624,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc
index 1b4b7c3..299c539 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_enumeration_interface.cc
@@ -183,6 +183,11 @@
bool get_enumProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsEnumerationInterface::PrototypeClass(context);
@@ -226,6 +231,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc
index f6bb0dd..5030193 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exception_object_interface.cc
@@ -181,6 +181,11 @@
bool get_error(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsExceptionObjectInterface::PrototypeClass(context);
@@ -224,6 +229,11 @@
bool get_message(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsExceptionObjectInterface::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc
index 64559ee..8b3aff7 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_exceptions_interface.cc
@@ -181,6 +181,11 @@
bool get_attributeThrowsException(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsExceptionsInterface::PrototypeClass(context);
@@ -224,6 +229,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc
index 4789a3a..41a46d6 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_extended_idl_attributes_interface.cc
@@ -180,6 +180,11 @@
bool get_default(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsExtendedIDLAttributesInterface::PrototypeClass(context);
@@ -223,6 +228,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc
index f597106..e854293 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_garbage_collection_test_interface.cc
@@ -185,6 +185,11 @@
bool get_previous(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsGarbageCollectionTestInterface::PrototypeClass(context);
@@ -228,6 +233,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -275,6 +285,11 @@
bool get_next(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsGarbageCollectionTestInterface::PrototypeClass(context);
@@ -318,6 +333,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc
index 6effd9d..7957be4 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_indexed_getter_interface.cc
@@ -290,6 +290,11 @@
bool get_length(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsIndexedGetterInterface::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc
index 024a736..c9d71d7 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_interface_with_unsupported_properties.cc
@@ -180,6 +180,11 @@
bool get_supportedAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsInterfaceWithUnsupportedProperties::PrototypeClass(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc
index 513dd5a..3874d45 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_named_indexed_getter_interface.cc
@@ -372,6 +372,11 @@
bool get_length(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNamedIndexedGetterInterface::PrototypeClass(context);
@@ -415,6 +420,11 @@
bool get_propertyOnBaseClass(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNamedIndexedGetterInterface::PrototypeClass(context);
@@ -458,6 +468,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc
index 243e148..f73f3c5 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nested_put_forwards_interface.cc
@@ -184,6 +184,11 @@
bool get_nestedForwardingAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNestedPutForwardsInterface::PrototypeClass(context);
@@ -227,6 +232,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc
index 8e96f5a..9fc4e54 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_nullable_types_test_interface.cc
@@ -184,6 +184,11 @@
bool get_nullableBooleanProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNullableTypesTestInterface::PrototypeClass(context);
@@ -227,6 +232,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -274,6 +284,11 @@
bool get_nullableNumericProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNullableTypesTestInterface::PrototypeClass(context);
@@ -317,6 +332,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -364,6 +384,11 @@
bool get_nullableStringProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNullableTypesTestInterface::PrototypeClass(context);
@@ -407,6 +432,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -454,6 +484,11 @@
bool get_nullableObjectProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNullableTypesTestInterface::PrototypeClass(context);
@@ -497,6 +532,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc
index a06e9d8..c335147 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_numeric_types_test_interface.cc
@@ -180,6 +180,11 @@
bool get_byteProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -223,6 +228,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -270,6 +280,11 @@
bool get_byteClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -313,6 +328,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -360,6 +380,11 @@
bool get_octetProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -403,6 +428,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -450,6 +480,11 @@
bool get_octetClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -493,6 +528,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -540,6 +580,11 @@
bool get_shortProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -583,6 +628,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -630,6 +680,11 @@
bool get_shortClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -673,6 +728,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -720,6 +780,11 @@
bool get_unsignedShortProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -763,6 +828,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -810,6 +880,11 @@
bool get_unsignedShortClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -853,6 +928,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -900,6 +980,11 @@
bool get_longProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -943,6 +1028,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -990,6 +1080,11 @@
bool get_longClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1033,6 +1128,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1080,6 +1180,11 @@
bool get_unsignedLongProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1123,6 +1228,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1170,6 +1280,11 @@
bool get_unsignedLongClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1213,6 +1328,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1260,6 +1380,11 @@
bool get_longLongProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1303,6 +1428,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1350,6 +1480,11 @@
bool get_longLongClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1393,6 +1528,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1440,6 +1580,11 @@
bool get_unsignedLongLongProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1483,6 +1628,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1530,6 +1680,11 @@
bool get_unsignedLongLongClampProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1573,6 +1728,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1620,6 +1780,11 @@
bool get_doubleProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1663,6 +1828,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -1710,6 +1880,11 @@
bool get_unrestrictedDoubleProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsNumericTypesTestInterface::PrototypeClass(context);
@@ -1753,6 +1928,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc
index d80da47..af0e29b 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_object_type_bindings_interface.cc
@@ -192,6 +192,11 @@
bool get_arbitraryObject(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsObjectTypeBindingsInterface::PrototypeClass(context);
@@ -235,6 +240,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -282,6 +292,11 @@
bool get_baseInterface(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsObjectTypeBindingsInterface::PrototypeClass(context);
@@ -325,6 +340,11 @@
bool get_derivedInterface(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsObjectTypeBindingsInterface::PrototypeClass(context);
@@ -368,6 +388,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -415,6 +440,11 @@
bool get_objectProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsObjectTypeBindingsInterface::PrototypeClass(context);
@@ -458,6 +488,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc
index a4bbd60..f25d3fb 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_put_forwards_interface.cc
@@ -184,6 +184,11 @@
bool get_forwardingAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsPutForwardsInterface::PrototypeClass(context);
@@ -227,6 +232,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -287,6 +297,11 @@
MozjsExceptionState exception_state(context);
JS::RootedValue result_value(context);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
if (!exception_state.is_exception_set()) {
@@ -304,6 +319,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
MozjsExceptionState exception_state(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc
index c51a115..8526725 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_static_properties_interface.cc
@@ -186,6 +186,11 @@
MozjsExceptionState exception_state(context);
JS::RootedValue result_value(context);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
if (!exception_state.is_exception_set()) {
@@ -203,6 +208,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
MozjsExceptionState exception_state(context);
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc
index e861ff7..480fab8 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_stringifier_attribute_interface.cc
@@ -180,6 +180,11 @@
bool get_theStringifierAttribute(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsStringifierAttributeInterface::PrototypeClass(context);
@@ -223,6 +228,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc
index a9026b2..7908828 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_union_types_interface.cc
@@ -188,6 +188,11 @@
bool get_unionProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsUnionTypesInterface::PrototypeClass(context);
@@ -231,6 +236,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -278,6 +288,11 @@
bool get_unionWithNullableMemberProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsUnionTypesInterface::PrototypeClass(context);
@@ -321,6 +336,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -368,6 +388,11 @@
bool get_nullableUnionProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsUnionTypesInterface::PrototypeClass(context);
@@ -411,6 +436,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -458,6 +488,11 @@
bool get_unionBaseProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsUnionTypesInterface::PrototypeClass(context);
@@ -501,6 +536,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc
index f0b91a4..949d54e 100644
--- a/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc
+++ b/src/cobalt/bindings/generated/mozjs45/testing/cobalt/bindings/testing/mozjs_window.cc
@@ -385,6 +385,11 @@
bool get_windowProperty(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsWindow::PrototypeClass(context);
@@ -428,6 +433,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
@@ -475,6 +485,11 @@
bool get_window(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsWindow::PrototypeClass(context);
@@ -518,6 +533,11 @@
bool get_onEvent(
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
MozjsWindow::PrototypeClass(context);
@@ -561,6 +581,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
const JSClass* proto_class =
diff --git a/src/cobalt/bindings/mozjs45/templates/interface.cc.template b/src/cobalt/bindings/mozjs45/templates/interface.cc.template
index 00e5080..aa7bbf0 100644
--- a/src/cobalt/bindings/mozjs45/templates/interface.cc.template
+++ b/src/cobalt/bindings/mozjs45/templates/interface.cc.template
@@ -336,6 +336,11 @@
"the value in the interface definition.";
{% endif %}
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
MozjsExceptionState exception_state(context);
JS::RootedValue result_value(context);
@@ -416,8 +421,12 @@
{% if attribute.is_constructor_attribute %}
bool get_{{attribute.idl_name}}(
JSContext* context, unsigned argc, JS::Value* vp) {
-
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
JS::RootedObject global_object(
context, JS_GetGlobalForObject(context, object));
@@ -438,6 +447,11 @@
JSContext* context, unsigned argc, JS::Value* vp) {
{% endif %}
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
{% if not attribute.is_static %}
{{ check_if_object_implements_interface() }}
@@ -463,6 +477,11 @@
{% endif %}
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ if (!args.thisv().isObject()) {
+ MozjsExceptionState exception(context);
+ exception.SetSimpleException(script::kTypeError, "Invalid this.");
+ return false;
+ }
JS::RootedObject object(context, &args.thisv().toObject());
{% if attribute.is_static %}
diff --git a/src/cobalt/bindings/testing/getter_setter_test.cc b/src/cobalt/bindings/testing/getter_setter_test.cc
index 1db2969..137643d 100644
--- a/src/cobalt/bindings/testing/getter_setter_test.cc
+++ b/src/cobalt/bindings/testing/getter_setter_test.cc
@@ -450,6 +450,42 @@
EXPECT_STREQ("true", result.c_str());
}
+TEST_F(DerivedGetterSetterBindingsTest,
+ GetterCanHandleAllJavaScriptValueTypes) {
+ const char* script = R"EOF(
+ const getter = Object.getOwnPropertyDescriptor(
+ ArbitraryInterface.prototype, "arbitraryProperty").get;
+ [null, undefined, false, 0, "", {}, Symbol("")]
+ .map(value => {
+ try { getter.call(value); }
+ catch (ex) { return ex.toString().startsWith("TypeError"); }
+ return false;
+ })
+ .every(result => result);
+ )EOF";
+ std::string result;
+ EXPECT_TRUE(EvaluateScript(script, &result));
+ EXPECT_STREQ("true", result.c_str());
+}
+
+TEST_F(DerivedGetterSetterBindingsTest,
+ SetterCanHandleAllJavaScriptValueTypes) {
+ const char* script = R"EOF(
+ const setter = Object.getOwnPropertyDescriptor(
+ ArbitraryInterface.prototype, "arbitraryProperty").set;
+ [null, undefined, false, 0, "", {}, Symbol("")]
+ .map(value => {
+ try { setter.call(value); }
+ catch (ex) { return ex.toString().startsWith("TypeError"); }
+ return false;
+ })
+ .every(result => result);
+ )EOF";
+ std::string result;
+ EXPECT_TRUE(EvaluateScript(script, &result));
+ EXPECT_STREQ("true", result.c_str());
+}
+
} // namespace testing
} // namespace bindings
} // namespace cobalt
diff --git a/src/cobalt/bindings/testing/interface_object_test.cc b/src/cobalt/bindings/testing/interface_object_test.cc
index 19e6126..1096554 100644
--- a/src/cobalt/bindings/testing/interface_object_test.cc
+++ b/src/cobalt/bindings/testing/interface_object_test.cc
@@ -109,6 +109,22 @@
EXPECT_STREQ("false", result.c_str());
}
+TEST_F(InterfaceObjectTest, FunctionCanHandleAllJavaScriptValueTypes) {
+ const char* script = R"EOF(
+ const f = ArbitraryInterface.prototype.ArbitraryFunction;
+ [null, undefined, false, 0, "", {}, Symbol("")]
+ .map(value => {
+ try { f.call(value); }
+ catch (ex) { return ex.toString().startsWith("TypeError"); }
+ return false;
+ })
+ .every(result => result);
+ )EOF";
+ std::string result;
+ EXPECT_TRUE(EvaluateScript(script, &result));
+ EXPECT_STREQ("true", result.c_str());
+}
+
} // namespace testing
} // namespace bindings
} // namespace cobalt
diff --git a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
index f6620f0..1f2ea29 100644
--- a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
+++ b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
@@ -328,7 +328,7 @@
if (TypeParam::min_value() < 0) {
expected_result = StringPrintf("-%" PRIu64 "", kRangeBound);
EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
- .WillOnce(Return(-kRangeBound));
+ .WillOnce(Return(-static_cast<int64_t>(kRangeBound)));
EXPECT_TRUE(this->EvaluateScript(script, &result));
EXPECT_STREQ(expected_result.c_str(), result.c_str());
}
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 4948758..3d88ac6 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -29,6 +29,7 @@
#include "base/string_util.h"
#include "base/time.h"
#include "build/build_config.h"
+#include "cobalt/base/accessibility_settings_changed_event.h"
#include "cobalt/base/application_event.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/base/deep_link_event.h"
@@ -47,16 +48,10 @@
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
#include "cobalt/storage/savegame_fake.h"
#endif
+#include "cobalt/system_window/input_event.h"
#include "cobalt/trace_event/scoped_trace_to_file.h"
#include "googleurl/src/gurl.h"
-#if defined(__LB_SHELL__)
-#if !defined(__LB_SHELL__FOR_RELEASE__)
-#include "lbshell/src/lb_memory_manager.h"
-#endif // defined(__LB_SHELL__FOR_RELEASE__)
-#include "lbshell/src/lb_memory_pages.h"
-#endif // defined(__LB_SHELL__)
#include "starboard/configuration.h"
-#include "starboard/log.h"
namespace cobalt {
namespace browser {
@@ -606,11 +601,6 @@
base::Bind(&Application::OnNetworkEvent, base::Unretained(this));
event_dispatcher_.AddEventCallback(network::NetworkEvent::TypeId(),
network_event_callback_);
- application_event_callback_ =
- base::Bind(&Application::OnApplicationEvent, base::Unretained(this));
- event_dispatcher_.AddEventCallback(base::ApplicationEvent::TypeId(),
- application_event_callback_);
-
deep_link_event_callback_ =
base::Bind(&Application::OnDeepLinkEvent, base::Unretained(this));
event_dispatcher_.AddEventCallback(base::DeepLinkEvent::TypeId(),
@@ -666,8 +656,6 @@
// Unregister event callbacks.
event_dispatcher_.RemoveEventCallback(network::NetworkEvent::TypeId(),
network_event_callback_);
- event_dispatcher_.RemoveEventCallback(base::ApplicationEvent::TypeId(),
- application_event_callback_);
event_dispatcher_.RemoveEventCallback(
base::DeepLinkEvent::TypeId(), deep_link_event_callback_);
@@ -686,9 +674,7 @@
return;
}
- event_dispatcher_.DispatchEvent(make_scoped_ptr<base::Event>(
- new base::ApplicationEvent(kSbEventTypeStart)));
- app_status_ = kRunningAppStatus;
+ OnApplicationEvent(kSbEventTypeStart);
}
void Application::Quit() {
@@ -706,6 +692,47 @@
app_status_ = kQuitAppStatus;
}
+void Application::HandleStarboardEvent(const SbEvent* starboard_event) {
+ DCHECK(starboard_event);
+
+ // Forward input events to |SystemWindow|.
+ if (starboard_event->type == kSbEventTypeInput) {
+ system_window::HandleInputEvent(starboard_event);
+ return;
+ }
+
+ // Create a Cobalt event from the Starboard event, if recognized.
+ switch (starboard_event->type) {
+ case kSbEventTypePause:
+ case kSbEventTypeUnpause:
+ case kSbEventTypeSuspend:
+ case kSbEventTypeResume:
+ OnApplicationEvent(starboard_event->type);
+ break;
+ case kSbEventTypeNetworkConnect:
+ DispatchEventInternal(
+ new network::NetworkEvent(network::NetworkEvent::kConnection));
+ break;
+ case kSbEventTypeNetworkDisconnect:
+ DispatchEventInternal(
+ new network::NetworkEvent(network::NetworkEvent::kDisconnection));
+ break;
+ case kSbEventTypeLink: {
+ const char* link = static_cast<const char*>(starboard_event->data);
+ DispatchEventInternal(new base::DeepLinkEvent(link));
+ break;
+ }
+#if SB_API_VERSION >= 4
+ case kSbEventTypeAccessiblitySettingsChanged:
+ DispatchEventInternal(new base::AccessibilitySettingsChangedEvent());
+ break;
+#endif // SB_API_VERSION >= 4
+ default:
+ DLOG(WARNING) << "Unhandled Starboard event of type: "
+ << starboard_event->type;
+ }
+}
+
void Application::OnNetworkEvent(const base::Event* event) {
TRACE_EVENT0("cobalt::browser", "Application::OnNetworkEvent()");
DCHECK(network_event_thread_checker_.CalledOnValidThread());
@@ -727,37 +754,53 @@
}
}
-void Application::OnApplicationEvent(const base::Event* event) {
+void Application::OnApplicationEvent(SbEventType event_type) {
TRACE_EVENT0("cobalt::browser", "Application::OnApplicationEvent()");
DCHECK(application_event_thread_checker_.CalledOnValidThread());
- const base::ApplicationEvent* app_event =
- base::polymorphic_downcast<const base::ApplicationEvent*>(event);
- if (app_event->type() == kSbEventTypeStop) {
- DLOG(INFO) << "Got quit event.";
- app_status_ = kWillQuitAppStatus;
- Quit();
- } else if (app_event->type() == kSbEventTypePause) {
- DLOG(INFO) << "Got pause event.";
- app_status_ = kPausedAppStatus;
- ++app_pause_count_;
- browser_module_->Pause();
- } else if (app_event->type() == kSbEventTypeUnpause) {
- DLOG(INFO) << "Got unpause event.";
- app_status_ = kRunningAppStatus;
- ++app_unpause_count_;
- browser_module_->Unpause();
- } else if (app_event->type() == kSbEventTypeSuspend) {
- DLOG(INFO) << "Got suspend event.";
- app_status_ = kSuspendedAppStatus;
- ++app_suspend_count_;
- browser_module_->Suspend();
- DLOG(INFO) << "Finished suspending.";
- } else if (app_event->type() == kSbEventTypeResume) {
- DLOG(INFO) << "Got resume event.";
- app_status_ = kPausedAppStatus;
- ++app_resume_count_;
- browser_module_->Resume();
- DLOG(INFO) << "Finished resuming.";
+ switch (event_type) {
+ case kSbEventTypeStop:
+ DLOG(INFO) << "Got quit event.";
+ app_status_ = kWillQuitAppStatus;
+ Quit();
+ DLOG(INFO) << "Finished quitting.";
+ break;
+ case kSbEventTypeStart:
+ DLOG(INFO) << "Got start event.";
+ app_status_ = kRunningAppStatus;
+ browser_module_->Start();
+ DLOG(INFO) << "Finished starting.";
+ break;
+ case kSbEventTypePause:
+ DLOG(INFO) << "Got pause event.";
+ app_status_ = kPausedAppStatus;
+ ++app_pause_count_;
+ browser_module_->Pause();
+ DLOG(INFO) << "Finished pausing.";
+ break;
+ case kSbEventTypeUnpause:
+ DLOG(INFO) << "Got unpause event.";
+ app_status_ = kRunningAppStatus;
+ ++app_unpause_count_;
+ browser_module_->Unpause();
+ DLOG(INFO) << "Finished unpausing.";
+ break;
+ case kSbEventTypeSuspend:
+ DLOG(INFO) << "Got suspend event.";
+ app_status_ = kSuspendedAppStatus;
+ ++app_suspend_count_;
+ browser_module_->Suspend();
+ DLOG(INFO) << "Finished suspending.";
+ break;
+ case kSbEventTypeResume:
+ DLOG(INFO) << "Got resume event.";
+ app_status_ = kPausedAppStatus;
+ ++app_resume_count_;
+ browser_module_->Resume();
+ DLOG(INFO) << "Finished resuming.";
+ break;
+ default:
+ NOTREACHED() << "Unexpected event type: " << event_type;
+ return;
}
}
@@ -877,5 +920,9 @@
browser_module_->CheckMemory(used_cpu_memory, used_gpu_memory);
}
+void Application::DispatchEventInternal(base::Event* event) {
+ event_dispatcher_.DispatchEvent(make_scoped_ptr<base::Event>(event));
+}
+
} // namespace browser
} // namespace cobalt
diff --git a/src/cobalt/browser/application.h b/src/cobalt/browser/application.h
index a8a5597..ab3ce08 100644
--- a/src/cobalt/browser/application.h
+++ b/src/cobalt/browser/application.h
@@ -24,6 +24,7 @@
#include "cobalt/browser/browser_module.h"
#include "cobalt/browser/memory_tracker/tool.h"
#include "cobalt/system_window/system_window.h"
+#include "starboard/event.h"
#if defined(ENABLE_WEBDRIVER)
#include "cobalt/webdriver/web_driver_module.h"
@@ -36,21 +37,21 @@
namespace cobalt {
namespace browser {
-// The Application base class is meant to manage the main thread's UI
-// message loop. A platform-specific application will be created via
-// CreateApplication(). This class and all of its subclasses are not designed
-// to be thread safe.
+// The Application class is meant to manage the main thread's UI message
+// loop. This class is not designed to be thread safe.
class Application {
public:
+ // The passed in |quit_closure| can be called internally by the Application to
+ // signal that it would like to quit.
+ Application(const base::Closure& quit_closure, bool should_preload);
virtual ~Application();
// Start from a preloaded state.
void Start();
void Quit();
+ void HandleStarboardEvent(const SbEvent* event);
protected:
- Application(const base::Closure& quit_closure, bool should_preload);
-
MessageLoop* message_loop() { return message_loop_; }
private:
@@ -64,7 +65,7 @@
void OnNetworkEvent(const base::Event* event);
// Called to handle an application event.
- void OnApplicationEvent(const base::Event* event);
+ void OnApplicationEvent(SbEventType event_type);
// Called to handle a deep link event.
void OnDeepLinkEvent(const base::Event* event);
@@ -83,7 +84,6 @@
// Event callbacks.
base::EventCallback network_event_callback_;
- base::EventCallback application_event_callback_;
base::EventCallback deep_link_event_callback_;
// Thread checkers to ensure that callbacks for network and application events
@@ -113,6 +113,7 @@
kQuitAppStatus,
kShutDownAppStatus,
};
+
enum NetworkStatus {
kDisconnectedNetworkStatus,
kConnectedNetworkStatus,
@@ -144,8 +145,8 @@
void RegisterUserLogs();
void UpdateAndMaybeRegisterUserAgent();
-
void UpdatePeriodicStats();
+ void DispatchEventInternal(base::Event* event);
static ssize_t available_memory_;
static int64 lifetime_in_ms_;
@@ -167,16 +168,6 @@
scoped_ptr<memory_tracker::Tool> memory_tracker_tool_;
};
-// Factory method for creating a started application. The passed in
-// |quit_closure| can be called internally by the application to signal that it
-// would like to quit.
-scoped_ptr<Application> CreateApplication(const base::Closure& quit_closure);
-
-// Factory method for creating a preloading application. The passed in
-// |quit_closure| can be called internally by the application to signal that it
-// would like to quit.
-scoped_ptr<Application> PreloadApplication(const base::Closure& quit_closure);
-
} // namespace browser
} // namespace cobalt
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index 015dd40..d744b06 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -182,43 +182,6 @@
return options; // Copy.
}
-void ApplyAutoMemSettings(const memory_settings::AutoMem& auto_mem,
- BrowserModule::Options* options) {
- SB_LOG(INFO) << "\n\n"
- << auto_mem.ToPrettyPrintString(SbLogIsTty()) << "\n\n";
-
- options->web_module_options.image_cache_capacity =
- static_cast<int>(auto_mem.image_cache_size_in_bytes()->value());
-
- options->renderer_module_options.skia_cache_size_in_bytes =
- static_cast<int>(auto_mem.skia_cache_size_in_bytes()->value());
-
- const memory_settings::TextureDimensions skia_glyph_atlas_texture_dimensions =
- auto_mem.skia_atlas_texture_dimensions()->value();
-
- // Right now the bytes_per_pixel is assumed in the engine. Any other value
- // is currently forbidden.
- if (skia_glyph_atlas_texture_dimensions.bytes_per_pixel() > 0) {
- DCHECK_EQ(2, skia_glyph_atlas_texture_dimensions.bytes_per_pixel());
- options->renderer_module_options.skia_glyph_texture_atlas_dimensions =
- math::Size(skia_glyph_atlas_texture_dimensions.width(),
- skia_glyph_atlas_texture_dimensions.height());
- }
-
- options->web_module_options.remote_typeface_cache_capacity =
- static_cast<int>(auto_mem.remote_typeface_cache_size_in_bytes()->value());
-
- options->web_module_options.javascript_options.gc_threshold_bytes =
- static_cast<size_t>(auto_mem.javascript_gc_threshold_in_bytes()->value());
-
- options->renderer_module_options.software_surface_cache_size_in_bytes =
- static_cast<int>(
- auto_mem.software_surface_cache_size_in_bytes()->value());
- options->renderer_module_options.offscreen_target_cache_size_in_bytes =
- static_cast<int>(
- auto_mem.offscreen_target_cache_size_in_bytes()->value());
-}
-
} // namespace
BrowserModule::BrowserModule(const GURL& url,
@@ -321,6 +284,13 @@
if (application_state_ == base::kApplicationStateStarted ||
application_state_ == base::kApplicationStatePaused) {
InitializeSystemWindow();
+ } else if (application_state_ == base::kApplicationStatePreloading) {
+#if defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
+ // Preloading is not supported on platforms that allocate ArrayBuffers on
+ // GPU memory.
+ NOTREACHED();
+#endif // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
+ resource_provider_stub_.emplace(true /*allocate_image_data*/);
}
#if defined(ENABLE_DEBUG_CONSOLE)
@@ -527,7 +497,8 @@
const browser::WebModule::LayoutResults& layout_results) {
TRACE_EVENT0("cobalt::browser", "BrowserModule::OnRenderTreeProduced()");
DCHECK_EQ(MessageLoop::current(), self_message_loop_);
- if (!render_tree_combiner_) {
+ if (application_state_ == base::kApplicationStatePreloading ||
+ !render_tree_combiner_) {
return;
}
@@ -634,7 +605,8 @@
TRACE_EVENT0("cobalt::browser",
"BrowserModule::OnDebugConsoleRenderTreeProduced()");
DCHECK_EQ(MessageLoop::current(), self_message_loop_);
- if (!render_tree_combiner_) {
+ if (application_state_ == base::kApplicationStatePreloading ||
+ !render_tree_combiner_) {
return;
}
@@ -874,9 +846,10 @@
void BrowserModule::Start() {
TRACE_EVENT0("cobalt::browser", "BrowserModule::Start()");
DCHECK(application_state_ == base::kApplicationStatePreloading);
- render_tree::ResourceProvider* resource_provider = GetResourceProvider();
- FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_,
- Start(resource_provider));
+
+ SuspendInternal(true /*is_start*/);
+ StartOrResumeInternal(true /*is_start*/);
+
application_state_ = base::kApplicationStateStarted;
}
@@ -896,52 +869,10 @@
void BrowserModule::Suspend() {
TRACE_EVENT0("cobalt::browser", "BrowserModule::Suspend()");
- DCHECK(application_state_ == base::kApplicationStatePaused);
+ DCHECK(application_state_ == base::kApplicationStatePaused ||
+ application_state_ == base::kApplicationStatePreloading);
- // First suspend all our web modules which implies that they will release
- // their resource provider and all resources created through it.
- FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_, Suspend());
-
- // Flush out any submitted render trees pushed since we started shutting down
- // the web modules above.
- render_tree_submission_queue_.ProcessAll();
-
-#if defined(ENABLE_SCREENSHOT)
- // The screenshot writer may be holding on to a reference to a render tree
- // which could in turn be referencing resources like images, so clear that
- // out.
- if (screen_shot_writer_) {
- screen_shot_writer_->ClearLastPipelineSubmission();
- }
-#endif
-
- // Clear out the render tree combiner so that it doesn't hold on to any
- // render tree resources either.
- if (render_tree_combiner_) {
- render_tree_combiner_->Reset();
- }
-
-#if defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
- // Note that the following function call will leak the GPU memory allocated.
- // This is because after renderer_module_->Suspend() is called it is no longer
- // safe to release the GPU memory allocated.
- //
- // The following code can call reset() to release the allocated memory but the
- // memory may still be used by XHR and ArrayBuffer. As this feature is only
- // used on platform without Resume() support, it is safer to leak the memory
- // then to release it.
- dom::ArrayBuffer::Allocator* allocator = array_buffer_allocator_.release();
-#endif // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
-
- if (media_module_) {
- media_module_->Suspend();
- }
-
- if (renderer_module_) {
- // Place the renderer module into a suspended state where it releases all
- // its graphical resources.
- renderer_module_->Suspend();
- }
+ SuspendInternal(false /*is_start*/);
application_state_ = base::kApplicationStateSuspended;
}
@@ -950,23 +881,7 @@
TRACE_EVENT0("cobalt::browser", "BrowserModule::Resume()");
DCHECK(application_state_ == base::kApplicationStateSuspended);
- renderer_module_->Resume();
-
- // Note that at this point, it is probable that this resource provider is
- // different than the one that was managed in the associated call to
- // Suspend().
- render_tree::ResourceProvider* resource_provider = GetResourceProvider();
-
- media_module_->Resume(resource_provider);
-
-#if defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
- // Resume() is not supported on platforms that allocates ArrayBuffer on GPU
- // memory.
- NOTREACHED();
-#endif // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
-
- FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_,
- Resume(resource_provider));
+ StartOrResumeInternal(false /*is_start*/);
application_state_ = base::kApplicationStatePaused;
}
@@ -974,6 +889,10 @@
void BrowserModule::CheckMemory(
const int64_t& used_cpu_memory,
const base::optional<int64_t>& used_gpu_memory) {
+ if (!auto_mem_) {
+ return;
+ }
+
memory_settings_checker_.RunChecks(*auto_mem_, used_cpu_memory,
used_gpu_memory);
}
@@ -1039,6 +958,11 @@
render_tree::ResourceProvider* BrowserModule::GetResourceProvider() {
if (!renderer_module_) {
+ if (resource_provider_stub_) {
+ DCHECK(application_state_ == base::kApplicationStatePreloading);
+ return &(resource_provider_stub_.value());
+ }
+
return NULL;
}
@@ -1046,13 +970,14 @@
}
void BrowserModule::InitializeSystemWindow() {
+ resource_provider_stub_ = base::nullopt;
system_window_.reset(new system_window::SystemWindow(
event_dispatcher_, options_.requested_viewport_size));
auto_mem_.reset(new memory_settings::AutoMem(
GetViewportSize(), options_.command_line_auto_mem_settings,
options_.build_auto_mem_settings));
- ApplyAutoMemSettings(*auto_mem_, &options_);
+ ApplyAutoMemSettings();
input_device_manager_ = input::InputDeviceManager::CreateFromWindow(
base::Bind(&BrowserModule::OnKeyEventProduced,
@@ -1079,7 +1004,8 @@
#if defined(ENABLE_SCREENSHOT)
screen_shot_writer_.reset(new ScreenShotWriter(renderer_module_->pipeline()));
#endif // defined(ENABLE_SCREENSHOT)
- // TODO: Pass in dialog closure instead of system window.
+ // TODO: Pass in dialog closure instead of system window, and initialize
+ // earlier.
h5vcc_url_handler_.reset(new H5vccURLHandler(this, system_window_.get()));
media_module_ =
@@ -1087,6 +1013,113 @@
options_.media_module_options);
}
+void BrowserModule::UpdateFromSystemWindow() {
+ math::Size size = GetViewportSize();
+ float video_pixel_ratio = system_window_->GetVideoPixelRatio();
+#if defined(ENABLE_DEBUG_CONSOLE)
+ if (debug_console_) {
+ debug_console_->SetSize(size, video_pixel_ratio);
+ }
+#endif // defined(ENABLE_DEBUG_CONSOLE)
+
+ if (splash_screen_) {
+ splash_screen_->SetSize(size, video_pixel_ratio);
+ }
+
+ if (web_module_) {
+ web_module_->SetCamera3D(input_device_manager_->camera_3d());
+ web_module_->SetMediaModule(media_module_.get());
+ web_module_->SetSize(size, video_pixel_ratio);
+ }
+}
+
+void BrowserModule::SuspendInternal(bool is_start) {
+ TRACE_EVENT1("cobalt::browser", "BrowserModule::SuspendInternal", "is_start",
+ is_start ? "true" : "false");
+ // First suspend all our web modules which implies that they will release
+ // their resource provider and all resources created through it.
+ if (is_start) {
+ FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_, Prestart());
+ } else {
+ FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_, Suspend());
+ }
+
+ // Flush out any submitted render trees pushed since we started shutting down
+ // the web modules above.
+ render_tree_submission_queue_.ProcessAll();
+
+#if defined(ENABLE_SCREENSHOT)
+ // The screenshot writer may be holding on to a reference to a render tree
+ // which could in turn be referencing resources like images, so clear that
+ // out.
+ if (screen_shot_writer_) {
+ screen_shot_writer_->ClearLastPipelineSubmission();
+ }
+#endif
+
+ // Clear out the render tree combiner so that it doesn't hold on to any
+ // render tree resources either.
+ if (render_tree_combiner_) {
+ render_tree_combiner_->Reset();
+ }
+
+#if defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
+ // Note that the following function call will leak the GPU memory allocated.
+ // This is because after renderer_module_->Suspend() is called it is no longer
+ // safe to release the GPU memory allocated.
+ //
+ // The following code can call reset() to release the allocated memory but the
+ // memory may still be used by XHR and ArrayBuffer. As this feature is only
+ // used on platform without Resume() support, it is safer to leak the memory
+ // then to release it.
+ dom::ArrayBuffer::Allocator* allocator = array_buffer_allocator_.release();
+#endif // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
+
+ if (media_module_) {
+ media_module_->Suspend();
+ }
+
+ if (renderer_module_) {
+ // Place the renderer module into a suspended state where it releases all
+ // its graphical resources.
+ renderer_module_->Suspend();
+ }
+}
+
+void BrowserModule::StartOrResumeInternal(bool is_start) {
+ TRACE_EVENT1("cobalt::browser", "BrowserModule::StartOrResumeInternal",
+ "is_start", is_start ? "true" : "false");
+ render_tree::ResourceProvider* resource_provider = NULL;
+ if (!renderer_module_) {
+ InitializeSystemWindow();
+ UpdateFromSystemWindow();
+ resource_provider = GetResourceProvider();
+ } else {
+ renderer_module_->Resume();
+
+ // Note that at this point, it is probable that this resource provider is
+ // different than the one that was managed in the associated call to
+ // Suspend().
+ resource_provider = GetResourceProvider();
+
+ media_module_->Resume(resource_provider);
+ }
+
+#if defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
+ // Start() and Resume() are not supported on platforms that allocate
+ // ArrayBuffers in GPU memory.
+ NOTREACHED();
+#endif // defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
+
+ if (is_start) {
+ FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_,
+ Start(resource_provider));
+ } else {
+ FOR_EACH_OBSERVER(LifecycleObserver, lifecycle_observers_,
+ Resume(resource_provider));
+ }
+}
+
math::Size BrowserModule::GetViewportSize() {
// We trust the renderer module the most, if it exists.
if (renderer_module_) {
@@ -1111,5 +1144,48 @@
return math::Size(1280, 720);
}
+void BrowserModule::ApplyAutoMemSettings() {
+ LOG(INFO) << "\n\n" << auto_mem_->ToPrettyPrintString(SbLogIsTty()) << "\n\n";
+
+ // Web Module options.
+ options_.web_module_options.image_cache_capacity =
+ static_cast<int>(auto_mem_->image_cache_size_in_bytes()->value());
+ options_.web_module_options.remote_typeface_cache_capacity = static_cast<int>(
+ auto_mem_->remote_typeface_cache_size_in_bytes()->value());
+ options_.web_module_options.javascript_options.gc_threshold_bytes =
+ static_cast<size_t>(
+ auto_mem_->javascript_gc_threshold_in_bytes()->value());
+ if (web_module_) {
+ web_module_->SetImageCacheCapacity(
+ auto_mem_->image_cache_size_in_bytes()->value());
+ web_module_->SetRemoteTypefaceCacheCapacity(
+ auto_mem_->remote_typeface_cache_size_in_bytes()->value());
+ web_module_->SetJavascriptGcThreshold(
+ auto_mem_->javascript_gc_threshold_in_bytes()->value());
+ }
+
+ // Renderer Module options.
+ options_.renderer_module_options.skia_cache_size_in_bytes =
+ static_cast<int>(auto_mem_->skia_cache_size_in_bytes()->value());
+ options_.renderer_module_options.software_surface_cache_size_in_bytes =
+ static_cast<int>(
+ auto_mem_->software_surface_cache_size_in_bytes()->value());
+ options_.renderer_module_options.offscreen_target_cache_size_in_bytes =
+ static_cast<int>(
+ auto_mem_->offscreen_target_cache_size_in_bytes()->value());
+
+ const memory_settings::TextureDimensions skia_glyph_atlas_texture_dimensions =
+ auto_mem_->skia_atlas_texture_dimensions()->value();
+ if (skia_glyph_atlas_texture_dimensions.bytes_per_pixel() > 0) {
+ // Right now the bytes_per_pixel is assumed in the engine. Any other value
+ // is currently forbidden.
+ DCHECK_EQ(2, skia_glyph_atlas_texture_dimensions.bytes_per_pixel());
+
+ options_.renderer_module_options.skia_glyph_texture_atlas_dimensions =
+ math::Size(skia_glyph_atlas_texture_dimensions.width(),
+ skia_glyph_atlas_texture_dimensions.height());
+ }
+}
+
} // namespace browser
} // namespace cobalt
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index 066aa04..fcba62b 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -43,6 +43,8 @@
#include "cobalt/input/input_device_manager.h"
#include "cobalt/layout/layout_manager.h"
#include "cobalt/network/network_module.h"
+#include "cobalt/render_tree/resource_provider.h"
+#include "cobalt/render_tree/resource_provider_stub.h"
#include "cobalt/renderer/renderer_module.h"
#include "cobalt/storage/storage_manager.h"
#include "cobalt/system_window/system_window.h"
@@ -268,6 +270,16 @@
// Initializes the system window, and all components that require it.
void InitializeSystemWindow();
+ // Updates all components that have already been created with information
+ // resulting from the creation of the system window.
+ void UpdateFromSystemWindow();
+
+ // Does all the steps for either a Suspend or the first half of a Start.
+ void SuspendInternal(bool is_start);
+
+ // Does all the steps for either a Resume or the second half of a Start.
+ void StartOrResumeInternal(bool is_start);
+
// Gets a viewport size to use for now. This may change depending on the
// current application state. While preloading, this returns the requested
// viewport size. If there was no requested viewport size, it returns a
@@ -275,6 +287,9 @@
// it returns the confirmed size of the window.
math::Size GetViewportSize();
+ // Applies the current AutoMem settings to all applicable submodules.
+ void ApplyAutoMemSettings();
+
// TODO:
// WeakPtr usage here can be avoided if BrowserModule has a thread to
// own where it can ensure that its tasks are all resolved when it is
@@ -326,6 +341,10 @@
// display and graphics context to the rasterizer and rendering pipeline.
scoped_ptr<renderer::RendererModule> renderer_module_;
+ // A stub implementation of ResourceProvider that can be used until a real
+ // ResourceProvider is created. Only valid in the Preloading state.
+ base::optional<render_tree::ResourceProviderStub> resource_provider_stub_;
+
// Optional memory allocator used by ArrayBuffer.
scoped_ptr<dom::ArrayBuffer::Allocator> array_buffer_allocator_;
diff --git a/src/cobalt/browser/cobalt.gyp b/src/cobalt/browser/cobalt.gyp
index d2d2f29..473f353 100644
--- a/src/cobalt/browser/cobalt.gyp
+++ b/src/cobalt/browser/cobalt.gyp
@@ -20,30 +20,23 @@
{
'target_name': 'cobalt',
'type': '<(final_executable_type)',
+ 'dependencies': [
+ '<(DEPTH)/cobalt/browser/browser.gyp:browser',
+ ],
'conditions': [
['cobalt_enable_lib == 1', {
- 'sources': ['lib/main.cc',],
- 'all_dependent_settings': {
- 'target_conditions': [
- ['_type=="executable" and _toolset=="target"', {
- 'sources': [
- 'lib/imported/main_stub.cc',
- ],
- }],
- ],
- },
+ 'sources': ['lib/main.cc',],
+ 'all_dependent_settings': {
+ 'target_conditions': [
+ ['_type=="executable" and _toolset=="target"', {
+ 'sources': [
+ 'lib/imported/main_stub.cc',
+ ],
+ }],
+ ],
+ },
}, {
- 'sources': ['main.cc',],
- }],
- ['OS=="lb_shell"', {
- 'dependencies': [
- '<(DEPTH)/cobalt/browser/<(actual_target_arch)/platform_browser.gyp:platform_browser',
- ],
- }],
- ['OS=="starboard"', {
- 'dependencies': [
- '<(DEPTH)/cobalt/browser/starboard/platform_browser.gyp:platform_browser',
- ],
+ 'sources': ['main.cc',],
}],
['cobalt_copy_test_data == 1', {
'dependencies': [
@@ -78,18 +71,7 @@
],
'dependencies': [
'cobalt',
- ],
- 'conditions': [
- ['OS=="lb_shell"', {
- 'dependencies': [
- '<(DEPTH)/cobalt/browser/<(actual_target_arch)/platform_browser.gyp:platform_browser',
- ],
- }],
- ['OS=="starboard"', {
- 'dependencies': [
- '<(DEPTH)/cobalt/browser/starboard/platform_browser.gyp:platform_browser',
- ],
- }],
+ '<(DEPTH)/cobalt/browser/browser.gyp:browser',
],
},
{
diff --git a/src/cobalt/browser/debug_console.h b/src/cobalt/browser/debug_console.h
index 3782f40..9ecbef5 100644
--- a/src/cobalt/browser/debug_console.h
+++ b/src/cobalt/browser/debug_console.h
@@ -63,7 +63,12 @@
// Returns the currently set debug console visibility mode.
int GetMode();
+ void SetSize(const math::Size& window_dimensions, float video_pixel_ratio) {
+ web_module_->SetSize(window_dimensions, video_pixel_ratio);
+ }
+
// LifecycleObserver implementation.
+ void Prestart() OVERRIDE { web_module_->Prestart(); }
void Start(render_tree::ResourceProvider* resource_provider) OVERRIDE {
web_module_->Start(resource_provider);
}
diff --git a/src/cobalt/browser/lib/main.cc b/src/cobalt/browser/lib/main.cc
index 5d0fb44..13657ee 100644
--- a/src/cobalt/browser/lib/main.cc
+++ b/src/cobalt/browser/lib/main.cc
@@ -17,7 +17,6 @@
#include "cobalt/base/wrap_main.h"
#include "cobalt/browser/application.h"
#include "cobalt/browser/lib/imported/main.h"
-#include "cobalt/browser/starboard/event_handler.h"
#include "starboard/event.h"
#include "starboard/input.h"
@@ -25,11 +24,24 @@
cobalt::browser::Application* g_application = NULL;
+void PreloadApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
+ const base::Closure& quit_closure) {
+ DCHECK(!g_application);
+ g_application =
+ new cobalt::browser::Application(quit_closure, true /*should_preload*/);
+ DCHECK(g_application);
+}
+
void StartApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
const base::Closure& quit_closure) {
- DCHECK(!g_application);
LOG(INFO) << "Starting application!";
- g_application = cobalt::browser::CreateApplication(quit_closure).release();
+ if (!g_application) {
+ g_application = new cobalt::browser::Application(quit_closure,
+ false /*should_preload*/);
+ DCHECK(g_application);
+ } else {
+ g_application->Start();
+ }
DCHECK(g_application);
CbLibOnCobaltInitialized();
}
@@ -41,14 +53,15 @@
g_application = NULL;
}
-void HandleEvent(const SbEvent* starboard_event) {
+void HandleStarboardEvent(const SbEvent* starboard_event) {
+ DCHECK(starboard_event);
if (!CbLibHandleEvent(starboard_event)) {
- cobalt::browser::EventHandler::HandleEvent(starboard_event);
+ DCHECK(g_application);
+ g_application->HandleStarboardEvent(starboard_event);
}
}
} // namespace
-COBALT_WRAP_EVENT_MAIN(StartApplication,
- HandleEvent,
- StopApplication);
+COBALT_WRAP_MAIN(PreloadApplication, StartApplication, HandleStarboardEvent,
+ StopApplication);
diff --git a/src/cobalt/browser/lifecycle_observer.h b/src/cobalt/browser/lifecycle_observer.h
index fb69e9e..2e1b1ec 100644
--- a/src/cobalt/browser/lifecycle_observer.h
+++ b/src/cobalt/browser/lifecycle_observer.h
@@ -24,6 +24,9 @@
// A pure virtual interface for observers of the application lifecycle.
class LifecycleObserver {
public:
+ // Sent before sending Start when transitioning from Preloading to Started.
+ virtual void Prestart() = 0;
+
// Start running visibly with the given graphics ResourceProvider, loading if
// necessary. This represents a transition from Preloading to Started, so it
// only makes sense if the object is in the Preloading state.
diff --git a/src/cobalt/browser/main.cc b/src/cobalt/browser/main.cc
index f237b47..f97546e 100644
--- a/src/cobalt/browser/main.cc
+++ b/src/cobalt/browser/main.cc
@@ -16,9 +16,6 @@
#include "base/logging.h"
#include "cobalt/base/wrap_main.h"
#include "cobalt/browser/application.h"
-#if defined(OS_STARBOARD)
-#include "cobalt/browser/starboard/event_handler.h"
-#endif
namespace {
@@ -27,19 +24,20 @@
void PreloadApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
const base::Closure& quit_closure) {
DCHECK(!g_application);
- g_application = cobalt::browser::PreloadApplication(quit_closure).release();
+ g_application =
+ new cobalt::browser::Application(quit_closure, true /*should_preload*/);
DCHECK(g_application);
}
void StartApplication(int /*argc*/, char** /*argv*/, const char* /*link*/,
const base::Closure& quit_closure) {
if (!g_application) {
- g_application = cobalt::browser::CreateApplication(quit_closure).release();
+ g_application = new cobalt::browser::Application(quit_closure,
+ false /*should_preload*/);
+ DCHECK(g_application);
} else {
g_application->Start();
}
-
- DCHECK(g_application);
}
void StopApplication() {
@@ -48,11 +46,17 @@
g_application = NULL;
}
+void HandleStarboardEvent(const SbEvent* starboard_event) {
+ DCHECK(starboard_event);
+ DCHECK(g_application);
+ g_application->HandleStarboardEvent(starboard_event);
+}
+
} // namespace
#if defined(OS_STARBOARD)
-COBALT_WRAP_MAIN(PreloadApplication, StartApplication,
- cobalt::browser::EventHandler::HandleEvent, StopApplication);
+COBALT_WRAP_MAIN(PreloadApplication, StartApplication, HandleStarboardEvent,
+ StopApplication);
#else
COBALT_WRAP_BASE_MAIN(StartApplication, StopApplication);
#endif
diff --git a/src/cobalt/browser/memory_tracker/tool.cc b/src/cobalt/browser/memory_tracker/tool.cc
index 5083f99..9a95e1b 100644
--- a/src/cobalt/browser/memory_tracker/tool.cc
+++ b/src/cobalt/browser/memory_tracker/tool.cc
@@ -121,6 +121,24 @@
std::string arg_str = command_arg.substr(begin_idx, length);
return arg_str;
}
+
+struct DisableMemoryTrackerInScope {
+ explicit DisableMemoryTrackerInScope(MemoryTracker* tracker)
+ : tracker_(tracker) {
+ if (tracker_) {
+ tracker_->SetMemoryTrackingEnabled(false);
+ }
+ }
+
+ ~DisableMemoryTrackerInScope() {
+ if (tracker_) {
+ tracker_->SetMemoryTrackingEnabled(true);
+ }
+ }
+
+ MemoryTracker* tracker_;
+};
+
} // namespace.
class MemoryTrackerThreadImpl : public Tool {
@@ -307,6 +325,7 @@
// Time until output is triggered.
int sampling_time_ms = F::ToMilliseconds(num_mins);
// Create a thread that will gather memory metrics for startup.
+ DisableMemoryTrackerInScope disable_in_scope(memory_tracker);
tool_ptr.reset(new PrintCSVTool(sampling_interval_ms, sampling_time_ms));
break;
}
@@ -314,6 +333,7 @@
memory_tracker = MemoryTracker::Get();
memory_tracker->InstallGlobalTrackingHooks();
// Create a thread that will continuously report memory use.
+ DisableMemoryTrackerInScope disable_in_scope(memory_tracker);
tool_ptr.reset(new PrintTool);
break;
}
@@ -321,12 +341,14 @@
memory_tracker = MemoryTracker::Get();
memory_tracker->InstallGlobalTrackingHooks();
// Create a thread that will continuously report memory use.
+ DisableMemoryTrackerInScope disable_in_scope(memory_tracker);
tool_ptr.reset(new CompressedTimeSeriesTool);
break;
}
case kBinnerAnalytics: {
memory_tracker = MemoryTracker::Get();
memory_tracker->InstallGlobalTrackingHooks();
+ DisableMemoryTrackerInScope disable_in_scope(memory_tracker);
// Create a thread that will continuously report javascript memory
// analytics.
tool_ptr.reset(new MemorySizeBinnerTool(tool_arg));
@@ -368,6 +390,7 @@
}
if (tool_ptr.get()) {
+ DisableMemoryTrackerInScope disable_in_scope(memory_tracker);
base::SimpleThread* thread =
new ToolThread(memory_tracker, // May be NULL.
tool_ptr.release(), new SbLogger);
diff --git a/src/cobalt/browser/memory_tracker/tool/tool_impl_test.cc b/src/cobalt/browser/memory_tracker/tool/tool_impl_test.cc
index 1a963e9..b5a59e9 100644
--- a/src/cobalt/browser/memory_tracker/tool/tool_impl_test.cc
+++ b/src/cobalt/browser/memory_tracker/tool/tool_impl_test.cc
@@ -73,7 +73,7 @@
// Expect data.
found = (csv_string.find("2,1") != std::string::npos);
- SbMemoryFree(dummy_memory);
+ SbMemoryDeallocate(dummy_memory);
}
// Tests the expectation that AllocationSizeBinner will correctly bin
diff --git a/src/cobalt/browser/memory_tracker/tool/tool_thread.cc b/src/cobalt/browser/memory_tracker/tool/tool_thread.cc
index 23ce566..a6e4a27 100644
--- a/src/cobalt/browser/memory_tracker/tool/tool_thread.cc
+++ b/src/cobalt/browser/memory_tracker/tool/tool_thread.cc
@@ -65,6 +65,10 @@
}
ToolThread::~ToolThread() {
+ nb::analytics::MemoryTracker* memory_tracker = params_->memory_tracker();
+ if (memory_tracker) {
+ memory_tracker->SetMemoryTrackerDebugCallback(nullptr);
+ }
Join();
tool_.reset();
params_.reset();
diff --git a/src/cobalt/browser/screen_shot_writer.cc b/src/cobalt/browser/screen_shot_writer.cc
index 00ecfc8..e534c76 100644
--- a/src/cobalt/browser/screen_shot_writer.cc
+++ b/src/cobalt/browser/screen_shot_writer.cc
@@ -41,8 +41,8 @@
// No conversion needed here, simply write out the pixels as is.
return EncodeRGBAToBuffer(static_cast<uint8_t*>(bitmap.pixelRef()->pixels()),
- bitmap.width(), bitmap.height(), bitmap.rowBytes(),
- out_num_bytes);
+ bitmap.width(), bitmap.height(),
+ static_cast<int>(bitmap.rowBytes()), out_num_bytes);
}
} // namespace
@@ -107,8 +107,9 @@
size_t num_bytes) {
DCHECK_EQ(MessageLoop::current(), screenshot_thread_.message_loop());
// Blocking write to output_path.
- int bytes_written = file_util::WriteFile(
- output_path, reinterpret_cast<char*>(png_data.get()), num_bytes);
+ int bytes_written =
+ file_util::WriteFile(output_path, reinterpret_cast<char*>(png_data.get()),
+ static_cast<int>(num_bytes));
DLOG_IF(ERROR, bytes_written != num_bytes) << "Error writing PNG to file.";
// Notify the caller that the screenshot is complete.
diff --git a/src/cobalt/browser/snapshot_app_stats.cc b/src/cobalt/browser/snapshot_app_stats.cc
index 0b83f02..aa502ab 100644
--- a/src/cobalt/browser/snapshot_app_stats.cc
+++ b/src/cobalt/browser/snapshot_app_stats.cc
@@ -141,7 +141,8 @@
cobalt::browser::switches::kDebugConsoleMode, "off");
// Create the application object just like is done in the Cobalt main app.
- g_application = cobalt::browser::CreateApplication(quit_closure).release();
+ g_application =
+ new cobalt::browser::Application(quit_closure, false /*should_preload*/);
// Create a thread to start a timer for kSecondsToWait seconds after which
// we will take a snapshot of the CVals at that time and then quit the
diff --git a/src/cobalt/browser/splash_screen.h b/src/cobalt/browser/splash_screen.h
index e775e2a..1780bd5 100644
--- a/src/cobalt/browser/splash_screen.h
+++ b/src/cobalt/browser/splash_screen.h
@@ -41,7 +41,12 @@
float layout_refresh_rate, const GURL& url);
~SplashScreen();
+ void SetSize(const math::Size& window_dimensions, float video_pixel_ratio) {
+ web_module_->SetSize(window_dimensions, video_pixel_ratio);
+ }
+
// LifecycleObserver implementation.
+ void Prestart() OVERRIDE { web_module_->Prestart(); }
void Start(render_tree::ResourceProvider* resource_provider) OVERRIDE {
web_module_->Start(resource_provider);
}
diff --git a/src/cobalt/browser/starboard/application.cc b/src/cobalt/browser/starboard/application.cc
deleted file mode 100644
index 1c3e5fe..0000000
--- a/src/cobalt/browser/starboard/application.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "cobalt/browser/application.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "cobalt/browser/starboard/event_handler.h"
-#include "starboard/system.h"
-
-namespace cobalt {
-namespace browser {
-
-class ApplicationStarboard : public Application {
- public:
- ApplicationStarboard(const base::Closure& quit_closure, bool should_preload)
- : Application(quit_closure, should_preload),
- event_handler_(&event_dispatcher_) {}
-
- private:
- // Event handler to receive Starboard events, convert to Cobalt events
- // and dispatch to the rest of the system.
- EventHandler event_handler_;
-};
-
-scoped_ptr<Application> CreateApplication(const base::Closure& quit_closure) {
- return scoped_ptr<Application>(
- new ApplicationStarboard(quit_closure, false /*should_preload*/));
-}
-
-scoped_ptr<Application> PreloadApplication(const base::Closure& quit_closure) {
- return scoped_ptr<Application>(
- new ApplicationStarboard(quit_closure, true /*should_preload*/));
-}
-
-} // namespace browser
-} // namespace cobalt
diff --git a/src/cobalt/browser/starboard/event_handler.cc b/src/cobalt/browser/starboard/event_handler.cc
deleted file mode 100644
index dab7e1b..0000000
--- a/src/cobalt/browser/starboard/event_handler.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "cobalt/browser/starboard/event_handler.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "cobalt/base/accessibility_settings_changed_event.h"
-#include "cobalt/base/application_event.h"
-#include "cobalt/base/deep_link_event.h"
-#include "cobalt/network/network_event.h"
-#include "cobalt/system_window/input_event.h"
-
-namespace cobalt {
-namespace browser {
-
-namespace {
-EventHandler* g_the_event_handler = NULL;
-} // namespace
-
-EventHandler::EventHandler(base::EventDispatcher* event_dispatcher)
- : event_dispatcher_(event_dispatcher) {
- DCHECK(!g_the_event_handler) << "There should be only one event handler.";
- g_the_event_handler = this;
-}
-
-// static
-void EventHandler::HandleEvent(const SbEvent* starboard_event) {
- DCHECK(starboard_event);
-
- // Forward input events to |SystemWindow|.
- if (starboard_event->type == kSbEventTypeInput) {
- system_window::HandleInputEvent(starboard_event);
- return;
- }
-
- // Handle all other events internally.
- DCHECK(g_the_event_handler);
- g_the_event_handler->DispatchEvent(starboard_event);
-}
-
-void EventHandler::DispatchEventInternal(base::Event* event) const {
- event_dispatcher_->DispatchEvent(make_scoped_ptr<base::Event>(event));
-}
-
-void EventHandler::DispatchEvent(const SbEvent* starboard_event) const {
- // Create a Cobalt event from the Starboard event, if recognized.
- switch (starboard_event->type) {
- case kSbEventTypePause:
- case kSbEventTypeUnpause:
- case kSbEventTypeSuspend:
- case kSbEventTypeResume:
- case kSbEventTypeStart:
- DispatchEventInternal(new base::ApplicationEvent(starboard_event->type));
- break;
- case kSbEventTypeNetworkConnect:
- DispatchEventInternal(
- new network::NetworkEvent(network::NetworkEvent::kConnection));
- break;
- case kSbEventTypeNetworkDisconnect:
- DispatchEventInternal(
- new network::NetworkEvent(network::NetworkEvent::kDisconnection));
- break;
- case kSbEventTypeLink: {
- const char* link = static_cast<const char*>(starboard_event->data);
- DispatchEventInternal(new base::DeepLinkEvent(link));
- break;
- }
-#if SB_API_VERSION >= 4
- case kSbEventTypeAccessiblitySettingsChanged:
- DispatchEventInternal(new base::AccessibilitySettingsChangedEvent());
- break;
-#endif // SB_API_VERSION >= 4
- default:
- DLOG(WARNING) << "Unhandled Starboard event of type: "
- << starboard_event->type;
- }
-}
-
-} // namespace browser
-} // namespace cobalt
diff --git a/src/cobalt/browser/starboard/event_handler.h b/src/cobalt/browser/starboard/event_handler.h
deleted file mode 100644
index 13391d2..0000000
--- a/src/cobalt/browser/starboard/event_handler.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_
-#define COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_
-
-#include "cobalt/base/event_dispatcher.h"
-#include "starboard/event.h"
-
-namespace cobalt {
-namespace browser {
-
-class EventHandler {
- public:
- explicit EventHandler(base::EventDispatcher* event_dispatcher);
-
- // Static event handler called by |SbEventHandle|. Forwards input events to
- // |system_window::HandleInputEvent| and passes all other events to
- // |DispatchEvent|.
- static void HandleEvent(const SbEvent* event);
-
- private:
- // Creates a Cobalt event from a Starboard event and dispatches to the rest
- // of the system via |event_dispatcher_|.
- void DispatchEvent(const SbEvent* event) const;
-
- void DispatchEventInternal(base::Event*) const;
-
- // The event dispatcher that dispatches Cobalt events to the rest of the
- // system.
- base::EventDispatcher* event_dispatcher_;
-};
-
-} // namespace browser
-} // namespace cobalt
-
-#endif // COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_
diff --git a/src/cobalt/browser/starboard/platform_browser.gyp b/src/cobalt/browser/starboard/platform_browser.gyp
deleted file mode 100644
index 13e5af6..0000000
--- a/src/cobalt/browser/starboard/platform_browser.gyp
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- 'targets': [
- {
- 'target_name': 'platform_browser',
- 'type': 'static_library',
- 'sources': [
- 'application.cc',
- 'event_handler.cc',
- 'event_handler.h',
- ],
- 'dependencies': [
- '<(DEPTH)/cobalt/browser/browser.gyp:browser',
- ],
- 'export_dependent_settings': [
- '<(DEPTH)/cobalt/browser/browser.gyp:browser',
- ],
- },
- ],
-}
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index 2c107df..2c39eed 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -102,7 +102,8 @@
extern const char kVideoDecoderStub[] = "video_decoder_stub";
// Enable text-to-speech functionality, for platforms that implement the speech
-// synthesis API.
+// synthesis API. If the platform doesn't have speech synthesis, TTSLogger will
+// be used instead.
const char kUseTTS[] = "use_tts";
// Port that the WebDriver server should be listening on.
diff --git a/src/cobalt/browser/testdata/deep-link-demo/deep-link-demo.html b/src/cobalt/browser/testdata/deep-link-demo/deep-link-demo.html
new file mode 100644
index 0000000..a99d33d
--- /dev/null
+++ b/src/cobalt/browser/testdata/deep-link-demo/deep-link-demo.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script type="text/javascript">
+ console.log("h5vcc.runtime.initialDeepLink: " +
+ h5vcc.runtime.initialDeepLink);
+
+ h5vcc.runtime.onDeepLink = function(link) {
+ console.log("h5vcc.runtime.onDeepLink: " + link);
+ };
+ </script>
+</head>
+<body style="background-color:#48C"></body>
+</html>
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index 48094a9..8a4b237 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -152,6 +152,11 @@
#endif // ENABLE_DEBUG_CONSOLE
void SetSize(math::Size window_dimensions, float video_pixel_ratio);
+ void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
+ void SetMediaModule(media::MediaModule* media_module);
+ void SetImageCacheCapacity(int64_t bytes);
+ void SetRemoteTypefaceCacheCapacity(int64_t bytes);
+ void SetJavascriptGcThreshold(int64_t bytes);
// Sets the application state, asserts preconditions to transition to that
// state, and dispatches any precipitate web events.
@@ -160,7 +165,10 @@
// Suspension of the WebModule is a two-part process since a message loop
// gap is needed in order to give a chance to handle loader callbacks
// that were initiated from a loader thread.
- void SuspendLoaders();
+ //
+ // If |update_application_state| is false, then SetApplicationState will not
+ // be called, and no state transition events will be generated.
+ void SuspendLoaders(bool update_application_state);
void FinishSuspend();
// See LifecycleObserver. These functions do not implement the interface, but
@@ -213,6 +221,9 @@
// Handle queued pointer events. Called by LayoutManager on_layout callback.
void HandlePointerEvents();
+ // Initializes the ResourceProvider and dependent resources.
+ void SetResourceProvider(render_tree::ResourceProvider* resource_provider);
+
// Thread checker ensures all calls to the WebModule are made from the same
// thread that it is created in.
base::ThreadChecker thread_checker_;
@@ -455,7 +466,6 @@
media_source_registry_.reset(new dom::MediaSource::Registry);
media_session_client_ = media_session::MediaSessionClient::Create();
-
window_ = new dom::Window(
data.window_dimensions.width(), data.window_dimensions.height(),
data.video_pixel_ratio, data.initial_application_state, css_parser_.get(),
@@ -605,7 +615,7 @@
web_module_stat_tracker_->OnEndInjectEvent(
window_->HasPendingAnimationFrameCallbacks(),
- layout_manager_->IsNewRenderTreePending());
+ layout_manager_->IsRenderTreePending());
}
void WebModule::Impl::InjectKeyboardEvent(scoped_refptr<dom::Element> element,
@@ -663,7 +673,7 @@
// Notify the stat tracker that the animation frame callbacks have finished.
// This may end the current event being tracked.
web_module_stat_tracker_->OnRanAnimationFrameCallbacks(
- layout_manager_->IsNewRenderTreePending());
+ layout_manager_->IsRenderTreePending());
}
void WebModule::Impl::OnRenderTreeProduced(
@@ -761,20 +771,57 @@
}
}
-void WebModule::Impl::SetSize(math::Size /*window_dimensions*/,
- float /*video_pixel_ratio*/) {
- NOTIMPLEMENTED();
+void WebModule::Impl::SetImageCacheCapacity(int64_t bytes) {
+ image_cache_->SetCapacity(static_cast<uint32>(bytes));
+}
+
+void WebModule::Impl::SetRemoteTypefaceCacheCapacity(int64_t bytes) {
+ remote_typeface_cache_->SetCapacity(static_cast<uint32>(bytes));
+}
+
+void WebModule::Impl::SetJavascriptGcThreshold(int64_t bytes) {
+ javascript_engine_->SetGcThreshold(bytes);
+}
+
+void WebModule::Impl::SetSize(math::Size window_dimensions,
+ float video_pixel_ratio) {
+ window_->SetSize(window_dimensions.width(), window_dimensions.height(),
+ video_pixel_ratio);
+}
+
+void WebModule::Impl::SetCamera3D(
+ const scoped_refptr<input::Camera3D>& camera_3d) {
+ window_->SetCamera3D(camera_3d);
+}
+
+void WebModule::Impl::SetMediaModule(media::MediaModule* media_module) {
+ window_->set_can_play_type_handler(media_module);
+ window_->set_web_media_player_factory(media_module);
+ environment_settings_->set_media_module(media_module);
+ environment_settings_->set_can_play_type_handler(media_module);
}
void WebModule::Impl::SetApplicationState(base::ApplicationState state) {
window_->SetApplicationState(state);
}
+void WebModule::Impl::SetResourceProvider(
+ render_tree::ResourceProvider* resource_provider) {
+ resource_provider_ = resource_provider;
+ if (resource_provider_) {
+ loader_factory_->Resume(resource_provider_);
+
+ // Permit render trees to be generated again. Layout will have been
+ // invalidated with the call to Suspend(), so the layout manager's first
+ // task will be to perform a full re-layout.
+ layout_manager_->Resume();
+ }
+}
+
void WebModule::Impl::Start(render_tree::ResourceProvider* resource_provider) {
TRACE_EVENT0("cobalt::browser", "WebModule::Impl::Start()");
+ SetResourceProvider(resource_provider);
SetApplicationState(base::kApplicationStateStarted);
- // TODO: Initialize resource provider here rather than constructor.
- DCHECK(resource_provider == resource_provider_);
}
void WebModule::Impl::Pause() {
@@ -787,10 +834,12 @@
SetApplicationState(base::kApplicationStateStarted);
}
-void WebModule::Impl::SuspendLoaders() {
+void WebModule::Impl::SuspendLoaders(bool update_application_state) {
TRACE_EVENT0("cobalt::browser", "WebModule::Impl::SuspendLoaders()");
- SetApplicationState(base::kApplicationStateSuspended);
+ if (update_application_state) {
+ SetApplicationState(base::kApplicationStateSuspended);
+ }
// Purge the resource caches before running any suspend logic. This will force
// any pending callbacks that the caches are batching to run.
@@ -840,18 +889,7 @@
void WebModule::Impl::Resume(render_tree::ResourceProvider* resource_provider) {
TRACE_EVENT0("cobalt::browser", "WebModule::Impl::Resume()");
- DCHECK(resource_provider);
- DCHECK(!resource_provider_);
-
- resource_provider_ = resource_provider;
-
- loader_factory_->Resume(resource_provider_);
-
- // Permit render trees to be generated again. Layout will have been
- // invalidated with the call to Suspend(), so the layout manager's first task
- // will be to perform a full re-layout.
- layout_manager_->Resume();
-
+ SetResourceProvider(resource_provider);
SetApplicationState(base::kApplicationStatePaused);
}
@@ -1110,6 +1148,55 @@
window_dimensions, video_pixel_ratio));
}
+void WebModule::SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d) {
+ message_loop()->PostTask(
+ FROM_HERE, base::Bind(&WebModule::Impl::SetCamera3D,
+ base::Unretained(impl_.get()), camera_3d));
+}
+
+void WebModule::SetMediaModule(media::MediaModule* media_module) {
+ message_loop()->PostTask(
+ FROM_HERE, base::Bind(&WebModule::Impl::SetMediaModule,
+ base::Unretained(impl_.get()), media_module));
+}
+
+void WebModule::SetImageCacheCapacity(int64_t bytes) {
+ message_loop()->PostTask(FROM_HERE,
+ base::Bind(&WebModule::Impl::SetImageCacheCapacity,
+ base::Unretained(impl_.get()), bytes));
+}
+
+void WebModule::SetRemoteTypefaceCacheCapacity(int64_t bytes) {
+ message_loop()->PostTask(
+ FROM_HERE, base::Bind(&WebModule::Impl::SetRemoteTypefaceCacheCapacity,
+ base::Unretained(impl_.get()), bytes));
+}
+
+void WebModule::SetJavascriptGcThreshold(int64_t bytes) {
+ message_loop()->PostTask(
+ FROM_HERE, base::Bind(&WebModule::Impl::SetJavascriptGcThreshold,
+ base::Unretained(impl_.get()), bytes));
+}
+
+void WebModule::Prestart() {
+ // Must only be called by a thread external from the WebModule thread.
+ DCHECK_NE(MessageLoop::current(), message_loop());
+
+ // We must block here so that we don't queue the finish until after
+ // SuspendLoaders has run to completion, and therefore has already queued any
+ // precipitate tasks.
+ message_loop()->PostBlockingTask(
+ FROM_HERE, base::Bind(&WebModule::Impl::SuspendLoaders,
+ base::Unretained(impl_.get()),
+ false /*update_application_state*/));
+
+ // We must block here so that the call doesn't return until the web
+ // application has had a chance to process the whole event.
+ message_loop()->PostBlockingTask(FROM_HERE,
+ base::Bind(&WebModule::Impl::FinishSuspend,
+ base::Unretained(impl_.get())));
+}
+
void WebModule::Start(render_tree::ResourceProvider* resource_provider) {
// Must only be called by a thread external from the WebModule thread.
DCHECK_NE(MessageLoop::current(), message_loop());
@@ -1117,9 +1204,8 @@
// We must block here so that the call doesn't return until the web
// application has had a chance to process the whole event.
message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&WebModule::Impl::Start, base::Unretained(impl_.get()),
- base::Unretained(resource_provider)));
+ FROM_HERE, base::Bind(&WebModule::Impl::Start,
+ base::Unretained(impl_.get()), resource_provider));
}
void WebModule::Pause() {
@@ -1151,9 +1237,10 @@
// We must block here so that we don't queue the finish until after
// SuspendLoaders has run to completion, and therefore has already queued any
// precipitate tasks.
- message_loop()->PostBlockingTask(FROM_HERE,
- base::Bind(&WebModule::Impl::SuspendLoaders,
- base::Unretained(impl_.get())));
+ message_loop()->PostBlockingTask(
+ FROM_HERE, base::Bind(&WebModule::Impl::SuspendLoaders,
+ base::Unretained(impl_.get()),
+ true /*update_application_state*/));
// We must block here so that the call doesn't return until the web
// application has had a chance to process the whole event.
@@ -1189,7 +1276,7 @@
}
topmost_event_target_->MaybeSendPointerEvents(event);
}
- } while (event && !layout_manager_->IsNewRenderTreePending());
+ } while (event && !layout_manager_->IsRenderTreePending());
}
} // namespace browser
diff --git a/src/cobalt/browser/web_module.h b/src/cobalt/browser/web_module.h
index 47c22ee..ad3ab1e 100644
--- a/src/cobalt/browser/web_module.h
+++ b/src/cobalt/browser/web_module.h
@@ -239,7 +239,14 @@
// not different from the current parameters.
void SetSize(const math::Size& window_dimensions, float video_pixel_ratio);
+ void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
+ void SetMediaModule(media::MediaModule* media_module);
+ void SetImageCacheCapacity(int64_t bytes);
+ void SetRemoteTypefaceCacheCapacity(int64_t bytes);
+ void SetJavascriptGcThreshold(int64_t bytes);
+
// LifecycleObserver implementation
+ void Prestart() OVERRIDE;
void Start(render_tree::ResourceProvider* resource_provider) OVERRIDE;
void Pause() OVERRIDE;
void Unpause() OVERRIDE;
diff --git a/src/cobalt/browser/win/application.cc b/src/cobalt/browser/win/application.cc
deleted file mode 100644
index fb88256..0000000
--- a/src/cobalt/browser/win/application.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "cobalt/browser/application.h"
-
-namespace cobalt {
-namespace browser {
-
-class ApplicationWin : public Application {
- public:
- explicit ApplicationWin(const base::Closure& quit_closure)
- : Application(quit_closure) {}
- ~ApplicationWin() OVERRIDE {}
-};
-
-scoped_ptr<Application> CreateApplication(const base::Closure& quit_closure) {
- return scoped_ptr<Application>(new ApplicationWin(quit_closure));
-}
-
-} // namespace browser
-} // namespace cobalt
diff --git a/src/cobalt/browser/win/platform_browser.gyp b/src/cobalt/browser/win/platform_browser.gyp
deleted file mode 100644
index cd002f7..0000000
--- a/src/cobalt/browser/win/platform_browser.gyp
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- 'targets': [
- {
- 'target_name': 'platform_browser',
- 'type': 'static_library',
- 'sources': [
- 'application.cc',
- ],
- 'dependencies': [
- '<(DEPTH)/cobalt/browser/browser.gyp:browser',
- ],
- },
- ],
-}
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index d7461cb..58c7a27 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-78263
\ No newline at end of file
+81256
\ No newline at end of file
diff --git a/src/cobalt/build/build_config.h b/src/cobalt/build/build_config.h
new file mode 100644
index 0000000..bfe3df5
--- /dev/null
+++ b/src/cobalt/build/build_config.h
@@ -0,0 +1,53 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_BUILD_BUILD_CONFIG_H_
+#define COBALT_BUILD_BUILD_CONFIG_H_
+
+#if COBALT_MEDIA_BUFFER_INITIAL_CAPACITY < 0
+#error cobalt_media_buffer_initial_capacity has to be greater than or equal to 0
+#endif // COBALT_MEDIA_BUFFER_INITIAL_CAPACITY < 0
+
+#if COBALT_MEDIA_BUFFER_ALLOCATION_UNIT < 0
+#error cobalt_media_buffer_allocation_unit has to be greater than or equal to 0
+#endif // COBALT_MEDIA_BUFFER_ALLOCATION_UNIT < 0
+
+#if COBALT_MEDIA_BUFFER_ALIGNMENT < 0
+#error "cobalt_media_buffer_alignment has to be greater than or equal to 0."
+#endif // COBALT_MEDIA_BUFFER_ALIGNMENT < 0
+
+#if COBALT_MEDIA_BUFFER_PADDING < 0
+#error "cobalt_media_buffer_padding has to be greater than or equal to 0."
+#endif // COBALT_MEDIA_BUFFER_PADDING < 0
+
+#if COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET < 8 * 1024 * 1024
+#error cobalt_media_buffer_progressive_budget has to be greater than or equal \
+ to 8 MB.
+#endif // COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET < 0
+
+#if COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET <= 0
+#error "cobalt_media_buffer_non_video_budget has to be greater than 0."
+#endif // COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET < 0
+
+#if COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P <= 0
+#error "cobalt_media_buffer_video_budget_1080p has to be greater than 0."
+#endif // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P < 0
+
+#if COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K < COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P
+#error cobalt_media_buffer_video_budget_4k has to be greater than or equal to \
+ cobalt_media_buffer_video_budget_1080p.
+#endif // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K <
+ // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P
+
+#endif // COBALT_BUILD_BUILD_CONFIG_H_
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index 439781f..96d4005 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -135,11 +135,6 @@
'cobalt_version%': 0,
# Contains the name of the hosting OS. The value is defined by gyp_cobalt.
'host_os%': 'win',
- # The "real" target_arch that is used to select the correct delegate source.
- # TODO: Investigate why adding % will break the build on platforms
- # other than Windows
- # TODO: Remove after starboard.
- 'actual_target_arch': '<(target_arch)',
# The target platform id as a string, like 'ps3', 'ps4', etc..
'sb_target_platform': '',
@@ -229,9 +224,6 @@
# Used by cobalt/media/media.gyp to pick a proper media platform.
'sb_media_platform%': 'starboard',
- # Needed for backwards compatibility with lbshell code.
- 'lbshell_root%': '<(DEPTH)/lbshell',
-
# The relative path from src/ to the directory containing the
# starboard_platform.gyp file. It is currently set to
# 'starboard/<(target_arch)' to make semi-starboard platforms work.
@@ -436,7 +428,6 @@
'platform_libraries%': [],
-
# The only currently-supported Javascript engine is 'mozjs-45'.
# TODO: Figure out how to massage gyp the right way to make this work
# as expected, rather than requiring it to be set for each platform.
@@ -456,7 +447,7 @@
# Use media source extension implementation that is conformed to the
# Candidate Recommandation of July 5th 2016.
- 'cobalt_media_source_2016%': 0,
+ 'cobalt_media_source_2016%': 1,
# Note that the following media buffer related variables are only used when
# |cobalt_media_source_2016| is set to 1.
@@ -469,18 +460,43 @@
# value is "file" the media stack will still allocate memory to cache the
# the buffers in use.
'cobalt_media_buffer_storage_type%': 'memory',
+ # When either |cobalt_media_buffer_initial_capacity| or
+ # |cobalt_media_buffer_allocation_unit| isn't zero, media buffers will be
+ # allocated using a memory pool. Set the following variable to 1 to
+ # allocate the media buffer pool memory on demand and return all memory to
+ # the system when there is no media buffer allocated. Setting the following
+ # value to 0 results in that Cobalt will allocate
+ # |cobalt_media_buffer_initial_capacity| bytes for media buffer on startup
+ # and will not release any media buffer memory back to the system even if
+ # there is no media buffers allocated.
+ 'cobalt_media_buffer_pool_allocate_on_demand%': 1,
# The amount of memory that will be used to store media buffers allocated
# during system startup. To allocate a large chunk at startup helps with
- # reducing frafmentation and can avoid failures to allocate incrementally.
+ # reducing fragmentation and can avoid failures to allocate incrementally.
# This can be set to 0.
- 'cobalt_media_buffer_initial_capacity%': 0 * 1024 * 1024,
+ 'cobalt_media_buffer_initial_capacity%': 21 * 1024 * 1024,
# When the media stack needs more memory to store media buffers, it will
# allocate extra memory in units of |cobalt_media_buffer_allocation_unit|.
# This can be set to 0, in which case the media stack will allocate extra
# memory on demand. When |cobalt_media_buffer_initial_capacity| and this
# value are both set to 0, the media stack will allocate individual buffers
# directly using SbMemory functions.
- 'cobalt_media_buffer_allocation_unit%': 0 * 1024 * 1024,
+ 'cobalt_media_buffer_allocation_unit%': 1 * 1024 * 1024,
+
+ # The media buffer will be allocated using the following alignment. Set
+ # this to a larger value may increase the memory consumption of media
+ # buffers.
+ 'cobalt_media_buffer_alignment%': 0,
+ # Extra bytes allocated at the end of a media buffer to ensure that the
+ # buffer can be use optimally by specific instructions like SIMD. Set to 0
+ # to remove any padding.
+ 'cobalt_media_buffer_padding%': 0,
+
+ # The memory used when playing mp4 videos that is not in DASH format. The
+ # resolution of such videos shouldn't go beyond 1080p. Its value should be
+ # less than the sum of 'cobalt_media_buffer_non_video_budget' and
+ # 'cobalt_media_buffer_video_budget_1080p' but not less than 8 MB.
+ 'cobalt_media_buffer_progressive_budget%': 12 * 1024 * 1024,
# Specifies the maximum amount of memory used by audio or text buffers of
# media source before triggering a garbage collection. A large value will
@@ -521,11 +537,15 @@
},
'defines': [
'COBALT',
+ 'COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND=<(cobalt_media_buffer_pool_allocate_on_demand)',
+ 'COBALT_MEDIA_BUFFER_INITIAL_CAPACITY=<(cobalt_media_buffer_initial_capacity)',
+ 'COBALT_MEDIA_BUFFER_ALLOCATION_UNIT=<(cobalt_media_buffer_allocation_unit)',
+ 'COBALT_MEDIA_BUFFER_ALIGNMENT=<(cobalt_media_buffer_alignment)',
+ 'COBALT_MEDIA_BUFFER_PADDING=<(cobalt_media_buffer_padding)',
+ 'COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET=<(cobalt_media_buffer_progressive_budget)',
'COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET=<(cobalt_media_buffer_non_video_budget)',
'COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P=<(cobalt_media_buffer_video_budget_1080p)',
'COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K=<(cobalt_media_buffer_video_budget_4k)',
- 'COBALT_MEDIA_BUFFER_INITIAL_CAPACITY=<(cobalt_media_buffer_initial_capacity)',
- 'COBALT_MEDIA_BUFFER_ALLOCATION_UNIT=<(cobalt_media_buffer_allocation_unit)',
],
'cflags': [ '<@(compiler_flags)' ],
'ldflags': [ '<@(linker_flags)' ],
diff --git a/src/cobalt/build/config/starboard.py b/src/cobalt/build/config/starboard.py
index 07ffc4b..ecba441 100644
--- a/src/cobalt/build/config/starboard.py
+++ b/src/cobalt/build/config/starboard.py
@@ -31,12 +31,26 @@
return True
def GetEnvironmentVariables(self):
- raise NotImplementedError
+ return {}
def GetToolchain(self):
"""Returns the instance of the toolchain implementation class."""
return None
+ def GetTargetToolchain(self):
+ """Returns a list of target tools."""
+ # TODO: If this method throws |NotImplementedError|, GYP will fall back to
+ # the legacy toolchain. Once all platforms are migrated to the
+ # abstract toolchain, this method should be made |@abstractmethod|.
+ raise NotImplementedError()
+
+ def GetHostToolchain(self):
+ """Returns a list of host tools."""
+ # TODO: If this method throws |NotImplementedError|, GYP will fall back to
+ # the legacy toolchain. Once all platforms are migrated to the
+ # abstract toolchain, this method should be made |@abstractmethod|.
+ raise NotImplementedError()
+
def GetVariables(self, config, use_clang=0):
use_asan = 0
use_tsan = 0
diff --git a/src/cobalt/doc/lifecycle.md b/src/cobalt/doc/lifecycle.md
new file mode 100644
index 0000000..a75d2fb
--- /dev/null
+++ b/src/cobalt/doc/lifecycle.md
@@ -0,0 +1,137 @@
+# Application Lifecycle
+
+In order to meet common needs of applications running on CE devices, Cobalt
+implements a well-defined web application lifecycle, managing resources and
+notifying the application as appropriate.
+
+## Application States
+
+Starboard Application State | Page Visibility State | Window Focused
+:-------------------------- | :-------------------- | :-------------
+*Preloading* | prerender | false
+*Started* | visible | true
+*Paused* | visible | false
+*Suspended* | hidden | false
+
+### Preloading
+
+The application is not visible, and will receive no input, but is running. Only
+possible to enter as the start state. May transition to *Started* or *Suspended*
+at any time.
+
+#### Expectations for the web application
+
+Initialize as much as possible to get to an interactive state. There is no
+official signal for an application that has finished preloading.
+
+#### Expectations for the porter
+
+For applications that can be preloaded, the platform should send
+`kSbEventTypePreload` as the first Starboard event instead of
+`kSbEventTypeStart`. `src/starboard/shared/starboard/application.cc` subclasses
+can opt-in to already implemented support for the `--preload` command-line
+switch.
+
+The platform should then send `kSbEventTypeStart` when the application is first
+brought to the foreground. In Linux desktop (linux-x64x11), this can be done by
+sending a `SIGCONT` to the process that is in the *Preloading* state.
+
+If the platform wants to only give applications a certain amount of time to
+preload, they can send `kSbEventTypeSuspend` to halt preloading and move to the
+*Suspended* state. In Linux desktop, this can be done by sending SIGUSR1 to the
+process that is in the *Preloading* state.
+
+### Started
+
+The application is running, visible, and interactive. The normal foreground
+application state. May be the start state, can be entered from *Preloading*, or
+*Paused*.
+
+May only transition to *Paused*. In Linux desktop, this happens anytime the
+top-level Cobalt X11 window loses focus. Linux transition back to *Started* when
+the top-level Cobalt X11 window gains focus again.
+
+### Paused
+
+The application may be fully visible, partially visible, or completely obscured,
+but it has lost input focus, so will receive no input events. It has been
+allowed to retain all its resources for a very quick return to *Started*, and
+the application is still running. May be entered from or transition to *Started*
+or *Suspended*.
+
+### Suspended
+
+The application is not visible, and, once *Suspended*, will not run any
+code. All graphics and media resources will be revoked until resumed, so the
+application should expect all images to be lost, all caches to be cleared, and
+all network requests to be aborted. The application may be terminated in this
+state without notification.
+
+#### Expectations for the web application
+
+The application should **shut down** playback, releasing resources. On resume,
+all resources need to be reloaded, and playback should be reinitialized where it
+left off, or at the nearest key frame.
+
+#### Expectations for the porter
+
+The platform Starboard implementation **must always** send events in the
+prescribed order - meaning, for example, that it should never send a
+`kSbEventTypeSuspend` event unless in the *Preloading* or *Paused* states.
+
+Currently, Cobalt does not manually stop JavaScript execution when it goes into
+the *Suspended* state. In Linux desktop, it expects that a `SIGSTOP` will be
+raised, causing all the threads not to get any more CPU time until resumed. This
+will be fixed in a future version of Cobalt.
+
+## Implementing the Application Lifecycle (for the porter)
+
+Most porters will want to subclass either `starboard::shared::Application` (in
+`src/starboard/shared/starboard/application.cc`) or
+`starboard::shared::QueueApplication` (in
+`src/starboard/shared/starboard/queue_application.cc`), as these are reference
+classes that rigorously implement the Starboard application lifecycle. They are
+optional, and platforms can directly dispatch events to SbEventHandle(), but it
+is then up to them to ensure that events are **always** sent in the correct
+state as specified in the Starboard documentation.
+
+`starboard::shared::Application` guarantees the correct ordering by implementing
+a small state machine that ignores invalid application state transitions, and
+inserts any necessary transitions to make them valid. For example, you can call
+`starboard::shared::Application::Suspend()`, and if you are in *Paused*, it will
+just dispatch a `kSbEventTypeSuspend` event. But if you call `Suspend()` in the
+*Started* state, it will dispatch `kSbEventTypePause` and then
+`kSbEventTypeSuspend` events. If you call `Suspend()` in the *Suspended* state,
+it just does nothing.
+
+To control starting up in the *Preloading* state, `Application` subclasses must
+override two functions:
+
+``` c++
+class MyApplication : public shared::starboard::QueueApplication {
+ // [ ... ]
+ bool IsStartImmediate() SB_OVERRIDE;
+ bool IsPreloadImmediate() SB_OVERRIDE;
+ // [ ... ]
+}
+```
+
+To start up in the *Preloading* state, `IsStartImmediate()` should return
+`false` and `IsPreloadImmediate()` should return `true`.
+
+To start up in the *Starting* state (which is the default), `IsStartImmediate()`
+should return `true` and `IsPreloadImmediate()` will not be called.
+
+To delay starting up until some later event, `IsStartImmediate()` and
+`IsPreloadImmediate()` should both return `false`. No initial event will be
+automatically sent to the application, and it is then up to the porter to
+dispatch a `kSbEventTypeStart` or `kSbEventTypePreload` event as the first
+event. This is useful if you need to wait for an asynchronous system activity to
+complete before starting Cobalt.
+
+To support the `--preload` command-line argument:
+
+``` c++
+ bool IsStartImmediate() SB_OVERRIDE { return !HasPreloadSwitch(); }
+ bool IsPreloadImmediate() SB_OVERRIDE { return HasPreloadSwitch(); }
+```
diff --git a/src/cobalt/dom/blob_test.cc b/src/cobalt/dom/blob_test.cc
index 1e015a5..8b0016e 100644
--- a/src/cobalt/dom/blob_test.cc
+++ b/src/cobalt/dom/blob_test.cc
@@ -38,7 +38,7 @@
scoped_refptr<DataView> data_view =
new DataView(array_buffer, &exception_state);
data_view->SetInt16(0, static_cast<int16>(0x0607), &exception_state);
- data_view->SetInt16(3, static_cast<int16>(0xABCD), &exception_state);
+ data_view->SetInt16(3, static_cast<int16>(0x7BCD), &exception_state);
scoped_refptr<Blob> blob_with_buffer = new Blob(NULL, array_buffer);
ASSERT_EQ(5, blob_with_buffer->size());
@@ -47,7 +47,7 @@
EXPECT_EQ(0x6, blob_with_buffer->data()[0]);
EXPECT_EQ(0x7, blob_with_buffer->data()[1]);
EXPECT_EQ(0, blob_with_buffer->data()[2]);
- EXPECT_EQ(0xAB, blob_with_buffer->data()[3]);
+ EXPECT_EQ(0x7B, blob_with_buffer->data()[3]);
EXPECT_EQ(0xCD, blob_with_buffer->data()[4]);
scoped_refptr<DataView> data_view_mid_3 =
@@ -63,7 +63,7 @@
EXPECT_EQ(0x6, blob_with_parts->data()[0]);
EXPECT_EQ(0x7, blob_with_parts->data()[5]);
EXPECT_EQ(0, blob_with_parts->data()[6]);
- EXPECT_EQ(0xAB, blob_with_parts->data()[11]);
+ EXPECT_EQ(0x7B, blob_with_parts->data()[11]);
EXPECT_EQ(0xCD, blob_with_parts->data()[12]);
}
diff --git a/src/cobalt/dom/document.cc b/src/cobalt/dom/document.cc
index f0cda7e..aaa034b 100644
--- a/src/cobalt/dom/document.cc
+++ b/src/cobalt/dom/document.cc
@@ -740,6 +740,11 @@
#endif // defined(ENABLE_PARTIAL_LAYOUT_CONTROL)
void Document::SetViewport(const math::Size& viewport_size) {
+ if (viewport_size_ && viewport_size_->width() == viewport_size.width() &&
+ viewport_size_->height() == viewport_size.height()) {
+ return;
+ }
+
viewport_size_ = viewport_size;
initial_computed_style_data_ = CreateInitialComputedStyle(*viewport_size_);
initial_computed_style_declaration_->SetData(initial_computed_style_data_);
@@ -751,6 +756,8 @@
if (current_html) {
current_html->InvalidateComputedStylesOfNodeAndDescendants();
}
+
+ RecordMutation();
}
Document::~Document() {
diff --git a/src/cobalt/dom/dom_settings.h b/src/cobalt/dom/dom_settings.h
index 507c723..c6b8895 100644
--- a/src/cobalt/dom/dom_settings.h
+++ b/src/cobalt/dom/dom_settings.h
@@ -101,6 +101,9 @@
}
network::NetworkModule* network_module() const { return network_module_; }
media::MediaModule* media_module() const { return media_module_; }
+ void set_media_module(media::MediaModule* media_module) {
+ media_module_ = media_module;
+ }
script::JavaScriptEngine* javascript_engine() const {
return javascript_engine_;
}
@@ -113,6 +116,10 @@
media::CanPlayTypeHandler* can_play_type_handler() const {
return can_play_type_handler_;
}
+ void set_can_play_type_handler(
+ media::CanPlayTypeHandler* can_play_type_handler) {
+ can_play_type_handler_ = can_play_type_handler;
+ }
MutationObserverTaskManager* mutation_observer_task_manager() const {
return mutation_observer_task_manager_;
}
diff --git a/src/cobalt/dom/event_target.h b/src/cobalt/dom/event_target.h
index 9af3d72..df9e286 100644
--- a/src/cobalt/dom/event_target.h
+++ b/src/cobalt/dom/event_target.h
@@ -230,6 +230,13 @@
SetAttributeEventListener(base::Tokens::playing(), event_listener);
}
+ const EventListenerScriptValue* onresize() {
+ return GetAttributeEventListener(base::Tokens::resize());
+ }
+ void set_onresize(const EventListenerScriptValue& event_listener) {
+ SetAttributeEventListener(base::Tokens::resize(), event_listener);
+ }
+
const EventListenerScriptValue* onpointerdown() {
return GetAttributeEventListener(base::Tokens::pointerdown());
}
diff --git a/src/cobalt/dom/global_event_handlers.idl b/src/cobalt/dom/global_event_handlers.idl
index cdacb6b..31627a2 100644
--- a/src/cobalt/dom/global_event_handlers.idl
+++ b/src/cobalt/dom/global_event_handlers.idl
@@ -42,6 +42,8 @@
attribute EventHandler onplay;
attribute EventHandler onplaying;
+ attribute EventHandler onresize;
+
// Extensions for the Pointer Events recommendation.
// https://www.w3.org/TR/2015/REC-pointerevents-20150224/#extensions-to-the-globaleventhandlers-interface
attribute EventHandler onpointerdown;
diff --git a/src/cobalt/dom/html_element_context.h b/src/cobalt/dom/html_element_context.h
index 970bc32..d7054db 100644
--- a/src/cobalt/dom/html_element_context.h
+++ b/src/cobalt/dom/html_element_context.h
@@ -77,9 +77,17 @@
media::CanPlayTypeHandler* can_play_type_handler() {
return can_play_type_handler_;
}
+ void set_can_play_type_handler(
+ media::CanPlayTypeHandler* can_play_type_handler) {
+ can_play_type_handler_ = can_play_type_handler;
+ }
media::WebMediaPlayerFactory* web_media_player_factory() {
return web_media_player_factory_;
}
+ void set_web_media_player_factory(
+ media::WebMediaPlayerFactory* web_media_player_factory) {
+ web_media_player_factory_ = web_media_player_factory;
+ }
script::ScriptRunner* script_runner() const { return script_runner_; }
@@ -135,7 +143,7 @@
cssom::CSSParser* const css_parser_;
Parser* const dom_parser_;
media::CanPlayTypeHandler* can_play_type_handler_;
- media::WebMediaPlayerFactory* const web_media_player_factory_;
+ media::WebMediaPlayerFactory* web_media_player_factory_;
script::ScriptRunner* const script_runner_;
script::ScriptValueFactory* const script_value_factory_;
MediaSourceRegistry* const media_source_registry_;
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc
index 6db5f93..733bfd2 100644
--- a/src/cobalt/dom/node.cc
+++ b/src/cobalt/dom/node.cc
@@ -885,14 +885,14 @@
GatherInclusiveAncestorsObservers();
if (!observers->empty()) {
MutationReporter mutation_reporter(this, observers.Pass());
- scoped_refptr<dom::NodeList> added_nodes = new dom::NodeList();
+ scoped_refptr<dom::NodeList> new_added_nodes = new dom::NodeList();
if (node) {
- added_nodes->AppendNode(node);
+ new_added_nodes->AppendNode(node);
}
- if (added_nodes->length() > 0 || removed_nodes->length() > 0) {
- mutation_reporter.ReportChildListMutation(
- added_nodes, removed_nodes, NULL /* previous_sibling */,
- NULL /* next_sibling */);
+ if (new_added_nodes->length() > 0 || removed_nodes->length() > 0) {
+ mutation_reporter.ReportChildListMutation(new_added_nodes, removed_nodes,
+ NULL /* previous_sibling */,
+ NULL /* next_sibling */);
}
}
}
diff --git a/src/cobalt/dom/screen.h b/src/cobalt/dom/screen.h
index 1fd43ff..5118a4a 100644
--- a/src/cobalt/dom/screen.h
+++ b/src/cobalt/dom/screen.h
@@ -25,9 +25,12 @@
// https://www.w3.org/TR/2013/WD-cssom-view-20131217/#the-screen-interface
class Screen : public script::Wrappable {
public:
- Screen(int width, int height)
- : width_(static_cast<float>(width)),
- height_(static_cast<float>(height)) {}
+ Screen(int width, int height) { SetSize(width, height); }
+
+ void SetSize(int width, int height) {
+ width_ = static_cast<float>(width);
+ height_ = static_cast<float>(height);
+ }
// Web API
// https://www.w3.org/TR/2013/WD-cssom-view-20131217/#the-screen-interface
diff --git a/src/cobalt/dom/window.cc b/src/cobalt/dom/window.cc
index 856d46f..eaba14d 100644
--- a/src/cobalt/dom/window.cc
+++ b/src/cobalt/dom/window.cc
@@ -141,7 +141,6 @@
ALLOW_THIS_IN_INITIALIZER_LIST(
relay_on_load_event_(new RelayLoadEvent(this))),
console_(new Console(execution_state)),
- camera_3d_(new Camera3D(camera_3d)),
ALLOW_THIS_IN_INITIALIZER_LIST(window_timers_(new WindowTimers(this))),
ALLOW_THIS_IN_INITIALIZER_LIST(animation_frame_request_callback_list_(
new AnimationFrameRequestCallbackList(this))),
@@ -161,6 +160,7 @@
#endif
document_->AddObserver(relay_on_load_event_.get());
html_element_context_->page_visibility_state()->AddObserver(this);
+ SetCamera3D(camera_3d);
// Document load start is deferred from this constructor so that we can be
// guaranteed that this Window object is fully constructed before document
@@ -168,7 +168,6 @@
MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&Window::StartDocumentLoad, this, fetcher_factory,
url, dom_parser, error_callback));
- camera_3d_->StartOrientationEvents(base::AsWeakPtr(this));
}
void Window::StartDocumentLoad(
@@ -432,6 +431,28 @@
document_->set_synchronous_layout_callback(synchronous_layout_callback);
}
+void Window::SetSize(int width, int height, float device_pixel_ratio) {
+ if (width_ == width && height_ == height &&
+ device_pixel_ratio_ == device_pixel_ratio) {
+ return;
+ }
+
+ width_ = width;
+ height_ = height;
+ device_pixel_ratio_ = device_pixel_ratio;
+ screen_->SetSize(width, height);
+
+ // This will cause layout invalidation.
+ document_->SetViewport(math::Size(width, height));
+
+ PostToDispatchEvent(FROM_HERE, base::Tokens::resize());
+}
+
+void Window::SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d) {
+ camera_3d_ = new Camera3D(camera_3d);
+ camera_3d_->StartOrientationEvents(base::AsWeakPtr(this));
+}
+
void Window::OnWindowFocusChanged(bool has_focus) {
DispatchEvent(
new Event(has_focus ? base::Tokens::focus() : base::Tokens::blur()));
diff --git a/src/cobalt/dom/window.h b/src/cobalt/dom/window.h
index 1ab441c..8c669e8 100644
--- a/src/cobalt/dom/window.h
+++ b/src/cobalt/dom/window.h
@@ -30,6 +30,7 @@
#include "cobalt/dom/csp_delegate_type.h"
#include "cobalt/dom/dom_stat_tracker.h"
#include "cobalt/dom/event_target.h"
+#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/media_query_list.h"
#include "cobalt/dom/parser.h"
#if defined(ENABLE_TEST_RUNNER)
@@ -76,7 +77,6 @@
class Element;
class Event;
class History;
-class HTMLElementContext;
class LocalStorageDatabase;
class Location;
class MediaSource;
@@ -287,6 +287,21 @@
void SetSynchronousLayoutCallback(
const base::Closure& synchronous_layout_callback);
+ void SetSize(int width, int height, float device_pixel_ratio);
+
+ void SetCamera3D(const scoped_refptr<input::Camera3D>& camera_3d);
+
+ void set_can_play_type_handler(
+ media::CanPlayTypeHandler* can_play_type_handler) {
+ html_element_context_->set_can_play_type_handler(can_play_type_handler);
+ }
+
+ void set_web_media_player_factory(
+ media::WebMediaPlayerFactory* web_media_player_factory) {
+ html_element_context_->set_web_media_player_factory(
+ web_media_player_factory);
+ }
+
// Sets the current application state, forwarding on to the
// PageVisibilityState associated with it and its document, causing
// precipitate events to be dispatched.
diff --git a/src/cobalt/h5vcc/h5vcc_accessibility.cc b/src/cobalt/h5vcc/h5vcc_accessibility.cc
index d6f9aec..2f9ddb7 100644
--- a/src/cobalt/h5vcc/h5vcc_accessibility.cc
+++ b/src/cobalt/h5vcc/h5vcc_accessibility.cc
@@ -28,8 +28,8 @@
namespace h5vcc {
namespace {
-#if SB_HAS(SPEECH_SYNTHESIS)
-bool IsTextToSpeechEnabled() {
+
+bool ShouldForceTextToSpeech() {
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
// Check for a command-line override to enable TTS.
CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -37,6 +37,11 @@
return true;
}
#endif // defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
+ return false;
+}
+
+#if SB_HAS(SPEECH_SYNTHESIS)
+bool IsTextToSpeechEnabled() {
#if SB_API_VERSION >= 4
// Check if the tts feature is enabled in Starboard.
SbAccessibilityTextToSpeechSettings tts_settings = {0};
@@ -49,6 +54,7 @@
return false;
}
#endif // SB_HAS(SPEECH_SYNTHESIS)
+
} // namespace
H5vccAccessibility::H5vccAccessibility(
@@ -61,17 +67,22 @@
base::AccessibilitySettingsChangedEvent::TypeId(),
base::Bind(&H5vccAccessibility::OnApplicationEvent,
base::Unretained(this)));
+ if (ShouldForceTextToSpeech()) {
#if SB_HAS(SPEECH_SYNTHESIS)
- if (IsTextToSpeechEnabled()) {
+ // Create a StarboardTTSEngine if the platform has speech synthesis.
+ tts_engine_.reset(new accessibility::StarboardTTSEngine());
+#else
+ tts_engine_.reset(new accessibility::TTSLogger());
+#endif
+ }
+
+#if SB_HAS(SPEECH_SYNTHESIS)
+ if (!tts_engine_ && IsTextToSpeechEnabled()) {
// Create a StarboardTTSEngine if TTS is enabled.
tts_engine_.reset(new accessibility::StarboardTTSEngine());
}
-#endif // SB_HAS(SPEECH_SYNTHESIS)
-#if !defined(COBALT_BUILD_TYPE_GOLD)
- if (!tts_engine_) {
- tts_engine_.reset(new accessibility::TTSLogger());
- }
-#endif // !defined(COBALT_BUILD_TYPE_GOLD)
+#endif
+
if (tts_engine_) {
screen_reader_.reset(new accessibility::ScreenReader(
window->document(), tts_engine_.get(), mutation_observer_task_manager));
diff --git a/src/cobalt/input/input.gyp b/src/cobalt/input/input.gyp
index b220f36..5a31e33 100644
--- a/src/cobalt/input/input.gyp
+++ b/src/cobalt/input/input.gyp
@@ -21,8 +21,11 @@
'camera_3d.h',
'create_default_camera_3d.h',
'input_device_manager.h',
+ 'input_device_manager_desktop.cc',
+ 'input_device_manager_desktop.h',
'input_device_manager_fuzzer.cc',
'input_device_manager_fuzzer.h',
+ 'input_device_manager_starboard.cc',
'input_poller.h',
'input_poller_impl.cc',
'input_poller_impl.h',
@@ -40,20 +43,6 @@
'<(DEPTH)/cobalt/system_window/system_window.gyp:system_window',
],
'conditions': [
- ['OS=="starboard"', {
- 'sources': [
- 'input_device_manager_desktop.cc',
- 'input_device_manager_desktop.h',
- 'input_device_manager_starboard.cc',
- ],
- }],
- ['OS!="starboard" and actual_target_arch=="win"', {
- 'sources': [
- 'input_device_manager_<(actual_target_arch).cc',
- 'input_device_manager_desktop.cc',
- 'input_device_manager_desktop.h',
- ],
- }],
['enable_vr==1', {
'sources': [
'private/camera_3d_vr.cc',
diff --git a/src/cobalt/layout/container_box.cc b/src/cobalt/layout/container_box.cc
index fa33ea8..b7edf46 100644
--- a/src/cobalt/layout/container_box.cc
+++ b/src/cobalt/layout/container_box.cc
@@ -83,14 +83,14 @@
update_size_results_valid_ = false;
// Check to see if the split sibling is positioned, which means that it
- // needs to invalidate its cross references.
- // NOTE: Only block level and atomic inline-level elements are transformable.
- // As these are not splittable, the split sibling does not need to be checked
- // for being transformed.
- // https://www.w3.org/TR/css-transforms-1/#transformable-element
- DCHECK(!split_sibling->IsTransformable());
- if (split_sibling->IsPositioned() || split_sibling->IsStackingContext()) {
+ // needs to invalidate its containing block's cross references.
+ bool is_positioned = split_sibling->IsPositioned();
+ if (is_positioned) {
split_sibling->GetContainingBlock()->are_cross_references_valid_ = false;
+ }
+ // Check to see if the split sibling is a stacking context child, which means
+ // that it needs to invalidate its stacking context's cross references.
+ if (is_positioned || split_sibling->IsStackingContext()) {
split_sibling->GetStackingContext()->are_cross_references_valid_ = false;
}
@@ -153,6 +153,23 @@
DCHECK(negative_z_index_stacking_context_children_.empty());
GetStackingContext()->are_cross_references_valid_ = false;
}
+ } else if (computed_style()->overflow().get() ==
+ cssom::KeywordValue::GetHidden() &&
+ !IsStackingContext()) {
+ // If this container box hides overflow and isn't a stacking context, then
+ // the nearest ancestor that is a stacking context needs to be invalidated.
+ // The reason for this is that the ancestor stacking context may have
+ // stacking context children that include this container as an overflow
+ // hidden containing block.
+ // NOTE: GetStackingContext() can't simply be called, because that will
+ // incorrectly return the parent, regardless of whether or not it is a
+ // stacking context, in the case where the containing block is not
+ // positioned.
+ ContainerBox* stacking_context_ancestor = parent();
+ while (!stacking_context_ancestor->IsStackingContext()) {
+ stacking_context_ancestor = stacking_context_ancestor->parent();
+ }
+ stacking_context_ancestor->are_cross_references_valid_ = false;
}
// Invalidate the render tree nodes now that the children have changed.
diff --git a/src/cobalt/layout/layout.cc b/src/cobalt/layout/layout.cc
index 98c2d6d..1a9fb07 100644
--- a/src/cobalt/layout/layout.cc
+++ b/src/cobalt/layout/layout.cc
@@ -127,20 +127,11 @@
}
}
-scoped_refptr<render_tree::Node> Layout(
- const icu::Locale& locale, const scoped_refptr<dom::Document>& document,
- int dom_max_element_depth, UsedStyleProvider* used_style_provider,
+scoped_refptr<render_tree::Node> GenerateRenderTreeFromBoxTree(
+ UsedStyleProvider* used_style_provider,
LayoutStatTracker* layout_stat_tracker,
- icu::BreakIterator* line_break_iterator,
- icu::BreakIterator* character_break_iterator,
scoped_refptr<BlockLevelBlockContainerBox>* initial_containing_block) {
- TRACE_EVENT0("cobalt::layout", "Layout()");
- UpdateComputedStylesAndLayoutBoxTree(
- locale, document, dom_max_element_depth, used_style_provider,
- layout_stat_tracker, line_break_iterator, character_break_iterator,
- initial_containing_block);
-
- // Add to render tree.
+ TRACE_EVENT0("cobalt::layout", "GenerateRenderTreeFromBoxTree()");
render_tree::CompositionNode::Builder render_tree_root_builder;
{
TRACE_EVENT0("cobalt::layout", kBenchmarkStatRenderAndAnimate);
diff --git a/src/cobalt/layout/layout.h b/src/cobalt/layout/layout.h
index a777318..678fe54 100644
--- a/src/cobalt/layout/layout.h
+++ b/src/cobalt/layout/layout.h
@@ -38,7 +38,8 @@
// (https://www.w3.org/TR/CSS2/visuren.html) as recommended by a newer draft
// (http://dev.w3.org/csswg/css-box/) which is undergoing active changes.
-// Update the computed styles, then generate and layout the box tree.
+// Update the computed styles, then generate and layout the box tree produced
+// by the given document.
void UpdateComputedStylesAndLayoutBoxTree(
const icu::Locale& locale, const scoped_refptr<dom::Document>& document,
int dom_max_element_depth, UsedStyleProvider* used_style_provider,
@@ -47,15 +48,11 @@
icu::BreakIterator* character_break_iterator,
scoped_refptr<BlockLevelBlockContainerBox>* initial_containing_block);
-// Main entry point to the layout engine.
-// Produces the render tree (along with corresponding animations) which is a
-// result of recursive layout of the given HTML element.
-scoped_refptr<render_tree::Node> Layout(
- const icu::Locale& locale, const scoped_refptr<dom::Document>& document,
- int dom_max_element_depth, UsedStyleProvider* used_style_provider,
+// Generates the render tree (along with corresponding animations) of the box
+// tree contained within the provided containing block.
+scoped_refptr<render_tree::Node> GenerateRenderTreeFromBoxTree(
+ UsedStyleProvider* used_style_provider,
LayoutStatTracker* layout_stat_tracker,
- icu::BreakIterator* line_break_iterator,
- icu::BreakIterator* character_break_iterator,
scoped_refptr<BlockLevelBlockContainerBox>* initial_containing_block);
} // namespace layout
diff --git a/src/cobalt/layout/layout_manager.cc b/src/cobalt/layout/layout_manager.cc
index dfb4b44..e9b8319 100644
--- a/src/cobalt/layout/layout_manager.cc
+++ b/src/cobalt/layout/layout_manager.cc
@@ -59,9 +59,10 @@
void Suspend();
void Resume();
- bool IsNewRenderTreePending() const;
+ bool IsRenderTreePending() const;
private:
+ void DirtyLayout();
void StartLayoutTimer();
void DoLayoutAndProduceRenderTree();
@@ -76,11 +77,13 @@
const OnLayoutCallback on_layout_callback_;
const LayoutTrigger layout_trigger_;
- // This flag indicates whether or not we should do a re-layout. The flag
- // is checked at a regular interval (e.g. 60Hz) and if it is set to true,
- // a layout is initiated and it is set back to false. Events such as
- // DOM mutations will set this flag back to true.
- base::CVal<bool> layout_dirty_;
+ // Setting these flags triggers an update of the layout box tree and the
+ // generation of a new render tree at a regular interval (e.g. 60Hz). Events
+ // such as DOM mutations cause them to be set to true. While the render tree
+ // is excusively produced at the regular interval, the box tree can also be
+ // updated via a call to DoSynchronousLayout().
+ bool are_computed_styles_and_box_tree_dirty_;
+ base::CVal<bool> is_render_tree_pending_;
// Construction of |BreakIterator| requires a disk read, so we cache them
// in the layout manager in order to reuse them with all layouts happening
@@ -164,9 +167,10 @@
on_render_tree_produced_callback_(on_render_tree_produced),
on_layout_callback_(on_layout),
layout_trigger_(layout_trigger),
- layout_dirty_(StringPrintf("%s.Layout.IsDirty", name.c_str()), true,
- "Non-zero when the layout is dirty and a new render tree "
- "is pending."),
+ are_computed_styles_and_box_tree_dirty_(true),
+ is_render_tree_pending_(
+ StringPrintf("%s.Layout.IsRenderTreePending", name.c_str()), true,
+ "Non-zero when a new render tree is pending."),
layout_timer_(true, true, true),
dom_max_element_depth_(dom_max_element_depth),
layout_refresh_rate_(layout_refresh_rate),
@@ -210,7 +214,7 @@
#if defined(ENABLE_TEST_RUNNER)
if (layout_trigger_ == kTestRunnerMode &&
!window_->test_runner()->should_wait()) {
- layout_dirty_ = true;
+ DirtyLayout();
// Run the |DoLayoutAndProduceRenderTree| task after onload event finished.
MessageLoop::current()->PostTask(
@@ -223,7 +227,7 @@
void LayoutManager::Impl::OnMutation() {
if (layout_trigger_ == kOnDocumentMutation) {
- layout_dirty_ = true;
+ DirtyLayout();
}
}
@@ -233,11 +237,14 @@
return;
}
- layout::UpdateComputedStylesAndLayoutBoxTree(
- locale_, window_->document(), dom_max_element_depth_,
- used_style_provider_.get(), layout_stat_tracker_,
- line_break_iterator_.get(), character_break_iterator_.get(),
- &initial_containing_block_);
+ if (are_computed_styles_and_box_tree_dirty_) {
+ layout::UpdateComputedStylesAndLayoutBoxTree(
+ locale_, window_->document(), dom_max_element_depth_,
+ used_style_provider_.get(), layout_stat_tracker_,
+ line_break_iterator_.get(), character_break_iterator_.get(),
+ &initial_containing_block_);
+ are_computed_styles_and_box_tree_dirty_ = false;
+ }
}
void LayoutManager::Impl::Suspend() {
@@ -258,18 +265,18 @@
void LayoutManager::Impl::Resume() {
// Mark that we are no longer suspended and indicate that the layout is
// dirty since when Suspend() was called we invalidated our previous layout.
- layout_dirty_ = true;
+ DirtyLayout();
suspended_ = false;
}
-bool LayoutManager::Impl::IsNewRenderTreePending() const {
- return layout_dirty_;
+bool LayoutManager::Impl::IsRenderTreePending() const {
+ return is_render_tree_pending_;
}
#if defined(ENABLE_TEST_RUNNER)
void LayoutManager::Impl::DoTestRunnerLayoutCallback() {
DCHECK_EQ(kTestRunnerMode, layout_trigger_);
- layout_dirty_ = true;
+ DirtyLayout();
if (layout_trigger_ == kTestRunnerMode &&
window_->test_runner()->should_wait()) {
@@ -285,6 +292,11 @@
}
#endif // ENABLE_TEST_RUNNER
+void LayoutManager::Impl::DirtyLayout() {
+ are_computed_styles_and_box_tree_dirty_ = true;
+ is_render_tree_pending_ = true;
+}
+
void LayoutManager::Impl::StartLayoutTimer() {
// TODO: Eventually we would like to instead base our layouts off of a
// "refresh" signal generated by the rasterizer, instead of trying to
@@ -317,7 +329,7 @@
bool has_layout_processing_started = false;
if (window_->HasPendingAnimationFrameCallbacks()) {
- if (layout_dirty_) {
+ if (are_computed_styles_and_box_tree_dirty_) {
has_layout_processing_started = true;
TRACE_EVENT_BEGIN0("cobalt::layout", kBenchmarkStatLayout);
// Update our computed style before running animation callbacks, so that
@@ -334,7 +346,10 @@
window_->RunAnimationFrameCallbacks();
}
- if (layout_dirty_) {
+ // It should never be possible for for the computed styles and box tree to
+ // be dirty when a render tree is not pending.
+ DCHECK(is_render_tree_pending_ || !are_computed_styles_and_box_tree_dirty_);
+ if (is_render_tree_pending_) {
if (!has_layout_processing_started) {
// We want to catch the beginning of all layout processing. If it didn't
// begin before the call to RunAnimationFrameCallbacks(), then the flow
@@ -342,11 +357,19 @@
TRACE_EVENT_BEGIN0("cobalt::layout", kBenchmarkStatLayout);
}
- scoped_refptr<render_tree::Node> render_tree_root = layout::Layout(
- locale_, window_->document(), dom_max_element_depth_,
- used_style_provider_.get(), layout_stat_tracker_,
- line_break_iterator_.get(), character_break_iterator_.get(),
- &initial_containing_block_);
+ if (are_computed_styles_and_box_tree_dirty_) {
+ layout::UpdateComputedStylesAndLayoutBoxTree(
+ locale_, window_->document(), dom_max_element_depth_,
+ used_style_provider_.get(), layout_stat_tracker_,
+ line_break_iterator_.get(), character_break_iterator_.get(),
+ &initial_containing_block_);
+ are_computed_styles_and_box_tree_dirty_ = false;
+ }
+
+ scoped_refptr<render_tree::Node> render_tree_root =
+ layout::GenerateRenderTreeFromBoxTree(used_style_provider_.get(),
+ layout_stat_tracker_,
+ &initial_containing_block_);
bool run_on_render_tree_produced_callback = true;
#if defined(ENABLE_TEST_RUNNER)
if (layout_trigger_ == kTestRunnerMode &&
@@ -361,8 +384,7 @@
*document->timeline()->current_time())));
}
- layout_dirty_ = false;
-
+ is_render_tree_pending_ = false;
TRACE_EVENT_END0("cobalt::layout", kBenchmarkStatLayout);
}
@@ -384,8 +406,8 @@
void LayoutManager::Suspend() { impl_->Suspend(); }
void LayoutManager::Resume() { impl_->Resume(); }
-bool LayoutManager::IsNewRenderTreePending() const {
- return impl_->IsNewRenderTreePending();
+bool LayoutManager::IsRenderTreePending() const {
+ return impl_->IsRenderTreePending();
}
} // namespace layout
diff --git a/src/cobalt/layout/layout_manager.h b/src/cobalt/layout/layout_manager.h
index 6830336..1a973a5 100644
--- a/src/cobalt/layout/layout_manager.h
+++ b/src/cobalt/layout/layout_manager.h
@@ -74,7 +74,7 @@
void Suspend();
void Resume();
- bool IsNewRenderTreePending() const;
+ bool IsRenderTreePending() const;
private:
class Impl;
diff --git a/src/cobalt/loader/image/image_data_decoder.cc b/src/cobalt/loader/image/image_data_decoder.cc
index af95b3b..33e939f 100644
--- a/src/cobalt/loader/image/image_data_decoder.cc
+++ b/src/cobalt/loader/image/image_data_decoder.cc
@@ -112,9 +112,6 @@
if (!image_data_) {
DLOG(WARNING) << "Failed to allocate image data (" << size.width() << "x"
<< size.height() << ").";
- // We want to know in debug if we have problems allocating image data.
- // It should never happen.
- DCHECK(false);
}
return image_data_;
}
diff --git a/src/cobalt/loader/loader.gyp b/src/cobalt/loader/loader.gyp
index b9bdc78..b4fb1fe 100644
--- a/src/cobalt/loader/loader.gyp
+++ b/src/cobalt/loader/loader.gyp
@@ -129,6 +129,7 @@
'<(DEPTH)/testing/gtest.gyp:gtest',
'loader',
'loader_copy_test_data',
+ '<@(cobalt_platform_dependencies)',
],
},
diff --git a/src/cobalt/loader/loader_factory.cc b/src/cobalt/loader/loader_factory.cc
index b2e68eb..d65a87b 100644
--- a/src/cobalt/loader/loader_factory.cc
+++ b/src/cobalt/loader/loader_factory.cc
@@ -122,8 +122,6 @@
void LoaderFactory::Resume(render_tree::ResourceProvider* resource_provider) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(resource_provider);
- DCHECK(!resource_provider_);
- DCHECK(is_suspended_);
is_suspended_ = false;
resource_provider_ = resource_provider;
diff --git a/src/cobalt/loader/mesh/mesh_decoder.cc b/src/cobalt/loader/mesh/mesh_decoder.cc
index 2964508..556e191 100644
--- a/src/cobalt/loader/mesh/mesh_decoder.cc
+++ b/src/cobalt/loader/mesh/mesh_decoder.cc
@@ -180,7 +180,7 @@
render_tree::ResourceProvider* resource_provider, uint8_t version,
uint32_t flags, const uint8* data, size_t data_size) {
MeshDecoderSink::MeshCollectionList mesh_collection_list;
- uint32 crc = -1;
+ uint32 crc = kuint32max;
if (!DecodeBoxContents(resource_provider, version, flags, data, data_size,
&mesh_collection_list, &crc)) {
diff --git a/src/cobalt/loader/mesh/projection_codec/projection_decoder.cc b/src/cobalt/loader/mesh/projection_codec/projection_decoder.cc
index fe7a421..1635eb2 100644
--- a/src/cobalt/loader/mesh/projection_codec/projection_decoder.cc
+++ b/src/cobalt/loader/mesh/projection_codec/projection_decoder.cc
@@ -625,7 +625,7 @@
int v_index = 0;
int bits_per_vertex_index =
static_cast<int>(ceil(log2(static_cast<double>(num_verts * 2))));
- for (uint32_t i = 0; i < num_indices; ++i) {
+ for (uint32_t j = 0; j < num_indices; ++j) {
v_index += ZigZagDecode32(GetBits(bits_per_vertex_index));
// Check that this vertex index is in range before sending it off.
diff --git a/src/cobalt/media/base/decoder_buffer.cc b/src/cobalt/media/base/decoder_buffer.cc
index b01b364..919f9ca 100644
--- a/src/cobalt/media/base/decoder_buffer.cc
+++ b/src/cobalt/media/base/decoder_buffer.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "cobalt/media/base/decoder_buffer.h"
+
+#include "cobalt/build/build_config.h"
#include "starboard/memory.h"
namespace cobalt {
@@ -10,73 +12,63 @@
DecoderBuffer::ScopedAllocatorPtr::ScopedAllocatorPtr(Allocator* allocator,
Type type, size_t size)
- : allocator_(allocator), type_(type), ptr_(NULL) {
+ : allocator_(allocator), type_(type) {
if (size > 0) {
DCHECK(allocator_);
- ptr_ = static_cast<uint8_t*>(
- allocator_->Allocate(type_, size + kPaddingSize, kAlignmentSize));
- if (ptr_) {
- SbMemorySet(ptr_ + size, 0, kPaddingSize);
+ allocations_ = allocator_->Allocate(size + COBALT_MEDIA_BUFFER_PADDING,
+ COBALT_MEDIA_BUFFER_ALIGNMENT,
+ static_cast<intptr_t>(type));
+#if COBALT_MEDIA_BUFFER_PADDING > 0
+ if (allocations_.number_of_buffers() > 0) {
+ char zeros[COBALT_MEDIA_BUFFER_PADDING + 1] = {0};
+ allocations_.Write(size, zeros, COBALT_MEDIA_BUFFER_PADDING);
+ allocations_.ShrinkTo(size);
}
+#endif // COBALT_MEDIA_BUFFER_PADDING > 0
}
}
DecoderBuffer::ScopedAllocatorPtr::~ScopedAllocatorPtr() {
// |allocator_| can be NULL for EOS buffer.
- if (allocator_ && ptr_) {
- allocator_->Free(type_, ptr_);
+ if (allocator_) {
+ allocator_->Free(allocations_);
}
}
DecoderBuffer::DecoderBuffer()
- : allocator_(NULL),
- type_(DemuxerStream::UNKNOWN),
- allocated_size_(0),
- size_(0),
- data_(NULL, DemuxerStream::UNKNOWN, 0),
- side_data_size_(0),
- side_data_(NULL, DemuxerStream::UNKNOWN, 0),
+ : data_(NULL, DemuxerStream::UNKNOWN, 0),
splice_timestamp_(kNoTimestamp),
is_key_frame_(false) {}
DecoderBuffer::DecoderBuffer(Allocator* allocator, Type type, size_t size)
- : allocator_(allocator),
- type_(type),
- allocated_size_(size),
- size_(size),
- data_(allocator_, type, size),
- side_data_size_(0),
- side_data_(allocator_, type, 0),
+ : data_(allocator, type, size),
splice_timestamp_(kNoTimestamp),
is_key_frame_(false) {}
DecoderBuffer::DecoderBuffer(Allocator* allocator, Type type,
- const uint8_t* data, size_t size,
- const uint8_t* side_data, size_t side_data_size)
- : allocator_(allocator),
- type_(type),
- allocated_size_(size),
- size_(size),
- data_(allocator_, type, size),
- side_data_size_(side_data_size),
- side_data_(allocator_, type, side_data_size),
+ const uint8_t* data, size_t size)
+ : data_(allocator, type, size),
splice_timestamp_(kNoTimestamp),
is_key_frame_(false) {
if (!data) {
- CHECK_EQ(size_, 0u);
- CHECK(!side_data);
+ CHECK_EQ(size, 0u);
return;
}
- SbMemoryCopy(data_.get(), data, size_);
+ allocations().Write(0, data, size);
+}
- if (!side_data) {
- CHECK_EQ(side_data_size, 0u);
- return;
+DecoderBuffer::DecoderBuffer(Allocator* allocator, Type type,
+ Allocator::Allocations allocations)
+ : data_(allocator, type, allocations.size()),
+ splice_timestamp_(kNoTimestamp),
+ is_key_frame_(false) {
+ int offset = 0;
+ for (int i = 0; i < allocations.number_of_buffers(); ++i) {
+ this->allocations().Write(offset, allocations.buffers()[i],
+ allocations.buffer_sizes()[i]);
+ offset += allocations.buffer_sizes()[i];
}
-
- DCHECK_GT(side_data_size_, 0u);
- SbMemoryCopy(side_data_.get(), side_data, side_data_size_);
}
DecoderBuffer::~DecoderBuffer() {}
@@ -101,7 +93,7 @@
// If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
CHECK(data);
scoped_refptr<DecoderBuffer> decoder_buffer =
- new DecoderBuffer(allocator, type, data, data_size, NULL, 0);
+ new DecoderBuffer(allocator, type, data, data_size);
if (decoder_buffer->has_data()) {
return decoder_buffer;
}
@@ -109,21 +101,6 @@
}
// static
-scoped_refptr<DecoderBuffer> DecoderBuffer::CopyFrom(
- Allocator* allocator, Type type, const uint8_t* data, size_t data_size,
- const uint8_t* side_data, size_t side_data_size) {
- // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
- CHECK(data);
- CHECK(side_data);
- scoped_refptr<DecoderBuffer> decoder_buffer = new DecoderBuffer(
- allocator, type, data, data_size, side_data, side_data_size);
- if (decoder_buffer->has_data() && decoder_buffer->has_side_data()) {
- return decoder_buffer;
- }
- return NULL;
-}
-
-// static
scoped_refptr<DecoderBuffer> DecoderBuffer::CreateEOSBuffer() {
return make_scoped_refptr(new DecoderBuffer);
}
@@ -154,8 +131,7 @@
std::ostringstream s;
s << "type: " << GetTypeName()
<< " timestamp: " << timestamp_.InMicroseconds()
- << " duration: " << duration_.InMicroseconds() << " size: " << size_
- << " side_data_size: " << side_data_size_
+ << " duration: " << duration_.InMicroseconds() << " size: " << data_size()
<< " is_key_frame: " << is_key_frame_
<< " encrypted: " << (decrypt_config_ != NULL) << " discard_padding (ms): ("
<< discard_padding_.first.InMilliseconds() << ", "
diff --git a/src/cobalt/media/base/decoder_buffer.h b/src/cobalt/media/base/decoder_buffer.h
index ec7b3d7..d8b72a0 100644
--- a/src/cobalt/media/base/decoder_buffer.h
+++ b/src/cobalt/media/base/decoder_buffer.h
@@ -19,6 +19,7 @@
#include "cobalt/media/base/demuxer_stream.h"
#include "cobalt/media/base/media_export.h"
#include "cobalt/media/base/timestamp_constants.h"
+#include "nb/multipart_allocator.h"
#include "starboard/memory.h"
#include "starboard/types.h"
@@ -38,22 +39,7 @@
: public base::RefCountedThreadSafe<DecoderBuffer> {
public:
typedef DemuxerStream::Type Type;
-
- class Allocator {
- public:
- typedef DecoderBuffer::Type Type;
-
- virtual ~Allocator() {}
-
- // Allocate a memory block that contains at least |size| bytes and its
- // address is aligned to |alignment|. It returns NULL on failure.
- virtual void* Allocate(Type type, size_t size, size_t alignment) = 0;
- // Free a memory block previously allocated by calling Allocate(). No-op on
- // NULL.
- virtual void Free(Type type, void* ptr) = 0;
- };
-
- static const size_t kAlignmentSize = 128;
+ typedef nb::MultipartAllocator Allocator;
// Create a DecoderBuffer whose |data_| points to a memory with at least
// |size| bytes. Buffer will be padded and aligned as necessary.
@@ -68,15 +54,6 @@
const uint8_t* data,
size_t size);
- // Create a DecoderBuffer whose |data_| is copied from |data| and |side_data_|
- // is copied from |side_data|. Buffers will be padded and aligned as necessary
- // Data pointers must not be NULL and sizes must be >= 0. The buffer's
- // |is_key_frame_| will default to false.
- static scoped_refptr<DecoderBuffer> CopyFrom(Allocator* allocator, Type type,
- const uint8_t* data, size_t size,
- const uint8_t* side_data,
- size_t side_data_size);
-
// Create a DecoderBuffer indicating we've reached end of stream.
//
// Calling any method other than end_of_stream() on the resulting buffer
@@ -85,11 +62,11 @@
// Returns the allocator. This is usually used when creating a copy of the
// buffer.
- Allocator* allocator() const { return allocator_; }
+ Allocator* allocator() const { return data_.allocator(); }
// Gets the parser's media type associated with this buffer. Value is
// meaningless for EOS buffers.
- Type type() const { return type_; }
+ Type type() const { return data_.type(); }
const char* GetTypeName() const;
base::TimeDelta timestamp() const {
@@ -114,39 +91,21 @@
duration_ = duration;
}
- bool has_data() const { return data_.get() != NULL; }
+ bool has_data() const { return allocations().number_of_buffers() > 0; }
- const uint8_t* data() const {
- DCHECK(!end_of_stream());
- return data_.get();
+ const Allocator::Allocations& allocations() const {
+ return data_.allocations();
}
+ Allocator::Allocations& allocations() { return data_.allocations(); }
- uint8_t* writable_data() {
- DCHECK(!end_of_stream());
- return data_.get();
- }
-
- size_t allocated_size() const { return allocated_size_; }
size_t data_size() const {
DCHECK(!end_of_stream());
- return size_;
+ return data_.allocations().size();
}
void shrink_to(size_t size) {
- DCHECK_LE(size, allocated_size_);
- size_ = size;
- }
-
- bool has_side_data() const { return side_data_.get() != NULL; }
-
- const uint8_t* side_data() const {
- DCHECK(!end_of_stream());
- return side_data_.get();
- }
-
- size_t side_data_size() const {
- DCHECK(!end_of_stream());
- return side_data_size_;
+ DCHECK_GE(static_cast<int>(size), 0);
+ allocations().ShrinkTo(static_cast<int>(size));
}
// A discard window indicates the amount of data which should be discard from
@@ -176,7 +135,7 @@
}
// If there's no data in this buffer, it represents end of stream.
- bool end_of_stream() const { return data_.get() == NULL; }
+ bool end_of_stream() const { return !has_data(); }
// Indicates this buffer is part of a splice around |splice_timestamp_|.
// Returns kNoTimestamp if the buffer is not part of a splice.
@@ -220,41 +179,39 @@
// set to NULL and |buffer_size_| to 0. |is_key_frame_| will default to
// false.
DecoderBuffer(Allocator* allocator, Type type, const uint8_t* data,
- size_t size, const uint8_t* side_data, size_t side_data_size);
+ size_t size);
+
+ // Allocates a buffer to copy the data in |allocations|. Buffer will be
+ // padded and aligned as necessary. |is_key_frame_| will default to false.
+ DecoderBuffer(Allocator* allocator, Type type,
+ Allocator::Allocations allocations);
+
virtual ~DecoderBuffer();
private:
class ScopedAllocatorPtr {
public:
- // Extra bytes allocated at the end of a buffer to ensure that the buffer
- // can be use optimally by specific instructions like SIMD.
- static const size_t kPaddingSize = 32;
-
ScopedAllocatorPtr(Allocator* allocator, Type type, size_t size);
~ScopedAllocatorPtr();
- uint8_t* get() { return ptr_; }
- const uint8_t* get() const { return ptr_; }
+
+ const Allocator::Allocations& allocations() const { return allocations_; }
+ Allocator::Allocations& allocations() { return allocations_; }
+
+ Allocator* allocator() const { return allocator_; }
+ Type type() const { return type_; }
private:
Allocator* allocator_;
Type type_;
- uint8_t* ptr_;
+ Allocator::Allocations allocations_;
DISALLOW_COPY_AND_ASSIGN(ScopedAllocatorPtr);
};
- Allocator* allocator_;
-
- Type type_;
-
base::TimeDelta timestamp_;
base::TimeDelta duration_;
- const size_t allocated_size_;
- size_t size_;
ScopedAllocatorPtr data_;
- size_t side_data_size_;
- ScopedAllocatorPtr side_data_;
scoped_ptr<DecryptConfig> decrypt_config_;
DiscardPadding discard_padding_;
base::TimeDelta splice_timestamp_;
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index d91a113..cb8749c 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -161,9 +161,13 @@
return;
}
- DecodingBuffers::iterator iter = decoding_buffers_.find(buffer->data());
+ const auto& allocations = buffer->allocations();
+ DCHECK_GT(allocations.number_of_buffers(), 0);
+
+ DecodingBuffers::iterator iter =
+ decoding_buffers_.find(allocations.buffers()[0]);
if (iter == decoding_buffers_.end()) {
- decoding_buffers_[buffer->data()] = std::make_pair(buffer, 1);
+ decoding_buffers_[allocations.buffers()[0]] = std::make_pair(buffer, 1);
} else {
++iter->second.second;
}
@@ -178,30 +182,25 @@
video_info.frame_width = frame_width_;
video_info.frame_height = frame_height_;
-#if SB_API_VERSION >= 4
SbMediaColorMetadata sb_media_color_metadata =
MediaToSbMediaColorMetadata(video_config_.webm_color_metadata());
video_info.color_metadata = &sb_media_color_metadata;
-#endif
+
if (is_encrypted) {
FillDrmSampleInfo(buffer, &drm_info, &subsample_mapping);
}
-#if SB_API_VERSION >= 4
- const void* sample_buffers[] = {buffer->data()};
- int sample_buffer_sizes[] = {buffer->data_size()};
SbPlayerWriteSample(player_, DemuxerStreamTypeToSbMediaType(type),
- sample_buffers, sample_buffer_sizes, 1,
+#if SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
+ allocations.buffers(), allocations.buffer_sizes(),
+#else // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
+ const_cast<const void**>(allocations.buffers()),
+ const_cast<int*>(allocations.buffer_sizes()),
+#endif // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
+ allocations.number_of_buffers(),
TimeDeltaToSbMediaTime(buffer->timestamp()),
type == DemuxerStream::VIDEO ? &video_info : NULL,
drm_info.subsample_count > 0 ? &drm_info : NULL);
-#else // SB_API_VERSION >= 4
- SbPlayerWriteSample(player_, DemuxerStreamTypeToSbMediaType(type),
- buffer->data(), buffer->data_size(),
- TimeDeltaToSbMediaTime(buffer->timestamp()),
- type == DemuxerStream::VIDEO ? &video_info : NULL,
- drm_info.subsample_count > 0 ? &drm_info : NULL);
-#endif // SB_API_VERSION >= 4
}
void StarboardPlayer::SetBounds(const gfx::Rect& rect) {
@@ -503,9 +502,11 @@
void StarboardPlayer::ClearDecoderBufferCache() {
DCHECK(message_loop_->BelongsToCurrentThread());
- base::TimeDelta media_time;
- GetInfo(NULL, NULL, &media_time);
- decoder_buffer_cache_.ClearSegmentsBeforeMediaTime(media_time);
+ if (state_ != kResuming) {
+ base::TimeDelta media_time;
+ GetInfo(NULL, NULL, &media_time);
+ decoder_buffer_cache_.ClearSegmentsBeforeMediaTime(media_time);
+ }
message_loop_->PostDelayedTask(
FROM_HERE,
diff --git a/src/cobalt/media/base/stream_parser_buffer.cc b/src/cobalt/media/base/stream_parser_buffer.cc
index 3680f9c..dc5b14e 100644
--- a/src/cobalt/media/base/stream_parser_buffer.cc
+++ b/src/cobalt/media/base/stream_parser_buffer.cc
@@ -12,32 +12,6 @@
namespace cobalt {
namespace media {
-static scoped_refptr<StreamParserBuffer> CopyBuffer(
- const StreamParserBuffer& buffer) {
- if (buffer.end_of_stream()) return StreamParserBuffer::CreateEOSBuffer();
-
- scoped_refptr<StreamParserBuffer> copied_buffer =
- StreamParserBuffer::CopyFrom(
- buffer.allocator(), buffer.data(), buffer.data_size(),
- buffer.side_data(), buffer.side_data_size(), buffer.is_key_frame(),
- buffer.type(), buffer.track_id());
- copied_buffer->SetDecodeTimestamp(buffer.GetDecodeTimestamp());
- copied_buffer->SetConfigId(buffer.GetConfigId());
- copied_buffer->set_timestamp(buffer.timestamp());
- copied_buffer->set_duration(buffer.duration());
- copied_buffer->set_is_duration_estimated(buffer.is_duration_estimated());
- copied_buffer->set_discard_padding(buffer.discard_padding());
- copied_buffer->set_splice_timestamp(buffer.splice_timestamp());
- const DecryptConfig* decrypt_config = buffer.decrypt_config();
- if (decrypt_config) {
- copied_buffer->set_decrypt_config(scoped_ptr<DecryptConfig>(
- new DecryptConfig(decrypt_config->key_id(), decrypt_config->iv(),
- decrypt_config->subsamples())));
- }
-
- return copied_buffer;
-}
-
scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() {
return make_scoped_refptr(new StreamParserBuffer);
}
@@ -46,16 +20,7 @@
Allocator* allocator, const uint8_t* data, int data_size, bool is_key_frame,
Type type, TrackId track_id) {
return make_scoped_refptr(new StreamParserBuffer(
- allocator, data, data_size, NULL, 0, is_key_frame, type, track_id));
-}
-
-scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
- Allocator* allocator, const uint8_t* data, int data_size,
- const uint8_t* side_data, int side_data_size, bool is_key_frame, Type type,
- TrackId track_id) {
- return make_scoped_refptr(
- new StreamParserBuffer(allocator, data, data_size, side_data,
- side_data_size, is_key_frame, type, track_id));
+ allocator, data, data_size, is_key_frame, type, track_id));
}
DecodeTimestamp StreamParserBuffer::GetDecodeTimestamp() const {
@@ -77,11 +42,9 @@
StreamParserBuffer::StreamParserBuffer(Allocator* allocator,
const uint8_t* data, int data_size,
- const uint8_t* side_data,
- int side_data_size, bool is_key_frame,
- Type type, TrackId track_id)
- : DecoderBuffer(allocator, type, data, data_size, side_data,
- side_data_size),
+ bool is_key_frame, Type type,
+ TrackId track_id)
+ : DecoderBuffer(allocator, type, data, data_size),
decode_timestamp_(kNoDecodeTimestamp()),
config_id_(kInvalidConfigId),
track_id_(track_id),
@@ -96,6 +59,23 @@
if (is_key_frame) set_is_key_frame(true);
}
+StreamParserBuffer::StreamParserBuffer(Allocator* allocator,
+ Allocator::Allocations allocations,
+ bool is_key_frame, Type type,
+ TrackId track_id)
+ : DecoderBuffer(allocator, type, allocations),
+ decode_timestamp_(kNoDecodeTimestamp()),
+ config_id_(kInvalidConfigId),
+ track_id_(track_id),
+ is_duration_estimated_(false) {
+ // TODO(scherkus): Should DataBuffer constructor accept a timestamp and
+ // duration to force clients to set them? Today they end up being zero which
+ // is both a common and valid value and could lead to bugs.
+ set_duration(kNoTimestamp);
+
+ if (is_key_frame) set_is_key_frame(true);
+}
+
StreamParserBuffer::~StreamParserBuffer() {}
int StreamParserBuffer::GetConfigId() const { return config_id_; }
@@ -126,7 +106,7 @@
DCHECK(!is_duration_estimated_);
// Make a copy of this first, before making any changes.
- scoped_refptr<StreamParserBuffer> overlapping_buffer = CopyBuffer(*this);
+ scoped_refptr<StreamParserBuffer> overlapping_buffer = Clone();
overlapping_buffer->set_splice_timestamp(kNoTimestamp);
const scoped_refptr<StreamParserBuffer>& first_splice_buffer =
@@ -135,9 +115,8 @@
// Ensure the given buffers are actually before the splice point.
DCHECK(first_splice_buffer->timestamp() <= overlapping_buffer->timestamp());
- // TODO(dalecurtis): We should also clear |data| and |side_data|, but since
- // that implies EOS care must be taken to ensure there are no clients relying
- // on that behavior.
+ // TODO(dalecurtis): We should also clear |data|, but since that implies EOS
+ // care must be taken to ensure there are no clients relying on that behavior.
// Move over any preroll from this buffer.
if (preroll_buffer_.get()) {
@@ -172,7 +151,7 @@
DCHECK(!buffer->preroll_buffer().get());
DCHECK(buffer->splice_buffers().empty());
DCHECK(!buffer->is_duration_estimated());
- splice_buffers_.push_back(CopyBuffer(*buffer.get()));
+ splice_buffers_.push_back(buffer->Clone());
splice_buffers_.back()->set_splice_timestamp(splice_timestamp());
}
@@ -206,5 +185,29 @@
if (preroll_buffer_.get()) preroll_buffer_->set_timestamp(timestamp);
}
+scoped_refptr<StreamParserBuffer> StreamParserBuffer::Clone() const {
+ if (end_of_stream()) {
+ return StreamParserBuffer::CreateEOSBuffer();
+ }
+
+ scoped_refptr<StreamParserBuffer> clone = new StreamParserBuffer(
+ allocator(), allocations(), is_key_frame(), type(), track_id());
+ clone->SetDecodeTimestamp(GetDecodeTimestamp());
+ clone->SetConfigId(GetConfigId());
+ clone->set_timestamp(timestamp());
+ clone->set_duration(duration());
+ clone->set_is_duration_estimated(is_duration_estimated());
+ clone->set_discard_padding(discard_padding());
+ clone->set_splice_timestamp(splice_timestamp());
+ const DecryptConfig* decrypt_config = this->decrypt_config();
+ if (decrypt_config) {
+ clone->set_decrypt_config(scoped_ptr<DecryptConfig>(
+ new DecryptConfig(decrypt_config->key_id(), decrypt_config->iv(),
+ decrypt_config->subsamples())));
+ }
+
+ return clone;
+}
+
} // namespace media
} // namespace cobalt
diff --git a/src/cobalt/media/base/stream_parser_buffer.h b/src/cobalt/media/base/stream_parser_buffer.h
index 34bf0d6..f715824 100644
--- a/src/cobalt/media/base/stream_parser_buffer.h
+++ b/src/cobalt/media/base/stream_parser_buffer.h
@@ -112,10 +112,6 @@
static scoped_refptr<StreamParserBuffer> CopyFrom(
Allocator* allocator, const uint8_t* data, int data_size,
bool is_key_frame, Type type, TrackId track_id);
- static scoped_refptr<StreamParserBuffer> CopyFrom(
- Allocator* allocator, const uint8_t* data, int data_size,
- const uint8_t* side_data, int side_data_size, bool is_key_frame,
- Type type, TrackId track_id);
// Decode timestamp. If not explicitly set, or set to kNoTimestamp, the
// value will be taken from the normal timestamp.
@@ -176,10 +172,13 @@
// The default ctor creates an EOS buffer without specific stream type.
StreamParserBuffer();
StreamParserBuffer(Allocator* allocator, const uint8_t* data, int data_size,
- const uint8_t* side_data, int side_data_size,
+ bool is_key_frame, Type type, TrackId track_id);
+ StreamParserBuffer(Allocator* allocator, Allocator::Allocations allocations,
bool is_key_frame, Type type, TrackId track_id);
~StreamParserBuffer() OVERRIDE;
+ scoped_refptr<StreamParserBuffer> Clone() const;
+
DecodeTimestamp decode_timestamp_;
int config_id_;
TrackId track_id_;
diff --git a/src/cobalt/media/decoder_buffer_allocator.cc b/src/cobalt/media/decoder_buffer_allocator.cc
index 7097815..fd9f178 100644
--- a/src/cobalt/media/decoder_buffer_allocator.cc
+++ b/src/cobalt/media/decoder_buffer_allocator.cc
@@ -14,6 +14,9 @@
#include "cobalt/media/decoder_buffer_allocator.h"
+#include <vector>
+
+#include "nb/allocator.h"
#include "nb/memory_scope.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/configuration.h"
@@ -22,50 +25,211 @@
namespace cobalt {
namespace media {
-DecoderBufferAllocator::DecoderBufferAllocator() : memory_block_(NULL) {
- TRACK_MEMORY_SCOPE("Media");
- if (COBALT_MEDIA_BUFFER_INITIAL_CAPACITY > 0) {
- memory_block_ = SbMemoryAllocateAligned(
- DecoderBuffer::kAlignmentSize, COBALT_MEDIA_BUFFER_INITIAL_CAPACITY);
- }
+namespace {
- if (COBALT_MEDIA_BUFFER_INITIAL_CAPACITY > 0 ||
- COBALT_MEDIA_BUFFER_ALLOCATION_UNIT > 0) {
- // TODO: Support COBALT_MEDIA_BUFFER_ALLOCATION_UNIT > 0.
- memory_pool_.set(starboard::make_scoped_ptr(new nb::FirstFitMemoryPool(
- memory_block_, COBALT_MEDIA_BUFFER_INITIAL_CAPACITY)));
- }
+const bool kEnableMultiblockAllocate = false;
+const bool kEnableAllocationLog = false;
+
+const std::size_t kAllocationRecordGranularity = 512 * 1024;
+const std::size_t kSmallAllocationThreshold = 512;
+
+bool IsLargeAllocation(std::size_t size) {
+ return size > kSmallAllocationThreshold;
+}
+
+} // namespace
+
+DecoderBufferAllocator::DecoderBufferAllocator() {
+#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+#if COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND
+ DLOG(INFO) << "Allocated media buffer pool on demand.";
+#else // COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND
+ TRACK_MEMORY_SCOPE("Media");
+
+ reuse_allcator_.reset(new ReuseAllcator(&fallback_allocator_,
+ COBALT_MEDIA_BUFFER_INITIAL_CAPACITY,
+ COBALT_MEDIA_BUFFER_ALLOCATION_UNIT));
+ DLOG(INFO) << "Allocated " << COBALT_MEDIA_BUFFER_INITIAL_CAPACITY
+ << " bytes for media buffer pool as its initial buffer.";
+#endif // COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND
+#else // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+ DLOG(INFO) << "Allocated media buffer memory using SbMemory* functions.";
+#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
}
DecoderBufferAllocator::~DecoderBufferAllocator() {
- if (memory_pool_.is_valid()) {
- DCHECK_EQ(memory_pool_->GetAllocated(), 0);
- }
-
- if (memory_block_) {
- SbMemoryDeallocateAligned(memory_block_);
- }
-}
-
-void* DecoderBufferAllocator::Allocate(Type type, size_t size,
- size_t alignment) {
+#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
TRACK_MEMORY_SCOPE("Media");
- UNREFERENCED_PARAMETER(type);
- if (memory_pool_.is_valid()) {
- return memory_pool_->Allocate(size, alignment);
- }
- return SbMemoryAllocateAligned(alignment, size);
+ starboard::ScopedLock scoped_lock(mutex_);
+
+ if (reuse_allcator_) {
+ DCHECK_EQ(reuse_allcator_->GetAllocated(), 0);
+ reuse_allcator_.reset();
+ }
+#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
}
-void DecoderBufferAllocator::Free(Type type, void* ptr) {
- UNREFERENCED_PARAMETER(type);
- if (memory_pool_.is_valid()) {
- memory_pool_->Free(ptr);
- return;
+DecoderBuffer::Allocator::Allocations DecoderBufferAllocator::Allocate(
+ size_t size, size_t alignment, intptr_t context) {
+ TRACK_MEMORY_SCOPE("Media");
+
+#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+ starboard::ScopedLock scoped_lock(mutex_);
+
+ if (!reuse_allcator_) {
+ reuse_allcator_.reset(new ReuseAllcator(
+ &fallback_allocator_, COBALT_MEDIA_BUFFER_INITIAL_CAPACITY,
+ COBALT_MEDIA_BUFFER_ALLOCATION_UNIT));
+ DLOG(INFO) << "Returned " << COBALT_MEDIA_BUFFER_INITIAL_CAPACITY
+ << " bytes from media buffer pool to system.";
}
- SbMemoryDeallocateAligned(ptr);
+ if (!kEnableMultiblockAllocate || kEnableAllocationLog) {
+ void* p = reuse_allcator_->Allocate(size, alignment);
+ LOG_IF(INFO, kEnableAllocationLog)
+ << "======== Media Allocation Log " << p << " " << size << " "
+ << alignment << " " << context;
+ UpdateAllocationRecord();
+ return Allocations(p, size);
+ }
+
+ std::size_t allocated_size = size;
+ void* p =
+ reuse_allcator_->AllocateBestBlock(alignment, context, &allocated_size);
+ DCHECK_LE(allocated_size, size);
+ if (allocated_size == size) {
+ UpdateAllocationRecord();
+ return Allocations(p, size);
+ }
+
+ std::vector<void*> buffers = {p};
+ std::vector<int> buffer_sizes = {static_cast<int>(allocated_size)};
+ size -= allocated_size;
+
+ while (size > 0) {
+ allocated_size = size;
+ void* p =
+ reuse_allcator_->AllocateBestBlock(alignment, context, &allocated_size);
+ DCHECK_LE(allocated_size, size);
+ buffers.push_back(p);
+ buffer_sizes.push_back(allocated_size);
+
+ size -= allocated_size;
+ }
+ UpdateAllocationRecord(buffers.size());
+ return Allocations(static_cast<int>(buffers.size()), buffers.data(),
+ buffer_sizes.data());
+#else // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+ return Allocations(SbMemoryAllocateAligned(alignment, size), size);
+#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+}
+
+void DecoderBufferAllocator::Free(Allocations allocations) {
+ TRACK_MEMORY_SCOPE("Media");
+
+#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+ starboard::ScopedLock scoped_lock(mutex_);
+
+ DCHECK(reuse_allcator_);
+
+ if (kEnableAllocationLog) {
+ DCHECK_EQ(allocations.number_of_buffers(), 1);
+ LOG(INFO) << "======== Media Allocation Log " << allocations.buffers()[0];
+ }
+ for (int i = 0; i < allocations.number_of_buffers(); ++i) {
+ reuse_allcator_->Free(allocations.buffers()[i]);
+ }
+#if COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND
+ if (reuse_allcator_->GetAllocated() == 0) {
+ DLOG(INFO) << "Freed " << reuse_allcator_->GetCapacity()
+ << " bytes of media buffer pool `on demand`.";
+ reuse_allcator_.reset();
+ }
+#endif // COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND
+#else // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+ for (int i = 0; i < allocations.number_of_buffers(); ++i) {
+ SbMemoryDeallocateAligned(allocations.buffers()[i]);
+ }
+#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+}
+
+DecoderBufferAllocator::ReuseAllcator::ReuseAllcator(
+ Allocator* fallback_allocator, std::size_t initial_capacity,
+ std::size_t allocation_increment)
+ : BidirectionalFitReuseAllocator(fallback_allocator, initial_capacity,
+ kSmallAllocationThreshold,
+ allocation_increment) {}
+
+DecoderBufferAllocator::ReuseAllcator::FreeBlockSet::iterator
+DecoderBufferAllocator::ReuseAllcator::FindBestFreeBlock(
+ std::size_t size, std::size_t alignment, intptr_t context,
+ FreeBlockSet::iterator begin, FreeBlockSet::iterator end,
+ bool* allocate_from_front) {
+ SB_DCHECK(allocate_from_front);
+
+ auto free_block_iter =
+ FindFreeBlock(size, alignment, begin, end, allocate_from_front);
+ if (free_block_iter != end) {
+ return free_block_iter;
+ }
+
+ *allocate_from_front = IsLargeAllocation(size);
+ *allocate_from_front = context == 1;
+ if (*allocate_from_front) {
+ for (FreeBlockSet::iterator it = begin; it != end; ++it) {
+ if (it->CanFullfill(1, alignment)) {
+ return it;
+ }
+ }
+
+ return end;
+ }
+
+ FreeBlockSet::reverse_iterator rbegin(end);
+ FreeBlockSet::reverse_iterator rend(begin);
+ for (FreeBlockSet::reverse_iterator it = rbegin; it != rend; ++it) {
+ if (it->CanFullfill(1, alignment)) {
+ return --it.base();
+ }
+ }
+ return end;
+}
+
+void DecoderBufferAllocator::UpdateAllocationRecord(
+ std::size_t blocks /*= 1*/) const {
+#if !defined(COBALT_BUILD_TYPE_GOLD)
+ // This code is not quite multi-thread safe but is safe enough for tracking
+ // purposes.
+ static std::size_t max_allocated = COBALT_MEDIA_BUFFER_INITIAL_CAPACITY / 2;
+ static std::size_t max_capacity = COBALT_MEDIA_BUFFER_INITIAL_CAPACITY;
+ static std::size_t max_blocks = 1;
+
+ bool new_max_reached = false;
+ if (reuse_allcator_->GetAllocated() >
+ max_allocated + kAllocationRecordGranularity) {
+ max_allocated = reuse_allcator_->GetAllocated();
+ new_max_reached = true;
+ }
+ if (reuse_allcator_->GetCapacity() >
+ max_capacity + kAllocationRecordGranularity) {
+ max_capacity = reuse_allcator_->GetCapacity();
+ new_max_reached = true;
+ }
+ if (blocks > max_blocks) {
+ max_blocks = blocks;
+ new_max_reached = true;
+ }
+ if (new_max_reached) {
+ SB_LOG(ERROR) << "======== New Media Buffer Allocation Record ========\n"
+ << "\tMax Allocated: " << max_allocated
+ << " Max Capacity: " << max_capacity
+ << " Max Blocks: " << max_blocks;
+ // TODO: Enable the following line once PrintAllocations() accepts max line
+ // as a parameter.
+ // reuse_allcator_->PrintAllocations();
+ }
+#endif // !defined(COBALT_BUILD_TYPE_GOLD)
}
} // namespace media
diff --git a/src/cobalt/media/decoder_buffer_allocator.h b/src/cobalt/media/decoder_buffer_allocator.h
index 8fa87f2..303708a 100644
--- a/src/cobalt/media/decoder_buffer_allocator.h
+++ b/src/cobalt/media/decoder_buffer_allocator.h
@@ -17,23 +17,48 @@
#include "base/compiler_specific.h"
#include "cobalt/media/base/decoder_buffer.h"
-#include "nb/memory_pool.h"
-#include "starboard/common/locked_ptr.h"
+#include "nb/bidirectional_fit_reuse_allocator.h"
+#include "nb/starboard_memory_allocator.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/mutex.h"
namespace cobalt {
namespace media {
+#if COBALT_MEDIA_BUFFER_INITIAL_CAPACITY > 0 || \
+ COBALT_MEDIA_BUFFER_ALLOCATION_UNIT > 0
+#define COBALT_MEDIA_BUFFER_USING_MEMORY_POOL 1
+#endif // COBALT_MEDIA_BUFFER_INITIAL_CAPACITY == 0 &&
+ // COBALT_MEDIA_BUFFER_ALLOCATION_UNIT == 0
+
class DecoderBufferAllocator : public DecoderBuffer::Allocator {
public:
DecoderBufferAllocator();
~DecoderBufferAllocator() OVERRIDE;
- void* Allocate(Type type, size_t size, size_t alignment) OVERRIDE;
- void Free(Type type, void* ptr) OVERRIDE;
+ Allocations Allocate(size_t size, size_t alignment,
+ intptr_t context) OVERRIDE;
+ void Free(Allocations allocations) OVERRIDE;
private:
- void* memory_block_;
- starboard::LockedPtr<nb::FirstFitMemoryPool> memory_pool_;
+#if COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
+ class ReuseAllcator : public nb::BidirectionalFitReuseAllocator {
+ public:
+ ReuseAllcator(Allocator* fallback_allocator, std::size_t initial_capacity,
+ std::size_t allocation_increment);
+
+ FreeBlockSet::iterator FindBestFreeBlock(
+ std::size_t size, std::size_t alignment, intptr_t context,
+ FreeBlockSet::iterator begin, FreeBlockSet::iterator end,
+ bool* allocate_from_front) SB_OVERRIDE;
+ };
+
+ void UpdateAllocationRecord(std::size_t blocks = 1) const;
+
+ starboard::Mutex mutex_;
+ nb::StarboardMemoryAllocator fallback_allocator_;
+ starboard::scoped_ptr<ReuseAllcator> reuse_allcator_;
+#endif // COBALT_MEDIA_BUFFER_USING_MEMORY_POOL
};
} // namespace media
diff --git a/src/cobalt/media/filters/shell_au.cc b/src/cobalt/media/filters/shell_au.cc
index c1ac30d..0472a1b 100644
--- a/src/cobalt/media/filters/shell_au.cc
+++ b/src/cobalt/media/filters/shell_au.cc
@@ -14,6 +14,8 @@
#include "cobalt/media/filters/shell_au.h"
+#include <algorithm>
+
#include "cobalt/media/base/decoder_buffer.h"
#include "cobalt/media/base/endian_util.h"
#include "cobalt/media/base/timestamp_constants.h"
@@ -33,6 +35,38 @@
return true;
}
+bool ReadBytes(uint64 offset, size_t size, DecoderBuffer* decoder_buffer,
+ uint64 decoder_buffer_offset, ShellDataSourceReader* reader) {
+ size_t buffer_index = 0;
+ auto& allocations = decoder_buffer->allocations();
+ while (size > 0) {
+ if (buffer_index >= allocations.number_of_buffers()) {
+ NOTREACHED();
+ return false;
+ }
+ size_t buffer_size = allocations.buffer_sizes()[buffer_index];
+ if (buffer_size <= decoder_buffer_offset) {
+ decoder_buffer_offset -= buffer_size;
+ } else {
+ size_t bytes_to_read = std::min(
+ size, buffer_size - static_cast<size_t>(decoder_buffer_offset));
+ uint8_t* destination =
+ static_cast<uint8_t*>(allocations.buffers()[buffer_index]);
+ if (reader->BlockingRead(offset, bytes_to_read,
+ destination + decoder_buffer_offset) !=
+ bytes_to_read) {
+ DLOG(ERROR) << "unable to download AU";
+ return false;
+ }
+ decoder_buffer_offset = 0;
+ size -= bytes_to_read;
+ }
+ ++buffer_index;
+ }
+
+ return true;
+}
+
// ==== ShellEndOfStreamAU ==================================================
class ShellEndOfStreamAU : public ShellAU {
@@ -114,9 +148,7 @@
bool ShellAudioAU::Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) {
DCHECK_LE(size_ + prepend_size_, buffer->data_size());
- if (!ReadBytes(offset_, size_, buffer->writable_data() + prepend_size_,
- reader))
- return false;
+ if (!ReadBytes(offset_, size_, buffer, prepend_size_, reader)) return false;
if (!parser_->Prepend(this, buffer)) {
DLOG(ERROR) << "prepend fail";
@@ -183,20 +215,21 @@
bool ShellVideoAU::Read(ShellDataSourceReader* reader, DecoderBuffer* buffer) {
size_t au_left = size_; // bytes left in the AU
uint64 au_offset = offset_; // offset to read in the reader
- size_t buf_left = buffer->allocated_size(); // bytes left in the buffer
+ size_t buf_left = buffer->data_size(); // bytes left in the buffer
// The current write position in the buffer
- uint8* buf = buffer->writable_data() + prepend_size_;
+ int64_t decoder_buffer_offset = prepend_size_;
// The NALU is stored as [size][data][size][data].... We are going to
// transform it into [start code][data][start code][data]....
// The length of size is indicated by length_of_nalu_size_
- while (au_left >= length_of_nalu_size_ && buf_left >= kAnnexBStartCode) {
+ while (au_left >= length_of_nalu_size_ && buf_left >= kAnnexBStartCodeSize) {
uint8 size_buf[4];
uint32 nal_size;
// Store [start code]
- endian_util::store_uint32_big_endian(kAnnexBStartCode, buf);
- buf += kAnnexBStartCodeSize;
+ buffer->allocations().Write(decoder_buffer_offset, kAnnexBStartCode,
+ kAnnexBStartCodeSize);
+ decoder_buffer_offset += kAnnexBStartCodeSize;
buf_left -= kAnnexBStartCodeSize;
// Read [size]
@@ -218,9 +251,12 @@
if (au_left < nal_size || buf_left < nal_size) break;
// Read the [data] from reader into buf
- if (!ReadBytes(au_offset, nal_size, buf, reader)) return false;
+ if (!ReadBytes(au_offset, nal_size, buffer, decoder_buffer_offset,
+ reader)) {
+ return false;
+ }
- buf += nal_size;
+ decoder_buffer_offset += nal_size;
au_offset += nal_size;
au_left -= nal_size;
buf_left -= nal_size;
@@ -231,7 +267,7 @@
return false;
}
- size_ = buf - buffer->writable_data();
+ size_ = decoder_buffer_offset;
buffer->shrink_to(size_);
if (!parser_->Prepend(this, buffer)) {
diff --git a/src/cobalt/media/filters/shell_au.h b/src/cobalt/media/filters/shell_au.h
index 3fa5527..ffd827a 100644
--- a/src/cobalt/media/filters/shell_au.h
+++ b/src/cobalt/media/filters/shell_au.h
@@ -24,9 +24,8 @@
class ShellParser;
-// AnnexB start code is 4 bytes 0x00000001 big-endian
static const int kAnnexBStartCodeSize = 4;
-static const uint32 kAnnexBStartCode = 0x00000001;
+static const uint8_t kAnnexBStartCode[] = {0, 0, 0, 1};
// The basic unit of currency between ShellDemuxer and ShellParser, the ShellAU
// defines all needed information for a given AccessUnit (Frame) of encoded
diff --git a/src/cobalt/media/filters/shell_avc_parser.cc b/src/cobalt/media/filters/shell_avc_parser.cc
index ed3873f..70756cb 100644
--- a/src/cobalt/media/filters/shell_avc_parser.cc
+++ b/src/cobalt/media/filters/shell_avc_parser.cc
@@ -54,35 +54,37 @@
NOTREACHED() << "bad input to Prepend()";
return false;
}
- uint8* prepend_buffer = buffer->writable_data();
- if (!prepend_buffer) {
- NOTREACHED() << "empty/undersized buffer to Prepend()";
- return false;
- }
if (au->GetType() == DemuxerStream::VIDEO) {
- if (au->AddPrepend())
- SbMemoryCopy(prepend_buffer, video_prepend_, video_prepend_size_);
+ if (au->AddPrepend()) {
+ if (buffer->data_size() <= video_prepend_size_) {
+ NOTREACHED() << "empty/undersized buffer to Prepend()";
+ return false;
+ }
+ buffer->allocations().Write(0, video_prepend_, video_prepend_size_);
+ }
} else if (au->GetType() == DemuxerStream::AUDIO) {
-#if defined(COBALT_WIN)
- // We use raw AAC instead of ADTS on these platforms.
- DCHECK(audio_prepend_.empty());
- return true;
-#endif
- if (audio_prepend_.empty()) // valid ADTS header not available
+ if (audio_prepend_.size() < 6) {
+ // valid ADTS header not available
return false;
+ }
+ if (buffer->data_size() <= audio_prepend_.size()) {
+ NOTREACHED() << "empty/undersized buffer to Prepend()";
+ return false;
+ }
// audio, need to copy ADTS header and then add buffer size
uint32 buffer_size = au->GetSize() + audio_prepend_.size();
// we can't express an AU size larger than 13 bits, something's bad here.
if (buffer_size & 0xffffe000) {
return false;
}
- SbMemoryCopy(prepend_buffer, &audio_prepend_[0], audio_prepend_.size());
+ std::vector<uint8_t> audio_prepend(audio_prepend_);
// OR size into buffer, byte 3 gets 2 MSb of 13-bit size
- prepend_buffer[3] |= (uint8)((buffer_size & 0x00001800) >> 11);
+ audio_prepend[3] |= (uint8)((buffer_size & 0x00001800) >> 11);
// byte 4 gets bits 10-3 of size
- prepend_buffer[4] = (uint8)((buffer_size & 0x000007f8) >> 3);
+ audio_prepend[4] = (uint8)((buffer_size & 0x000007f8) >> 3);
// byte 5 gets bits 2-0 of size
- prepend_buffer[5] |= (uint8)((buffer_size & 0x00000007) << 5);
+ audio_prepend[5] |= (uint8)((buffer_size & 0x00000007) << 5);
+ buffer->allocations().Write(0, audio_prepend.data(), audio_prepend.size());
} else {
NOTREACHED() << "unsupported demuxer stream type.";
return false;
@@ -424,14 +426,14 @@
return false;
}
// start code for sps comes first
- endian_util::store_uint32_big_endian(kAnnexBStartCode, video_prepend_);
+ SbMemoryCopy(video_prepend_, kAnnexBStartCode, kAnnexBStartCodeSize);
// followed by sps body
SbMemoryCopy(video_prepend_ + kAnnexBStartCodeSize, sps, sps_size);
int prepend_offset = kAnnexBStartCodeSize + sps_size;
if (pps_size > 0) {
// pps start code comes next
- endian_util::store_uint32_big_endian(kAnnexBStartCode,
- video_prepend_ + prepend_offset);
+ SbMemoryCopy(video_prepend_ + prepend_offset, kAnnexBStartCode,
+ kAnnexBStartCodeSize);
prepend_offset += kAnnexBStartCodeSize;
// followed by pps
SbMemoryCopy(video_prepend_ + prepend_offset, pps, pps_size);
@@ -463,11 +465,6 @@
audio_prepend_[4] = 0;
audio_prepend_[5] &= 0x1f;
-#if defined(COBALT_WIN)
- // We use raw AAC instead of ADTS on these platforms.
- audio_prepend_.clear();
-#endif // defined(COBALT_WIN)
-
const bool kSbrInMimetype = false;
audio_config_.Initialize(
kCodecAAC, kSampleFormatS16, aac.GetChannelLayout(kSbrInMimetype),
diff --git a/src/cobalt/media/filters/shell_demuxer.cc b/src/cobalt/media/filters/shell_demuxer.cc
index 6704e5e..e81de45 100644
--- a/src/cobalt/media/filters/shell_demuxer.cc
+++ b/src/cobalt/media/filters/shell_demuxer.cc
@@ -38,7 +38,8 @@
: demuxer_(demuxer),
type_(type),
last_buffer_timestamp_(kNoTimestamp),
- stopped_(false) {
+ stopped_(false),
+ total_buffer_size_(0) {
TRACE_EVENT0("media_stack", "ShellDemuxerStream::ShellDemuxerStream()");
DCHECK(demuxer_);
}
@@ -68,6 +69,7 @@
TRACE_EVENT0("media_stack", "ShellDemuxerStream::Read() EOS sent.");
} else {
// Do not pop EOS buffers, so that subsequent read requests also get EOS
+ total_buffer_size_ -= buffer->data_size();
buffer_queue_.pop_front();
}
read_cb.Run(
@@ -134,6 +136,9 @@
} else {
// save the buffer for next read request
buffer_queue_.push_back(buffer);
+ if (!buffer->end_of_stream()) {
+ total_buffer_size_ += buffer->data_size();
+ }
}
}
@@ -142,12 +147,18 @@
return last_buffer_timestamp_;
}
+size_t ShellDemuxerStream::GetTotalBufferSize() const {
+ base::AutoLock auto_lock(lock_);
+ return total_buffer_size_;
+}
+
void ShellDemuxerStream::FlushBuffers() {
TRACE_EVENT0("media_stack", "ShellDemuxerStream::FlushBuffers()");
base::AutoLock auto_lock(lock_);
// TODO: Investigate if the following warning is valid.
DLOG_IF(WARNING, !read_queue_.empty()) << "Read requests should be empty";
buffer_queue_.clear();
+ total_buffer_size_ = 0;
last_buffer_timestamp_ = kNoTimestamp;
}
@@ -156,6 +167,7 @@
DCHECK(demuxer_->MessageLoopBelongsToCurrentThread());
base::AutoLock auto_lock(lock_);
buffer_queue_.clear();
+ total_buffer_size_ = 0;
last_buffer_timestamp_ = kNoTimestamp;
// fulfill any pending callbacks with EOS buffers set to end timestamp
for (ReadQueue::iterator it = read_queue_.begin(); it != read_queue_.end();
@@ -345,8 +357,19 @@
DCHECK(requested_au_);
if (requested_au_ && !stopped_) {
- // Note that this relies on "new DecoderBuffer" returns NULL if it is unable
- // to allocate any DecoderBuffer.
+ size_t total_buffer_size = audio_demuxer_stream_->GetTotalBufferSize() +
+ video_demuxer_stream_->GetTotalBufferSize();
+ if (total_buffer_size >= COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET) {
+ // Retry after 100 milliseconds.
+ const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(100);
+ blocking_thread_.message_loop()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ShellDemuxer::AllocateBuffer, base::Unretained(this)),
+ kDelay);
+ return;
+ }
+ // Note that "new DecoderBuffer" may return NULL if it is unable to allocate
+ // any DecoderBuffer.
scoped_refptr<DecoderBuffer> decoder_buffer(
DecoderBuffer::Create(buffer_allocator_, requested_au_->GetType(),
requested_au_->GetMaxSize()));
diff --git a/src/cobalt/media/filters/shell_demuxer.h b/src/cobalt/media/filters/shell_demuxer.h
index 8aab57d..f976278 100644
--- a/src/cobalt/media/filters/shell_demuxer.h
+++ b/src/cobalt/media/filters/shell_demuxer.h
@@ -61,6 +61,7 @@
void FlushBuffers();
void Stop();
base::TimeDelta GetLastBufferTimestamp() const;
+ size_t GetTotalBufferSize() const;
private:
// The Ranges object doesn't offer a complement object so we rebuild
@@ -91,6 +92,8 @@
typedef std::deque<ReadCB> ReadQueue;
ReadQueue read_queue_;
+ size_t total_buffer_size_;
+
DISALLOW_COPY_AND_ASSIGN(ShellDemuxerStream);
};
diff --git a/src/cobalt/media/formats/webm/webm_cluster_parser.cc b/src/cobalt/media/formats/webm/webm_cluster_parser.cc
index a8fac84..38a1234 100644
--- a/src/cobalt/media/formats/webm/webm_cluster_parser.cc
+++ b/src/cobalt/media/formats/webm/webm_cluster_parser.cc
@@ -509,9 +509,9 @@
// TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId
// type with remapped bytestream track numbers and allow multiple tracks as
// applicable. See https://crbug.com/341581.
- buffer = StreamParserBuffer::CopyFrom(
- buffer_allocator_, data + data_offset, size - data_offset, additional,
- additional_size, is_keyframe, buffer_type, track_num);
+ buffer = StreamParserBuffer::CopyFrom(buffer_allocator_, data + data_offset,
+ size - data_offset, is_keyframe,
+ buffer_type, track_num);
if (decrypt_config) buffer->set_decrypt_config(decrypt_config.Pass());
} else {
@@ -527,8 +527,7 @@
// applicable. See https://crbug.com/341581.
buffer = StreamParserBuffer::CopyFrom(
buffer_allocator_, reinterpret_cast<const uint8_t*>(content.data()),
- content.length(), &side_data[0], side_data.size(), true, buffer_type,
- track_num);
+ content.length(), true, buffer_type, track_num);
}
buffer->set_timestamp(timestamp);
diff --git a/src/cobalt/media/media.gyp b/src/cobalt/media/media.gyp
index c287bdb..30a6943 100644
--- a/src/cobalt/media/media.gyp
+++ b/src/cobalt/media/media.gyp
@@ -26,8 +26,11 @@
'fetcher_buffered_data_source.h',
'media_module.cc',
'media_module.h',
+ 'media_module_<(sb_media_platform).cc',
'media_module_stub.cc',
'media_module_stub.h',
+ 'shell_media_platform_<(sb_media_platform).cc',
+ 'shell_media_platform_<(sb_media_platform).h',
'shell_video_data_allocator_common.cc',
'shell_video_data_allocator_common.h',
'web_media_player_factory.h',
@@ -41,34 +44,12 @@
'<(DEPTH)/media/media.gyp:media',
],
'conditions': [
- ['OS=="starboard"', {
- 'sources': [
- 'media_module_<(sb_media_platform).cc',
- 'shell_media_platform_<(sb_media_platform).cc',
- 'shell_media_platform_<(sb_media_platform).h',
- ],
- }],
- ['OS=="starboard" and sb_media_platform == "ps4"', {
+ ['sb_media_platform == "ps4"', {
'sources': [
'decoder_working_memory_allocator_impl_ps4.cc',
'decoder_working_memory_allocator_impl_ps4.h',
],
}],
- ['OS=="lb_shell"', {
- 'sources': [
- 'media_module_<(actual_target_arch).cc',
- ],
- 'include_dirs': [
- '<(lbshell_root)/src',
- '<(lbshell_root)/src/platform/<(target_arch)',
- ],
- }],
- ['OS=="lb_shell" and target_arch == "ps3"', {
- 'sources': [
- 'shell_media_platform_ps3.cc',
- 'shell_media_platform_ps3.h',
- ],
- }],
['enable_map_to_mesh == 1', {
'defines' : ['ENABLE_MAP_TO_MESH'],
}],
diff --git a/src/cobalt/network/network.gyp b/src/cobalt/network/network.gyp
index e77f82c..5d7efa7 100644
--- a/src/cobalt/network/network.gyp
+++ b/src/cobalt/network/network.gyp
@@ -40,6 +40,9 @@
'persistent_cookie_store.cc',
'persistent_cookie_store.h',
'proxy_config_service.h',
+ 'starboard/network_system.cc',
+ 'starboard/proxy_config_service.cc',
+ 'starboard/user_agent_string_factory_starboard.cc',
'switches.cc',
'switches.h',
'url_request_context.cc',
@@ -76,19 +79,6 @@
'ENABLE_NETWORK_LOGGING',
],
}],
- ['OS=="starboard"', {
- 'sources': [
- 'starboard/network_system.cc',
- 'starboard/proxy_config_service.cc',
- 'starboard/user_agent_string_factory_starboard.cc',
- ],
- }, {
- 'sources': [
- '<(actual_target_arch)/network_system.cc',
- '<(actual_target_arch)/proxy_config_service.cc',
- '<(actual_target_arch)/user_agent_string_factory_<(actual_target_arch).cc',
- ],
- }],
],
'export_dependent_settings': [
'<(DEPTH)/net/net.gyp:net',
diff --git a/src/cobalt/page_visibility/page_visibility.gyp b/src/cobalt/page_visibility/page_visibility.gyp
index e943727..015f78ac 100644
--- a/src/cobalt/page_visibility/page_visibility.gyp
+++ b/src/cobalt/page_visibility/page_visibility.gyp
@@ -14,7 +14,7 @@
{
'variables': {
- 'cobalt_code': 1,
+ 'sb_pedantic_warnings': 1,
},
'targets': [
{
diff --git a/src/cobalt/page_visibility/page_visibility_state.cc b/src/cobalt/page_visibility/page_visibility_state.cc
index 56081ea..ce7efc5 100644
--- a/src/cobalt/page_visibility/page_visibility_state.cc
+++ b/src/cobalt/page_visibility/page_visibility_state.cc
@@ -14,9 +14,16 @@
#include "cobalt/page_visibility/page_visibility_state.h"
+#include "base/debug/trace_event.h"
+#include "base/stringprintf.h"
+
namespace cobalt {
namespace page_visibility {
+#define STATE_STRING(state) \
+ base::StringPrintf("%s (%d)", base::GetApplicationStateString(state), \
+ static_cast<int>(state))
+
namespace {
// Converts an ApplicationState to a VisibilityState.
VisibilityState ToVisibilityState(base::ApplicationState state) {
@@ -30,7 +37,7 @@
case base::kApplicationStateStopped:
return kVisibilityStateHidden;
default:
- NOTREACHED() << "Invalid Application State: " << state;
+ NOTREACHED() << "Invalid Application State: " << STATE_STRING(state);
return kVisibilityStateHidden;
}
}
@@ -45,22 +52,27 @@
case base::kApplicationStateStopped:
return false;
default:
- NOTREACHED() << "Invalid Application State: " << state;
+ NOTREACHED() << "Invalid Application State: " << STATE_STRING(state);
return false;
}
}
} // namespace
PageVisibilityState::PageVisibilityState()
- : application_state_(base::kApplicationStateStarted) {}
+ : application_state_(base::kApplicationStateStarted) {
+ DLOG(INFO) << __FUNCTION__
+ << ": app_state=" << STATE_STRING(application_state_);
+}
PageVisibilityState::PageVisibilityState(
base::ApplicationState initial_application_state)
: application_state_(initial_application_state) {
+ DLOG(INFO) << __FUNCTION__
+ << ": app_state=" << STATE_STRING(application_state_);
DCHECK((application_state_ == base::kApplicationStateStarted) ||
(application_state_ == base::kApplicationStatePreloading) ||
(application_state_ == base::kApplicationStatePaused))
- << "application_state_=" << application_state_;
+ << "application_state_=" << STATE_STRING(application_state_);
}
bool PageVisibilityState::HasWindowFocus() const {
@@ -72,9 +84,12 @@
}
void PageVisibilityState::SetApplicationState(base::ApplicationState state) {
+ TRACE_EVENT1("cobalt::page_visibility",
+ "PageVisibilityState::SetApplicationState", "state",
+ STATE_STRING(state).c_str());
if (application_state_ == state) {
DLOG(WARNING) << __FUNCTION__ << ": Attempt to re-enter "
- << application_state_;
+ << STATE_STRING(application_state_);
return;
}
@@ -83,30 +98,47 @@
switch (application_state_) {
case base::kApplicationStatePaused:
DCHECK(state == base::kApplicationStateSuspended ||
- state == base::kApplicationStateStarted);
+ state == base::kApplicationStateStarted)
+ << ": application_state_=" << STATE_STRING(application_state_)
+ << ", state=" << STATE_STRING(state);
+
break;
case base::kApplicationStatePreloading:
DCHECK(state == base::kApplicationStateSuspended ||
- state == base::kApplicationStateStarted);
+ state == base::kApplicationStateStarted)
+ << ": application_state_=" << STATE_STRING(application_state_)
+ << ", state=" << STATE_STRING(state);
+ break;
case base::kApplicationStateStarted:
- DCHECK(state == base::kApplicationStatePaused);
+ DCHECK(state == base::kApplicationStatePaused)
+ << ": application_state_=" << STATE_STRING(application_state_)
+ << ", state=" << STATE_STRING(state);
break;
case base::kApplicationStateStopped:
DCHECK(state == base::kApplicationStatePreloading ||
- state == base::kApplicationStateStarted);
+ state == base::kApplicationStateStarted)
+ << ": application_state_=" << STATE_STRING(application_state_)
+ << ", state=" << STATE_STRING(state);
break;
case base::kApplicationStateSuspended:
DCHECK(state == base::kApplicationStatePaused ||
- state == base::kApplicationStateStopped);
+ state == base::kApplicationStateStopped)
+ << ": application_state_=" << STATE_STRING(application_state_)
+ << ", state=" << STATE_STRING(state);
break;
default:
- NOTREACHED() << application_state_;
+ NOTREACHED() << ": application_state_="
+ << STATE_STRING(application_state_)
+ << ", state=" << STATE_STRING(state);
+
break;
}
}
bool old_has_focus = HasFocus(application_state_);
VisibilityState old_visibility_state = ToVisibilityState(application_state_);
+ DLOG(INFO) << __FUNCTION__ << ": " << STATE_STRING(application_state_)
+ << " -> " << STATE_STRING(state);
application_state_ = state;
bool has_focus = HasFocus(application_state_);
VisibilityState visibility_state = ToVisibilityState(application_state_);
diff --git a/src/cobalt/render_tree/resource_provider_stub.h b/src/cobalt/render_tree/resource_provider_stub.h
index 826c1ea..aee3f69 100644
--- a/src/cobalt/render_tree/resource_provider_stub.h
+++ b/src/cobalt/render_tree/resource_provider_stub.h
@@ -68,6 +68,7 @@
return descriptor_;
}
+ void ReleaseMemory() { memory_.reset(); }
uint8* GetMemory() OVERRIDE { return memory_.get(); }
private:
@@ -106,18 +107,16 @@
Internal::kRobotoXHeightSizeMultiplier * font_size),
glyph_bounds_(
0,
- -std::max(
- static_cast<int>(
- Internal::kDefaultCharacterRobotoGlyphHeightSizeMultiplier *
- font_size),
- 1),
+ std::max(
+ Internal::kDefaultCharacterRobotoGlyphHeightSizeMultiplier *
+ font_size,
+ 1.0f),
Internal::kDefaultCharacterRobotoGlyphWidthSizeMultiplier *
font_size,
std::max(
- static_cast<int>(
- Internal::kDefaultCharacterRobotoGlyphHeightSizeMultiplier *
- font_size),
- 1)) {}
+ Internal::kDefaultCharacterRobotoGlyphHeightSizeMultiplier *
+ font_size,
+ 1.0f)) {}
TypefaceId GetTypefaceId() const OVERRIDE { return typeface_->GetId(); }
@@ -215,6 +214,9 @@
// Return the stub versions defined above for each resource.
class ResourceProviderStub : public ResourceProvider {
public:
+ ResourceProviderStub() : release_image_data_(false) {}
+ explicit ResourceProviderStub(bool release_image_data)
+ : release_image_data_(release_image_data) {}
~ResourceProviderStub() OVERRIDE {}
void Finish() OVERRIDE {}
@@ -239,6 +241,9 @@
scoped_refptr<Image> CreateImage(scoped_ptr<ImageData> source_data) OVERRIDE {
scoped_ptr<ImageDataStub> skia_source_data(
base::polymorphic_downcast<ImageDataStub*>(source_data.release()));
+ if (release_image_data_) {
+ skia_source_data->ReleaseMemory();
+ }
return make_scoped_refptr(new ImageStub(skia_source_data.Pass()));
}
@@ -377,6 +382,8 @@
UNREFERENCED_PARAMETER(root);
return scoped_refptr<Image>(NULL);
}
+
+ bool release_image_data_;
};
} // namespace render_tree
diff --git a/src/cobalt/renderer/backend/backend.gyp b/src/cobalt/renderer/backend/backend.gyp
index b2f6e71..59c9b4a 100644
--- a/src/cobalt/renderer/backend/backend.gyp
+++ b/src/cobalt/renderer/backend/backend.gyp
@@ -25,17 +25,7 @@
'dependencies': [
'<(DEPTH)/cobalt/base/base.gyp:base',
'<(DEPTH)/cobalt/math/math.gyp:math',
- ],
- 'conditions': [
- ['OS=="starboard"', {
- 'dependencies': [
- '<(DEPTH)/cobalt/renderer/backend/starboard/platform_backend.gyp:renderer_platform_backend',
- ],
- }, {
- 'dependencies': [
- '<(DEPTH)/cobalt/renderer/backend/<(actual_target_arch)/platform_backend.gyp:renderer_platform_backend',
- ],
- }],
+ '<(DEPTH)/cobalt/renderer/backend/starboard/platform_backend.gyp:renderer_platform_backend',
],
},
],
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_object.cc b/src/cobalt/renderer/rasterizer/egl/draw_object.cc
index 1cae058..9dc8082 100644
--- a/src/cobalt/renderer/rasterizer/egl/draw_object.cc
+++ b/src/cobalt/renderer/rasterizer/egl/draw_object.cc
@@ -34,6 +34,8 @@
DrawObject::BaseState::BaseState(const BaseState& other)
: transform(other.transform),
scissor(other.scissor),
+ rounded_scissor_rect(other.rounded_scissor_rect),
+ rounded_scissor_corners(other.rounded_scissor_corners),
opacity(other.opacity) {}
DrawObject::DrawObject(const BaseState& base_state)
@@ -72,6 +74,30 @@
};
GL_CALL(glUniform4fv(rect_uniform, 1, rect_data));
+ // Tweak corners that are square-ish so they have values that play
+ // nicely with the shader. Interpolating x^2 / a^2 + y^2 / b^2 does not
+ // work well when |a| or |b| are very small.
+ if (inset_corners.top_left.horizontal <= 0.5f ||
+ inset_corners.top_left.vertical <= 0.5f) {
+ inset_corners.top_left.horizontal = 0.0f;
+ inset_corners.top_left.vertical = 0.0f;
+ }
+ if (inset_corners.top_right.horizontal <= 0.5f ||
+ inset_corners.top_right.vertical <= 0.5f) {
+ inset_corners.top_right.horizontal = 0.0f;
+ inset_corners.top_right.vertical = 0.0f;
+ }
+ if (inset_corners.bottom_left.horizontal <= 0.5f ||
+ inset_corners.bottom_left.vertical <= 0.5f) {
+ inset_corners.bottom_left.horizontal = 0.0f;
+ inset_corners.bottom_left.vertical = 0.0f;
+ }
+ if (inset_corners.bottom_right.horizontal <= 0.5f ||
+ inset_corners.bottom_right.vertical <= 0.5f) {
+ inset_corners.bottom_right.horizontal = 0.0f;
+ inset_corners.bottom_right.vertical = 0.0f;
+ }
+
// The corners data is a mat4 with each vector representing a corner
// (ordered top left, top right, bottom left, bottom right). Each corner
// vec4 represents (start.xy, radius.xy).
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_object.h b/src/cobalt/renderer/rasterizer/egl/draw_object.h
index 691b06c..cc40d09 100644
--- a/src/cobalt/renderer/rasterizer/egl/draw_object.h
+++ b/src/cobalt/renderer/rasterizer/egl/draw_object.h
@@ -43,6 +43,12 @@
math::Matrix3F transform;
math::Rect scissor;
+
+ // |rounded_scissor_rect| is only relevant when |rounded_scissor_corners|
+ // exists.
+ math::RectF rounded_scissor_rect;
+ OptionalRoundedCorners rounded_scissor_corners;
+
float opacity;
};
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.h b/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.h
index 1cc0862..85b356c 100644
--- a/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.h
+++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_color_texture.h
@@ -15,7 +15,6 @@
#ifndef COBALT_RENDERER_RASTERIZER_EGL_DRAW_RECT_COLOR_TEXTURE_H_
#define COBALT_RENDERER_RASTERIZER_EGL_DRAW_RECT_COLOR_TEXTURE_H_
-#include "base/callback.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/render_tree/color_rgba.h"
@@ -49,8 +48,6 @@
math::RectF rect_;
uint32_t color_;
const backend::TextureEGL* texture_;
- base::Closure draw_offscreen_;
- base::Closure draw_onscreen_;
uint8_t* vertex_buffer_;
float texcoord_clamp_[4]; // texcoord clamping (min u, min v, max u, max v)
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.h b/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.h
index 18363a8..756d971 100644
--- a/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.h
+++ b/src/cobalt/renderer/rasterizer/egl/draw_rect_texture.h
@@ -15,7 +15,6 @@
#ifndef COBALT_RENDERER_RASTERIZER_EGL_DRAW_RECT_TEXTURE_H_
#define COBALT_RENDERER_RASTERIZER_EGL_DRAW_RECT_TEXTURE_H_
-#include "base/callback.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/renderer/backend/egl/texture.h"
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.cc b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.cc
new file mode 100644
index 0000000..c56a4ba
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.cc
@@ -0,0 +1,116 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/renderer/rasterizer/egl/draw_rrect_color.h"
+
+#include <GLES2/gl2.h>
+
+#include "cobalt/renderer/backend/egl/utils.h"
+#include "egl/generated_shader_impl.h"
+#include "starboard/memory.h"
+
+namespace cobalt {
+namespace renderer {
+namespace rasterizer {
+namespace egl {
+
+namespace {
+const int kVertexCount = 4;
+
+struct VertexAttributes {
+ float position[2];
+ float offset[2];
+ uint32_t color;
+};
+
+void SetVertex(VertexAttributes* vertex, float x, float y, uint32_t color) {
+ vertex->position[0] = x;
+ vertex->position[1] = y;
+ vertex->offset[0] = x;
+ vertex->offset[1] = y;
+ vertex->color = color;
+}
+} // namespace
+
+DrawRRectColor::DrawRRectColor(GraphicsState* graphics_state,
+ const BaseState& base_state, const math::RectF& rect,
+ const render_tree::RoundedCorners& corners,
+ const render_tree::ColorRGBA& color)
+ : DrawObject(base_state),
+ rect_(rect),
+ corners_(corners),
+ vertex_buffer_(NULL) {
+ color_ = GetGLRGBA(color * base_state_.opacity);
+ corners_.Normalize(rect_);
+ graphics_state->ReserveVertexData(kVertexCount * sizeof(VertexAttributes));
+}
+
+void DrawRRectColor::ExecuteUpdateVertexBuffer(
+ GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) {
+ // Draw the rect with an extra pixel outset for anti-aliasing. The fragment
+ // shader will handle the rounded corners.
+ VertexAttributes attributes[kVertexCount];
+ math::RectF outer_rect(rect_);
+ outer_rect.Outset(1.0f, 1.0f);
+ SetVertex(&attributes[0], outer_rect.x(), outer_rect.y(), color_);
+ SetVertex(&attributes[1], outer_rect.right(), outer_rect.y(), color_);
+ SetVertex(&attributes[2], outer_rect.right(), outer_rect.bottom(), color_);
+ SetVertex(&attributes[3], outer_rect.x(), outer_rect.bottom(), color_);
+ vertex_buffer_ = graphics_state->AllocateVertexData(sizeof(attributes));
+ SbMemoryCopy(vertex_buffer_, attributes, sizeof(attributes));
+}
+
+void DrawRRectColor::ExecuteRasterize(
+ GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) {
+ ShaderProgram<ShaderVertexColorOffset,
+ ShaderFragmentColorRrect>* program;
+ program_manager->GetProgram(&program);
+ graphics_state->UseProgram(program->GetHandle());
+ graphics_state->UpdateClipAdjustment(
+ program->GetVertexShader().u_clip_adjustment());
+ graphics_state->UpdateTransformMatrix(
+ program->GetVertexShader().u_view_matrix(),
+ base_state_.transform);
+ graphics_state->Scissor(base_state_.scissor.x(), base_state_.scissor.y(),
+ base_state_.scissor.width(), base_state_.scissor.height());
+ graphics_state->VertexAttribPointer(
+ program->GetVertexShader().a_position(), 2, GL_FLOAT, GL_FALSE,
+ sizeof(VertexAttributes), vertex_buffer_ +
+ offsetof(VertexAttributes, position));
+ graphics_state->VertexAttribPointer(
+ program->GetVertexShader().a_color(), 4, GL_UNSIGNED_BYTE, GL_TRUE,
+ sizeof(VertexAttributes), vertex_buffer_ +
+ offsetof(VertexAttributes, color));
+ graphics_state->VertexAttribPointer(
+ program->GetVertexShader().a_offset(), 2, GL_FLOAT, GL_FALSE,
+ sizeof(VertexAttributes), vertex_buffer_ +
+ offsetof(VertexAttributes, offset));
+ graphics_state->VertexAttribFinish();
+ SetRRectUniforms(program->GetFragmentShader().u_rect(),
+ program->GetFragmentShader().u_corners(),
+ rect_, corners_, 0.5f);
+ GL_CALL(glDrawArrays(GL_TRIANGLE_FAN, 0, kVertexCount));
+}
+
+base::TypeId DrawRRectColor::GetTypeId() const {
+ return ShaderProgram<ShaderVertexColorOffset,
+ ShaderFragmentColorRrect>::GetTypeId();
+}
+
+} // namespace egl
+} // namespace rasterizer
+} // namespace renderer
+} // namespace cobalt
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.h b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.h
new file mode 100644
index 0000000..c5cd055
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color.h
@@ -0,0 +1,56 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_RENDERER_RASTERIZER_EGL_DRAW_RRECT_COLOR_H_
+#define COBALT_RENDERER_RASTERIZER_EGL_DRAW_RRECT_COLOR_H_
+
+#include "cobalt/math/rect_f.h"
+#include "cobalt/render_tree/color_rgba.h"
+#include "cobalt/render_tree/rounded_corners.h"
+#include "cobalt/renderer/rasterizer/egl/draw_object.h"
+
+namespace cobalt {
+namespace renderer {
+namespace rasterizer {
+namespace egl {
+
+// Handles drawing a colored rounded rect.
+class DrawRRectColor : public DrawObject {
+ public:
+ DrawRRectColor(GraphicsState* graphics_state,
+ const BaseState& base_state,
+ const math::RectF& rect,
+ const render_tree::RoundedCorners& corners,
+ const render_tree::ColorRGBA& color);
+
+ void ExecuteUpdateVertexBuffer(GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) OVERRIDE;
+ void ExecuteRasterize(GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) OVERRIDE;
+ base::TypeId GetTypeId() const OVERRIDE;
+
+ private:
+ math::RectF rect_;
+ render_tree::RoundedCorners corners_;
+ uint32_t color_;
+
+ uint8_t* vertex_buffer_;
+};
+
+} // namespace egl
+} // namespace rasterizer
+} // namespace renderer
+} // namespace cobalt
+
+#endif // COBALT_RENDERER_RASTERIZER_EGL_DRAW_RRECT_COLOR_H_
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.cc b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.cc
new file mode 100644
index 0000000..bad11de
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.cc
@@ -0,0 +1,180 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h"
+
+#include <GLES2/gl2.h>
+
+#include "base/basictypes.h"
+#include "cobalt/renderer/backend/egl/utils.h"
+#include "egl/generated_shader_impl.h"
+#include "starboard/memory.h"
+
+namespace cobalt {
+namespace renderer {
+namespace rasterizer {
+namespace egl {
+
+namespace {
+const int kVertexCount = 4;
+
+struct VertexAttributes {
+ float position[2];
+ float offset[2];
+ float texcoord[2];
+};
+
+void SetVertex(VertexAttributes* vertex, float x, float y, float u, float v) {
+ vertex->position[0] = x;
+ vertex->position[1] = y;
+ vertex->offset[0] = x;
+ vertex->offset[1] = y;
+ vertex->texcoord[0] = u;
+ vertex->texcoord[1] = v;
+}
+} // namespace
+
+DrawRRectColorTexture::DrawRRectColorTexture(GraphicsState* graphics_state,
+ const BaseState& base_state, const math::RectF& rect,
+ const render_tree::ColorRGBA& color, const backend::TextureEGL* texture,
+ const math::Matrix3F& texcoord_transform,
+ bool clamp_texcoords)
+ : DrawObject(base_state),
+ texcoord_transform_(texcoord_transform),
+ rect_(rect),
+ texture_(texture),
+ vertex_buffer_(NULL),
+ clamp_texcoords_(clamp_texcoords),
+ tile_texture_(false) {
+ DCHECK(base_state_.rounded_scissor_corners);
+ color_ = color * base_state_.opacity;
+ graphics_state->ReserveVertexData(kVertexCount * sizeof(VertexAttributes));
+}
+
+void DrawRRectColorTexture::ExecuteUpdateVertexBuffer(
+ GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) {
+ VertexAttributes attributes[kVertexCount];
+ SetVertex(&attributes[0], rect_.x(), rect_.y(),
+ texcoord_transform_(0, 2), texcoord_transform_(1, 2)); // uv = (0,0)
+ SetVertex(&attributes[1], rect_.right(), rect_.y(),
+ texcoord_transform_(0, 0) + texcoord_transform_(0, 2), // uv = (1,0)
+ texcoord_transform_(1, 0) + texcoord_transform_(1, 2));
+ SetVertex(&attributes[2], rect_.right(), rect_.bottom(),
+ texcoord_transform_(0, 0) + texcoord_transform_(0, 1) + // uv = (1,1)
+ texcoord_transform_(0, 2),
+ texcoord_transform_(1, 0) + texcoord_transform_(1, 1) +
+ texcoord_transform_(1, 2));
+ SetVertex(&attributes[3], rect_.x(), rect_.bottom(),
+ texcoord_transform_(0, 1) + texcoord_transform_(0, 2), // uv = (0,1)
+ texcoord_transform_(1, 1) + texcoord_transform_(1, 2));
+ vertex_buffer_ = graphics_state->AllocateVertexData(sizeof(attributes));
+ SbMemoryCopy(vertex_buffer_, attributes, sizeof(attributes));
+
+ // Find minimum and maximum texcoord values.
+ texcoord_clamp_[0] = attributes[0].texcoord[0];
+ texcoord_clamp_[1] = attributes[0].texcoord[1];
+ texcoord_clamp_[2] = attributes[0].texcoord[0];
+ texcoord_clamp_[3] = attributes[0].texcoord[1];
+ for (int i = 1; i < arraysize(attributes); ++i) {
+ float texcoord_u = attributes[i].texcoord[0];
+ float texcoord_v = attributes[i].texcoord[1];
+ if (texcoord_clamp_[0] > texcoord_u) {
+ texcoord_clamp_[0] = texcoord_u;
+ } else if (texcoord_clamp_[2] < texcoord_u) {
+ texcoord_clamp_[2] = texcoord_u;
+ }
+ if (texcoord_clamp_[1] > texcoord_v) {
+ texcoord_clamp_[1] = texcoord_v;
+ } else if (texcoord_clamp_[3] < texcoord_v) {
+ texcoord_clamp_[3] = texcoord_v;
+ }
+ }
+
+ tile_texture_ = texcoord_clamp_[0] < 0.0f || texcoord_clamp_[1] < 0.0f ||
+ texcoord_clamp_[2] > 1.0f || texcoord_clamp_[3] > 1.0f;
+
+ if (clamp_texcoords_) {
+ // Inset 0.5-epsilon so the border texels are still sampled, but nothing
+ // beyond.
+ const float kTexelInset = 0.499f;
+ texcoord_clamp_[0] += kTexelInset / texture_->GetSize().width();
+ texcoord_clamp_[1] += kTexelInset / texture_->GetSize().height();
+ texcoord_clamp_[2] -= kTexelInset / texture_->GetSize().width();
+ texcoord_clamp_[3] -= kTexelInset / texture_->GetSize().height();
+ }
+}
+
+void DrawRRectColorTexture::ExecuteRasterize(
+ GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) {
+ ShaderProgram<ShaderVertexOffsetTexcoord,
+ ShaderFragmentTexcoordColorRrect>* program;
+ program_manager->GetProgram(&program);
+ graphics_state->UseProgram(program->GetHandle());
+ graphics_state->UpdateClipAdjustment(
+ program->GetVertexShader().u_clip_adjustment());
+ graphics_state->UpdateTransformMatrix(
+ program->GetVertexShader().u_view_matrix(),
+ base_state_.transform);
+ graphics_state->Scissor(base_state_.scissor.x(), base_state_.scissor.y(),
+ base_state_.scissor.width(), base_state_.scissor.height());
+ graphics_state->VertexAttribPointer(
+ program->GetVertexShader().a_position(), 2, GL_FLOAT, GL_FALSE,
+ sizeof(VertexAttributes), vertex_buffer_ +
+ offsetof(VertexAttributes, position));
+ graphics_state->VertexAttribPointer(
+ program->GetVertexShader().a_offset(), 2, GL_FLOAT, GL_FALSE,
+ sizeof(VertexAttributes), vertex_buffer_ +
+ offsetof(VertexAttributes, offset));
+ graphics_state->VertexAttribPointer(
+ program->GetVertexShader().a_texcoord(), 2, GL_FLOAT, GL_FALSE,
+ sizeof(VertexAttributes), vertex_buffer_ +
+ offsetof(VertexAttributes, texcoord));
+ graphics_state->VertexAttribFinish();
+
+ SetRRectUniforms(program->GetFragmentShader().u_rect(),
+ program->GetFragmentShader().u_corners(),
+ base_state_.rounded_scissor_rect,
+ *base_state_.rounded_scissor_corners, 0.5f);
+ GL_CALL(glUniform4f(program->GetFragmentShader().u_color(),
+ color_.r(), color_.g(), color_.b(), color_.a()));
+ GL_CALL(glUniform4fv(program->GetFragmentShader().u_texcoord_clamp(), 1,
+ texcoord_clamp_));
+
+ if (tile_texture_) {
+ graphics_state->ActiveBindTexture(
+ program->GetFragmentShader().u_texture_texunit(),
+ texture_->GetTarget(), texture_->gl_handle(), GL_REPEAT);
+ GL_CALL(glDrawArrays(GL_TRIANGLE_FAN, 0, kVertexCount));
+ graphics_state->ActiveBindTexture(
+ program->GetFragmentShader().u_texture_texunit(),
+ texture_->GetTarget(), texture_->gl_handle(), GL_CLAMP_TO_EDGE);
+ } else {
+ graphics_state->ActiveBindTexture(
+ program->GetFragmentShader().u_texture_texunit(),
+ texture_->GetTarget(), texture_->gl_handle());
+ GL_CALL(glDrawArrays(GL_TRIANGLE_FAN, 0, kVertexCount));
+ }
+}
+
+base::TypeId DrawRRectColorTexture::GetTypeId() const {
+ return ShaderProgram<ShaderVertexOffsetTexcoord,
+ ShaderFragmentTexcoordColorRrect>::GetTypeId();
+}
+
+} // namespace egl
+} // namespace rasterizer
+} // namespace renderer
+} // namespace cobalt
diff --git a/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h
new file mode 100644
index 0000000..c65347e
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h
@@ -0,0 +1,63 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_RENDERER_RASTERIZER_EGL_DRAW_RRECT_COLOR_TEXTURE_H_
+#define COBALT_RENDERER_RASTERIZER_EGL_DRAW_RRECT_COLOR_TEXTURE_H_
+
+#include "cobalt/math/matrix3_f.h"
+#include "cobalt/math/rect_f.h"
+#include "cobalt/render_tree/color_rgba.h"
+#include "cobalt/renderer/backend/egl/texture.h"
+#include "cobalt/renderer/rasterizer/egl/draw_object.h"
+
+namespace cobalt {
+namespace renderer {
+namespace rasterizer {
+namespace egl {
+
+// Handles drawing a textured rounded rectangle modulated by a given color.
+class DrawRRectColorTexture : public DrawObject {
+ public:
+ DrawRRectColorTexture(GraphicsState* graphics_state,
+ const BaseState& base_state,
+ const math::RectF& rect,
+ const render_tree::ColorRGBA& color,
+ const backend::TextureEGL* texture,
+ const math::Matrix3F& texcoord_transform,
+ bool clamp_texcoords);
+
+ void ExecuteUpdateVertexBuffer(GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) OVERRIDE;
+ void ExecuteRasterize(GraphicsState* graphics_state,
+ ShaderProgramManager* program_manager) OVERRIDE;
+ base::TypeId GetTypeId() const OVERRIDE;
+
+ private:
+ math::Matrix3F texcoord_transform_;
+ math::RectF rect_;
+ render_tree::ColorRGBA color_;
+ const backend::TextureEGL* texture_;
+
+ uint8_t* vertex_buffer_;
+ float texcoord_clamp_[4]; // texcoord clamping (min u, min v, max u, max v)
+ bool clamp_texcoords_;
+ bool tile_texture_;
+};
+
+} // namespace egl
+} // namespace rasterizer
+} // namespace renderer
+} // namespace cobalt
+
+#endif // COBALT_RENDERER_RASTERIZER_EGL_DRAW_RRECT_COLOR_TEXTURE_H_
diff --git a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
index 3360ba3..7775f65 100644
--- a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
+++ b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.cc
@@ -15,57 +15,11 @@
#include "cobalt/renderer/rasterizer/egl/offscreen_target_manager.h"
#include <algorithm>
+#include <unordered_map>
-#include "base/hash_tables.h"
#include "cobalt/renderer/rasterizer/egl/rect_allocator.h"
#include "third_party/skia/include/core/SkRefCnt.h"
-namespace {
-// Structure describing the key for render target allocations in a given
-// offscreen target atlas.
-struct AllocationKey {
- AllocationKey(const cobalt::render_tree::Node* tree_node,
- const cobalt::math::SizeF& alloc_size)
- : node_id(tree_node->GetId()),
- size(alloc_size) {}
-
- bool operator==(const AllocationKey& other) const {
- return node_id == other.node_id && size == other.size;
- }
-
- bool operator!=(const AllocationKey& other) const {
- return node_id != other.node_id || size != other.size;
- }
-
- bool operator<(const AllocationKey& rhs) const {
- return (node_id < rhs.node_id) ||
- (node_id == rhs.node_id &&
- (size.width() < rhs.size.width() ||
- (size.width() == rhs.size.width() &&
- size.height() < rhs.size.height())));
- }
-
- int64_t node_id;
- cobalt::math::SizeF size;
-};
-} // namespace
-
-namespace BASE_HASH_NAMESPACE {
-#if defined(BASE_HASH_USE_HASH_STRUCT)
-template <>
-struct hash<AllocationKey> {
- size_t operator()(const AllocationKey& key) const {
- return static_cast<size_t>(key.node_id);
- }
-};
-#else
-template <>
-inline size_t hash_value<AllocationKey>(const AllocationKey& key) {
- return static_cast<size_t>(key.node_id);
-}
-#endif
-} // namespace BASE_HASH_NAMESPACE
-
namespace cobalt {
namespace renderer {
namespace rasterizer {
@@ -73,7 +27,15 @@
namespace {
-typedef base::hash_map<AllocationKey, math::Rect> AllocationMap;
+struct AllocationMapValue {
+ AllocationMapValue(const OffscreenTargetManager::ErrorData& in_error_data,
+ const math::RectF& in_target_region)
+ : error_data(in_error_data), target_region(in_target_region) {}
+ OffscreenTargetManager::ErrorData error_data;
+ math::RectF target_region;
+};
+
+typedef std::unordered_multimap<int64_t, AllocationMapValue> AllocationMap;
int32_t NextPowerOf2(int32_t num) {
// Return the smallest power of 2 that is greater than or equal to num.
@@ -173,23 +135,36 @@
}
bool OffscreenTargetManager::GetCachedOffscreenTarget(
- const render_tree::Node* node, const math::SizeF& size,
+ const render_tree::Node* node, const CacheErrorFunction& error_function,
TargetInfo* out_target_info) {
- AllocationMap::iterator iter = offscreen_cache_->allocation_map.find(
- AllocationKey(node, size));
- if (iter != offscreen_cache_->allocation_map.end()) {
+ // Find the cache of the given node (if any) with the lowest error.
+ AllocationMap::iterator best_iter = offscreen_cache_->allocation_map.end();
+ float best_error = 2.0f;
+
+ auto range = offscreen_cache_->allocation_map.equal_range(node->GetId());
+ for (auto iter = range.first; iter != range.second; ++iter) {
+ float error = error_function.Run(iter->second.error_data);
+ if (best_error > error) {
+ best_error = error;
+ best_iter = iter;
+ }
+ }
+
+ // A cache entry matches the caller's criteria only if error < 1.
+ if (best_error < 1.0f) {
offscreen_cache_->allocations_used += 1;
out_target_info->framebuffer = offscreen_cache_->framebuffer.get();
out_target_info->skia_canvas = offscreen_cache_->skia_surface->getCanvas();
- out_target_info->region = iter->second;
+ out_target_info->region = best_iter->second.target_region;
return true;
}
+
return false;
}
void OffscreenTargetManager::AllocateOffscreenTarget(
const render_tree::Node* node, const math::SizeF& size,
- TargetInfo* out_target_info) {
+ const ErrorData& error_data, TargetInfo* out_target_info) {
// Pad the offscreen target size to prevent interpolation with unwanted
// texels when rendering the results.
const int kInterpolatePad = 1;
@@ -200,13 +175,13 @@
DCHECK(IsPowerOf2(offscreen_target_size_mask_.width() + 1));
DCHECK(IsPowerOf2(offscreen_target_size_mask_.height() + 1));
math::Size target_size(
- (static_cast<int>(size.width()) + 2 * kInterpolatePad +
+ (static_cast<int>(std::ceil(size.width())) + 2 * kInterpolatePad +
offscreen_target_size_mask_.width()) &
~offscreen_target_size_mask_.width(),
- (static_cast<int>(size.height()) + 2 * kInterpolatePad +
+ (static_cast<int>(std::ceil(size.height())) + 2 * kInterpolatePad +
offscreen_target_size_mask_.height()) &
~offscreen_target_size_mask_.height());
- math::Rect target_rect(0, 0, 0, 0);
+ math::RectF target_rect(0.0f, 0.0f, 0.0f, 0.0f);
OffscreenAtlas* atlas = NULL;
// See if there's room in the offscreen cache for additional targets.
@@ -232,6 +207,9 @@
} else {
// Inset to prevent interpolation with unwanted pixels at the edge.
target_rect.Inset(kInterpolatePad, kInterpolatePad);
+ DCHECK_LE(size.width(), target_rect.width());
+ DCHECK_LE(size.height(), target_rect.height());
+ target_rect.set_size(size);
// Clear the atlas if this will be the first draw into it.
if (atlas->allocation_map.empty()) {
@@ -239,7 +217,7 @@
}
atlas->allocation_map.insert(AllocationMap::value_type(
- AllocationKey(node, size), target_rect));
+ node->GetId(), AllocationMapValue(error_data, target_rect)));
atlas->allocations_used += 1;
atlas->needs_flush = true;
diff --git a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
index 02c0704..3dc7803 100644
--- a/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
+++ b/src/cobalt/renderer/rasterizer/egl/offscreen_target_manager.h
@@ -48,6 +48,14 @@
math::RectF region;
};
+ // Offscreen targets are cached with additional ErrorData. When searching for
+ // a match, the caller specifies an error function which is used to verify
+ // that a particular cache entry is suitable for use. A cache entry is
+ // suitable if CacheErrorFunction(ErrorData) < 1. If multiple entries meet
+ // this criteria, then the entry with the lowest error is chosen.
+ typedef math::RectF ErrorData;
+ typedef base::Callback<float(const ErrorData&)> CacheErrorFunction;
+
OffscreenTargetManager(backend::GraphicsContextEGL* graphics_context,
const CreateFallbackSurfaceFunction& create_fallback_surface,
size_t memory_limit);
@@ -65,14 +73,14 @@
// otherwise, they are untouched.
// The returned values are only valid until the next call to Update().
bool GetCachedOffscreenTarget(
- const render_tree::Node* node, const math::SizeF& size,
+ const render_tree::Node* node, const CacheErrorFunction& error_function,
TargetInfo* out_target_info);
// Allocate an offscreen target of the specified size.
// The returned values are only valid until the next call to Update().
void AllocateOffscreenTarget(
const render_tree::Node* node, const math::SizeF& size,
- TargetInfo* out_target_info);
+ const ErrorData& error_data, TargetInfo* out_target_info);
private:
// Use an atlas for offscreen targets.
diff --git a/src/cobalt/renderer/rasterizer/egl/rasterizer.gyp b/src/cobalt/renderer/rasterizer/egl/rasterizer.gyp
index 42e592e..9fc7942 100644
--- a/src/cobalt/renderer/rasterizer/egl/rasterizer.gyp
+++ b/src/cobalt/renderer/rasterizer/egl/rasterizer.gyp
@@ -57,6 +57,10 @@
'draw_rect_shadow_blur.cc',
'draw_rect_texture.h',
'draw_rect_texture.cc',
+ 'draw_rrect_color.h',
+ 'draw_rrect_color.cc',
+ 'draw_rrect_color_texture.h',
+ 'draw_rrect_color_texture.cc',
'graphics_state.h',
'graphics_state.cc',
'hardware_rasterizer.cc',
diff --git a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
index b3c6c7b..88d6bdd 100644
--- a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
@@ -34,6 +34,8 @@
#include "cobalt/renderer/rasterizer/egl/draw_rect_shadow_blur.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_texture.h"
+#include "cobalt/renderer/rasterizer/egl/draw_rrect_color.h"
+#include "cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h"
#include "cobalt/renderer/rasterizer/skia/hardware_image.h"
#include "cobalt/renderer/rasterizer/skia/image.h"
@@ -71,6 +73,75 @@
0, 0, 1);
}
+bool ImageNodeSupportedNatively(render_tree::ImageNode* image_node) {
+ skia::Image* skia_image = base::polymorphic_downcast<skia::Image*>(
+ image_node->data().source.get());
+ if (skia_image->GetTypeId() == base::GetTypeId<skia::SinglePlaneImage>() &&
+ skia_image->CanRenderInSkia()) {
+ return true;
+ }
+ return false;
+}
+
+bool RoundedViewportSupportedForSource(render_tree::Node* source) {
+ base::TypeId source_type = source->GetTypeId();
+ if (source_type == base::GetTypeId<render_tree::ImageNode>()) {
+ render_tree::ImageNode* image_node =
+ base::polymorphic_downcast<render_tree::ImageNode*>(source);
+ return ImageNodeSupportedNatively(image_node);
+ } else if (source_type == base::GetTypeId<render_tree::CompositionNode>()) {
+ // If this is a composition of valid sources, then rendering with a rounded
+ // viewport is also supported.
+ render_tree::CompositionNode* composition_node =
+ base::polymorphic_downcast<render_tree::CompositionNode*>(source);
+ typedef render_tree::CompositionNode::Children Children;
+ const Children& children = composition_node->data().children();
+
+ for (Children::const_iterator iter = children.begin();
+ iter != children.end(); ++iter) {
+ if (!RoundedViewportSupportedForSource(iter->get())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+// Return the error value of a given offscreen taget cache entry.
+// |desired_bounds| specifies the world-space bounds to which an offscreen
+// target will be rendered.
+// |cached_bounds| specifies the world-space bounds used when the offscreen
+// target was generated.
+// Lower return values indicate better fits. Only cache entries with an error
+// less than 1 will be considered suitable.
+float OffscreenTargetErrorFunction(const math::RectF& desired_bounds,
+ const math::RectF& cached_bounds) {
+ // The cached contents must be within 0.5 pixels of the desired size to avoid
+ // scaling artifacts.
+ if (std::abs(desired_bounds.width() - cached_bounds.width()) >= 0.5f ||
+ std::abs(desired_bounds.height() - cached_bounds.height()) >= 0.5f) {
+ return 1.0f;
+ }
+
+ // The cached contents' sub-pixel offset must be within 0.5 pixels to ensure
+ // appropriate positioning.
+ math::PointF desired_offset(
+ desired_bounds.x() - std::floor(desired_bounds.x()),
+ desired_bounds.y() - std::floor(desired_bounds.y()));
+ math::PointF cached_offset(
+ cached_bounds.x() - std::floor(cached_bounds.x()),
+ cached_bounds.y() - std::floor(cached_bounds.y()));
+ float error_x = std::abs(desired_offset.x() - cached_offset.x());
+ float error_y = std::abs(desired_offset.y() - cached_offset.y());
+ if (error_x >= 0.5f || error_y >= 0.5f) {
+ return 1.0f;
+ }
+
+ return error_x + error_y;
+}
+
} // namespace
RenderTreeNodeVisitor::RenderTreeNodeVisitor(GraphicsState* graphics_state,
@@ -99,12 +170,14 @@
math::Matrix3F old_transform = draw_state_.transform;
draw_state_.transform = draw_state_.transform *
math::TranslateMatrix(data.offset().x(), data.offset().y());
+ draw_state_.rounded_scissor_rect.Offset(-data.offset());
const render_tree::CompositionNode::Children& children =
data.children();
for (render_tree::CompositionNode::Children::const_iterator iter =
children.begin(); iter != children.end(); ++iter) {
(*iter)->Accept(this);
}
+ draw_state_.rounded_scissor_rect.Offset(data.offset());
draw_state_.transform = old_transform;
}
@@ -130,16 +203,30 @@
void RenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) {
const render_tree::FilterNode::Builder& data = filter_node->data();
- // If this is only a viewport filter w/o rounded edges, and the current
- // transform matrix keeps the filter as an orthogonal rect, then collapse
- // the node.
+ // Handle viewport-only filter.
if (data.viewport_filter &&
- !data.viewport_filter->has_rounded_corners() &&
!data.opacity_filter &&
!data.blur_filter &&
!data.map_to_mesh_filter) {
const math::Matrix3F& transform = draw_state_.transform;
- if (IsOnlyScaleAndTranslate(transform)) {
+ if (data.viewport_filter->has_rounded_corners()) {
+ // Certain source nodes have an optimized path for rendering inside
+ // rounded viewports.
+ if (RoundedViewportSupportedForSource(data.source)) {
+ DCHECK(!draw_state_.rounded_scissor_corners);
+ draw_state_.rounded_scissor_rect = data.viewport_filter->viewport();
+ draw_state_.rounded_scissor_corners =
+ data.viewport_filter->rounded_corners();
+ draw_state_.rounded_scissor_corners->Normalize(
+ draw_state_.rounded_scissor_rect);
+ data.source->Accept(this);
+ draw_state_.rounded_scissor_corners = base::nullopt;
+ return;
+ }
+ } else if (IsOnlyScaleAndTranslate(transform)) {
+ // Orthogonal viewport filters without rounded corners can be collapsed
+ // into the world-space scissor.
+
// Transform local viewport to world viewport.
const math::RectF& filter_viewport = data.viewport_filter->viewport();
math::RectF transformed_viewport(
@@ -254,6 +341,11 @@
return;
}
+ if (!ImageNodeSupportedNatively(image_node)) {
+ FallbackRasterize(image_node);
+ return;
+ }
+
skia::Image* skia_image =
base::polymorphic_downcast<skia::Image*>(data.source.get());
bool clamp_texcoords = false;
@@ -299,7 +391,14 @@
return;
}
- if (clamp_texcoords || !is_opaque) {
+ if (draw_state_.rounded_scissor_corners) {
+ // Transparency is used to anti-alias the rounded rect.
+ is_opaque = false;
+ draw.reset(new DrawRRectColorTexture(graphics_state_, draw_state_,
+ data.destination_rect, kOpaqueWhite,
+ hardware_image->GetTextureEGL(), texcoord_transform,
+ clamp_texcoords));
+ } else if (clamp_texcoords || !is_opaque) {
draw.reset(new DrawRectColorTexture(graphics_state_, draw_state_,
data.destination_rect, kOpaqueWhite,
hardware_image->GetTextureEGL(), texcoord_transform,
@@ -365,7 +464,8 @@
// offscreen target, then use a single shader to render those.
const bool border_supported = !data.border;
- if (data.rounded_corners) {
+ if (data.rounded_corners && brush &&
+ brush->GetTypeId() != base::GetTypeId<render_tree::SolidColorBrush>()) {
FallbackRasterize(rect_node);
} else if (!brush_supported) {
FallbackRasterize(rect_node);
@@ -373,7 +473,6 @@
FallbackRasterize(rect_node);
} else {
DCHECK(!data.border);
- const math::RectF& content_rect(data.rect);
// Handle drawing the content.
if (brush) {
@@ -383,26 +482,33 @@
base::polymorphic_downcast<const render_tree::SolidColorBrush*>
(brush.get());
const render_tree::ColorRGBA& brush_color(solid_brush->color());
- render_tree::ColorRGBA content_color(
+ render_tree::ColorRGBA color(
brush_color.r() * brush_color.a(),
brush_color.g() * brush_color.a(),
brush_color.b() * brush_color.a(),
brush_color.a());
- scoped_ptr<DrawObject> draw(new DrawPolyColor(graphics_state_,
- draw_state_, content_rect, content_color));
- if (draw_state_.opacity * content_color.a() == 1.0f) {
- AddOpaqueDraw(draw.Pass(), rect_node->GetBounds());
- } else {
+ if (data.rounded_corners) {
+ scoped_ptr<DrawObject> draw(new DrawRRectColor(graphics_state_,
+ draw_state_, data.rect, *data.rounded_corners, color));
+ // Transparency is used for anti-aliasing.
AddTransparentDraw(draw.Pass(), rect_node->GetBounds());
+ } else {
+ scoped_ptr<DrawObject> draw(new DrawPolyColor(graphics_state_,
+ draw_state_, data.rect, color));
+ if (draw_state_.opacity * color.a() == 1.0f) {
+ AddOpaqueDraw(draw.Pass(), rect_node->GetBounds());
+ } else {
+ AddTransparentDraw(draw.Pass(), rect_node->GetBounds());
+ }
}
} else {
const render_tree::LinearGradientBrush* linear_brush =
base::polymorphic_downcast<const render_tree::LinearGradientBrush*>
(brush.get());
scoped_ptr<DrawObject> draw(new DrawRectLinearGradient(graphics_state_,
- draw_state_, content_rect, *linear_brush));
+ draw_state_, data.rect, *linear_brush));
// The draw may use transparent pixels to ensure only pixels in the
- // content_rect are modified.
+ // specified area are modified.
AddTransparentDraw(draw.Pass(), rect_node->GetBounds());
}
}
@@ -490,7 +596,7 @@
math::RectF* out_content_rect) {
// Default to telling the caller that nothing should be rendered.
*out_content_cached = true;
- out_content_rect->SetRect(0, 0, 0, 0);
+ out_content_rect->SetRect(0.0f, 0.0f, 0.0f, 0.0f);
if (!allow_offscreen_targets_) {
failed_offscreen_target_request_ = true;
@@ -506,48 +612,37 @@
// Request a slightly larger render target than the calculated bounds. The
// rasterizer may use an extra pixel along the edge of anti-aliased objects.
const float kBorderWidth = 1.0f;
-
- // The render target cache keys off the render_tree Node and target size.
- // Since the size is rounded, it is possible to be a fraction of a pixel
- // off. However, this in turn allows for a cache hit for "close-enough"
- // renderings. To minimize offset errors, use the nearest full pixel offset.
- const float kFractionPad = 1.0f;
- float offset_x = std::floor(mapped_bounds.x() + 0.5f);
- float offset_y = std::floor(mapped_bounds.y() + 0.5f);
math::PointF content_offset(
- offset_x - kBorderWidth - kFractionPad,
- offset_y - kBorderWidth - kFractionPad);
+ std::floor(mapped_bounds.x() - kBorderWidth),
+ std::floor(mapped_bounds.y() - kBorderWidth));
math::SizeF content_size(
- std::ceil(mapped_bounds.width() + 2.0f * kBorderWidth + kFractionPad),
- std::ceil(mapped_bounds.height() + 2.0f * kBorderWidth + kFractionPad));
+ std::ceil(mapped_bounds.right() + kBorderWidth - content_offset.x()),
+ std::ceil(mapped_bounds.bottom() + kBorderWidth - content_offset.y()));
+
+ // Get a suitable cache of the render tree node if one exists, or allocate
+ // a new offscreen target if possible. The OffscreenTargetErrorFunction will
+ // determine whether any caches are fit for use.
*out_content_cached = offscreen_target_manager_->GetCachedOffscreenTarget(
- node, content_size, out_target_info);
+ node, base::Bind(&OffscreenTargetErrorFunction, mapped_bounds),
+ out_target_info);
if (!(*out_content_cached)) {
offscreen_target_manager_->AllocateOffscreenTarget(node,
- content_size, out_target_info);
+ content_size, mapped_bounds, out_target_info);
}
- // If no offscreen target was available, then set the content_rect as if
- // rendering will occur on the current render target.
+ // If no offscreen target could be allocated, then the render tree node will
+ // be rendered directly onto the main framebuffer. Use the current scissor
+ // to minimize what has to be drawn.
if (out_target_info->framebuffer == nullptr) {
- mapped_bounds.Outset(kBorderWidth, kBorderWidth);
- mapped_bounds.Intersect(draw_state_.scissor);
- if (mapped_bounds.IsEmpty()) {
+ math::RectF content_bounds(content_offset, content_size);
+ content_bounds.Intersect(draw_state_.scissor);
+ if (content_bounds.IsEmpty()) {
return;
}
- float left = std::floor(mapped_bounds.x());
- float right = std::ceil(mapped_bounds.right());
- float top = std::floor(mapped_bounds.y());
- float bottom = std::ceil(mapped_bounds.bottom());
- content_offset.SetPoint(left, top);
- content_size.SetSize(right - left, bottom - top);
- } else {
- DCHECK_LE(content_size.width(), out_target_info->region.width());
- DCHECK_LE(content_size.height(), out_target_info->region.height());
+ content_offset = content_bounds.origin();
+ content_size = content_bounds.size();
}
- out_target_info->region.set_size(content_size);
-
out_content_rect->set_origin(content_offset);
out_content_rect->set_size(content_size);
}
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_between_rrects.glsl b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_between_rrects.glsl
index 5e400d1..f2897ad 100644
--- a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_between_rrects.glsl
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_between_rrects.glsl
@@ -26,43 +26,10 @@
varying vec2 v_offset;
varying vec4 v_color;
-// Return 0 if the current point is inside the rounded rect, or scale towards 1
-// as it goes outside a 1-pixel anti-aliasing border.
-float GetRRectScale(vec4 rect, mat4 corners) {
- vec4 select_corner = vec4(
- step(v_offset.x, corners[0].x) * step(v_offset.y, corners[0].y),
- step(corners[1].x, v_offset.x) * step(v_offset.y, corners[1].y),
- step(v_offset.x, corners[2].x) * step(corners[2].y, v_offset.y),
- step(corners[3].x, v_offset.x) * step(corners[3].y, v_offset.y));
- if (dot(select_corner, vec4(1.0)) > 0.5) {
- // Estimate the amount of anti-aliasing that should be used by comparing
- // x^2 / a^2 + y^2 / b^2 for the ellipse and ellipse + 1 pixel.
- vec4 corner = corners * select_corner;
- vec2 pixel_offset = v_offset - corner.xy;
-
- if (corner.z * corner.w < 0.1) {
- // This is a square corner.
- return min(length(pixel_offset), 1.0);
- }
-
- vec2 offset_min = pixel_offset / corner.zw;
- vec2 offset_max = pixel_offset / (corner.zw + vec2(1.0));
- float result_min = dot(offset_min, offset_min);
- float result_max = dot(offset_max, offset_max);
-
- // Return 1.0 if outside, or interpolate if in the border, or 0 if inside.
- return (result_max >= 1.0) ? 1.0 :
- max(result_min - 1.0, 0.0) / (result_min - result_max);
- }
-
- return clamp(rect.x - v_offset.x, 0.0, 1.0) +
- clamp(v_offset.x - rect.z, 0.0, 1.0) +
- clamp(rect.y - v_offset.y, 0.0, 1.0) +
- clamp(v_offset.y - rect.w, 0.0, 1.0);
-}
+#include "function_is_outside_rrect.inc"
void main() {
- float inner_scale = GetRRectScale(u_inner_rect, u_inner_corners);
- float outer_scale = GetRRectScale(u_outer_rect, u_outer_corners);
- gl_FragColor = v_color * inner_scale * (1.0 - outer_scale);
+ float inner_scale = IsOutsideRRect(v_offset, u_inner_rect, u_inner_corners);
+ float outer_scale = IsOutsideRRect(v_offset, u_outer_rect, u_outer_corners);
+ gl_FragColor = v_color * (inner_scale * (1.0 - outer_scale));
}
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_blur_rrects.glsl b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_blur_rrects.glsl
index 120b988..1d17a97 100644
--- a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_blur_rrects.glsl
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_blur_rrects.glsl
@@ -41,40 +41,7 @@
varying vec2 v_offset;
varying vec4 v_color;
-// Return 0 if the current point is inside the rounded rect, or scale towards 1
-// as it goes outside a 1-pixel anti-aliasing border.
-float GetRRectScale(vec4 rect, mat4 corners) {
- vec4 select_corner = vec4(
- step(v_offset.x, corners[0].x) * step(v_offset.y, corners[0].y),
- step(corners[1].x, v_offset.x) * step(v_offset.y, corners[1].y),
- step(v_offset.x, corners[2].x) * step(corners[2].y, v_offset.y),
- step(corners[3].x, v_offset.x) * step(corners[3].y, v_offset.y));
- if (dot(select_corner, vec4(1.0)) > 0.5) {
- // Estimate the amount of anti-aliasing that should be used by comparing
- // x^2 / a^2 + y^2 / b^2 for the ellipse and ellipse + 1 pixel.
- vec4 corner = corners * select_corner;
- vec2 pixel_offset = v_offset - corner.xy;
-
- if (corner.z * corner.w < 0.1) {
- // This is a square corner.
- return min(length(pixel_offset), 1.0);
- }
-
- vec2 offset_min = pixel_offset / corner.zw;
- vec2 offset_max = pixel_offset / (corner.zw + vec2(1.0));
- float result_min = dot(offset_min, offset_min);
- float result_max = dot(offset_max, offset_max);
-
- // Return 1.0 if outside, or interpolate if in the border, or 0 if inside.
- return (result_max >= 1.0) ? 1.0 :
- max(result_min - 1.0, 0.0) / (result_min - result_max);
- }
-
- return clamp(rect.x - v_offset.x, 0.0, 1.0) +
- clamp(v_offset.x - rect.z, 0.0, 1.0) +
- clamp(rect.y - v_offset.y, 0.0, 1.0) +
- clamp(v_offset.y - rect.w, 0.0, 1.0);
-}
+#include "function_is_outside_rrect.inc"
// Calculate the distance from a point in the first quadrant to an ellipse
// centered at the origin.
@@ -161,8 +128,9 @@
}
void main() {
- float scissor_scale = GetRRectScale(u_scissor_rect, u_scissor_corners) *
- u_scale_add.x + u_scale_add.y;
+ float scissor_scale =
+ IsOutsideRRect(v_offset, u_scissor_rect, u_scissor_corners) *
+ u_scale_add.x + u_scale_add.y;
vec2 pos = GetBlurPosition(u_spread_rect, u_spread_corners) *
u_sigma_scale + u_sigma_tweak;
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_rrect.glsl b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_rrect.glsl
new file mode 100644
index 0000000..26549ed
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_rrect.glsl
@@ -0,0 +1,32 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+precision mediump float;
+
+// A rounded rect is represented by a vec4 specifying (min.xy, max.xy), and a
+// matrix of corners. Each vector in the matrix represents a corner (order:
+// top left, top right, bottom left, bottom right). Each corner vec4 represents
+// (start.xy, radius.xy).
+uniform vec4 u_rect;
+uniform mat4 u_corners;
+
+varying vec2 v_offset;
+varying vec4 v_color;
+
+#include "function_is_outside_rrect.inc"
+
+void main() {
+ float scale = IsOutsideRRect(v_offset, u_rect, u_corners);
+ gl_FragColor = v_color * (1.0 - scale);
+}
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_texcoord_color_rrect.glsl b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_texcoord_color_rrect.glsl
new file mode 100644
index 0000000..34a25ad
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_texcoord_color_rrect.glsl
@@ -0,0 +1,37 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+precision mediump float;
+
+uniform vec4 u_color;
+uniform vec4 u_texcoord_clamp;
+uniform sampler2D u_texture;
+
+// A rounded rect is represented by a vec4 specifying (min.xy, max.xy), and a
+// matrix of corners. Each vector in the matrix represents a corner (order:
+// top left, top right, bottom left, bottom right). Each corner vec4 represents
+// (start.xy, radius.xy).
+uniform vec4 u_rect;
+uniform mat4 u_corners;
+
+varying vec2 v_offset;
+varying vec2 v_texcoord;
+
+#include "function_is_outside_rrect.inc"
+
+void main() {
+ float scale = IsOutsideRRect(v_offset, u_rect, u_corners);
+ gl_FragColor = u_color * (1.0 - scale) * texture2D(u_texture,
+ clamp(v_texcoord, u_texcoord_clamp.xy, u_texcoord_clamp.zw));
+}
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/function_is_outside_rrect.inc b/src/cobalt/renderer/rasterizer/egl/shaders/function_is_outside_rrect.inc
new file mode 100644
index 0000000..e3e58b9
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/function_is_outside_rrect.inc
@@ -0,0 +1,51 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Return 0 if the given point is inside the rounded rect, or scale towards 1
+// as it goes outside a 1-pixel anti-aliasing border.
+// |rect| represents (min.xy, max.xy) of the encompassing rectangle.
+// |corners| is a matrix with each vec4 representing (start.xy, radius.xy) of
+// a corner. The order is top left, top right, bottom left, bottom right.
+float IsOutsideRRect(vec2 point, vec4 rect, mat4 corners) {
+ vec4 select_corner = vec4(
+ step(point.x, corners[0].x) * step(point.y, corners[0].y),
+ step(corners[1].x, point.x) * step(point.y, corners[1].y),
+ step(point.x, corners[2].x) * step(corners[2].y, point.y),
+ step(corners[3].x, point.x) * step(corners[3].y, point.y));
+ if (dot(select_corner, vec4(1.0)) > 0.5) {
+ // Estimate the amount of anti-aliasing that should be used by comparing
+ // x^2 / a^2 + y^2 / b^2 for the ellipse and ellipse + 1 pixel.
+ vec4 corner = corners * select_corner;
+ vec2 pixel_offset = point - corner.xy;
+
+ if (abs(corner.z - corner.w) < 0.1) {
+ // This is a square or round corner.
+ return clamp(length(pixel_offset) - corner.z, 0.0, 1.0);
+ }
+
+ vec2 offset_min = pixel_offset / corner.zw;
+ vec2 offset_max = pixel_offset / (corner.zw + vec2(1.0));
+ float result_min = dot(offset_min, offset_min);
+ float result_max = dot(offset_max, offset_max);
+
+ // Return 1.0 if outside, or interpolate if in the border, or 0 if inside.
+ return (result_max >= 1.0) ? 1.0 :
+ max(result_min - 1.0, 0.0) / (result_min - result_max);
+ }
+
+ return clamp(rect.x - point.x, 0.0, 1.0) +
+ clamp(point.x - rect.z, 0.0, 1.0) +
+ clamp(rect.y - point.y, 0.0, 1.0) +
+ clamp(point.y - rect.w, 0.0, 1.0);
+}
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py b/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py
index 30bdd79..d253ccd 100644
--- a/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py
@@ -70,42 +70,57 @@
return 'Shader' + class_name
-def GetDataDefinitionStringForFile(filename):
- """Returns a string containing C++ array definition for file contents."""
- with open(filename, 'rb') as f:
- # Read the file contents.
- file_contents = f.read()
+def ReadShaderFile(filename):
+ """Parse the given shader file. Handle #include and strip comments."""
+ path_dir = os.path.dirname(filename)
- # Strip comments and blank lines.
+ def HandleInclude(line):
+ # Handle #include directive if the given line specifies it.
+ if line.startswith('#include "') and line.endswith('"'):
+ include_filename = line[10:-1]
+ return ReadShaderFile(os.path.join(path_dir, include_filename))
+ else:
+ return line
+
+ with open(filename, 'rb') as f:
+ # Read the file and strip comments.
+ file_contents = f.read()
file_contents = re.sub(r'/\*.*?\*/', '', file_contents, flags=re.DOTALL)
file_contents = re.sub(r'(\s)*//.*', '', file_contents)
- file_contents = re.sub('(^|\\n)(\\s)*\\n', '\\1', file_contents)
- # Remove any carriage returns (apitrace doesn't handle shader sources with
- # that character very well), and add a null terminator at the end.
- file_contents = file_contents.replace('\r', '') + '\0'
+ # Parse #include directives. This must be done after stripping comments as
+ # it's possible to have multi-line comments that encompass #includes.
+ lines = [HandleInclude(x) for x in file_contents.splitlines()]
- def GetChunk(contents, chunk_size):
- # Yield successive |chunk_size|-sized chunks from |contents|.
- for i in xrange(0, len(contents), chunk_size):
- yield contents[i:i + chunk_size]
+ # Join non-empty lines.
+ return '\n'.join(filter(None, lines))
- # Break up the data into chunk sizes such that the produced output lines
- # representing the data in the .h file are less than 80 characters long.
- length_of_output_byte_string = 6
- max_characters_per_line = 80
- chunk_size = max_characters_per_line / length_of_output_byte_string
- # Convert each byte to ASCII hexadecimal form and output that to the C++
- # header file, line-by-line.
- data_definition_string = '{\n'
- for output_line_data in GetChunk(file_contents, chunk_size):
- data_definition_string += (
- ' ' +
- ' '.join(['0x%02x,' % ord(y) for y in output_line_data]) +
- '\n')
- data_definition_string += '};\n'
- return data_definition_string
+def GetDataDefinitionStringForFile(filename):
+ """Returns a string containing C++ array definition for file contents."""
+ file_contents = ReadShaderFile(filename) + '\0'
+
+ def GetChunk(contents, chunk_size):
+ # Yield successive |chunk_size|-sized chunks from |contents|.
+ for i in xrange(0, len(contents), chunk_size):
+ yield contents[i:i + chunk_size]
+
+ # Break up the data into chunk sizes such that the produced output lines
+ # representing the data in the .h file are less than 80 characters long.
+ length_of_output_byte_string = 6
+ max_characters_per_line = 80
+ chunk_size = max_characters_per_line / length_of_output_byte_string
+
+ # Convert each byte to ASCII hexadecimal form and output that to the C++
+ # header file, line-by-line.
+ data_definition_string = '{\n'
+ for output_line_data in GetChunk(file_contents, chunk_size):
+ data_definition_string += (
+ ' ' +
+ ' '.join(['0x%02x,' % ord(y) for y in output_line_data]) +
+ '\n')
+ data_definition_string += '};\n'
+ return data_definition_string
def GetShaderSourceDefinitions(files):
@@ -352,9 +367,11 @@
def main(output_header_filename, output_source_filename, shader_files_file):
all_shader_files = []
with open(shader_files_file, 'r') as input_file:
- shader_files = input_file.readlines()
+ shader_files = input_file.read().splitlines()
for filename in shader_files:
- all_shader_files.append(filename.strip())
+ # Ignore *.inc files. These are include files and not shader files.
+ if not filename.lower().endswith('.inc'):
+ all_shader_files.append(filename)
GenerateSourceFile(output_source_filename, output_header_filename,
all_shader_files)
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/shaders.gyp b/src/cobalt/renderer/rasterizer/egl/shaders/shaders.gyp
index c3419a6..444d630 100644
--- a/src/cobalt/renderer/rasterizer/egl/shaders/shaders.gyp
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/shaders.gyp
@@ -19,17 +19,21 @@
'shader_impl_source': '<(output_dir)/generated_shader_impl.cc',
'generate_class_script': '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/generate_shader_impl.py',
'shader_sources': [
- '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_texcoord.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_color.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_color_between_rrects.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_color_blur.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_color_blur_rrects.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_color_include.glsl',
+ '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_color_rrect.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_color_texcoord.glsl',
- '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/vertex_texcoord.glsl',
+ '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_texcoord.glsl',
+ '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/fragment_texcoord_color_rrect.glsl',
+ '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/function_is_outside_rrect.inc',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/vertex_color.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/vertex_color_offset.glsl',
'<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/vertex_color_texcoord.glsl',
+ '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/vertex_offset_texcoord.glsl',
+ '<(DEPTH)/cobalt/renderer/rasterizer/egl/shaders/vertex_texcoord.glsl',
],
},
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/vertex_offset_texcoord.glsl b/src/cobalt/renderer/rasterizer/egl/shaders/vertex_offset_texcoord.glsl
new file mode 100644
index 0000000..df81d24
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/egl/shaders/vertex_offset_texcoord.glsl
@@ -0,0 +1,29 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+uniform vec4 u_clip_adjustment;
+uniform mat3 u_view_matrix;
+attribute vec2 a_position;
+attribute vec2 a_offset;
+attribute vec2 a_texcoord;
+varying vec2 v_offset;
+varying vec2 v_texcoord;
+
+void main() {
+ vec3 pos2d = u_view_matrix * vec3(a_position, 1);
+ gl_Position = vec4(pos2d.xy * u_clip_adjustment.xy +
+ u_clip_adjustment.zw, 0, pos2d.z);
+ v_offset = a_offset;
+ v_texcoord = a_texcoord;
+}
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index 0becedb..7315496 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -1890,6 +1890,18 @@
new ImageNode(image)));
}
+TEST_F(PixelTest, EllipticalViewportOverCompositionOfImages) {
+ scoped_refptr<Image> image =
+ CreateColoredCheckersImage(GetResourceProvider(), output_surface_size());
+
+ CompositionNode::Builder builder(Vector2dF(25, 50));
+ builder.AddChild(new ImageNode(image, RectF(0, 0, 75, 50)));
+ builder.AddChild(new ImageNode(image, RectF(75, 50, 75, 50)));
+ TestTree(new FilterNode(
+ ViewportFilter(RectF(25, 50, 150, 100), RoundedCorners(75, 50)),
+ new CompositionNode(builder.Pass())));
+}
+
TEST_F(PixelTest, EllipticalViewportOverWrappingImage) {
scoped_refptr<Image> image =
CreateColoredCheckersImage(GetResourceProvider(), output_surface_size());
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
index 6ff0f21..c385813 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -54,6 +54,7 @@
submit_offscreen_callback_(submit_offscreen_callback),
purge_skia_font_caches_on_destruction_(
purge_skia_font_caches_on_destruction),
+ max_texture_size_(gr_context->getMaxTextureSize()),
self_message_loop_(MessageLoop::current()) {
// Initialize the font manager now to ensure that it doesn't get initialized
// on multiple threads simultaneously later.
@@ -67,8 +68,7 @@
decode_target_graphics_context_provider_.gles_context_runner =
&HardwareResourceProvider::GraphicsContextRunner;
decode_target_graphics_context_provider_.gles_context_runner_context = this;
-#endif // SB_API_VERSION >= 4 && \
- SB_HAS(GRAPHICS)
+#endif // SB_API_VERSION >= 4 && SB_HAS(GRAPHICS)
}
HardwareResourceProvider::~HardwareResourceProvider() {
@@ -110,6 +110,10 @@
DCHECK(PixelFormatSupported(pixel_format));
DCHECK(AlphaFormatSupported(alpha_format));
+ if (size.width() > max_texture_size_ || size.height() > max_texture_size_) {
+ return scoped_ptr<ImageData>(nullptr);
+ }
+
return scoped_ptr<ImageData>(new HardwareImageData(
cobalt_context_->system_egl()->AllocateTextureData(
size, ConvertRenderTreeFormatToGL(pixel_format)),
@@ -347,8 +351,7 @@
}
}
-#endif // SB_API_VERSION >= 4 && \
- SB_HAS(GRAPHICS)
+#endif // SB_API_VERSION >= 4 && SB_HAS(GRAPHICS)
scoped_ptr<RawImageMemory> HardwareResourceProvider::AllocateRawImageMemory(
size_t size_in_bytes, size_t alignment) {
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
index d5540a8..33ed4d2 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
@@ -145,6 +145,7 @@
const bool purge_skia_font_caches_on_destruction_;
TextShaper text_shaper_;
+ int max_texture_size_;
#if SB_API_VERSION >= 4 && SB_HAS(GRAPHICS)
static void GraphicsContextRunner(
@@ -154,8 +155,7 @@
SbDecodeTargetGraphicsContextProvider
decode_target_graphics_context_provider_;
-#endif // SB_API_VERSION >= 4 && \
- SB_HAS(GRAPHICS)
+#endif // SB_API_VERSION >= 4 && SB_HAS(GRAPHICS)
// We keep a handle to the message loop that this resource provider was
// created on. This message loop is used whenever we need to issue graphics
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
index 71ac5a6..b6714f6 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
+++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
@@ -31,6 +31,8 @@
'src/ports/SkFontStyleSet_cobalt.h',
'src/ports/SkFontUtil_cobalt.cc',
'src/ports/SkFontUtil_cobalt.h',
+ 'src/ports/SkFreeType_cobalt.cc',
+ 'src/ports/SkFreeType_cobalt.h',
'src/ports/SkOSFile_cobalt.cc',
'src/ports/SkStream_cobalt.cc',
'src/ports/SkStream_cobalt.h',
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi
index a256e78..cff46c8 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi
+++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_common.gypi
@@ -62,7 +62,7 @@
],
},
}],
- ['actual_target_arch == "win" or target_arch == "xb360"', {
+ ['target_arch == "win"', {
'variables': {
'skia_export_defines': [
# Required define by Skia to take certain code paths, such
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
index d26d31e..67576ee 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
@@ -14,14 +14,15 @@
#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.h"
-#include "base/debug/trace_event.h"
-#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.h"
-#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.h"
#include "SkData.h"
#include "SkGraphics.h"
#include "SkStream.h"
#include "SkString.h"
#include "SkTSearch.h"
+#include "base/debug/trace_event.h"
+#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.h"
+#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.h"
+#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.h"
SkFontMgr_Cobalt::SkFontMgr_Cobalt(
const char* cobalt_font_config_directory,
@@ -236,8 +237,8 @@
bool is_fixed_pitch;
SkTypeface::Style style;
SkString name;
- if (!SkTypeface_FreeType::ScanFont(stream, face_index, &name, &style,
- &is_fixed_pitch)) {
+ if (!sk_freetype_cobalt::ScanFont(stream, face_index, &name, &style,
+ &is_fixed_pitch)) {
return NULL;
}
return SkNEW_ARGS(SkTypeface_CobaltStream,
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
index 6196cc6..36315ef 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.cc
@@ -14,17 +14,15 @@
#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontStyleSet_cobalt.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
#include <cmath>
#include <limits>
+#include "SkOSFile.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
+#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.h"
#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkTypeface_cobalt.h"
-#include "SkOSFile.h"
namespace {
@@ -70,22 +68,6 @@
} // namespace
-// These functions are used by FreeType during FT_Open_Face.
-extern "C" {
-
-static unsigned long sk_cobalt_ft_stream_io(FT_Stream ftStream,
- unsigned long offset,
- unsigned char* buffer,
- unsigned long count) {
- SkStreamAsset* stream =
- static_cast<SkStreamAsset*>(ftStream->descriptor.pointer);
- stream->seek(offset);
- return stream->read(buffer, count);
-}
-
-static void sk_cobalt_ft_stream_close(FT_Stream) {}
-}
-
SkFontStyleSet_Cobalt::SkFontStyleSet_Cobalt(
const FontFamilyInfo& family_info, const char* base_path,
SkFileMemoryChunkStreamManager* const local_typeface_stream_manager,
@@ -319,73 +301,19 @@
return true;
}
- TRACE_EVENT0("cobalt::renderer", "GenerateStyleFaceInfo()");
+ // Providing a pointer to the character map will cause it to be generated
+ // during ScanFont. Only provide it if it hasn't already been generated.
+ font_character_map::CharacterMap* character_map =
+ !is_character_map_generated_ ? &character_map_ : NULL;
- FT_Library freetype_lib;
- if (FT_Init_FreeType(&freetype_lib) != 0) {
+ if (!sk_freetype_cobalt::ScanFont(
+ stream, style->face_index, &style->face_name, &style->face_style,
+ &style->face_is_fixed_pitch, character_map)) {
return false;
}
- FT_StreamRec streamRec;
- memset(&streamRec, 0, sizeof(streamRec));
- streamRec.size = stream->getLength();
- streamRec.descriptor.pointer = stream;
- streamRec.read = sk_cobalt_ft_stream_io;
- streamRec.close = sk_cobalt_ft_stream_close;
-
- FT_Open_Args args;
- memset(&args, 0, sizeof(args));
- args.flags = FT_OPEN_STREAM;
- args.stream = &streamRec;
-
- FT_Face face;
- FT_Error err = FT_Open_Face(freetype_lib, &args, style->face_index, &face);
- if (err) {
- FT_Done_FreeType(freetype_lib);
- return false;
- }
-
- int face_style = SkTypeface::kNormal;
- if (face->style_flags & FT_STYLE_FLAG_BOLD) {
- face_style |= SkTypeface::kBold;
- }
- if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
- face_style |= SkTypeface::kItalic;
- }
-
- style->face_name.set(face->family_name);
- style->face_style = static_cast<SkTypeface::Style>(face_style);
- style->face_is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
style->is_face_info_generated = true;
-
- // Map out this family's characters if they haven't been generated yet.
- if (!is_character_map_generated_) {
- FT_UInt glyph_index;
-
- int last_page = -1;
- font_character_map::PageCharacters* page_characters = NULL;
-
- SkUnichar code_point = FT_Get_First_Char(face, &glyph_index);
- while (glyph_index) {
- int page = font_character_map::GetPage(code_point);
- if (page != last_page) {
- page_characters = &character_map_[page];
- last_page = page;
- }
- page_characters->set(
- font_character_map::GetPageCharacterIndex(code_point));
-
- code_point = FT_Get_Next_Char(face, code_point, &glyph_index);
- }
-
- is_character_map_generated_ = true;
- }
-
- // release this font.
- FT_Done_Face(face);
-
- // shut down FreeType.
- FT_Done_FreeType(freetype_lib);
+ is_character_map_generated_ = true;
return true;
}
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.cc
new file mode 100644
index 0000000..6abacb8
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.cc
@@ -0,0 +1,182 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.h"
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_TYPE1_TABLES_H
+
+#include "SkFontStyle.h"
+#include "SkTSearch.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+
+namespace {
+
+// This logic is taken from SkTypeface_FreeType::ScanFont() and should be kept
+// in sync with it.
+SkTypeface::Style GenerateSkTypefaceStyleFromFace(FT_Face face) {
+ int weight = SkFontStyle::kNormal_Weight;
+ if (face->style_flags & FT_STYLE_FLAG_BOLD) {
+ weight = SkFontStyle::kBold_Weight;
+ }
+
+ PS_FontInfoRec psFontInfo;
+ TT_OS2* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face, ft_sfnt_os2));
+ if (os2 && os2->version != 0xffff) {
+ weight = os2->usWeightClass;
+ } else if (0 == FT_Get_PS_Font_Info(face, &psFontInfo) && psFontInfo.weight) {
+ static const struct {
+ char const* const name;
+ int const weight;
+ } commonWeights[] = {
+ // There are probably more common names, but these are known to exist.
+ {"all", SkFontStyle::kNormal_Weight}, // Multiple Masters usually
+ // default to normal.
+ {"black", SkFontStyle::kBlack_Weight},
+ {"bold", SkFontStyle::kBold_Weight},
+ {"book",
+ (SkFontStyle::kNormal_Weight + SkFontStyle::kLight_Weight) / 2},
+ {"demi", SkFontStyle::kSemiBold_Weight},
+ {"demibold", SkFontStyle::kSemiBold_Weight},
+ {"extra", SkFontStyle::kExtraBold_Weight},
+ {"extrabold", SkFontStyle::kExtraBold_Weight},
+ {"extralight", SkFontStyle::kExtraLight_Weight},
+ {"hairline", SkFontStyle::kThin_Weight},
+ {"heavy", SkFontStyle::kBlack_Weight},
+ {"light", SkFontStyle::kLight_Weight},
+ {"medium", SkFontStyle::kMedium_Weight},
+ {"normal", SkFontStyle::kNormal_Weight},
+ {"plain", SkFontStyle::kNormal_Weight},
+ {"regular", SkFontStyle::kNormal_Weight},
+ {"roman", SkFontStyle::kNormal_Weight},
+ {"semibold", SkFontStyle::kSemiBold_Weight},
+ {"standard", SkFontStyle::kNormal_Weight},
+ {"thin", SkFontStyle::kThin_Weight},
+ {"ultra", SkFontStyle::kExtraBold_Weight},
+ {"ultrabold", SkFontStyle::kExtraBold_Weight},
+ {"ultralight", SkFontStyle::kExtraLight_Weight},
+ };
+ int const index =
+ SkStrLCSearch(&commonWeights[0].name, SK_ARRAY_COUNT(commonWeights),
+ psFontInfo.weight, sizeof(commonWeights[0]));
+ if (index >= 0) {
+ weight = commonWeights[index].weight;
+ } else {
+ DLOG(ERROR) << "Do not recognize weight for:" << face->family_name << "("
+ << psFontInfo.weight << ")";
+ }
+ }
+
+ int face_style = SkTypeface::kNormal;
+ if (weight > 500) {
+ face_style |= SkTypeface::kBold;
+ }
+ if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
+ face_style |= SkTypeface::kItalic;
+ }
+
+ return static_cast<SkTypeface::Style>(face_style);
+}
+
+void GenerateCharacterMapFromFace(
+ FT_Face face, font_character_map::CharacterMap* character_map) {
+ TRACE_EVENT0("cobalt::renderer", "GenerateCharacterMapFromFace");
+
+ FT_UInt glyph_index;
+
+ int last_page = -1;
+ font_character_map::PageCharacters* page_characters = NULL;
+
+ SkUnichar code_point = FT_Get_First_Char(face, &glyph_index);
+ while (glyph_index) {
+ int page = font_character_map::GetPage(code_point);
+ if (page != last_page) {
+ page_characters = &(*character_map)[page];
+ last_page = page;
+ }
+ page_characters->set(font_character_map::GetPageCharacterIndex(code_point));
+
+ code_point = FT_Get_Next_Char(face, code_point, &glyph_index);
+ }
+}
+
+} // namespace
+
+// These functions are used by FreeType during FT_Open_Face.
+extern "C" {
+
+static unsigned long sk_freetype_cobalt_stream_io(FT_Stream ftStream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count) {
+ SkStreamAsset* stream =
+ static_cast<SkStreamAsset*>(ftStream->descriptor.pointer);
+ stream->seek(offset);
+ return stream->read(buffer, count);
+}
+
+static void sk_freetype_cobalt_stream_close(FT_Stream) {}
+}
+
+namespace sk_freetype_cobalt {
+
+bool ScanFont(SkStreamAsset* stream, int face_index, SkString* name,
+ SkTypeface::Style* style, bool* is_fixed_pitch,
+ font_character_map::CharacterMap* maybe_character_map /*=NULL*/) {
+ TRACE_EVENT0("cobalt::renderer", "SkFreeTypeUtil::ScanFont()");
+
+ FT_Library freetype_lib;
+ if (FT_Init_FreeType(&freetype_lib) != 0) {
+ return false;
+ }
+
+ FT_StreamRec streamRec;
+ memset(&streamRec, 0, sizeof(streamRec));
+ streamRec.size = stream->getLength();
+ streamRec.descriptor.pointer = stream;
+ streamRec.read = sk_freetype_cobalt_stream_io;
+ streamRec.close = sk_freetype_cobalt_stream_close;
+
+ FT_Open_Args args;
+ memset(&args, 0, sizeof(args));
+ args.flags = FT_OPEN_STREAM;
+ args.stream = &streamRec;
+
+ FT_Face face;
+ FT_Error err = FT_Open_Face(freetype_lib, &args, face_index, &face);
+ if (err) {
+ FT_Done_FreeType(freetype_lib);
+ return false;
+ }
+
+ name->set(face->family_name);
+ *style = GenerateSkTypefaceStyleFromFace(face);
+ *is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
+
+ if (maybe_character_map) {
+ GenerateCharacterMapFromFace(face, maybe_character_map);
+ }
+
+ // release this font.
+ FT_Done_Face(face);
+
+ // shut down FreeType.
+ FT_Done_FreeType(freetype_lib);
+ return true;
+}
+
+} // namespace sk_freetype_cobalt
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.h
new file mode 100644
index 0000000..70abeeb
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFreeType_cobalt.h
@@ -0,0 +1,33 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKFREETYPE_COBALT_H_
+#define COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKFREETYPE_COBALT_H_
+
+#include "SkStream.h"
+#include "SkTypeface.h"
+#include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h"
+
+namespace sk_freetype_cobalt {
+
+// Scans the font stream using FreeType, setting its name, style and whether or
+// not it has a fixed pitch. It also generates the font's character map if that
+// optional parameter is provided.
+bool ScanFont(SkStreamAsset* stream, int face_index, SkString* name,
+ SkTypeface::Style* style, bool* is_fixed_pitch,
+ font_character_map::CharacterMap* maybe_character_map = NULL);
+
+} // namespace sk_freetype_cobalt
+
+#endif // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKFREETYPE_COBALT_H_
diff --git a/src/cobalt/renderer/rasterizer/testdata/EllipticalViewportOverCompositionOfImages-expected.png b/src/cobalt/renderer/rasterizer/testdata/EllipticalViewportOverCompositionOfImages-expected.png
new file mode 100644
index 0000000..337f162
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/EllipticalViewportOverCompositionOfImages-expected.png
Binary files differ
diff --git a/src/cobalt/script/javascript_engine.h b/src/cobalt/script/javascript_engine.h
index 4ea8881..c8e4f72 100644
--- a/src/cobalt/script/javascript_engine.h
+++ b/src/cobalt/script/javascript_engine.h
@@ -70,6 +70,9 @@
// Returns true if the error handler could be installed. False otherwise.
virtual bool RegisterErrorHandler(ErrorHandler handler) = 0;
+ // Adjusts the memory threshold to force garbage collection.
+ virtual void SetGcThreshold(int64_t bytes) = 0;
+
protected:
virtual ~JavaScriptEngine() {}
friend class scoped_ptr<JavaScriptEngine>;
diff --git a/src/cobalt/script/mozjs-45/mozjs_engine.cc b/src/cobalt/script/mozjs-45/mozjs_engine.cc
index 720e71f..6a09beb 100644
--- a/src/cobalt/script/mozjs-45/mozjs_engine.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_engine.cc
@@ -235,6 +235,10 @@
return true;
}
+void MozjsEngine::SetGcThreshold(int64_t bytes) {
+ runtime_->gc.setMaxMallocBytes(static_cast<size_t>(bytes));
+}
+
void MozjsEngine::TimerGarbageCollect() {
TRACE_EVENT0("cobalt::script", "MozjsEngine::TimerGarbageCollect()");
CollectGarbage();
diff --git a/src/cobalt/script/mozjs-45/mozjs_engine.h b/src/cobalt/script/mozjs-45/mozjs_engine.h
index 9adb4e2..98094f1 100644
--- a/src/cobalt/script/mozjs-45/mozjs_engine.h
+++ b/src/cobalt/script/mozjs-45/mozjs_engine.h
@@ -40,6 +40,7 @@
void CollectGarbage() OVERRIDE;
void ReportExtraMemoryCost(size_t bytes) OVERRIDE;
bool RegisterErrorHandler(JavaScriptEngine::ErrorHandler handler) OVERRIDE;
+ void SetGcThreshold(int64_t bytes) OVERRIDE;
private:
void TimerGarbageCollect();
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
index 7f100d0..a075221 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.cc
@@ -250,17 +250,20 @@
context_, JS::UTF8Chars(script.c_str(), length), &length)
.get();
- bool success = false;
- if (inflated_buffer) {
- JS::CompileOptions options(context_);
- options.setFileAndLine(location.file_path.c_str(), location.line_number);
- success =
- JS::Evaluate(context_, options, inflated_buffer, length, out_result);
- js_free(inflated_buffer);
- } else {
+ if (!inflated_buffer) {
DLOG(ERROR) << "Malformed UTF-8 script.";
+ return false;
}
+ JS::CompileOptions options(context_);
+ options.setFileAndLine(location.file_path.c_str(), location.line_number);
+ bool success =
+ JS::Evaluate(context_, options, inflated_buffer, length, out_result);
+ if (!success && context_->isExceptionPending()) {
+ JS_ReportPendingException(context_);
+ }
+ js_free(inflated_buffer);
+
return success;
}
diff --git a/src/cobalt/script/mozjs/mozjs_engine.cc b/src/cobalt/script/mozjs/mozjs_engine.cc
index 0f1760e..cfc1c5e 100644
--- a/src/cobalt/script/mozjs/mozjs_engine.cc
+++ b/src/cobalt/script/mozjs/mozjs_engine.cc
@@ -27,6 +27,7 @@
#include "cobalt/script/mozjs/util/stack_trace_helpers.h"
#include "third_party/mozjs/cobalt_config/include/jscustomallocator.h"
#include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jscntxt.h"
#include "third_party/mozjs/js/src/jsdbgapi.h"
namespace cobalt {
@@ -184,6 +185,10 @@
return true;
}
+void MozjsEngine::SetGcThreshold(int64_t bytes) {
+ runtime_->setGCMaxMallocBytes(static_cast<size_t>(bytes));
+}
+
void MozjsEngine::TimerGarbageCollect() {
TRACE_EVENT0("cobalt::script", "MozjsEngine::TimerGarbageCollect()");
CollectGarbage();
diff --git a/src/cobalt/script/mozjs/mozjs_engine.h b/src/cobalt/script/mozjs/mozjs_engine.h
index 5c3d460..9dda81a 100644
--- a/src/cobalt/script/mozjs/mozjs_engine.h
+++ b/src/cobalt/script/mozjs/mozjs_engine.h
@@ -42,6 +42,7 @@
void CollectGarbage() OVERRIDE;
void ReportExtraMemoryCost(size_t bytes) OVERRIDE;
bool RegisterErrorHandler(JavaScriptEngine::ErrorHandler handler) OVERRIDE;
+ void SetGcThreshold(int64_t bytes) OVERRIDE;
private:
void TimerGarbageCollect();
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.cc b/src/cobalt/script/mozjs/mozjs_global_environment.cc
index 200095f..71b593d 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.cc
@@ -268,16 +268,22 @@
size_t length = script.size();
jschar* inflated_buffer =
js::InflateUTF8String(context_, script.c_str(), &length);
- bool success = false;
- if (inflated_buffer) {
- success = JS_EvaluateUCScript(context_, global_object, inflated_buffer,
- length, location.file_path.c_str(),
- location.line_number, out_result.address());
- js_free(inflated_buffer);
- } else {
+
+ if (!inflated_buffer) {
DLOG(ERROR) << "Malformed UTF-8 script.";
+ return false;
}
+ JS::CompileOptions options(context_);
+ options.setFileAndLine(location.file_path.c_str(), location.line_number);
+ bool success = JS_EvaluateUCScript(
+ context_, global_object, inflated_buffer, length,
+ location.file_path.c_str(), location.line_number, out_result.address());
+ if (!success && context_->isExceptionPending()) {
+ JS_ReportPendingException(context_);
+ }
+ js_free(inflated_buffer);
+
return success;
}
diff --git a/src/cobalt/storage/storage.gyp b/src/cobalt/storage/storage.gyp
index 94bfd46..6f18bc9 100644
--- a/src/cobalt/storage/storage.gyp
+++ b/src/cobalt/storage/storage.gyp
@@ -30,6 +30,7 @@
'sql_vfs.cc',
'sql_vfs.h',
'savegame_fake.cc',
+ 'savegame_starboard.cc',
'storage_manager.cc',
'storage_manager.h',
'upgrade/upgrade_reader.cc',
@@ -45,28 +46,6 @@
'<(DEPTH)/net/net.gyp:net',
'<(DEPTH)/sql/sql.gyp:sql',
],
- 'conditions': [
- ['OS=="starboard"', {
- 'sources': [
- 'savegame_starboard.cc',
- ],
- }],
- ['OS!="starboard" and target_arch=="ps3"', {
- 'sources': [
- 'savegame_ps3.cc',
- ],
- 'copies': [
- {
- 'destination': '<(static_contents_output_data_dir)',
- 'files': ['<(static_contents_source_dir)/platform/ps3/USRDIR/SAVE_ICON.PNG'],
- }],
- }],
- ['OS!="starboard" and actual_target_arch=="win"', {
- 'sources': [
- 'savegame_file.cc',
- ],
- }],
- ],
},
{
'target_name': 'storage_test',
diff --git a/src/cobalt/system_window/system_window.cc b/src/cobalt/system_window/system_window.cc
index 444b411..399e107 100644
--- a/src/cobalt/system_window/system_window.cc
+++ b/src/cobalt/system_window/system_window.cc
@@ -180,7 +180,8 @@
void SystemWindow::ShowDialog(
const SystemWindow::DialogOptions& options) {
- SbSystemPlatformErrorType error_type;
+ SbSystemPlatformErrorType error_type =
+ kSbSystemPlatformErrorTypeConnectionError;
switch (options.message_code) {
case kDialogConnectionError:
error_type = kSbSystemPlatformErrorTypeConnectionError;
diff --git a/src/cobalt/webdriver/algorithms.cc b/src/cobalt/webdriver/algorithms.cc
index 83379cf..a2fd622 100644
--- a/src/cobalt/webdriver/algorithms.cc
+++ b/src/cobalt/webdriver/algorithms.cc
@@ -41,26 +41,20 @@
// Note that non-breaking space is at the beginning to simplify definition of
// kWhitespaceCharsExcludingNonBreakingSpace below.
const char kWhitespaceChars[] =
- "\u00a0 "
- "\f\n\r\t\v\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006"
- "\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff";
+ u8"\u00a0 "
+ u8"\f\n\r\t\v\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006"
+ u8"\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff";
const char* kWhitespaceCharsExcludingNonBreakingSpace = kWhitespaceChars + 1;
// Defined in https://www.w3.org/TR/webdriver/#text.horizontal
-const char kHorizontalWhitespaceChars[] = " \f\t\v\u2028\u2029";
+const char kHorizontalWhitespaceChars[] = u8" \f\t\v\u2028\u2029";
// Defined in step 2.1 of the getElementText() algorithm in
// https://www.w3.org/TR/webdriver/#getelementtext
-const char kZeroWidthSpacesAndFeeds[] = "\f\v\u200b\u200e\u200f";
+const char kZeroWidthSpacesAndFeeds[] = u8"\f\v\u200b\u200e\u200f";
const char kNonBreakingSpace = '\xa0';
-bool IsWhitespace(char c) {
- DCHECK_NE(c, '\0');
- // strchr matches the nul-character, which is not a whitespace character.
- return strchr(kWhitespaceChars, c) != NULL;
-}
-
bool IsHorizontalWhitespace(char c) {
DCHECK_NE(c, '\0');
return strchr(kHorizontalWhitespaceChars, c) != NULL;
diff --git a/src/cobalt/webdriver/dispatcher.cc b/src/cobalt/webdriver/dispatcher.cc
index 6d1d408..5ea6726 100644
--- a/src/cobalt/webdriver/dispatcher.cc
+++ b/src/cobalt/webdriver/dispatcher.cc
@@ -145,8 +145,9 @@
CommandMapping* mapping = GetMappingForPath(tokenized_path, kMatchExact);
if (!mapping) {
// No commands registered for this path yet, so create a new CommandMapping.
+ int tokenized_path_size = static_cast<int>(tokenized_path.size());
CommandMappingLookup::iterator it = command_lookup_.insert(
- std::make_pair(tokenized_path.size(), CommandMapping(tokenized_path)));
+ std::make_pair(tokenized_path_size, CommandMapping(tokenized_path)));
mapping = &it->second;
}
diff --git a/src/cobalt/webdriver/get_element_text_test.cc b/src/cobalt/webdriver/get_element_text_test.cc
index a25c693..65036fe 100644
--- a/src/cobalt/webdriver/get_element_text_test.cc
+++ b/src/cobalt/webdriver/get_element_text_test.cc
@@ -83,7 +83,7 @@
} // namespace
TEST_F(GetElementTextTest, ZeroSpaceWidthIsRemoved) {
- AppendText("a\u200bb\u200ec\u200fd");
+ AppendText(u8"a\u200bb\u200ec\u200fd");
EXPECT_STREQ("abcd", algorithms::GetElementText(div_.get()).c_str());
}
@@ -94,7 +94,7 @@
TEST_F(GetElementTextTest, NoWrapStyle) {
div_->style()->set_white_space("nowrap", NULL);
- AppendText("a\n\nb\nc\td\u2028e\u2029f\xa0g");
+ AppendText(u8"a\n\nb\nc\td\u2028e\u2029f\xa0g");
EXPECT_STREQ("a b c d e f g", algorithms::GetElementText(div_.get()).c_str());
}
diff --git a/src/cobalt/webdriver/keyboard_test.cc b/src/cobalt/webdriver/keyboard_test.cc
index b961587..db1e7b7 100644
--- a/src/cobalt/webdriver/keyboard_test.cc
+++ b/src/cobalt/webdriver/keyboard_test.cc
@@ -174,7 +174,7 @@
TEST_F(KeyboardTest, Modifier) {
// \uE00A is the Alt-key modifier.
- std::string keys = "\uE00A";
+ std::string keys = u8"\uE00A";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
ASSERT_EQ(events_.size(), 1);
@@ -189,7 +189,7 @@
TEST_F(KeyboardTest, ModifiersAreKept) {
// \uE00A is the Alt-key modifier.
// \uE008 is the Shift-key modifier.
- std::string keys = "\uE00A\uE008";
+ std::string keys = u8"\uE00A\uE008";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
ASSERT_EQ(events_.size(), 2);
@@ -205,7 +205,7 @@
TEST_F(KeyboardTest, ModifiersAreReleased) {
// \uE00A is the Alt-key modifier.
// \uE008 is the Shift-key modifier.
- std::string keys = "\uE00A\uE008";
+ std::string keys = u8"\uE00A\uE008";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kReleaseModifiers, &events_);
ASSERT_EQ(events_.size(), 4);
@@ -223,7 +223,7 @@
TEST_F(KeyboardTest, SpecialCharacter) {
// \uE012 is the Left-arrow key.
- std::string keys = "\uE012";
+ std::string keys = u8"\uE012";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
ASSERT_EQ(events_.size(), 2);
@@ -236,7 +236,7 @@
TEST_F(KeyboardTest, ModifierIsSticky) {
// \uE00A is the Alt-key modifier. Corresponds to the kMenu key code.
- std::string keys = "\uE00AaB";
+ std::string keys = u8"\uE00AaB";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(alt)
@@ -264,7 +264,7 @@
TEST_F(KeyboardTest, ToggleModifier) {
// \uE008 is the Shift-key modifier.
- std::string keys = "\uE008a\uE008a";
+ std::string keys = u8"\uE008a\uE008a";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(shift)
@@ -289,7 +289,7 @@
}
TEST_F(KeyboardTest, NullClearsModifiers) {
- std::string keys = "\uE008\uE00A\uE000a";
+ std::string keys = u8"\uE008\uE00A\uE000a";
Keyboard::TranslateToKeyEvents(keys, Keyboard::kKeepModifiers, &events_);
// keydown(shift)
diff --git a/src/cobalt/websocket/web_socket_test.cc b/src/cobalt/websocket/web_socket_test.cc
index ebca33f..d2803e7 100644
--- a/src/cobalt/websocket/web_socket_test.cc
+++ b/src/cobalt/websocket/web_socket_test.cc
@@ -108,7 +108,6 @@
}
TEST_F(WebSocketTest, TestInitialReadyState) {
- scoped_ptr<FakeSettings> settings_;
scoped_refptr<WebSocket> ws(
new WebSocket(settings(), "ws://example.com", &exception_state_, false));
EXPECT_EQ(ws->ready_state(), WebSocket::kConnecting);
diff --git a/src/cobalt/xhr/xml_http_request.cc b/src/cobalt/xhr/xml_http_request.cc
index fb2b97d..7af4b99 100644
--- a/src/cobalt/xhr/xml_http_request.cc
+++ b/src/cobalt/xhr/xml_http_request.cc
@@ -163,8 +163,7 @@
error_(false),
sent_(false),
stop_timeout_(false),
- upload_complete_(false),
- did_add_ref_(false) {
+ upload_complete_(false) {
DCHECK(settings_);
dom::GlobalStats::GetInstance()->Add(this);
xhr_id_ = ++s_xhr_sequence_num_;
@@ -860,13 +859,9 @@
void XMLHttpRequest::PreventGarbageCollection() {
settings_->global_environment()->PreventGarbageCollection(
make_scoped_refptr(this));
- DCHECK(!did_add_ref_);
- did_add_ref_ = true;
}
void XMLHttpRequest::AllowGarbageCollection() {
- DCHECK(did_add_ref_);
-
bool is_active = (state_ == kOpened && sent_) || state_ == kHeadersReceived ||
state_ == kLoading;
bool has_event_listeners =
@@ -880,7 +875,6 @@
DCHECK_EQ((is_active && has_event_listeners), false);
- did_add_ref_ = false;
settings_->javascript_engine()->ReportExtraMemoryCost(
response_body_.capacity());
settings_->global_environment()->AllowGarbageCollection(
diff --git a/src/cobalt/xhr/xml_http_request.h b/src/cobalt/xhr/xml_http_request.h
index 6646e05..ab9a5e4 100644
--- a/src/cobalt/xhr/xml_http_request.h
+++ b/src/cobalt/xhr/xml_http_request.h
@@ -272,9 +272,6 @@
bool stop_timeout_;
bool upload_complete_;
- // For debugging our reference count manipulations.
- bool did_add_ref_;
-
static bool verbose_;
// Unique ID for debugging.
int xhr_id_;
diff --git a/src/googleurl/googleurl.gyp b/src/googleurl/googleurl.gyp
index 093a61d..4d44cf2 100644
--- a/src/googleurl/googleurl.gyp
+++ b/src/googleurl/googleurl.gyp
@@ -67,11 +67,6 @@
],
},
}],
- ['OS=="lb_shell"', {
- 'dependencies': [
- '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
- ],
- }],
['OS=="starboard"', {
'dependencies': [
'<(DEPTH)/starboard/starboard.gyp:starboard',
diff --git a/src/media/audio/shell_audio_streamer_starboard.cc b/src/media/audio/shell_audio_streamer_starboard.cc
deleted file mode 100644
index 22a143f..0000000
--- a/src/media/audio/shell_audio_streamer_starboard.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "media/audio/shell_audio_streamer.h"
-
-namespace media {
-
-void ShellAudioStreamer::Initialize() {}
-
-void ShellAudioStreamer::Terminate() {}
-
-ShellAudioStreamer* ShellAudioStreamer::Instance() {
- return NULL;
-}
-
-} // namespace media
diff --git a/src/media/base/decoder_buffer_cache.cc b/src/media/base/decoder_buffer_cache.cc
deleted file mode 100644
index 92d35ee..0000000
--- a/src/media/base/decoder_buffer_cache.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "media/base/decoder_buffer_cache.h"
-
-namespace media {
-
-DecoderBufferCache::DecoderBufferCache()
- : audio_buffer_index_(0), video_buffer_index_(0) {}
-
-void DecoderBufferCache::AddBuffer(DemuxerStream::Type type,
- const scoped_refptr<DecoderBuffer>& buffer) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (type == DemuxerStream::AUDIO) {
- audio_buffers_.push_back(buffer);
- if (buffer->IsKeyframe()) {
- audio_key_frame_timestamps_.push_back(buffer->GetTimestamp());
- }
- } else {
- DCHECK_EQ(type, DemuxerStream::VIDEO);
- video_buffers_.push_back(buffer);
- if (buffer->IsKeyframe()) {
- video_key_frame_timestamps_.push_back(buffer->GetTimestamp());
- }
- }
-}
-
-void DecoderBufferCache::ClearSegmentsBeforeMediaTime(
- base::TimeDelta media_time) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- ClearSegmentsBeforeMediaTime(media_time, &audio_buffers_,
- &audio_key_frame_timestamps_);
- ClearSegmentsBeforeMediaTime(media_time, &video_buffers_,
- &video_key_frame_timestamps_);
-}
-
-void DecoderBufferCache::ClearAll() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- audio_buffers_.clear();
- audio_key_frame_timestamps_.clear();
- video_buffers_.clear();
- video_key_frame_timestamps_.clear();
-}
-
-void DecoderBufferCache::StartResuming() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- audio_buffer_index_ = 0;
- video_buffer_index_ = 0;
-}
-
-scoped_refptr<DecoderBuffer> DecoderBufferCache::GetBuffer(
- DemuxerStream::Type type) const {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (type == DemuxerStream::AUDIO) {
- if (audio_buffer_index_ < audio_buffers_.size()) {
- return audio_buffers_[audio_buffer_index_];
- }
- return NULL;
- }
-
- DCHECK_EQ(type, DemuxerStream::VIDEO);
- if (video_buffer_index_ < video_buffers_.size()) {
- return video_buffers_[video_buffer_index_];
- }
- return NULL;
-}
-
-void DecoderBufferCache::AdvanceToNextBuffer(DemuxerStream::Type type) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (type == DemuxerStream::AUDIO) {
- ++audio_buffer_index_;
- } else {
- DCHECK_EQ(type, DemuxerStream::VIDEO);
- ++video_buffer_index_;
- }
-}
-
-// static
-void DecoderBufferCache::ClearSegmentsBeforeMediaTime(
- base::TimeDelta media_time,
- Buffers* buffers,
- KeyFrameTimestamps* key_frame_timestamps) {
- // Use K to denote a key frame and N for non-key frame. If the cache contains
- // K N N N N N N N N K N N N N N N N N K N N N N N N N N
- // |
- // media_time
- // Then we should remove everything before the key frame before the
- // |media_time| and turn the cache into:
- // K N N N N N N N N K N N N N N N N N
- // |
- // media_time
- // So we need at least two keyframes before we can remove any frames.
- while (key_frame_timestamps->size() > 1 &&
- key_frame_timestamps->at(1) <= media_time) {
- key_frame_timestamps->erase(key_frame_timestamps->begin());
- }
- if (key_frame_timestamps->empty()) {
- return;
- }
- while (scoped_refptr<DecoderBuffer> buffer = buffers->front()) {
- if (buffer->IsKeyframe() &&
- buffer->GetTimestamp() == key_frame_timestamps->front()) {
- break;
- }
- buffers->pop_front();
- }
-}
-
-} // namespace media
diff --git a/src/media/base/decoder_buffer_cache.h b/src/media/base/decoder_buffer_cache.h
deleted file mode 100644
index 49ba5ec..0000000
--- a/src/media/base/decoder_buffer_cache.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef MEDIA_BASE_DECODER_BUFFER_CACHE_H_
-#define MEDIA_BASE_DECODER_BUFFER_CACHE_H_
-
-#include <deque>
-
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "base/time.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/demuxer_stream.h"
-
-namespace media {
-
-// This class can be used to hold media buffers in decoding order. It also
-// provides function that given a media time, the function will find a key frame
-// before the media time and clear all buffers before the key frame. This class
-// can be used to "replay" the video from the current playback position and can
-// be useful to implement suspend/resume.
-class DecoderBufferCache {
- public:
- DecoderBufferCache();
-
- void AddBuffer(DemuxerStream::Type type,
- const scoped_refptr<DecoderBuffer>& buffer);
- void ClearSegmentsBeforeMediaTime(base::TimeDelta media_time);
- void ClearAll();
-
- // Start resuming, reset indices to audio/video buffers to the very beginning.
- void StartResuming();
- scoped_refptr<DecoderBuffer> GetBuffer(DemuxerStream::Type type) const;
- void AdvanceToNextBuffer(DemuxerStream::Type type);
-
- private:
- typedef std::deque<scoped_refptr<DecoderBuffer> > Buffers;
- typedef std::deque<base::TimeDelta> KeyFrameTimestamps;
-
- static void ClearSegmentsBeforeMediaTime(
- base::TimeDelta media_time,
- Buffers* buffers,
- KeyFrameTimestamps* key_frame_timestamps);
-
- base::ThreadChecker thread_checker_;
-
- Buffers audio_buffers_;
- KeyFrameTimestamps audio_key_frame_timestamps_;
-
- Buffers video_buffers_;
- KeyFrameTimestamps video_key_frame_timestamps_;
-
- size_t audio_buffer_index_;
- size_t video_buffer_index_;
-};
-
-} // namespace media
-
-#endif // MEDIA_BASE_DECODER_BUFFER_CACHE_H_
diff --git a/src/media/base/sbplayer_pipeline.cc b/src/media/base/sbplayer_pipeline.cc
deleted file mode 100644
index aaaff86..0000000
--- a/src/media/base/sbplayer_pipeline.cc
+++ /dev/null
@@ -1,846 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <vector>
-
-#include "base/basictypes.h" // For COMPILE_ASSERT
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/optional.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/time.h"
-#include "media/base/audio_decoder_config.h"
-#include "media/base/bind_to_loop.h"
-#include "media/base/channel_layout.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/demuxer.h"
-#include "media/base/demuxer_stream.h"
-#include "media/base/filter_collection.h"
-#include "media/base/media_export.h"
-#include "media/base/media_log.h"
-#include "media/base/pipeline.h"
-#include "media/base/pipeline_status.h"
-#include "media/base/ranges.h"
-#include "media/base/sbplayer_set_bounds_helper.h"
-#include "media/base/starboard_player.h"
-#include "media/base/starboard_utils.h"
-#include "media/base/video_decoder_config.h"
-#include "media/crypto/starboard_decryptor.h"
-#include "ui/gfx/size.h"
-
-namespace media {
-
-#if SB_HAS(PLAYER)
-
-using base::Time;
-using base::TimeDelta;
-
-namespace {
-
-// Used to post parameters to SbPlayerPipeline::StartTask() as the number of
-// parameters exceed what base::Bind() can support.
-struct StartTaskParameters {
- scoped_refptr<Demuxer> demuxer;
- SetDecryptorReadyCB decryptor_ready_cb;
- PipelineStatusCB ended_cb;
- PipelineStatusCB error_cb;
- PipelineStatusCB seek_cb;
- Pipeline::BufferingStateCB buffering_state_cb;
- base::Closure duration_change_cb;
-};
-
-// SbPlayerPipeline is a PipelineBase implementation that uses the SbPlayer
-// interface internally.
-class MEDIA_EXPORT SbPlayerPipeline : public Pipeline,
- public DemuxerHost,
- public StarboardPlayer::Host {
- public:
- // Constructs a media pipeline that will execute on |message_loop|.
- SbPlayerPipeline(PipelineWindow window,
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaLog* media_log);
- ~SbPlayerPipeline() OVERRIDE;
-
- void Suspend() OVERRIDE;
- void Resume() OVERRIDE;
- void Start(scoped_ptr<FilterCollection> filter_collection,
- const SetDecryptorReadyCB& decryptor_ready_cb,
- const PipelineStatusCB& ended_cb,
- const PipelineStatusCB& error_cb,
- const PipelineStatusCB& seek_cb,
- const BufferingStateCB& buffering_state_cb,
- const base::Closure& duration_change_cb) OVERRIDE;
-
- void Stop(const base::Closure& stop_cb) OVERRIDE;
- void Seek(TimeDelta time, const PipelineStatusCB& seek_cb);
- bool HasAudio() const OVERRIDE;
- bool HasVideo() const OVERRIDE;
-
- float GetPlaybackRate() const OVERRIDE;
- void SetPlaybackRate(float playback_rate) OVERRIDE;
- float GetVolume() const OVERRIDE;
- void SetVolume(float volume) OVERRIDE;
-
- TimeDelta GetMediaTime() const OVERRIDE;
- Ranges<TimeDelta> GetBufferedTimeRanges() OVERRIDE;
- TimeDelta GetMediaDuration() const OVERRIDE;
- int64 GetTotalBytes() const OVERRIDE;
- void GetNaturalVideoSize(gfx::Size* out_size) const OVERRIDE;
-
- bool DidLoadingProgress() const OVERRIDE;
- PipelineStatistics GetStatistics() const OVERRIDE;
- SetBoundsCB GetSetBoundsCB() OVERRIDE;
- void SetDecodeToTextureOutputMode(bool preference) OVERRIDE;
-
- private:
- void StartTask(const StartTaskParameters& parameters);
- void SetVolumeTask(float volume);
- void SetPlaybackRateTask(float volume);
- void SetDurationTask(TimeDelta duration);
-
- // DataSourceHost (by way of DemuxerHost) implementation.
- void SetTotalBytes(int64 total_bytes) OVERRIDE;
- void AddBufferedByteRange(int64 start, int64 end) OVERRIDE;
- void AddBufferedTimeRange(TimeDelta start, TimeDelta end) OVERRIDE;
-
- // DemuxerHost implementaion.
- void SetDuration(TimeDelta duration) OVERRIDE;
- void OnDemuxerError(PipelineStatus error) OVERRIDE;
-
- void CreatePlayer(SbDrmSystem drm_system);
- void SetDecryptor(Decryptor* decryptor);
- void OnDemuxerInitialized(PipelineStatus status);
- void OnDemuxerSeeked(PipelineStatus status);
- void OnDemuxerStopped();
- void OnDemuxerStreamRead(DemuxerStream::Type type,
- DemuxerStream::Status status,
- const scoped_refptr<DecoderBuffer>& buffer);
-
- // StarboardPlayer::Host implementation.
- void OnNeedData(DemuxerStream::Type type) OVERRIDE;
- void OnPlayerStatus(SbPlayerState state) OVERRIDE;
-
- void UpdateDecoderConfig(const scoped_refptr<DemuxerStream>& stream);
-
- void SuspendTask(base::WaitableEvent* done_event);
- void ResumeTask(base::WaitableEvent* done_event);
-
- // Message loop used to execute pipeline tasks. It is thread-safe.
- scoped_refptr<base::MessageLoopProxy> message_loop_;
-
- // The window this player associates with. It should only be assigned in the
- // dtor and accesed once by SbPlayerCreate().
- PipelineWindow window_;
-
- // Lock used to serialize access for the following member variables.
- mutable base::Lock lock_;
-
- // Amount of available buffered data. Set by filters.
- Ranges<int64> buffered_byte_ranges_;
- Ranges<TimeDelta> buffered_time_ranges_;
-
- // True when AddBufferedByteRange() has been called more recently than
- // DidLoadingProgress().
- mutable bool did_loading_progress_;
-
- // Total size of the media. Set by filters.
- int64 total_bytes_;
-
- // Video's natural width and height. Set by filters.
- gfx::Size natural_size_;
-
- // Current volume level (from 0.0f to 1.0f). This value is set immediately
- // via SetVolume() and a task is dispatched on the message loop to notify the
- // filters.
- float volume_;
-
- // Current playback rate (>= 0.0f). This value is set immediately via
- // SetPlaybackRate() and a task is dispatched on the message loop to notify
- // the filters.
- float playback_rate_;
-
- // Whether the media contains rendered audio and video streams.
- // TODO(fischman,scherkus): replace these with checks for
- // {audio,video}_decoder_ once extraction of {Audio,Video}Decoder from the
- // Filter heirarchy is done.
- bool has_audio_;
- bool has_video_;
-
- mutable PipelineStatistics statistics_;
-
- // The following member variables are only accessed by tasks posted to
- // |message_loop_|.
-
- // Temporary callback used for Stop().
- base::Closure stop_cb_;
-
- // Permanent callbacks passed in via Start().
- SetDecryptorReadyCB decryptor_ready_cb_;
- PipelineStatusCB ended_cb_;
- PipelineStatusCB error_cb_;
- BufferingStateCB buffering_state_cb_;
- base::Closure duration_change_cb_;
- base::optional<bool> decode_to_texture_output_mode_;
-
- // Demuxer reference used for setting the preload value.
- scoped_refptr<Demuxer> demuxer_;
- bool audio_read_in_progress_;
- bool video_read_in_progress_;
- TimeDelta duration_;
-
- scoped_refptr<SbPlayerSetBoundsHelper> set_bounds_helper_;
-
- // The following member variables can be accessed from WMPI thread but all
- // modifications to them happens on the pipeline thread. So any access of
- // them from the WMPI thread and any modification to them on the pipeline
- // thread has to guarded by lock. Access to them from the pipeline thread
- // needn't to be guarded.
-
- // Temporary callback used for Start() and Seek().
- PipelineStatusCB seek_cb_;
- base::TimeDelta seek_time_;
- scoped_ptr<StarboardPlayer> player_;
- bool suspended_;
-
- DISALLOW_COPY_AND_ASSIGN(SbPlayerPipeline);
-};
-
-SbPlayerPipeline::SbPlayerPipeline(
- PipelineWindow window,
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaLog* media_log)
- : window_(window),
- message_loop_(message_loop),
- total_bytes_(0),
- natural_size_(0, 0),
- volume_(1.f),
- playback_rate_(0.f),
- has_audio_(false),
- has_video_(false),
- audio_read_in_progress_(false),
- video_read_in_progress_(false),
- set_bounds_helper_(new SbPlayerSetBoundsHelper),
- suspended_(false) {}
-
-SbPlayerPipeline::~SbPlayerPipeline() {
- DCHECK(!player_);
-}
-
-void SbPlayerPipeline::Suspend() {
- DCHECK(!message_loop_->BelongsToCurrentThread());
-
- base::WaitableEvent waitable_event(true, /* manual_reset */
- false /* initially_signaled */);
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&SbPlayerPipeline::SuspendTask,
- base::Unretained(this), &waitable_event));
- waitable_event.Wait();
-}
-
-void SbPlayerPipeline::Resume() {
- DCHECK(!message_loop_->BelongsToCurrentThread());
-
- base::WaitableEvent waitable_event(true, /* manual_reset */
- false /* initially_signaled */);
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&SbPlayerPipeline::ResumeTask,
- base::Unretained(this), &waitable_event));
- waitable_event.Wait();
-}
-
-void SbPlayerPipeline::Start(scoped_ptr<FilterCollection> filter_collection,
- const SetDecryptorReadyCB& decryptor_ready_cb,
- const PipelineStatusCB& ended_cb,
- const PipelineStatusCB& error_cb,
- const PipelineStatusCB& seek_cb,
- const BufferingStateCB& buffering_state_cb,
- const base::Closure& duration_change_cb) {
- DCHECK(filter_collection);
-
- StartTaskParameters parameters;
- parameters.demuxer = filter_collection->GetDemuxer();
- parameters.decryptor_ready_cb = decryptor_ready_cb;
- parameters.ended_cb = ended_cb;
- parameters.error_cb = error_cb;
- parameters.seek_cb = seek_cb;
- parameters.buffering_state_cb = buffering_state_cb;
- parameters.duration_change_cb = duration_change_cb;
-
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::StartTask, this, parameters));
-}
-
-void SbPlayerPipeline::Stop(const base::Closure& stop_cb) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&SbPlayerPipeline::Stop, this, stop_cb));
- return;
- }
-
- DCHECK(stop_cb_.is_null());
- DCHECK(!stop_cb.is_null());
-
- if (player_) {
- scoped_ptr<StarboardPlayer> player;
- {
- base::AutoLock auto_lock(lock_);
- player = player_.Pass();
- }
-
- DLOG(INFO) << "Destroying SbPlayer.";
- player.reset();
- DLOG(INFO) << "SbPlayer destroyed.";
- }
-
- // When Stop() is in progress, we no longer need to call |error_cb_|.
- error_cb_.Reset();
- if (demuxer_) {
- stop_cb_ = stop_cb;
- demuxer_->Stop(base::Bind(&SbPlayerPipeline::OnDemuxerStopped, this));
- } else {
- stop_cb.Run();
- }
-}
-
-void SbPlayerPipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::Seek, this, time, seek_cb));
- return;
- }
-
- if (!player_) {
- seek_cb.Run(PIPELINE_ERROR_INVALID_STATE);
- return;
- }
-
- player_->PrepareForSeek();
-
- DCHECK(seek_cb_.is_null());
- DCHECK(!seek_cb.is_null());
-
- if (audio_read_in_progress_ || video_read_in_progress_) {
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::Seek, this, time, seek_cb));
- return;
- }
-
- {
- base::AutoLock auto_lock(lock_);
- seek_cb_ = seek_cb;
- seek_time_ = time;
- }
- demuxer_->Seek(time, BindToCurrentLoop(base::Bind(
- &SbPlayerPipeline::OnDemuxerSeeked, this)));
-}
-
-bool SbPlayerPipeline::HasAudio() const {
- base::AutoLock auto_lock(lock_);
- return has_audio_;
-}
-
-bool SbPlayerPipeline::HasVideo() const {
- base::AutoLock auto_lock(lock_);
- return has_video_;
-}
-
-float SbPlayerPipeline::GetPlaybackRate() const {
- base::AutoLock auto_lock(lock_);
- return playback_rate_;
-}
-
-void SbPlayerPipeline::SetPlaybackRate(float playback_rate) {
- base::AutoLock auto_lock(lock_);
- playback_rate_ = playback_rate;
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&SbPlayerPipeline::SetPlaybackRateTask, this, playback_rate));
-}
-
-float SbPlayerPipeline::GetVolume() const {
- base::AutoLock auto_lock(lock_);
- return volume_;
-}
-
-void SbPlayerPipeline::SetVolume(float volume) {
- if (volume < 0.0f || volume > 1.0f)
- return;
-
- base::AutoLock auto_lock(lock_);
- volume_ = volume;
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::SetVolumeTask, this, volume));
-}
-
-TimeDelta SbPlayerPipeline::GetMediaTime() const {
- base::AutoLock auto_lock(lock_);
-
- if (!seek_cb_.is_null()) {
- return seek_time_;
- }
- if (!player_) {
- return TimeDelta();
- }
- base::TimeDelta media_time;
- player_->GetInfo(&statistics_.video_frames_decoded,
- &statistics_.video_frames_dropped, &media_time);
- return media_time;
-}
-
-Ranges<TimeDelta> SbPlayerPipeline::GetBufferedTimeRanges() {
- base::AutoLock auto_lock(lock_);
- Ranges<TimeDelta> time_ranges;
- for (size_t i = 0; i < buffered_time_ranges_.size(); ++i) {
- time_ranges.Add(buffered_time_ranges_.start(i),
- buffered_time_ranges_.end(i));
- }
- NOTIMPLEMENTED();
- /*if (clock_->Duration() == TimeDelta() || total_bytes_ == 0)
- return time_ranges;
- for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) {
- TimeDelta start = TimeForByteOffset_Locked(buffered_byte_ranges_.start(i));
- TimeDelta end = TimeForByteOffset_Locked(buffered_byte_ranges_.end(i));
- // Cap approximated buffered time at the length of the video.
- end = std::min(end, clock_->Duration());
- time_ranges.Add(start, end);
- }*/
-
- return time_ranges;
-}
-
-TimeDelta SbPlayerPipeline::GetMediaDuration() const {
- base::AutoLock auto_lock(lock_);
- return duration_;
-}
-
-int64 SbPlayerPipeline::GetTotalBytes() const {
- base::AutoLock auto_lock(lock_);
- return total_bytes_;
-}
-
-void SbPlayerPipeline::GetNaturalVideoSize(gfx::Size* out_size) const {
- CHECK(out_size);
- base::AutoLock auto_lock(lock_);
- *out_size = natural_size_;
-}
-
-bool SbPlayerPipeline::DidLoadingProgress() const {
- base::AutoLock auto_lock(lock_);
- bool ret = did_loading_progress_;
- did_loading_progress_ = false;
- return ret;
-}
-
-PipelineStatistics SbPlayerPipeline::GetStatistics() const {
- base::AutoLock auto_lock(lock_);
- return statistics_;
-}
-
-Pipeline::SetBoundsCB SbPlayerPipeline::GetSetBoundsCB() {
- return base::Bind(&SbPlayerSetBoundsHelper::SetBounds, set_bounds_helper_);
-}
-
-void SbPlayerPipeline::SetDecodeToTextureOutputMode(bool enabled) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::SetDecodeToTextureOutputMode,
- this, enabled));
- return;
- }
-
- decode_to_texture_output_mode_ = enabled;
-}
-
-void SbPlayerPipeline::StartTask(const StartTaskParameters& parameters) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- DCHECK(!demuxer_);
-
- demuxer_ = parameters.demuxer;
- decryptor_ready_cb_ = parameters.decryptor_ready_cb;
- ended_cb_ = parameters.ended_cb;
- error_cb_ = parameters.error_cb;
- {
- base::AutoLock auto_lock(lock_);
- seek_cb_ = parameters.seek_cb;
- }
- buffering_state_cb_ = parameters.buffering_state_cb;
- duration_change_cb_ = parameters.duration_change_cb;
-
- demuxer_->Initialize(
- this, BindToCurrentLoop(
- base::Bind(&SbPlayerPipeline::OnDemuxerInitialized, this)));
-}
-
-void SbPlayerPipeline::SetVolumeTask(float volume) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (player_) {
- player_->SetVolume(volume_);
- }
-}
-
-void SbPlayerPipeline::SetPlaybackRateTask(float volume) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (player_) {
- player_->SetPlaybackRate(playback_rate_);
- }
-}
-
-void SbPlayerPipeline::SetDurationTask(TimeDelta duration) {
- DCHECK(message_loop_->BelongsToCurrentThread());
- if (!duration_change_cb_.is_null()) {
- duration_change_cb_.Run();
- }
-}
-
-void SbPlayerPipeline::SetTotalBytes(int64 total_bytes) {
- base::AutoLock auto_lock(lock_);
- total_bytes_ = total_bytes;
-}
-
-void SbPlayerPipeline::SetDuration(TimeDelta duration) {
- base::AutoLock auto_lock(lock_);
- duration_ = duration;
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&SbPlayerPipeline::SetDurationTask, this, duration));
-}
-
-void SbPlayerPipeline::OnDemuxerError(PipelineStatus error) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::OnDemuxerError, this, error));
- return;
- }
-
- if (error != PIPELINE_OK) {
- ResetAndRunIfNotNull(&error_cb_, error);
- }
-}
-
-void SbPlayerPipeline::AddBufferedByteRange(int64 start, int64 end) {
- base::AutoLock auto_lock(lock_);
- buffered_byte_ranges_.Add(start, end);
- did_loading_progress_ = true;
-}
-
-void SbPlayerPipeline::AddBufferedTimeRange(TimeDelta start, TimeDelta end) {
- base::AutoLock auto_lock(lock_);
- buffered_time_ranges_.Add(start, end);
- did_loading_progress_ = true;
-}
-
-void SbPlayerPipeline::CreatePlayer(SbDrmSystem drm_system) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (suspended_) {
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&SbPlayerPipeline::CreatePlayer, this, drm_system));
- return;
- }
-
- // TODO: Check |suspended_| here as the pipeline can be suspended before the
- // player is created. In this case we should delay creating the player as the
- // creation of player may fail.
- const AudioDecoderConfig& audio_config =
- demuxer_->GetStream(DemuxerStream::AUDIO)->audio_decoder_config();
- const VideoDecoderConfig& video_config =
- demuxer_->GetStream(DemuxerStream::VIDEO)->video_decoder_config();
-
- {
- base::AutoLock auto_lock(lock_);
- player_.reset(new StarboardPlayer(
- message_loop_, audio_config, video_config, window_, drm_system, this,
- set_bounds_helper_.get(), *decode_to_texture_output_mode_));
- SetPlaybackRateTask(playback_rate_);
- SetVolumeTask(volume_);
- }
-
- if (player_->IsValid()) {
- return;
- }
-
- player_.reset();
-
- PipelineStatusCB seek_cb;
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(!seek_cb_.is_null());
- seek_cb = base::ResetAndReturn(&seek_cb_);
- }
- seek_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
-}
-
-void SbPlayerPipeline::SetDecryptor(Decryptor* decryptor) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (!decryptor) {
- return;
- }
- StarboardDecryptor* sb_decryptor =
- reinterpret_cast<StarboardDecryptor*>(decryptor);
- CreatePlayer(sb_decryptor->drm_system());
-}
-
-void SbPlayerPipeline::OnDemuxerInitialized(PipelineStatus status) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (status != PIPELINE_OK) {
- ResetAndRunIfNotNull(&error_cb_, status);
- return;
- }
-
- if (demuxer_->GetStream(DemuxerStream::AUDIO) == NULL ||
- demuxer_->GetStream(DemuxerStream::VIDEO) == NULL) {
- ResetAndRunIfNotNull(&error_cb_, DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
- return;
- }
-
- {
- base::AutoLock auto_lock(lock_);
- has_audio_ = demuxer_->GetStream(DemuxerStream::AUDIO) != NULL;
- DCHECK(has_audio_);
- has_video_ = demuxer_->GetStream(DemuxerStream::VIDEO) != NULL;
-
- buffering_state_cb_.Run(kHaveMetadata);
-
- const AudioDecoderConfig& audio_config =
- demuxer_->GetStream(DemuxerStream::AUDIO)->audio_decoder_config();
- bool is_encrypted = audio_config.is_encrypted();
- if (has_video_) {
- const VideoDecoderConfig& video_config =
- demuxer_->GetStream(DemuxerStream::VIDEO)->video_decoder_config();
- natural_size_ = video_config.natural_size();
- is_encrypted |= video_config.is_encrypted();
- }
- if (is_encrypted) {
- decryptor_ready_cb_.Run(
- BindToCurrentLoop(base::Bind(&SbPlayerPipeline::SetDecryptor, this)));
- return;
- }
- }
-
- CreatePlayer(kSbDrmSystemInvalid);
-}
-
-void SbPlayerPipeline::OnDemuxerSeeked(PipelineStatus status) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (status == PIPELINE_OK) {
- player_->Seek(seek_time_);
- }
-}
-
-void SbPlayerPipeline::OnDemuxerStopped() {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::OnDemuxerStopped, this));
- return;
- }
-
- base::ResetAndReturn(&stop_cb_).Run();
-}
-
-void SbPlayerPipeline::OnDemuxerStreamRead(
- DemuxerStream::Type type,
- DemuxerStream::Status status,
- const scoped_refptr<DecoderBuffer>& buffer) {
- DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO)
- << "Unsupported DemuxerStream::Type " << type;
-
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&SbPlayerPipeline::OnDemuxerStreamRead, this,
- type, status, buffer));
- return;
- }
-
- scoped_refptr<DemuxerStream> stream = demuxer_->GetStream(type);
-
- // In case if Stop() has been called.
- if (!player_) {
- return;
- }
-
- if (status == DemuxerStream::kAborted) {
- if (type == DemuxerStream::AUDIO) {
- DCHECK(audio_read_in_progress_);
- audio_read_in_progress_ = false;
- } else {
- DCHECK(video_read_in_progress_);
- video_read_in_progress_ = false;
- }
- if (!seek_cb_.is_null()) {
- PipelineStatusCB seek_cb;
- {
- base::AutoLock auto_lock(lock_);
- seek_cb = base::ResetAndReturn(&seek_cb_);
- }
- seek_cb.Run(PIPELINE_OK);
- }
- return;
- }
-
- if (status == DemuxerStream::kConfigChanged) {
- UpdateDecoderConfig(stream);
- stream->Read(
- base::Bind(&SbPlayerPipeline::OnDemuxerStreamRead, this, type));
- return;
- }
-
- if (type == DemuxerStream::AUDIO) {
- audio_read_in_progress_ = false;
- } else {
- video_read_in_progress_ = false;
- }
-
- player_->WriteBuffer(type, buffer);
-}
-
-void SbPlayerPipeline::OnNeedData(DemuxerStream::Type type) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- // In case if Stop() has been called.
- if (!player_) {
- return;
- }
-
- if (type == DemuxerStream::AUDIO) {
- if (audio_read_in_progress_) {
- return;
- }
- audio_read_in_progress_ = true;
- } else {
- DCHECK_EQ(type, DemuxerStream::VIDEO);
- if (video_read_in_progress_) {
- return;
- }
- video_read_in_progress_ = true;
- }
- scoped_refptr<DemuxerStream> stream = demuxer_->GetStream(type);
- stream->Read(base::Bind(&SbPlayerPipeline::OnDemuxerStreamRead, this, type));
-}
-
-void SbPlayerPipeline::OnPlayerStatus(SbPlayerState state) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- // In case if Stop() has been called.
- if (!player_) {
- return;
- }
- switch (state) {
- case kSbPlayerStateInitialized:
- NOTREACHED();
- break;
- case kSbPlayerStatePrerolling:
- break;
- case kSbPlayerStatePresenting:
- buffering_state_cb_.Run(kPrerollCompleted);
- if (!seek_cb_.is_null()) {
- PipelineStatusCB seek_cb;
- {
- base::AutoLock auto_lock(lock_);
- seek_cb = base::ResetAndReturn(&seek_cb_);
- }
- seek_cb.Run(PIPELINE_OK);
- }
- break;
- case kSbPlayerStateEndOfStream:
- ended_cb_.Run(PIPELINE_OK);
- break;
- case kSbPlayerStateDestroyed:
- break;
- case kSbPlayerStateError:
- ResetAndRunIfNotNull(&error_cb_, PIPELINE_ERROR_DECODE);
- break;
- }
-}
-
-void SbPlayerPipeline::UpdateDecoderConfig(
- const scoped_refptr<DemuxerStream>& stream) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (stream->type() == DemuxerStream::AUDIO) {
- stream->audio_decoder_config();
- } else {
- DCHECK_EQ(stream->type(), DemuxerStream::VIDEO);
- const VideoDecoderConfig& decoder_config = stream->video_decoder_config();
- base::AutoLock auto_lock(lock_);
- natural_size_ = decoder_config.natural_size();
- player_->UpdateVideoResolution(static_cast<int>(natural_size_.width()),
- static_cast<int>(natural_size_.height()));
- }
-}
-
-void SbPlayerPipeline::SuspendTask(base::WaitableEvent* done_event) {
- DCHECK(message_loop_->BelongsToCurrentThread());
- DCHECK(done_event);
- DCHECK(!suspended_);
-
- if (suspended_) {
- done_event->Signal();
- return;
- }
-
- if (player_) {
- player_->Suspend();
- }
-
- suspended_ = true;
-
- done_event->Signal();
-}
-
-void SbPlayerPipeline::ResumeTask(base::WaitableEvent* done_event) {
- DCHECK(message_loop_->BelongsToCurrentThread());
- DCHECK(done_event);
- DCHECK(suspended_);
-
- if (!suspended_) {
- done_event->Signal();
- return;
- }
-
- if (player_) {
- player_->Resume();
- }
-
- suspended_ = false;
-
- done_event->Signal();
-}
-
-} // namespace
-
-#endif // SB_HAS(PLAYER)
-
-scoped_refptr<Pipeline> Pipeline::Create(
- PipelineWindow window,
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaLog* media_log) {
-#if SB_HAS(PLAYER)
- return new SbPlayerPipeline(window, message_loop, media_log);
-#else
- return NULL;
-#endif
-}
-
-} // namespace media
diff --git a/src/media/base/sbplayer_set_bounds_helper.cc b/src/media/base/sbplayer_set_bounds_helper.cc
deleted file mode 100644
index 5e96a94..0000000
--- a/src/media/base/sbplayer_set_bounds_helper.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "media/base/sbplayer_set_bounds_helper.h"
-
-#include "media/base/starboard_player.h"
-
-namespace media {
-
-void SbPlayerSetBoundsHelper::SetPlayer(StarboardPlayer* player) {
- base::Lock lock_;
- player_ = player;
-}
-
-bool SbPlayerSetBoundsHelper::SetBounds(const gfx::Rect& rect) {
- base::AutoLock auto_lock(lock_);
- if (!player_) {
- return false;
- }
- player_->SetBounds(rect);
- return true;
-}
-
-} // namespace media
diff --git a/src/media/base/sbplayer_set_bounds_helper.h b/src/media/base/sbplayer_set_bounds_helper.h
deleted file mode 100644
index 06affcf..0000000
--- a/src/media/base/sbplayer_set_bounds_helper.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef MEDIA_BASE_SBPLAYER_SET_BOUNDS_HELPER_H_
-#define MEDIA_BASE_SBPLAYER_SET_BOUNDS_HELPER_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "ui/gfx/rect.h"
-
-namespace media {
-
-class StarboardPlayer;
-
-class SbPlayerSetBoundsHelper
- : public base::RefCountedThreadSafe<SbPlayerSetBoundsHelper> {
- public:
- SbPlayerSetBoundsHelper() : player_(NULL) {}
-
- void SetPlayer(StarboardPlayer* player);
- bool SetBounds(const gfx::Rect& rect);
-
- private:
- base::Lock lock_;
- StarboardPlayer* player_;
-
- DISALLOW_COPY_AND_ASSIGN(SbPlayerSetBoundsHelper);
-};
-
-} // namespace media
-
-#endif // MEDIA_BASE_SBPLAYER_SET_BOUNDS_HELPER_H_
diff --git a/src/media/base/starboard_player.cc b/src/media/base/starboard_player.cc
deleted file mode 100644
index 55d813b..0000000
--- a/src/media/base/starboard_player.cc
+++ /dev/null
@@ -1,596 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "media/base/starboard_player.h"
-
-#error This implementation of StarboardPlayer is deprecated and will be removed
-#error in the next release. You should upgrade to Starboard version 4 and
-#error Cobalt 9 to use the StarboardPlayer implementation in cobalt/media.
-#error Please contact us *immediately* if the upcoming removal of this file
-#error will break your port.
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "media/base/shell_media_platform.h"
-#include "media/base/starboard_utils.h"
-#include "starboard/configuration.h"
-#include "starboard/memory.h"
-
-namespace media {
-
-StarboardPlayer::StarboardPlayer(
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
- const AudioDecoderConfig& audio_config,
- const VideoDecoderConfig& video_config,
- SbWindow window,
- SbDrmSystem drm_system,
- Host* host,
- SbPlayerSetBoundsHelper* set_bounds_helper,
- bool prefer_decode_to_texture)
- : message_loop_(message_loop),
- window_(window),
- drm_system_(drm_system),
- host_(host),
- set_bounds_helper_(set_bounds_helper),
- weak_this_(AsWeakPtr()),
- frame_width_(1),
- frame_height_(1),
- ticket_(SB_PLAYER_INITIAL_TICKET),
- volume_(1.0),
- playback_rate_(0.0),
- seek_pending_(false),
- state_(kPlaying) {
- DCHECK(audio_config.IsValidConfig());
- DCHECK(video_config.IsValidConfig());
- DCHECK(host_);
- DCHECK(set_bounds_helper_);
-
- audio_config_.CopyFrom(audio_config);
- video_config_.CopyFrom(video_config);
-
-#if SB_API_VERSION >= 4
- output_mode_ = ComputeSbPlayerOutputMode(
- MediaVideoCodecToSbMediaVideoCodec(video_config.codec()), drm_system,
- prefer_decode_to_texture);
-#endif // SB_API_VERSION >= 4
- CreatePlayer();
-
- message_loop->PostTask(
- FROM_HERE,
- base::Bind(&StarboardPlayer::ClearDecoderBufferCache, weak_this_));
-}
-
-StarboardPlayer::~StarboardPlayer() {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- set_bounds_helper_->SetPlayer(NULL);
-
- ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
- ShellVideoFrameProvider::kOutputModeInvalid);
-#if SB_API_VERSION >= 4
- ShellMediaPlatform::Instance()
- ->GetVideoFrameProvider()
- ->ResetGetCurrentSbDecodeTargetFunction();
-#endif // SB_API_VERSION >= 4
-
- SbPlayerDestroy(player_);
-}
-
-void StarboardPlayer::UpdateVideoResolution(int frame_width, int frame_height) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- frame_width_ = frame_width;
- frame_height_ = frame_height;
-}
-
-void StarboardPlayer::WriteBuffer(DemuxerStream::Type type,
- const scoped_refptr<DecoderBuffer>& buffer) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- // When |state_| is kPlaying, cache all buffer appended. When |state_| is
- // kSuspended, there may still be left-over buffers appended from the pipeline
- // so they also should be cached.
- // When |state_| is resuming, all buffers come from the cache and shouldn't be
- // cached.
- if (state_ != kResuming) {
- decoder_buffer_cache_.AddBuffer(type, buffer);
- }
-
- if (state_ == kSuspended) {
- DCHECK(!SbPlayerIsValid(player_));
- return;
- }
-
- DCHECK(SbPlayerIsValid(player_));
-
- if (buffer->IsEndOfStream()) {
- SbPlayerWriteEndOfStream(player_, DemuxerStreamTypeToSbMediaType(type));
- return;
- }
-
- DecodingBuffers::iterator iter = decoding_buffers_.find(buffer->GetData());
- if (iter == decoding_buffers_.end()) {
- decoding_buffers_[buffer->GetData()] = std::make_pair(buffer, 1);
- } else {
- ++iter->second.second;
- }
-
- SbDrmSampleInfo drm_info;
- SbDrmSubSampleMapping subsample_mapping;
- bool is_encrypted = buffer->GetDecryptConfig();
- SbMediaVideoSampleInfo video_info;
-
- drm_info.subsample_count = 0;
- video_info.is_key_frame = buffer->IsKeyframe();
- video_info.frame_width = frame_width_;
- video_info.frame_height = frame_height_;
-
-#if SB_API_VERSION >= 4
- SbMediaColorMetadata sb_media_color_metadata =
- MediaToSbMediaColorMetadata(video_config_.webm_color_metadata());
- video_info.color_metadata = &sb_media_color_metadata;
-#endif
- if (is_encrypted) {
- FillDrmSampleInfo(buffer, &drm_info, &subsample_mapping);
- }
-#if SB_API_VERSION >= 4
- const void* sample_buffers[] = {buffer->GetData()};
- int sample_buffer_sizes[] = {buffer->GetDataSize()};
- SbPlayerWriteSample(player_, DemuxerStreamTypeToSbMediaType(type),
- sample_buffers, sample_buffer_sizes, 1,
- TimeDeltaToSbMediaTime(buffer->GetTimestamp()),
- type == DemuxerStream::VIDEO ? &video_info : NULL,
- drm_info.subsample_count > 0 ? &drm_info : NULL);
-#else // SB_API_VERSION >= 4
- SbPlayerWriteSample(player_, DemuxerStreamTypeToSbMediaType(type),
- buffer->GetData(), buffer->GetDataSize(),
- TimeDeltaToSbMediaTime(buffer->GetTimestamp()),
- type == DemuxerStream::VIDEO ? &video_info : NULL,
- drm_info.subsample_count > 0 ? &drm_info : NULL);
-#endif // SB_API_VERSION >= 4
-}
-
-void StarboardPlayer::SetBounds(const gfx::Rect& rect) {
- DCHECK(SbPlayerIsValid(player_));
-
-#if SB_API_VERSION >= 4
- const int kZIndex = 0;
- SbPlayerSetBounds(player_, kZIndex, rect.x(), rect.y(), rect.width(),
- rect.height());
-#else // SB_API_VERSION >= 4
- SbPlayerSetBounds(player_, rect.x(), rect.y(), rect.width(), rect.height());
-#endif // SB_API_VERSION >= 4
-}
-
-void StarboardPlayer::PrepareForSeek() {
- DCHECK(message_loop_->BelongsToCurrentThread());
- ++ticket_;
-#if SB_API_VERSION < 4
- SbPlayerSetPause(player_, true);
-#else // SB_API_VERSION < 4
- SbPlayerSetPlaybackRate(player_, 0.f);
-#endif // SB_API_VERSION < 4
- seek_pending_ = true;
-}
-
-void StarboardPlayer::Seek(base::TimeDelta time) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- decoder_buffer_cache_.ClearAll();
-
- if (state_ == kSuspended) {
- DCHECK(!SbPlayerIsValid(player_));
- preroll_timestamp_ = time;
- return;
- }
-
- // If a seek happens during resuming, the pipeline will write samples from the
- // seek target time again so resuming can be aborted.
- if (state_ == kResuming) {
- state_ = kPlaying;
- }
-
- DCHECK(SbPlayerIsValid(player_));
-
- ++ticket_;
- SbPlayerSeek(player_, TimeDeltaToSbMediaTime(time), ticket_);
- seek_pending_ = false;
-#if SB_API_VERSION < 4
- SbPlayerSetPause(player_, playback_rate_ == 0.0);
-#else // SB_API_VERSION < 4
- SbPlayerSetPlaybackRate(player_, playback_rate_);
-#endif // SB_API_VERSION < 4
-}
-
-void StarboardPlayer::SetVolume(float volume) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- volume_ = volume;
-
- if (state_ == kSuspended) {
- DCHECK(!SbPlayerIsValid(player_));
- return;
- }
-
- DCHECK(SbPlayerIsValid(player_));
- SbPlayerSetVolume(player_, volume);
-}
-
-void StarboardPlayer::SetPlaybackRate(double playback_rate) {
- DCHECK(message_loop_->BelongsToCurrentThread());
- DCHECK(SbPlayerIsValid(player_));
-
- playback_rate_ = playback_rate;
-
- if (seek_pending_) {
- return;
- }
-
-#if SB_API_VERSION < 4
- SbPlayerSetPause(player_, playback_rate == 0.0);
-#else // SB_API_VERSION < 4
- SbPlayerSetPlaybackRate(player_, playback_rate);
-#endif // SB_API_VERSION < 4
-}
-
-void StarboardPlayer::GetInfo(uint32* video_frames_decoded,
- uint32* video_frames_dropped,
- base::TimeDelta* media_time) {
- DCHECK(video_frames_decoded || video_frames_dropped || media_time);
-
- base::AutoLock auto_lock(lock_);
- if (state_ == kSuspended) {
- DCHECK(!SbPlayerIsValid(player_));
-
- if (video_frames_decoded) {
- *video_frames_decoded = cached_video_frames_decoded_;
- }
- if (video_frames_dropped) {
- *video_frames_dropped = cached_video_frames_dropped_;
- }
- if (media_time) {
- *media_time = preroll_timestamp_;
- }
- return;
- }
-
- DCHECK(SbPlayerIsValid(player_));
-
- SbPlayerInfo info;
- SbPlayerGetInfo(player_, &info);
- if (video_frames_decoded) {
- *video_frames_decoded = info.total_video_frames;
- }
- if (video_frames_dropped) {
- *video_frames_dropped = info.dropped_video_frames;
- }
- if (media_time) {
- *media_time = SbMediaTimeToTimeDelta(info.current_media_pts);
- }
-}
-
-void StarboardPlayer::Suspend() {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- // Check if the player is already suspended.
- if (state_ == kSuspended) {
- DCHECK(!SbPlayerIsValid(player_));
- return;
- }
-
- DCHECK(SbPlayerIsValid(player_));
-
-#if SB_API_VERSION < 4
- SbPlayerSetPause(player_, true);
-#else // SB_API_VERSION < 4
- SbPlayerSetPlaybackRate(player_, 0.0);
-#endif // SB_API_VERSION < 4
-
- base::AutoLock auto_lock(lock_);
-
- state_ = kSuspended;
-
- SbPlayerInfo info;
- SbPlayerGetInfo(player_, &info);
- cached_video_frames_decoded_ = info.total_video_frames;
- cached_video_frames_dropped_ = info.dropped_video_frames;
- preroll_timestamp_ = SbMediaTimeToTimeDelta(info.current_media_pts);
-
- set_bounds_helper_->SetPlayer(NULL);
- SbPlayerDestroy(player_);
-
- player_ = kSbPlayerInvalid;
-}
-
-void StarboardPlayer::Resume() {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- // Check if the player is already resumed.
- if (state_ != kSuspended) {
- DCHECK(SbPlayerIsValid(player_));
- return;
- }
-
- DCHECK(!SbPlayerIsValid(player_));
-
- decoder_buffer_cache_.StartResuming();
-
- CreatePlayer();
-
- base::AutoLock auto_lock(lock_);
- state_ = kResuming;
-}
-
-namespace {
-#if SB_API_VERSION >= 4
-ShellVideoFrameProvider::OutputMode ToVideoFrameProviderOutputMode(
- SbPlayerOutputMode output_mode) {
- switch (output_mode) {
- case kSbPlayerOutputModeDecodeToTexture:
- return ShellVideoFrameProvider::kOutputModeDecodeToTexture;
- case kSbPlayerOutputModePunchOut:
- return ShellVideoFrameProvider::kOutputModePunchOut;
- case kSbPlayerOutputModeInvalid:
- return ShellVideoFrameProvider::kOutputModeInvalid;
- }
-
- NOTREACHED();
- return ShellVideoFrameProvider::kOutputModeInvalid;
-}
-#endif // #if SB_API_VERSION >= 4
-} // namespace
-
-void StarboardPlayer::CreatePlayer() {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- SbMediaAudioHeader audio_header;
- // TODO: Make this work with non AAC audio.
- audio_header.format_tag = 0x00ff;
- audio_header.number_of_channels =
- ChannelLayoutToChannelCount(audio_config_.channel_layout());
- audio_header.samples_per_second = audio_config_.samples_per_second();
- audio_header.average_bytes_per_second = 1;
- audio_header.block_alignment = 4;
- audio_header.bits_per_sample = audio_config_.bits_per_channel();
-#if SB_API_VERSION >= SB_AUDIO_SPECIFIC_CONFIG_AS_POINTER
- audio_header.audio_specific_config_size =
- static_cast<uint16_t>(audio_config_.extra_data_size());
- if (audio_header.audio_specific_config_size == 0) {
- audio_header.audio_specific_config = NULL;
- } else {
- audio_header.audio_specific_config =
- static_cast<int16_t*>(&audio_config_.extra_data()[0]);
- }
-#else // SB_API_VERSION >= SB_AUDIO_SPECIFIC_CONFIG_AS_POINTER
- audio_header.audio_specific_config_size = static_cast<uint16_t>(
- std::min(audio_config_.extra_data_size(),
- sizeof(audio_header.audio_specific_config)));
- if (audio_header.audio_specific_config_size > 0) {
- SbMemoryCopy(audio_header.audio_specific_config, audio_config_.extra_data(),
- audio_header.audio_specific_config_size);
- }
-#endif // SB_API_VERSION >= SB_AUDIO_SPECIFIC_CONFIG_AS_POINTER
-
- SbMediaAudioCodec audio_codec =
- MediaAudioCodecToSbMediaAudioCodec(audio_config_.codec());
- SbMediaVideoCodec video_codec =
- MediaVideoCodecToSbMediaVideoCodec(video_config_.codec());
-
-#if SB_API_VERSION >= 4
- DCHECK(SbPlayerOutputModeSupported(output_mode_, video_codec, drm_system_));
-#endif // SB_API_VERSION >= 4
-
- player_ = SbPlayerCreate(
- window_, video_codec, audio_codec, SB_PLAYER_NO_DURATION, drm_system_,
- &audio_header, &StarboardPlayer::DeallocateSampleCB,
- &StarboardPlayer::DecoderStatusCB, &StarboardPlayer::PlayerStatusCB, this
-#if SB_API_VERSION >= 4
- ,
- output_mode_,
- ShellMediaPlatform::Instance()->GetSbDecodeTargetGraphicsContextProvider()
-#elif SB_API_VERSION >= 3
- ,
- ShellMediaPlatform::Instance()->GetSbDecodeTargetProvider() // provider
-#endif // SB_API_VERSION >= 3
- );
-
-#if SB_API_VERSION >= 4
- if (output_mode_ == kSbPlayerOutputModeDecodeToTexture) {
- // If the player is setup to decode to texture, then provide Cobalt with
- // a method of querying that texture.
- ShellMediaPlatform::Instance()
- ->GetVideoFrameProvider()
- ->SetGetCurrentSbDecodeTargetFunction(
- base::Bind(&StarboardPlayer::GetCurrentSbDecodeTarget,
- base::Unretained(this)));
- }
- ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
- ToVideoFrameProviderOutputMode(output_mode_));
-#else // SB_API_VERSION >= 4
- ShellMediaPlatform::Instance()->GetVideoFrameProvider()->SetOutputMode(
- ShellVideoFrameProvider::kOutputModePunchOut);
-#endif // SB_API_VERSION >= 4
- set_bounds_helper_->SetPlayer(this);
-}
-
-#if SB_API_VERSION >= 4
-SbDecodeTarget StarboardPlayer::GetCurrentSbDecodeTarget() {
- return SbPlayerGetCurrentFrame(player_);
-}
-SbPlayerOutputMode StarboardPlayer::GetSbPlayerOutputMode() {
- return output_mode_;
-}
-#endif // SB_API_VERSION >= 4
-
-void StarboardPlayer::ClearDecoderBufferCache() {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- base::TimeDelta media_time;
- GetInfo(NULL, NULL, &media_time);
- decoder_buffer_cache_.ClearSegmentsBeforeMediaTime(media_time);
-
- message_loop_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&StarboardPlayer::ClearDecoderBufferCache, weak_this_),
- base::TimeDelta::FromMilliseconds(
- kClearDecoderCacheIntervalInMilliseconds));
-}
-
-void StarboardPlayer::OnDecoderStatus(SbPlayer player,
- SbMediaType type,
- SbPlayerDecoderState state,
- int ticket) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (player_ != player || ticket != ticket_) {
- return;
- }
-
- DCHECK_NE(state_, kSuspended);
-
- switch (state) {
- case kSbPlayerDecoderStateNeedsData:
- break;
- case kSbPlayerDecoderStateBufferFull:
- DLOG(WARNING) << "kSbPlayerDecoderStateBufferFull has been deprecated.";
- return;
- case kSbPlayerDecoderStateDestroyed:
- return;
- }
-
- if (state_ == kResuming) {
- DemuxerStream::Type stream_type = SbMediaTypeToDemuxerStreamType(type);
- if (decoder_buffer_cache_.GetBuffer(stream_type)) {
- WriteBuffer(stream_type, decoder_buffer_cache_.GetBuffer(stream_type));
- decoder_buffer_cache_.AdvanceToNextBuffer(stream_type);
- return;
- }
- if (!decoder_buffer_cache_.GetBuffer(DemuxerStream::AUDIO) &&
- !decoder_buffer_cache_.GetBuffer(DemuxerStream::VIDEO)) {
- state_ = kPlaying;
- }
- }
-
- host_->OnNeedData(SbMediaTypeToDemuxerStreamType(type));
-}
-
-void StarboardPlayer::OnPlayerStatus(SbPlayer player,
- SbPlayerState state,
- int ticket) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (player_ != player) {
- return;
- }
-
- DCHECK_NE(state_, kSuspended);
-
- if (ticket != SB_PLAYER_INITIAL_TICKET && ticket != ticket_) {
- return;
- }
-
- if (state == kSbPlayerStateInitialized) {
- if (ticket_ == SB_PLAYER_INITIAL_TICKET) {
- ++ticket_;
- }
- SbPlayerSeek(player_, TimeDeltaToSbMediaTime(preroll_timestamp_), ticket_);
- SetVolume(volume_);
-#if SB_API_VERSION < 4
- SbPlayerSetPause(player_, playback_rate_ == 0.0);
-#else // SB_API_VERSION < 4
- SbPlayerSetPlaybackRate(player_, playback_rate_);
-#endif // SB_API_VERSION < 4
- return;
- }
- host_->OnPlayerStatus(state);
-}
-
-void StarboardPlayer::OnDeallocateSample(const void* sample_buffer) {
- DCHECK(message_loop_->BelongsToCurrentThread());
-
- DecodingBuffers::iterator iter = decoding_buffers_.find(sample_buffer);
- DCHECK(iter != decoding_buffers_.end());
- if (iter == decoding_buffers_.end()) {
- LOG(ERROR) << "StarboardPlayer::OnDeallocateSample encounters unknown "
- << "sample_buffer " << sample_buffer;
- return;
- }
- --iter->second.second;
- if (iter->second.second == 0) {
- decoding_buffers_.erase(iter);
- }
-}
-
-// static
-void StarboardPlayer::DecoderStatusCB(SbPlayer player,
- void* context,
- SbMediaType type,
- SbPlayerDecoderState state,
- int ticket) {
- StarboardPlayer* helper = reinterpret_cast<StarboardPlayer*>(context);
- helper->message_loop_->PostTask(
- FROM_HERE, base::Bind(&StarboardPlayer::OnDecoderStatus,
- helper->weak_this_, player, type, state, ticket));
-}
-
-// static
-void StarboardPlayer::PlayerStatusCB(SbPlayer player,
- void* context,
- SbPlayerState state,
- int ticket) {
- StarboardPlayer* helper = reinterpret_cast<StarboardPlayer*>(context);
- helper->message_loop_->PostTask(
- FROM_HERE, base::Bind(&StarboardPlayer::OnPlayerStatus,
- helper->weak_this_, player, state, ticket));
-}
-
-// static
-void StarboardPlayer::DeallocateSampleCB(SbPlayer player,
- void* context,
- const void* sample_buffer) {
- StarboardPlayer* helper = reinterpret_cast<StarboardPlayer*>(context);
- helper->message_loop_->PostTask(
- FROM_HERE, base::Bind(&StarboardPlayer::OnDeallocateSample,
- helper->weak_this_, sample_buffer));
-}
-
-#if SB_API_VERSION >= 4
-// static
-SbPlayerOutputMode StarboardPlayer::ComputeSbPlayerOutputMode(
- SbMediaVideoCodec codec,
- SbDrmSystem drm_system,
- bool prefer_decode_to_texture) {
- // Try to choose the output mode according to the passed in value of
- // |prefer_decode_to_texture|. If the preferred output mode is unavailable
- // though, fallback to an output mode that is available.
- SbPlayerOutputMode output_mode = kSbPlayerOutputModeInvalid;
- if (SbPlayerOutputModeSupported(kSbPlayerOutputModePunchOut, codec,
- drm_system)) {
- output_mode = kSbPlayerOutputModePunchOut;
- }
- if ((prefer_decode_to_texture || output_mode == kSbPlayerOutputModeInvalid) &&
- SbPlayerOutputModeSupported(kSbPlayerOutputModeDecodeToTexture, codec,
- drm_system)) {
- output_mode = kSbPlayerOutputModeDecodeToTexture;
- }
- CHECK_NE(kSbPlayerOutputModeInvalid, output_mode);
-
- return output_mode;
-}
-#endif // SB_API_VERSION >= 4
-
-} // namespace media
diff --git a/src/media/base/starboard_player.h b/src/media/base/starboard_player.h
deleted file mode 100644
index 521065a..0000000
--- a/src/media/base/starboard_player.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef MEDIA_BASE_STARBOARD_PLAYER_H_
-#define MEDIA_BASE_STARBOARD_PLAYER_H_
-
-#include <map>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop_proxy.h"
-#include "base/synchronization/lock.h"
-#include "base/time.h"
-#include "media/base/audio_decoder_config.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/decoder_buffer_cache.h"
-#include "media/base/demuxer_stream.h"
-#include "media/base/sbplayer_set_bounds_helper.h"
-#include "media/base/video_decoder_config.h"
-#include "starboard/media.h"
-#include "starboard/player.h"
-
-namespace media {
-
-// TODO: Add switch to disable caching
-class StarboardPlayer : public base::SupportsWeakPtr<StarboardPlayer> {
- public:
- class Host {
- public:
- virtual void OnNeedData(DemuxerStream::Type type) = 0;
- virtual void OnPlayerStatus(SbPlayerState state) = 0;
-
- protected:
- ~Host() {}
- };
-
- StarboardPlayer(const scoped_refptr<base::MessageLoopProxy>& message_loop,
- const AudioDecoderConfig& audio_config,
- const VideoDecoderConfig& video_config,
- SbWindow window,
- SbDrmSystem drm_system,
- Host* host,
- SbPlayerSetBoundsHelper* set_bounds_helper,
- bool prefer_decode_to_texture);
- ~StarboardPlayer();
-
- bool IsValid() const { return SbPlayerIsValid(player_); }
-
- void UpdateVideoResolution(int frame_width, int frame_height);
-
- void WriteBuffer(DemuxerStream::Type type,
- const scoped_refptr<DecoderBuffer>& buffer);
- void SetBounds(const gfx::Rect& rect);
-
- void PrepareForSeek();
- void Seek(base::TimeDelta time);
-
- void SetVolume(float volume);
- void SetPlaybackRate(double playback_rate);
- void GetInfo(uint32* video_frames_decoded,
- uint32* video_frames_dropped,
- base::TimeDelta* media_time);
-
- void Suspend();
- void Resume();
-
-#if SB_API_VERSION >= 4
- SbDecodeTarget GetCurrentSbDecodeTarget();
- SbPlayerOutputMode GetSbPlayerOutputMode();
-#endif // SB_API_VERSION >= 4
-
- private:
- enum State {
- kPlaying,
- kSuspended,
- kResuming,
- };
-
- static const int64 kClearDecoderCacheIntervalInMilliseconds = 1000;
-
- // A map from raw data pointer returned by DecoderBuffer::GetData() to the
- // DecoderBuffer and a reference count. The reference count indicates how
- // many instances of the DecoderBuffer is currently being decoded in the
- // pipeline.
- typedef std::map<const void*, std::pair<scoped_refptr<DecoderBuffer>, int> >
- DecodingBuffers;
-
- void CreatePlayer();
- void ClearDecoderBufferCache();
-
- void OnDecoderStatus(SbPlayer player,
- SbMediaType type,
- SbPlayerDecoderState state,
- int ticket);
- void OnPlayerStatus(SbPlayer player, SbPlayerState state, int ticket);
- void OnDeallocateSample(const void* sample_buffer);
-
- static void DecoderStatusCB(SbPlayer player,
- void* context,
- SbMediaType type,
- SbPlayerDecoderState state,
- int ticket);
- static void PlayerStatusCB(SbPlayer player,
- void* context,
- SbPlayerState state,
- int ticket);
- static void DeallocateSampleCB(SbPlayer player,
- void* context,
- const void* sample_buffer);
-
-#if SB_API_VERSION >= 4
- // Returns the output mode that should be used for a video with the given
- // specifications.
- static SbPlayerOutputMode ComputeSbPlayerOutputMode(
- SbMediaVideoCodec codec,
- SbDrmSystem drm_system,
- bool prefer_decode_to_texture);
-#endif // SB_API_VERSION >= 4
-
- // The following variables are initialized in the ctor and never changed.
- const scoped_refptr<base::MessageLoopProxy> message_loop_;
- AudioDecoderConfig audio_config_;
- VideoDecoderConfig video_config_;
- const SbWindow window_;
- const SbDrmSystem drm_system_;
- Host* const host_;
- SbPlayerSetBoundsHelper* const set_bounds_helper_;
- const base::WeakPtr<StarboardPlayer> weak_this_;
-
- // The following variables are only changed or accessed from the
- // |message_loop_|.
- int frame_width_;
- int frame_height_;
- DecodingBuffers decoding_buffers_;
- int ticket_;
- float volume_;
- double playback_rate_;
- bool seek_pending_;
- DecoderBufferCache decoder_buffer_cache_;
-
- // The following variables can be accessed from GetInfo(), which can be called
- // from any threads. So some of their usages have to be guarded by |lock_|.
- base::Lock lock_;
- State state_;
- SbPlayer player_;
- uint32 cached_video_frames_decoded_;
- uint32 cached_video_frames_dropped_;
- base::TimeDelta preroll_timestamp_;
-
-#if SB_API_VERSION >= 4
- // Keep track of the output mode we are supposed to output to.
- SbPlayerOutputMode output_mode_;
-#endif // SB_API_VERSION >= 4
-};
-
-} // namespace media
-
-#endif // MEDIA_BASE_STARBOARD_PLAYER_H_
diff --git a/src/media/base/starboard_utils.cc b/src/media/base/starboard_utils.cc
deleted file mode 100644
index c66d3a6..0000000
--- a/src/media/base/starboard_utils.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "media/base/starboard_utils.h"
-
-#include "base/logging.h"
-
-using base::Time;
-using base::TimeDelta;
-
-namespace media {
-
-SbMediaAudioCodec MediaAudioCodecToSbMediaAudioCodec(AudioCodec codec) {
- if (codec == kCodecAAC) {
- return kSbMediaAudioCodecAac;
- } else if (codec == kCodecVorbis) {
- return kSbMediaAudioCodecVorbis;
- } else if (codec == kCodecOpus) {
- return kSbMediaAudioCodecOpus;
- }
- DLOG(ERROR) << "Unsupported audio codec " << codec;
- return kSbMediaAudioCodecNone;
-}
-
-SbMediaVideoCodec MediaVideoCodecToSbMediaVideoCodec(VideoCodec codec) {
- if (codec == kCodecH264) {
- return kSbMediaVideoCodecH264;
- } else if (codec == kCodecVC1) {
- return kSbMediaVideoCodecVc1;
- } else if (codec == kCodecMPEG2) {
- return kSbMediaVideoCodecMpeg2;
- } else if (codec == kCodecTheora) {
- return kSbMediaVideoCodecTheora;
- } else if (codec == kCodecVP8) {
- return kSbMediaVideoCodecVp8;
- } else if (codec == kCodecVP9) {
- return kSbMediaVideoCodecVp9;
- }
- DLOG(ERROR) << "Unsupported video codec " << codec;
- return kSbMediaVideoCodecNone;
-}
-
-TimeDelta SbMediaTimeToTimeDelta(SbMediaTime timestamp) {
- return TimeDelta::FromMicroseconds(timestamp * Time::kMicrosecondsPerSecond /
- kSbMediaTimeSecond);
-}
-
-SbMediaTime TimeDeltaToSbMediaTime(TimeDelta timedelta) {
- return timedelta.InMicroseconds() * kSbMediaTimeSecond /
- Time::kMicrosecondsPerSecond;
-}
-
-DemuxerStream::Type SbMediaTypeToDemuxerStreamType(SbMediaType type) {
- if (type == kSbMediaTypeAudio) {
- return DemuxerStream::AUDIO;
- }
- DCHECK_EQ(type, kSbMediaTypeVideo);
- return DemuxerStream::VIDEO;
-}
-
-SbMediaType DemuxerStreamTypeToSbMediaType(DemuxerStream::Type type) {
- if (type == DemuxerStream::AUDIO) {
- return kSbMediaTypeAudio;
- }
- DCHECK_EQ(type, DemuxerStream::VIDEO);
- return kSbMediaTypeVideo;
-}
-
-void FillDrmSampleInfo(const scoped_refptr<DecoderBuffer>& buffer,
- SbDrmSampleInfo* drm_info,
- SbDrmSubSampleMapping* subsample_mapping) {
- DCHECK(drm_info);
- DCHECK(subsample_mapping);
-
- const DecryptConfig* config = buffer->GetDecryptConfig();
- if (!config || config->iv().empty() || config->key_id().empty()) {
- drm_info->initialization_vector_size = 0;
- drm_info->identifier_size = 0;
- drm_info->subsample_count = 0;
- drm_info->subsample_mapping = NULL;
- return;
- }
-
- DCHECK_LE(config->iv().size(), sizeof(drm_info->initialization_vector));
- DCHECK_LE(config->key_id().size(), sizeof(drm_info->identifier));
-
- if (config->iv().size() > sizeof(drm_info->initialization_vector) ||
- config->key_id().size() > sizeof(drm_info->identifier)) {
- drm_info->initialization_vector_size = 0;
- drm_info->identifier_size = 0;
- drm_info->subsample_count = 0;
- drm_info->subsample_mapping = NULL;
- return;
- }
-
- memcpy(drm_info->initialization_vector, &config->iv()[0],
- config->iv().size());
- drm_info->initialization_vector_size = config->iv().size();
- memcpy(drm_info->identifier, &config->key_id()[0], config->key_id().size());
- drm_info->identifier_size = config->key_id().size();
- drm_info->subsample_count = config->subsamples().size();
-
- if (drm_info->subsample_count > 0) {
- COMPILE_ASSERT(sizeof(SbDrmSubSampleMapping) == sizeof(SubsampleEntry),
- SubSampleEntrySizesMatch);
- drm_info->subsample_mapping =
- reinterpret_cast<const SbDrmSubSampleMapping*>(
- &config->subsamples()[0]);
- } else {
- drm_info->subsample_count = 1;
- drm_info->subsample_mapping = subsample_mapping;
- subsample_mapping->clear_byte_count = 0;
- subsample_mapping->encrypted_byte_count = buffer->GetDataSize();
- }
-}
-
-#if SB_API_VERSION >= 4
-// Ensure that the enums in starboard/media.h match enums in gfx::ColorSpace.
-#define ENUM_EQ(a, b) \
- COMPILE_ASSERT(static_cast<int>(a) == static_cast<int>(b), mismatching_enums)
-
-// Ensure PrimaryId enums convert correctly.
-ENUM_EQ(kSbMediaPrimaryIdReserved0, gfx::ColorSpace::kPrimaryIdReserved0);
-ENUM_EQ(kSbMediaPrimaryIdBt709, gfx::ColorSpace::kPrimaryIdBt709);
-ENUM_EQ(kSbMediaPrimaryIdUnspecified, gfx::ColorSpace::kPrimaryIdUnspecified);
-ENUM_EQ(kSbMediaPrimaryIdReserved, gfx::ColorSpace::kPrimaryIdReserved);
-ENUM_EQ(kSbMediaPrimaryIdBt470M, gfx::ColorSpace::kPrimaryIdBt470M);
-ENUM_EQ(kSbMediaPrimaryIdBt470Bg, gfx::ColorSpace::kPrimaryIdBt470Bg);
-ENUM_EQ(kSbMediaPrimaryIdSmpte170M, gfx::ColorSpace::kPrimaryIdSmpte170M);
-ENUM_EQ(kSbMediaPrimaryIdSmpte240M, gfx::ColorSpace::kPrimaryIdSmpte240M);
-ENUM_EQ(kSbMediaPrimaryIdFilm, gfx::ColorSpace::kPrimaryIdFilm);
-ENUM_EQ(kSbMediaPrimaryIdBt2020, gfx::ColorSpace::kPrimaryIdBt2020);
-ENUM_EQ(kSbMediaPrimaryIdSmpteSt4281, gfx::ColorSpace::kPrimaryIdSmpteSt4281);
-ENUM_EQ(kSbMediaPrimaryIdSmpteSt4312, gfx::ColorSpace::kPrimaryIdSmpteSt4312);
-ENUM_EQ(kSbMediaPrimaryIdSmpteSt4321, gfx::ColorSpace::kPrimaryIdSmpteSt4321);
-ENUM_EQ(kSbMediaPrimaryIdLastStandardValue,
- gfx::ColorSpace::kPrimaryIdLastStandardValue);
-ENUM_EQ(kSbMediaPrimaryIdUnknown, gfx::ColorSpace::kPrimaryIdUnknown);
-ENUM_EQ(kSbMediaPrimaryIdXyzD50, gfx::ColorSpace::kPrimaryIdXyzD50);
-ENUM_EQ(kSbMediaPrimaryIdCustom, gfx::ColorSpace::kPrimaryIdCustom);
-ENUM_EQ(kSbMediaPrimaryIdLast, gfx::ColorSpace::kPrimaryIdLast);
-
-// Ensure TransferId enums convert correctly.
-ENUM_EQ(kSbMediaTransferIdReserved0, gfx::ColorSpace::kTransferIdReserved0);
-ENUM_EQ(kSbMediaTransferIdBt709, gfx::ColorSpace::kTransferIdBt709);
-ENUM_EQ(kSbMediaTransferIdUnspecified, gfx::ColorSpace::kTransferIdUnspecified);
-ENUM_EQ(kSbMediaTransferIdReserved, gfx::ColorSpace::kTransferIdReserved);
-ENUM_EQ(kSbMediaTransferIdGamma22, gfx::ColorSpace::kTransferIdGamma22);
-ENUM_EQ(kSbMediaTransferIdGamma28, gfx::ColorSpace::kTransferIdGamma28);
-ENUM_EQ(kSbMediaTransferIdSmpte170M, gfx::ColorSpace::kTransferIdSmpte170M);
-ENUM_EQ(kSbMediaTransferIdSmpte240M, gfx::ColorSpace::kTransferIdSmpte240M);
-ENUM_EQ(kSbMediaTransferIdLinear, gfx::ColorSpace::kTransferIdLinear);
-ENUM_EQ(kSbMediaTransferIdLog, gfx::ColorSpace::kTransferIdLog);
-ENUM_EQ(kSbMediaTransferIdLogSqrt, gfx::ColorSpace::kTransferIdLogSqrt);
-ENUM_EQ(kSbMediaTransferIdIec6196624, gfx::ColorSpace::kTransferIdIec6196624);
-ENUM_EQ(kSbMediaTransferIdBt1361Ecg, gfx::ColorSpace::kTransferIdBt1361Ecg);
-ENUM_EQ(kSbMediaTransferIdIec6196621, gfx::ColorSpace::kTransferIdIec6196621);
-ENUM_EQ(kSbMediaTransferId10BitBt2020, gfx::ColorSpace::kTransferId10BitBt2020);
-ENUM_EQ(kSbMediaTransferId12BitBt2020, gfx::ColorSpace::kTransferId12BitBt2020);
-ENUM_EQ(kSbMediaTransferIdSmpteSt2084, gfx::ColorSpace::kTransferIdSmpteSt2084);
-ENUM_EQ(kSbMediaTransferIdSmpteSt4281, gfx::ColorSpace::kTransferIdSmpteSt4281);
-ENUM_EQ(kSbMediaTransferIdAribStdB67, gfx::ColorSpace::kTransferIdAribStdB67);
-ENUM_EQ(kSbMediaTransferIdLastStandardValue,
- gfx::ColorSpace::kTransferIdLastStandardValue);
-ENUM_EQ(kSbMediaTransferIdUnknown, gfx::ColorSpace::kTransferIdUnknown);
-ENUM_EQ(kSbMediaTransferIdGamma24, gfx::ColorSpace::kTransferIdGamma24);
-ENUM_EQ(kSbMediaTransferIdSmpteSt2084NonHdr,
- gfx::ColorSpace::kTransferIdSmpteSt2084NonHdr);
-ENUM_EQ(kSbMediaTransferIdCustom, gfx::ColorSpace::kTransferIdCustom);
-ENUM_EQ(kSbMediaTransferIdLast, gfx::ColorSpace::kTransferIdLast);
-
-// Ensure MatrixId enums convert correctly.
-ENUM_EQ(kSbMediaMatrixIdRgb, gfx::ColorSpace::kMatrixIdRgb);
-ENUM_EQ(kSbMediaMatrixIdBt709, gfx::ColorSpace::kMatrixIdBt709);
-ENUM_EQ(kSbMediaMatrixIdUnspecified, gfx::ColorSpace::kMatrixIdUnspecified);
-ENUM_EQ(kSbMediaMatrixIdReserved, gfx::ColorSpace::kMatrixIdReserved);
-ENUM_EQ(kSbMediaMatrixIdFcc, gfx::ColorSpace::kMatrixIdFcc);
-ENUM_EQ(kSbMediaMatrixIdBt470Bg, gfx::ColorSpace::kMatrixIdBt470Bg);
-ENUM_EQ(kSbMediaMatrixIdSmpte170M, gfx::ColorSpace::kMatrixIdSmpte170M);
-ENUM_EQ(kSbMediaMatrixIdSmpte240M, gfx::ColorSpace::kMatrixIdSmpte240M);
-ENUM_EQ(kSbMediaMatrixIdYCgCo, gfx::ColorSpace::kMatrixIdYCgCo);
-ENUM_EQ(kSbMediaMatrixIdBt2020NonconstantLuminance,
- gfx::ColorSpace::kMatrixIdBt2020NonconstantLuminance);
-ENUM_EQ(kSbMediaMatrixIdBt2020ConstantLuminance,
- gfx::ColorSpace::kMatrixIdBt2020ConstantLuminance);
-ENUM_EQ(kSbMediaMatrixIdYDzDx, gfx::ColorSpace::kMatrixIdYDzDx);
-ENUM_EQ(kSbMediaMatrixIdLastStandardValue,
- gfx::ColorSpace::kMatrixIdLastStandardValue);
-ENUM_EQ(kSbMediaMatrixIdUnknown, gfx::ColorSpace::kMatrixIdUnknown);
-ENUM_EQ(kSbMediaMatrixIdLast, gfx::ColorSpace::kMatrixIdLast);
-
-// Ensure RangeId enums convert correctly.
-ENUM_EQ(kSbMediaRangeIdUnspecified, gfx::ColorSpace::kRangeIdUnspecified);
-ENUM_EQ(kSbMediaRangeIdLimited, gfx::ColorSpace::kRangeIdLimited);
-ENUM_EQ(kSbMediaRangeIdFull, gfx::ColorSpace::kRangeIdFull);
-ENUM_EQ(kSbMediaRangeIdDerived, gfx::ColorSpace::kRangeIdDerived);
-ENUM_EQ(kSbMediaRangeIdLast, gfx::ColorSpace::kRangeIdLast);
-
-SbMediaColorMetadata MediaToSbMediaColorMetadata(
- const WebMColorMetadata& webm_color_metadata) {
- SbMediaColorMetadata sb_media_color_metadata;
-
- // Copy the other color metadata below.
- sb_media_color_metadata.bits_per_channel = webm_color_metadata.BitsPerChannel;
- sb_media_color_metadata.chroma_subsampling_horizontal =
- webm_color_metadata.ChromaSubsamplingHorz;
- sb_media_color_metadata.chroma_subsampling_vertical =
- webm_color_metadata.ChromaSubsamplingVert;
- sb_media_color_metadata.cb_subsampling_horizontal =
- webm_color_metadata.CbSubsamplingHorz;
- sb_media_color_metadata.cb_subsampling_vertical =
- webm_color_metadata.CbSubsamplingVert;
- sb_media_color_metadata.chroma_siting_horizontal =
- webm_color_metadata.ChromaSitingHorz;
- sb_media_color_metadata.chroma_siting_vertical =
- webm_color_metadata.ChromaSitingVert;
-
- // Copy the HDR Metadata below.
- SbMediaMasteringMetadata sb_media_mastering_metadata;
- HDRMetadata hdr_metadata = webm_color_metadata.hdr_metadata;
- MasteringMetadata mastering_metadata = hdr_metadata.mastering_metadata;
-
- sb_media_mastering_metadata.primary_r_chromaticity_x =
- mastering_metadata.primary_r_chromaticity_x;
- sb_media_mastering_metadata.primary_r_chromaticity_y =
- mastering_metadata.primary_r_chromaticity_y;
-
- sb_media_mastering_metadata.primary_g_chromaticity_x =
- mastering_metadata.primary_g_chromaticity_x;
- sb_media_mastering_metadata.primary_g_chromaticity_y =
- mastering_metadata.primary_g_chromaticity_y;
-
- sb_media_mastering_metadata.primary_b_chromaticity_x =
- mastering_metadata.primary_b_chromaticity_x;
- sb_media_mastering_metadata.primary_b_chromaticity_y =
- mastering_metadata.primary_b_chromaticity_y;
-
- sb_media_mastering_metadata.white_point_chromaticity_x =
- mastering_metadata.white_point_chromaticity_x;
- sb_media_mastering_metadata.white_point_chromaticity_y =
- mastering_metadata.white_point_chromaticity_y;
-
- sb_media_mastering_metadata.luminance_max = mastering_metadata.luminance_max;
- sb_media_mastering_metadata.luminance_min = mastering_metadata.luminance_min;
-
- sb_media_color_metadata.mastering_metadata = sb_media_mastering_metadata;
- sb_media_color_metadata.max_cll = hdr_metadata.max_cll;
- sb_media_color_metadata.max_fall = hdr_metadata.max_fall;
-
- // Copy the color space below.
- gfx::ColorSpace color_space = webm_color_metadata.color_space;
- sb_media_color_metadata.primaries =
- static_cast<SbMediaPrimaryId>(color_space.primaries());
- sb_media_color_metadata.transfer =
- static_cast<SbMediaTransferId>(color_space.transfer());
- sb_media_color_metadata.matrix =
- static_cast<SbMediaMatrixId>(color_space.matrix());
- sb_media_color_metadata.range =
- static_cast<SbMediaRangeId>(color_space.range());
- if (sb_media_color_metadata.primaries == kSbMediaPrimaryIdCustom) {
- const float* custom_primary_matrix = color_space.custom_primary_matrix();
- SbMemoryCopy(sb_media_color_metadata.custom_primary_matrix,
- custom_primary_matrix, sizeof(custom_primary_matrix));
- }
-
- return sb_media_color_metadata;
-}
-#endif // SB_API_VERSION >= 4
-
-} // namespace media
diff --git a/src/media/base/starboard_utils.h b/src/media/base/starboard_utils.h
deleted file mode 100644
index e5112d1..0000000
--- a/src/media/base/starboard_utils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef MEDIA_BASE_STARBOARD_UTILS_H_
-#define MEDIA_BASE_STARBOARD_UTILS_H_
-
-#include "media/base/audio_decoder_config.h"
-#include "media/base/decoder_buffer.h"
-#include "media/base/demuxer_stream.h"
-#include "media/base/video_decoder_config.h"
-#include "starboard/drm.h"
-#include "starboard/media.h"
-
-namespace media {
-
-SbMediaAudioCodec MediaAudioCodecToSbMediaAudioCodec(AudioCodec codec);
-SbMediaVideoCodec MediaVideoCodecToSbMediaVideoCodec(VideoCodec codec);
-
-base::TimeDelta SbMediaTimeToTimeDelta(SbMediaTime timestamp);
-SbMediaTime TimeDeltaToSbMediaTime(base::TimeDelta timedelta);
-
-DemuxerStream::Type SbMediaTypeToDemuxerStreamType(SbMediaType type);
-SbMediaType DemuxerStreamTypeToSbMediaType(DemuxerStream::Type type);
-
-void FillDrmSampleInfo(const scoped_refptr<DecoderBuffer>& buffer,
- SbDrmSampleInfo* drm_info,
- SbDrmSubSampleMapping* subsample_mapping);
-
-#if SB_API_VERSION >= 4
-SbMediaColorMetadata MediaToSbMediaColorMetadata(
- const WebMColorMetadata& webm_color_metadata);
-#endif
-
-} // namespace media
-
-#endif // MEDIA_BASE_STARBOARD_UTILS_H_
diff --git a/src/media/crypto/shell_decryptor_factory.cc b/src/media/crypto/shell_decryptor_factory.cc
index 5fc5a59..ceaf4d2 100644
--- a/src/media/crypto/shell_decryptor_factory.cc
+++ b/src/media/crypto/shell_decryptor_factory.cc
@@ -16,39 +16,8 @@
#include "media/crypto/shell_decryptor_factory.h"
-#if defined(OS_STARBOARD)
-#include "media/crypto/starboard_decryptor.h"
-#include "starboard/configuration.h"
-#include "starboard/drm.h"
-#include "starboard/media.h"
-#endif // defined(OS_STARBOARD)
-
namespace media {
-#if defined(OS_STARBOARD)
-#if SB_CAN(MEDIA_USE_STARBOARD_PIPELINE)
-
-#define USE_STARBOARD_DECRYPTOR 1
-
-#endif // SB_CAN(MEDIA_USE_STARBOARD_PIPELINE)
-#endif // defined(OS_STARBOARD)
-
-#if defined(USE_STARBOARD_DECRYPTOR)
-// static
-bool ShellDecryptorFactory::Supports(const std::string& key_system) {
- // TODO: Hook up with codecs.
- return SbMediaIsSupported(kSbMediaVideoCodecNone, kSbMediaAudioCodecNone,
- key_system.c_str());
-}
-
-// static
-Decryptor* ShellDecryptorFactory::Create(const std::string& key_system,
- DecryptorClient* client) {
- return new StarboardDecryptor(key_system.c_str(), client);
-}
-
-#else // defined(USE_STARBOARD_DECRYPTOR)
-
// static
ShellDecryptorFactory::DecryptorRegistry ShellDecryptorFactory::registry_;
@@ -74,6 +43,4 @@
registry_[key_system] = create_cb;
}
-#endif // defined(USE_STARBOARD_DECRYPTOR)
-
} // namespace media
diff --git a/src/media/crypto/starboard_decryptor.cc b/src/media/crypto/starboard_decryptor.cc
deleted file mode 100644
index 9ee01d0..0000000
--- a/src/media/crypto/starboard_decryptor.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Definitions that allow for DRM support, common between Player and Decoder
-// interfaces.
-
-#include "media/crypto/starboard_decryptor.h"
-
-#include "base/logging.h"
-#include "media/base/decrypt_config.h"
-
-namespace media {
-
-namespace {
-
-std::string ToString(const void* buffer, int size) {
- const char* char_buffer = reinterpret_cast<const char*>(buffer);
- return std::string(char_buffer, char_buffer + size);
-}
-
-} // namespace
-
-StarboardDecryptor::StarboardDecryptor(const char* key_system,
- DecryptorClient* decryptor_client)
- : client_(decryptor_client) {
- drm_system_ =
- SbDrmCreateSystem(key_system, this, KeyRequestFunc, KeyAddedFunc);
-}
-
-StarboardDecryptor::~StarboardDecryptor() {
- SbDrmDestroySystem(drm_system_);
-}
-
-bool StarboardDecryptor::GenerateKeyRequest(const std::string& key_system,
- const std::string& type,
- const uint8_t* init_data,
- int init_data_length) {
- if (drm_system_ == kSbDrmSystemInvalid) {
- return false;
- }
- if (key_system_.empty()) {
- key_system_ = key_system;
- }
- DCHECK_EQ(key_system_, key_system);
- SbDrmGenerateSessionUpdateRequest(drm_system_,
-#if SB_API_VERSION >= 4
- 0, // No need to distinguish between
- // callbacks in EME 0.1b implementation.
-#endif // SB_API_VERSION >= 4
- type.c_str(), init_data, init_data_length);
- return true;
-}
-
-void StarboardDecryptor::AddKey(const std::string& key_system,
- const uint8_t* key,
- int key_length,
- const uint8_t* init_data,
- int init_data_length,
- const std::string& session_id) {
- SbDrmUpdateSession(drm_system_, key, key_length, session_id.c_str(),
- session_id.size());
-}
-
-void StarboardDecryptor::CancelKeyRequest(const std::string& key_system,
- const std::string& session_id) {
- SbDrmCloseSession(drm_system_, session_id.c_str(), session_id.size());
-}
-
-void StarboardDecryptor::RegisterKeyAddedCB(StreamType stream_type,
- const KeyAddedCB& key_added_cb) {
- NOTREACHED();
-}
-
-void StarboardDecryptor::Decrypt(StreamType stream_type,
- const scoped_refptr<DecoderBuffer>& encrypted,
- const DecryptCB& decrypt_cb) {
- decrypt_cb.Run(kSuccess, encrypted);
-}
-
-void StarboardDecryptor::CancelDecrypt(StreamType stream_type) {
- // no-op
-}
-
-void StarboardDecryptor::InitializeAudioDecoder(
- scoped_ptr<AudioDecoderConfig> config,
- const DecoderInitCB& init_cb) {
- // StarboardDecryptor does not support audio decoding.
- // This puts us in "decrypt only" mode.
- // Decoding is handled by the system default decoders.
- init_cb.Run(false);
-}
-
-void StarboardDecryptor::InitializeVideoDecoder(
- scoped_ptr<VideoDecoderConfig> config,
- const DecoderInitCB& init_cb) {
- // StarboardDecryptor does not support video decoding.
- // This puts us in "decrypt only" mode.
- // Decoding is handled by the system default decoders.
- init_cb.Run(false);
-}
-
-void StarboardDecryptor::DecryptAndDecodeAudio(
- const scoped_refptr<DecoderBuffer>& encrypted,
- const AudioDecodeCB& audio_decode_cb) {
- NOTREACHED();
-}
-
-void StarboardDecryptor::DecryptAndDecodeVideo(
- const scoped_refptr<DecoderBuffer>& encrypted,
- const VideoDecodeCB& video_decode_cb) {
- NOTREACHED();
-}
-
-void StarboardDecryptor::ResetDecoder(StreamType stream_type) {
- NOTREACHED();
-}
-
-void StarboardDecryptor::DeinitializeDecoder(StreamType stream_type) {
- NOTREACHED();
-}
-
-void StarboardDecryptor::OnKeyRequest(const void* session_id,
- int session_id_size,
- const void* content,
- int content_size,
- const char* url) {
- if (session_id) {
- client_->KeyMessage(key_system_, ToString(session_id, session_id_size),
- ToString(content, content_size), url);
- } else {
- client_->KeyError(key_system_, "", Decryptor::kUnknownError, 0);
- }
-}
-
-void StarboardDecryptor::OnKeyAdded(const void* session_id,
- int session_id_length,
- bool succeeded) {
- std::string session(
- reinterpret_cast<const char*>(session_id),
- reinterpret_cast<const char*>(session_id) + session_id_length);
-
- if (succeeded) {
- client_->KeyAdded(key_system_, session);
- } else {
- client_->KeyError(key_system_, session, Decryptor::kUnknownError, 0);
- }
-}
-
-// static
-void StarboardDecryptor::KeyRequestFunc(SbDrmSystem drm_system,
- void* context,
-#if SB_API_VERSION >= 4
- int /*ticket*/,
-#endif // SB_API_VERSION >= 4
- const void* session_id,
- int session_id_size,
- const void* content,
- int content_size,
- const char* url) {
- DCHECK(context);
- StarboardDecryptor* decryptor =
- reinterpret_cast<StarboardDecryptor*>(context);
- DCHECK_EQ(drm_system, decryptor->drm_system_);
-
- decryptor->OnKeyRequest(session_id, session_id_size, content, content_size,
- url);
-}
-
-// static
-void StarboardDecryptor::KeyAddedFunc(SbDrmSystem drm_system,
- void* context,
- const void* session_id,
- int session_id_length,
- bool succeeded) {
- DCHECK(context);
- StarboardDecryptor* decryptor =
- reinterpret_cast<StarboardDecryptor*>(context);
- DCHECK_EQ(drm_system, decryptor->drm_system_);
- decryptor->OnKeyAdded(session_id, session_id_length, succeeded);
-}
-
-} // namespace media
diff --git a/src/media/crypto/starboard_decryptor.h b/src/media/crypto/starboard_decryptor.h
deleted file mode 100644
index a2ffc17..0000000
--- a/src/media/crypto/starboard_decryptor.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Definitions that allow for DRM support, common between Player and Decoder
-// interfaces.
-
-#ifndef MEDIA_CRYPTO_STARBOARD_DECRYPTOR_H_
-#define MEDIA_CRYPTO_STARBOARD_DECRYPTOR_H_
-
-#include "build/build_config.h"
-
-#if !defined(OS_STARBOARD)
-#error "This class only works in Starboard!"
-#endif // !defined(OS_STARBOARD)
-
-#include <set>
-#include <string>
-
-#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
-#include "media/base/decryptor.h"
-#include "media/base/decryptor_client.h"
-#include "starboard/drm.h"
-
-namespace media {
-
-// This class implements the Decryptor interface based on Starboard DRM
-// functions provided in drm.h and media.h.
-class StarboardDecryptor : public Decryptor {
- public:
- StarboardDecryptor(const char* key_system, DecryptorClient* decryptor_client);
- ~StarboardDecryptor() OVERRIDE;
-
- SbDrmSystem drm_system() { return drm_system_; }
-
- // Decryptor implementation.
- bool GenerateKeyRequest(const std::string& key_system,
- const std::string& type,
- const uint8_t* init_data,
- int init_data_length) OVERRIDE;
- void AddKey(const std::string& key_system,
- const uint8_t* key,
- int key_length,
- const uint8_t* init_data,
- int init_data_length,
- const std::string& session_id) OVERRIDE;
- void CancelKeyRequest(const std::string& key_system,
- const std::string& session_id) OVERRIDE;
- void RegisterKeyAddedCB(StreamType stream_type,
- const KeyAddedCB& key_added_cb) OVERRIDE;
- void Decrypt(StreamType stream_type,
- const scoped_refptr<DecoderBuffer>& encrypted,
- const DecryptCB& decrypt_cb) OVERRIDE;
- void CancelDecrypt(StreamType stream_type) OVERRIDE;
- void InitializeAudioDecoder(scoped_ptr<AudioDecoderConfig> config,
- const DecoderInitCB& init_cb) OVERRIDE;
- void InitializeVideoDecoder(scoped_ptr<VideoDecoderConfig> config,
- const DecoderInitCB& init_cb) OVERRIDE;
- void DecryptAndDecodeAudio(const scoped_refptr<DecoderBuffer>& encrypted,
- const AudioDecodeCB& audio_decode_cb) OVERRIDE;
- void DecryptAndDecodeVideo(const scoped_refptr<DecoderBuffer>& encrypted,
- const VideoDecodeCB& video_decode_cb) OVERRIDE;
- void ResetDecoder(StreamType stream_type) OVERRIDE;
- void DeinitializeDecoder(StreamType stream_type) OVERRIDE;
-
- private:
- void OnKeyRequest(const void* session_id,
- int session_id_size,
- const void* content,
- int content_size,
- const char* url);
- void OnKeyAdded(const void* session_id,
- int session_id_length,
- bool succeeded);
-
- static void KeyRequestFunc(SbDrmSystem drm_system,
- void* context,
-#if SB_API_VERSION >= 4
- int ticket,
-#endif // SB_API_VERSION >= 4
- const void* session_id,
- int session_id_size,
- const void* content,
- int content_size,
- const char* url);
- static void KeyAddedFunc(SbDrmSystem drm_system,
- void* context,
- const void* session_id,
- int session_id_length,
- bool succeeded);
-
- // DecryptorClient through which key events are fired.
- // Calls to the client are both cheap and thread-safe.
- DecryptorClient* client_;
- SbDrmSystem drm_system_;
- std::string key_system_;
-
- std::set<std::string> keys_;
-
- DISALLOW_COPY_AND_ASSIGN(StarboardDecryptor);
-};
-
-} // namespace media
-
-#endif // MEDIA_CRYPTO_STARBOARD_DECRYPTOR_H_
diff --git a/src/media/filters/shell_audio_renderer_starboard.cc b/src/media/filters/shell_audio_renderer_starboard.cc
deleted file mode 100644
index 4c9dcea..0000000
--- a/src/media/filters/shell_audio_renderer_starboard.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2017 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "media/filters/shell_audio_renderer.h"
-
-namespace media {
-
-// static
-ShellAudioRenderer* ShellAudioRenderer::Create(
- media::AudioRendererSink* sink,
- const SetDecryptorReadyCB& set_decryptor_ready_cb,
- const scoped_refptr<base::MessageLoopProxy>& message_loop) {
- return NULL;
-}
-
-} // namespace media
diff --git a/src/media/media.gyp b/src/media/media.gyp
index 5757809..7aff606 100644
--- a/src/media/media.gyp
+++ b/src/media/media.gyp
@@ -575,17 +575,6 @@
['exclude', 'video/capture/fake_video_capture_device'],
],
'conditions': [
- ['target_arch=="xb1" and actual_target_arch!="win"', {
- 'dependencies' : [
- '../third_party/modp_b64/modp_b64.gyp:modp_b64',
- '<(lbshell_root)/build/projects/shell_scheme_handler.gyp:shell_scheme_handler',
- ],
- 'msvs_settings': {
- 'VCCLCompilerTool': {
- 'ComponentExtensions': 'true'
- },
- },
- }],
['target_arch=="linux"', {
'sources': [
'audio/shell_audio_streamer_linux.cc',
@@ -721,22 +710,6 @@
['exclude', 'shell_'],
],
}], # OS != "lb_shell" and OS != "starboard"
- ['OS == "lb_shell"', {
- 'include_dirs': [
- '<(lbshell_root)/src/platform/<(target_arch)/chromium',
- '<(lbshell_root)/src/platform/<(target_arch)/lb_shell',
- ],
- 'dependencies': [
- '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
- ],
- 'conditions': [
- ['(target_arch=="xb1" and actual_target_arch!="win") or target_arch=="xb360"', {
- 'sources': [
- '<!@(find <(lbshell_root)/src/platform/<(target_arch)/chromium/media -type f)',
- ],
- }],
- ],
- }], # OS == "lb_shell"
['OS == "starboard"', {
'dependencies': [
'<(DEPTH)/starboard/starboard.gyp:starboard',
@@ -745,30 +718,6 @@
'base/shell_cached_decoder_buffer.cc',
'base/shell_cached_decoder_buffer.h',
],
- 'conditions': [
- ['sb_media_platform == "starboard"', {
- 'sources': [
- 'audio/shell_audio_streamer_starboard.cc',
- 'base/decoder_buffer_cache.cc',
- 'base/decoder_buffer_cache.h',
- 'base/sbplayer_pipeline.cc',
- 'base/sbplayer_set_bounds_helper.cc',
- 'base/sbplayer_set_bounds_helper.h',
- 'base/starboard_player.cc',
- 'base/starboard_player.h',
- 'base/starboard_utils.cc',
- 'base/starboard_utils.h',
- 'crypto/starboard_decryptor.cc',
- 'crypto/starboard_decryptor.h',
- 'filters/shell_audio_renderer_starboard.cc',
- ],
- 'sources/': [
- ['exclude', '^base/pipeline_impl.cc'],
- ['exclude', '^filters/shell_audio_renderer_impl.cc'],
- ['exclude', '^filters/shell_video_renderer_impl.cc'],
- ],
- }],
- ],
}], # OS == "starboard"
['OS == "ios"', {
'includes': [
diff --git a/src/nb/analytics/memory_tracker_impl.cc b/src/nb/analytics/memory_tracker_impl.cc
index 3273bd8..8f4392b 100644
--- a/src/nb/analytics/memory_tracker_impl.cc
+++ b/src/nb/analytics/memory_tracker_impl.cc
@@ -227,7 +227,7 @@
void MemoryTrackerImpl::SetMemoryTrackerDebugCallback(
MemoryTrackerDebugCallback* cb) {
- debug_callback_ = cb;
+ debug_callback_.swap(cb);
}
MemoryTrackerImpl::DisableDeletionInScope::DisableDeletionInScope(
@@ -242,7 +242,7 @@
}
MemoryTrackerImpl::MemoryTrackerImpl()
- : thread_filter_id_(kSbThreadInvalidId), debug_callback_(NULL) {
+ : thread_filter_id_(kSbThreadInvalidId), debug_callback_(nullptr) {
total_bytes_allocated_.store(0);
global_hooks_installed_ = false;
Initialize(&sb_memory_tracker_, &nb_memory_scope_reporter_);
@@ -302,13 +302,15 @@
if (added) {
AddAllocationBytes(size);
group->AddAllocation(size);
- // Useful for investigating what the heck is being allocated. For example
- // the developer may want to track certain allocations that meet a certain
- // criteria.
- if (debug_callback_) {
+ ConcurrentPtr<MemoryTrackerDebugCallback>::Access access_ptr =
+ debug_callback_.access_ptr(SbThreadId());
+
+ // If access_ptr is valid then it is guaranteed to be alive for the
+ // duration of the scope.
+ if (access_ptr) {
const CallStack& callstack = *(callstack_tls_.GetOrCreate());
DisableDeletionInScope disable_deletion_tracking(this);
- debug_callback_->OnMemoryAllocation(memory, alloc_record, callstack);
+ access_ptr->OnMemoryAllocation(memory, alloc_record, callstack);
}
} else {
// Handles the case where the memory hasn't been properly been reported
@@ -348,15 +350,14 @@
AllocationRecord alloc_record;
bool removed = false;
- // Useful for investigating what the heck is being deallocated. For example
- // the developer may want to track certain allocations that meet a certain
- // criteria.
- if (debug_callback_) {
+ ConcurrentPtr<MemoryTrackerDebugCallback>::Access access_ptr =
+ debug_callback_.access_ptr(SbThreadId());
+
+ if (access_ptr) {
if (atomic_allocation_map_.Get(memory, &alloc_record)) {
DisableMemoryTrackingInScope no_memory_tracking(this);
const CallStack& callstack = (*callstack_tls_.GetOrCreate());
- debug_callback_->OnMemoryDeallocation(memory, alloc_record,
- callstack);
+ access_ptr->OnMemoryDeallocation(memory, alloc_record, callstack);
}
}
diff --git a/src/nb/analytics/memory_tracker_impl.h b/src/nb/analytics/memory_tracker_impl.h
index b45b1a3..f9abe92 100644
--- a/src/nb/analytics/memory_tracker_impl.h
+++ b/src/nb/analytics/memory_tracker_impl.h
@@ -17,14 +17,15 @@
#ifndef NB_MEMORY_TRACKER_IMPL_H_
#define NB_MEMORY_TRACKER_IMPL_H_
-#include "nb/analytics/memory_tracker_helpers.h"
#include "nb/analytics/memory_tracker.h"
+#include "nb/analytics/memory_tracker_helpers.h"
+#include "nb/concurrent_ptr.h"
#include "nb/memory_scope.h"
#include "nb/scoped_ptr.h"
#include "nb/thread_local_object.h"
#include "starboard/configuration.h"
-#include "starboard/memory_reporter.h"
#include "starboard/memory.h"
+#include "starboard/memory_reporter.h"
#include "starboard/mutex.h"
#include "starboard/time.h"
@@ -172,7 +173,7 @@
AtomicStringAllocationGroupMap alloc_group_map_;
atomic_int64_t total_bytes_allocated_;
- MemoryTrackerDebugCallback* debug_callback_;
+ ConcurrentPtr<MemoryTrackerDebugCallback> debug_callback_;
// THREAD LOCAL SECTION.
ThreadLocalBoolean memory_deletion_enabled_tls_;
diff --git a/src/nb/concurrent_ptr.h b/src/nb/concurrent_ptr.h
new file mode 100644
index 0000000..6f48bce
--- /dev/null
+++ b/src/nb/concurrent_ptr.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2017 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NB_CONCURRENT_PTR_H_
+#define NB_CONCURRENT_PTR_H_
+
+#include <algorithm>
+#include <atomic>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "starboard/atomic.h"
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/mutex.h"
+#include "starboard/types.h"
+
+namespace nb {
+namespace detail {
+class AtomicPointerBase;
+
+template <typename T>
+class AtomicPointer;
+
+template <typename T>
+class Access;
+} // namespace detail
+
+// ConcurrentPtr is similar to a scoped_ptr<> but with additional thread safe
+// guarantees on the lifespan of the owned pointer. Threads can get access
+// to the owned pointer using class ConcurrentPtr<T>::Access, which will lock
+// the lifetime of the pointer for the duration that ConcurrentPtr<T>::Access
+// object will remain in scope. Operations on the object pointed to by the
+// owned pointer has no additional thread safety guarantees.
+//
+//
+// ConcurrentPtr<T>::access_ptr(...) will take in an arbitrary id value and
+// will hash this id value to select one of the buckets. Good id's to pass in
+// include input from SbThreadGetId() or random numbers (std::rand() is known
+// to use internal locks on some implementations!).
+//
+// Performance:
+// To increase performance, the lifespan of ConcurrentPtr<T>::Access instance
+// should be as short as possible.
+//
+// The number of buckets has a large effect on performance. More buckets will
+// result in lower contention.
+//
+// A hashing function with good distribution will produce less contention.
+//
+// Example:
+// class MyClass { void Run(); };
+// ConcurrentPtr<MyClass> shared_concurrent_ptr_(new MyClass);
+//
+// // From all other threads.
+// ConcurrentPtr<MyClass>::Access access_ptr =
+// shared_concurrent_ptr_.access_ptr(SbThreadGetId());
+// // access_ptr now either holds a valid object pointer or either nullptr.
+// if (access_ptr) {
+// access_ptr->Run();
+// }
+template <typename T, typename KeyT = int64_t, typename HashT = std::hash<KeyT>>
+class ConcurrentPtr {
+ public:
+ ConcurrentPtr(T* ptr, size_t number_locks = 31) : ptr_(NULL) {
+ internal_construct(ptr, number_locks);
+ }
+ ~ConcurrentPtr() { internal_destruct(); }
+
+ // Used to access the underlying pointer to perform operations. The lifetime
+ // of the accessed pointer is guaranteed to be alive for the duration of the
+ // lifetime of this access object.
+ //
+ // Example
+ // ConcurrentPtr<MyClass>::Access access_ptr =
+ // shared_concurrent_ptr_.access_ptr(SbThreadGetId());
+ // if (access_ptr) {
+ // access_ptr->Run();
+ // }
+ using Access = nb::detail::Access<T>;
+
+ // Provides read access to the underlying pointer in a thread safe way.
+ inline Access access_ptr(const KeyT& seed) {
+ const size_t index = hasher_(seed) % table_.size();
+ AtomicPointer* atomic_ptr = table_[index];
+ return atomic_ptr->access_ptr();
+ }
+
+ void reset(T* value) { delete SetAllThenSwap(value); }
+ T* release() { return SetAllThenSwap(nullptr); }
+ T* swap(T* new_value) { return SetAllThenSwap(new_value); }
+
+ private:
+ using Mutex = starboard::Mutex;
+ using ScopedLock = starboard::ScopedLock;
+ using AtomicPointer = nb::detail::AtomicPointer<T>;
+
+ // Change all buckets to the new pointer. The old pointer is returned.
+ T* SetAllThenSwap(T* new_ptr) {
+ ScopedLock write_lock(pointer_write_mutex_);
+ for (auto it = table_.begin(); it != table_.end(); ++it) {
+ AtomicPointer* atomic_ptr = *it;
+ atomic_ptr->swap(new_ptr);
+ }
+ T* old_ptr = ptr_;
+ ptr_ = new_ptr;
+ return old_ptr;
+ }
+
+ void internal_construct(T* ptr, size_t number_locks) {
+ table_.resize(number_locks);
+ for (auto it = table_.begin(); it != table_.end(); ++it) {
+ *it = new AtomicPointer;
+ }
+ reset(ptr);
+ }
+
+ void internal_destruct() {
+ reset(nullptr);
+ for (auto it = table_.begin(); it != table_.end(); ++it) {
+ delete *it;
+ }
+ table_.clear();
+ }
+ HashT hasher_;
+ Mutex pointer_write_mutex_;
+ std::vector<AtomicPointer*> table_;
+ T* ptr_;
+};
+
+/////////////////////////// Implementation Details ////////////////////////////
+namespace detail {
+
+// Access is a smart pointer type which holds a lock to the underlying pointer
+// returned by ConcurrentPtr and AtomicPointer.
+template <typename T>
+class Access {
+ public:
+ Access() = delete;
+ // It's assumed that ref_count is incremented before being passed
+ // to this constructor.
+ inline Access(T* ptr, starboard::atomic_int32_t* ref_count)
+ : ref_count_(ref_count), ptr_(ptr) {}
+
+ Access(const Access& other) = delete;
+ // Allow move construction.
+ Access(Access&& other) = default;
+
+ inline ~Access() { release(); }
+
+ inline operator bool() const { return valid(); }
+ inline operator T*() const { return get(); }
+ inline T* operator->() { return get(); }
+ inline T* get() const { return ptr_; }
+ inline bool valid() const { return !!get(); }
+ inline void release() { internal_release(); }
+
+ private:
+ inline void internal_release() {
+ if (ref_count_) {
+ ref_count_->decrement();
+ ref_count_ = nullptr;
+ }
+ ptr_ = nullptr;
+ }
+ starboard::atomic_int32_t* ref_count_;
+ T* ptr_;
+};
+
+// AtomicPointer allows read access to a pointer through access_ptr()
+// and a form of atomic swap.
+template <typename T>
+class AtomicPointer {
+ public:
+ // Customer new/delete operators align AtomicPointers to cache
+ // lines for improved performance.
+ static void* operator new(std::size_t count) {
+ const int kCacheLineSize = 64;
+ return SbMemoryAllocateAligned(kCacheLineSize, count);
+ }
+ static void operator delete(void* ptr) { SbMemoryDeallocateAligned(ptr); }
+
+ AtomicPointer() : ptr_(nullptr), counter_(0) {}
+ ~AtomicPointer() { delete get(); }
+ inline T* swap(T* new_ptr) {
+ AcquireWriteLock();
+ T* old_ptr = get();
+ ptr_.store(new_ptr);
+ WaitForReadersToDrain();
+ ReleaseWriteLock();
+ return old_ptr;
+ }
+
+ inline void reset(T* new_ptr) { delete swap(new_ptr); }
+ inline T* get() { return ptr_.load(); }
+ inline Access<T> access_ptr() {
+ counter_.increment();
+ return Access<T>(ptr_.load(), &counter_);
+ }
+
+ private:
+ inline void AcquireWriteLock() {
+ write_mutex_.Acquire();
+ counter_.increment();
+ }
+ inline void WaitForReadersToDrain() {
+ int32_t expected_value = 1;
+ while (!counter_.compare_exchange_weak(&expected_value, 0)) {
+ SbThreadYield();
+ expected_value = 1;
+ }
+ }
+ inline void ReleaseWriteLock() { write_mutex_.Release(); }
+
+ starboard::Mutex write_mutex_;
+ starboard::atomic_int32_t counter_;
+ starboard::atomic_pointer<T*> ptr_;
+};
+} // namespace detail
+} // namespace nb
+
+#endif // NB_CONCURRENT_PTR_H_
diff --git a/src/nb/concurrent_ptr_test.cc b/src/nb/concurrent_ptr_test.cc
new file mode 100644
index 0000000..ff0b0ba
--- /dev/null
+++ b/src/nb/concurrent_ptr_test.cc
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "nb/concurrent_ptr.h"
+
+#include "nb/simple_thread.h"
+#include "starboard/atomic.h"
+#include "starboard/common/semaphore.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Number of threads for the thread test.
+#define NUM_THREADS 64
+
+namespace nb {
+
+using atomic_int32 = starboard::atomic_int32_t;
+using atomic_int64 = starboard::atomic_int64_t;
+using Semaphore = starboard::Semaphore;
+
+struct CountLifetime {
+ explicit CountLifetime(atomic_int32* shared_int) {
+ shared_int_ = shared_int;
+ shared_int_->increment();
+ }
+
+ ~CountLifetime() { shared_int_->decrement(); }
+
+ atomic_int32* shared_int_;
+};
+
+TEST(ConcurrentPtr, nullptr) {
+ ConcurrentPtr<int> concurrent_ptr(nullptr);
+ ConcurrentPtr<int>::Access access_ptr =
+ concurrent_ptr.access_ptr(SbThreadGetId());
+ ASSERT_FALSE(access_ptr);
+ ASSERT_FALSE(access_ptr.valid());
+ ASSERT_EQ(access_ptr.get(), nullptr);
+ access_ptr.release();
+ concurrent_ptr.reset(nullptr);
+}
+
+TEST(ConcurrentPtr, UseSingleThreaded) {
+ int* int_ptr = new int(1234);
+ ConcurrentPtr<int> concurrent_ptr(int_ptr);
+ ConcurrentPtr<int>::Access access_ptr =
+ concurrent_ptr.access_ptr(SbThreadGetId());
+
+ ASSERT_TRUE(access_ptr);
+ ASSERT_TRUE(access_ptr.valid());
+ ASSERT_EQ(int_ptr, access_ptr.get());
+ ASSERT_EQ(int_ptr, &(*access_ptr));
+ access_ptr.release();
+ int* int_ptr2 = concurrent_ptr.release();
+ ASSERT_EQ(int_ptr, int_ptr2);
+ ASSERT_EQ(1234, *int_ptr);
+ delete int_ptr;
+}
+
+TEST(ConcurrentPtr, ResetDeltesInternalObject) {
+ atomic_int32 counter(0);
+
+ CountLifetime* ptr = new CountLifetime(&counter);
+ EXPECT_EQ(1, counter.load());
+
+ ConcurrentPtr<CountLifetime> concurrent_ptr(ptr);
+ concurrent_ptr.reset(nullptr);
+ EXPECT_EQ(0, counter.load());
+}
+
+TEST(ConcurrentPtr, UsePointerOperators) {
+ ConcurrentPtr<atomic_int32> concurrent_ptr(new atomic_int32());
+ ConcurrentPtr<atomic_int32>::Access access_ptr =
+ concurrent_ptr.access_ptr(SbThreadGetId());
+ ASSERT_TRUE(access_ptr.valid());
+ ASSERT_TRUE(access_ptr.get());
+
+ {
+ atomic_int32& int_ref = *access_ptr;
+ ASSERT_EQ(0, int_ref.load());
+ }
+
+ ASSERT_EQ(0, access_ptr->load());
+ access_ptr->store(2);
+ ASSERT_EQ(2, access_ptr->load());
+}
+
+class ConcurrentPtrThreadWorker : public SimpleThread {
+ public:
+ ConcurrentPtrThreadWorker(Semaphore* thread_seal,
+ ConcurrentPtr<atomic_int32>* concurrent_ptr)
+ : SimpleThread("ConcurrentPtrThreadWorker"),
+ thread_seal_(thread_seal),
+ concurrent_ptr_(concurrent_ptr),
+ finished_(false) {
+ Start();
+ }
+
+ ConcurrentPtrThreadWorker(const ConcurrentPtrThreadWorker&) = delete;
+
+ ~ConcurrentPtrThreadWorker() {
+ finished_ = true;
+ Join();
+ }
+
+ virtual void Run() {
+ thread_seal_->Take(); // Pause until the main thread unblocks us.
+ int64_t yield_counter = 0;
+ while (!finished_) {
+ if (yield_counter++ % 512 == 0) { // Be nice to other threads.
+ SbThreadYield();
+ }
+ ConcurrentPtr<atomic_int32>::Access access_ptr =
+ concurrent_ptr_->access_ptr(SbThreadGetId());
+ if (access_ptr) {
+ access_ptr->load();
+ access_ptr->store(SbThreadGetId());
+ }
+ }
+ }
+
+ virtual void Cancel() { finished_ = true; }
+
+ private:
+ Semaphore* thread_seal_;
+ ConcurrentPtr<atomic_int32>* concurrent_ptr_;
+ bool finished_;
+};
+
+// Tests the expectation that the ConcurrentPtr can have it's underlying
+// pointer repeatedly reset and that all the reading threads will be guaranteed
+// to either be able to lock the pointer for it's use or be receive nullptr.
+TEST(ConcurrentPtr, ThreadStressTest) {
+ Semaphore thread_seal;
+ ConcurrentPtr<atomic_int32> concurrent_ptr(new atomic_int32);
+
+ std::vector<ConcurrentPtrThreadWorker*> threads;
+ const int kThreads = NUM_THREADS;
+ for (int i = 0; i < kThreads; ++i) {
+ threads.push_back(
+ new ConcurrentPtrThreadWorker(&thread_seal, &concurrent_ptr));
+ }
+
+ // Launch threads.
+ for (int i = 0; i < kThreads; ++i) {
+ thread_seal.Put();
+ }
+
+ // Repeatedly reset the underlying pointer. If there is a race
+ // condition then the program will crash.
+ const SbTime start_time = SbTimeGetNow();
+ const SbTime end_time = start_time + (kSbTimeMillisecond * 100);
+ while (SbTimeGetNow() < end_time) {
+ concurrent_ptr.reset(nullptr);
+ SbThreadYield();
+ concurrent_ptr.reset(new atomic_int32);
+ concurrent_ptr.reset(new atomic_int32);
+ SbThreadYield();
+ }
+
+ for (auto it = threads.begin(); it != threads.end(); ++it) {
+ delete *it;
+ }
+ threads.clear();
+}
+
+} // namespace nb.
diff --git a/src/nb/nb.gyp b/src/nb/nb.gyp
index 8523211..8c50a66 100644
--- a/src/nb/nb.gyp
+++ b/src/nb/nb.gyp
@@ -35,6 +35,7 @@
'bidirectional_fit_reuse_allocator.h',
'bidirectional_fit_reuse_allocator.cc',
'concurrent_map.h',
+ 'concurrent_ptr.h',
'first_fit_reuse_allocator.h',
'first_fit_reuse_allocator.cc',
'fixed_no_free_allocator.cc',
@@ -95,6 +96,7 @@
'atomic_test.cc',
'bidirectional_fit_reuse_allocator_test.cc',
'concurrent_map_test.cc',
+ 'concurrent_ptr_test.cc',
'first_fit_reuse_allocator_test.cc',
'fixed_no_free_allocator_test.cc',
'lexical_cast_test.cc',
diff --git a/src/nb/starboard_memory_allocator.h b/src/nb/starboard_memory_allocator.h
index 5f53112..62c59a3 100644
--- a/src/nb/starboard_memory_allocator.h
+++ b/src/nb/starboard_memory_allocator.h
@@ -38,7 +38,7 @@
std::size_t alignment) SB_OVERRIDE {
return Allocate(*size, alignment);
}
- void Free(void* memory) SB_OVERRIDE { SbMemoryDeallocate(memory); }
+ void Free(void* memory) SB_OVERRIDE { SbMemoryDeallocateAligned(memory); }
std::size_t GetCapacity() const SB_OVERRIDE {
// Returns 0 here to avoid tracking the allocated memory.
return 0;
diff --git a/src/net/base/mime_util_unittest.cc b/src/net/base/mime_util_unittest.cc
index c01b1d4..3a3b650 100644
--- a/src/net/base/mime_util_unittest.cc
+++ b/src/net/base/mime_util_unittest.cc
@@ -192,11 +192,7 @@
TEST(MimeUtilTest, TestIsMimeType) {
std::string nonAscii("application/nonutf8");
EXPECT_TRUE(IsMimeType(nonAscii));
-#if defined(OS_WIN)
- nonAscii.append(WideToUTF8(std::wstring(L"\u2603")));
-#else
- nonAscii.append("\u2603"); // unicode snowman
-#endif
+ nonAscii.append(u8"\u2603"); // unicode snowman
EXPECT_FALSE(IsMimeType(nonAscii));
EXPECT_TRUE(IsMimeType("application/mime"));
diff --git a/src/net/cookies/cookie_monster_unittest.cc b/src/net/cookies/cookie_monster_unittest.cc
index 86cecff..38f7378 100644
--- a/src/net/cookies/cookie_monster_unittest.cc
+++ b/src/net/cookies/cookie_monster_unittest.cc
@@ -1725,11 +1725,11 @@
// time and size of store to make sure we only get rid of cookies when
// we really should.
const struct TestCase {
- int num_cookies;
- int num_old_cookies;
- int expected_initial_cookies;
+ size_t num_cookies;
+ size_t num_old_cookies;
+ size_t expected_initial_cookies;
// Indexed by ExpiryAndKeyScheme
- int expected_cookies_after_set;
+ size_t expected_cookies_after_set;
} test_cases[] = {
{
// A whole lot of recent cookies; gc shouldn't happen.
@@ -1766,12 +1766,12 @@
test_case->num_cookies, test_case->num_old_cookies,
CookieMonster::kSafeFromGlobalPurgeDays * 2));
EXPECT_EQ(test_case->expected_initial_cookies,
- static_cast<int>(GetAllCookies(cm).size()))
+ GetAllCookies(cm).size())
<< "For test case " << ci;
// Will trigger GC
SetCookie(cm, GURL("http://newdomain.com"), "b=2");
EXPECT_EQ(test_case->expected_cookies_after_set,
- static_cast<int>((GetAllCookies(cm).size())))
+ (GetAllCookies(cm).size()))
<< "For test case " << ci;
}
}
diff --git a/src/sql/sql.gyp b/src/sql/sql.gyp
index ff30949..ef71147 100644
--- a/src/sql/sql.gyp
+++ b/src/sql/sql.gyp
@@ -30,11 +30,6 @@
'transaction.h',
],
'conditions': [
- ['OS=="lb_shell"', {
- 'dependencies': [
- '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
- ],
- }],
['OS=="starboard"', {
'dependencies': [
'<(DEPTH)/starboard/starboard.gyp:starboard',
diff --git a/src/starboard/CHANGELOG.md b/src/starboard/CHANGELOG.md
index 7ce54d9..acbe7b4 100644
--- a/src/starboard/CHANGELOG.md
+++ b/src/starboard/CHANGELOG.md
@@ -56,6 +56,9 @@
signal that the application may soon be terminated due to low memory
availability.
+### Interface change to SbPlayerWriteSample()
+`const` is added to `sample_buffers` and `sample_buffer_sizes` parameters.
+
## Version 5
### Add Speech Recognizer API
diff --git a/src/starboard/common/common.gyp b/src/starboard/common/common.gyp
index bfe17b0..bf285ef 100644
--- a/src/starboard/common/common.gyp
+++ b/src/starboard/common/common.gyp
@@ -43,6 +43,13 @@
# building Starboard client code.
'STARBOARD_IMPLEMENTATION',
],
+ 'conditions': [
+ ['custom_media_session_client==0', {
+ 'sources': [
+ '<(DEPTH)/starboard/shared/media_session/stub_playback_state.cc',
+ ],
+ }],
+ ]
},
],
}
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index 00dc565..d6007c9 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -76,6 +76,8 @@
SB_RELEASE_CANDIDATE_API_VERSION
#define SB_COLOR_KEYCODES_API_VERSION SB_RELEASE_CANDIDATE_API_VERSION
#define SB_LOW_MEMORY_EVENT_API_VERSION SB_RELEASE_CANDIDATE_API_VERSION
+#define SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION \
+ SB_RELEASE_CANDIDATE_API_VERSION
// --- Common Detected Features ----------------------------------------------
@@ -547,20 +549,6 @@
#error "SB_MEDIA_GPU_BUFFER_BUDGET is deprecated."
#endif // defined(SB_MEDIA_GPU_BUFFER_BUDGET)
-#if COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET <= 0
-#error "cobalt_media_buffer_non_video_budget has to be greater than 0."
-#endif // COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET < 0
-
-#if COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P <= 0
-#error "cobalt_media_buffer_video_budget_1080p has to be greater than 0."
-#endif // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P < 0
-
-#if COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K < COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P
-#error cobalt_media_buffer_video_budget_4k has to be greater than or equal to \
- cobalt_media_buffer_video_budget_1080p.
-#endif // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K <
- // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P
-
#endif // SB_API_VERSION >= 4
#if SB_API_VERSION >= 5
diff --git a/src/starboard/linux/shared/gyp_configuration.gypi b/src/starboard/linux/shared/gyp_configuration.gypi
index 01ca539..9500981 100644
--- a/src/starboard/linux/shared/gyp_configuration.gypi
+++ b/src/starboard/linux/shared/gyp_configuration.gypi
@@ -35,7 +35,6 @@
'-lavresample',
'-lavutil',
'-lpthread',
- '-lpulse',
'-lrt',
],
diff --git a/src/starboard/linux/x64x11/clang/3.3/atomic_public.h b/src/starboard/linux/x64x11/clang/3.3/atomic_public.h
deleted file mode 100644
index 2318bd7..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/atomic_public.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_LINUX_X64X11_CLANG_3_3_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_CLANG_3_3_ATOMIC_PUBLIC_H_
-
-#include "starboard/linux/x64x11/atomic_public.h"
-
-#endif // STARBOARD_LINUX_X64X11_CLANG_3_3_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/clang/3.3/compiler_flags.gypi b/src/starboard/linux/x64x11/clang/3.3/compiler_flags.gypi
deleted file mode 100644
index 22d5331..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/compiler_flags.gypi
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Platform specific compiler flags for Linux on Starboard. Included from
-# gyp_configuration.gypi.
-#
-{
- 'variables': {
- 'compiler_flags_host': [
- '-O2',
- ],
- 'linker_flags': [
- ],
- 'compiler_flags_debug': [
- '-frtti',
- '-O0',
- ],
- 'compiler_flags_devel': [
- '-frtti',
- '-O2',
- ],
- 'compiler_flags_qa': [
- '-fno-rtti',
- '-O2',
- '-gline-tables-only',
- ],
- 'compiler_flags_gold': [
- '-fno-rtti',
- '-O2',
- '-gline-tables-only',
- ],
- 'conditions': [
- ['clang==1', {
- 'common_clang_flags': [
- '-Werror',
- '-fcolor-diagnostics',
- # Default visibility to hidden, to enable dead stripping.
- '-fvisibility=hidden',
- # protobuf uses hash_map.
- '-Wno-deprecated',
- '-fno-exceptions',
- # Don't warn about the "struct foo f = {0};" initialization pattern.
- '-Wno-missing-field-initializers',
- '-fno-strict-aliasing', # See http://crbug.com/32204
- # Don't warn for invalid access to non-static data member of NULL object.
- '-Wno-invalid-offsetof',
- # Don't warn about any conversions.
- '-Wno-conversion',
- # Don't complain about unknown warning options
- '-Wno-unknown-warning-option',
- # Suppress: "warning: 'override' keyword is a C++11 extension"
- '-Wno-c++11-extensions',
- # Suppress "case value not in enumerated type"
- '-Wno-switch',
- # Suppress "'&&' within '||'"
- '-Wno-logical-op-parentheses',
- # Suppress "error: unused function"
- '-Wno-unused-function',
- # Suppress "comparison of unsigned enum expression < 0 is always false"
- '-Wno-tautological-compare',
- # Suppress "[type1] has C-linkage specified, but returns user-defined type [type2] which is incompatible with C"
- '-Wno-return-type-c-linkage',
- # Suppress "will never be executed"
- '-Wno-unreachable-code',
- # Suppress "++98 requires a copy constructor when binding a reference to a temporary"
- '-Wno-bind-to-temporary-copy',
- '-DHAS_LEAK_SANITIZER=0', # Clang 3.3 does not have Leak Sanitizer. This is
- # is important because it's assumed in chromium
- # that the two always are enabled together.
- # Suppress "template argument uses unnamed type"
- '-Wno-unnamed-type-template-args',
- ],
- }],
- ['cobalt_fastbuild==0', {
- 'compiler_flags_debug': [
- '-g',
- ],
- 'compiler_flags_devel': [
- '-g',
- ],
- 'compiler_flags_qa': [
- '-gline-tables-only',
- ],
- 'compiler_flags_gold': [
- '-gline-tables-only',
- ],
- }],
- ],
- },
-
- 'target_defaults': {
- 'cflags_c': [
- # Limit to C99. This allows Linux to be a canary build for any
- # C11 features that are not supported on some platforms' compilers.
- '-std=c99',
- ],
- 'cflags_cc': [
- '-std=gnu++98',
- ],
- 'target_conditions': [
- ['sb_pedantic_warnings==1', {
- 'cflags': [
- '-Wall',
- '-Wextra',
- '<@(common_clang_flags)',
- ],
- },{
- 'cflags': [
- '<@(common_clang_flags)',
- # 'this' pointer cannot be NULL...pointer may be assumed
- # to always convert to true.
- '-Wno-undefined-bool-conversion',
- # Skia doesn't use overrides.
- '-Wno-inconsistent-missing-override',
- # Do not warn about unused function params.
- '-Wno-unused-parameter',
- # shifting a negative signed value is undefined
- '-Wno-shift-negative-value',
- # Width of bit-field exceeds width of its type- value will be truncated
- '-Wno-bitfield-width',
- ],
- }],
- ['use_asan==1', {
- 'cflags': [
- '-fsanitize=address',
- '-fno-omit-frame-pointer',
- ],
- 'ldflags': [
- '-fsanitize=address',
- # Force linking of the helpers in sanitizer_options.cc
- '-Wl,-u_sanitizer_options_link_helper',
- ],
- 'defines': [
- 'ADDRESS_SANITIZER',
- ],
- }],
- ['use_tsan==1', {
- 'cflags': [
- '-fsanitize=thread',
- '-fno-omit-frame-pointer',
- ],
- 'ldflags': [
- '-fsanitize=thread',
- ],
- 'defines': [
- 'THREAD_SANITIZER',
- ],
- }],
- ],
- }, # end of target_defaults
-}
diff --git a/src/starboard/linux/x64x11/clang/3.3/configuration_public.h b/src/starboard/linux/x64x11/clang/3.3/configuration_public.h
deleted file mode 100644
index 1914518..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/configuration_public.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_LINUX_X64X11_CLANG_3_3_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_CLANG_3_3_CONFIGURATION_PUBLIC_H_
-
-#include "starboard/linux/x64x11/configuration_public.h"
-
-// Indicates that there is no support for alignment at greater than 16 bytes for
-// items on the stack.
-#define SB_HAS_QUIRK_DOES_NOT_STACK_ALIGN_OVER_16_BYTES 1
-
-#endif // STARBOARD_LINUX_X64X11_CLANG_3_3_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/clang/3.3/download_clang.sh b/src/starboard/linux/x64x11/clang/3.3/download_clang.sh
deleted file mode 100755
index f552ae8..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/download_clang.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This script downloads and compiles clang version 3.3.
-
-set -e
-
-toolchain_name="clang"
-version="3.3"
-toolchain_folder="x86_64-linux-gnu-${toolchain_name}-${version}"
-branch="release_33"
-
-binary_path="llvm/Release+Asserts/bin/clang++"
-build_duration="about 15 minutes"
-
-source ../../toolchain_paths.sh
-
-(
- git clone --branch ${branch} http://llvm.org/git/llvm.git
- cd llvm/tools/
- git clone --branch ${branch} http://llvm.org/git/clang.git
- cd ../projects/
- git clone --branch ${branch} http://llvm.org/git/compiler-rt.git
- cd ${toolchain_path}
-
- cd llvm
- # Specify a bootstrap compiler that is known to be available.
- CC=clang-3.6 CXX=clang++-3.6 \
- ./configure --enable-optimized --disable-doxygen --prefix=${PWD}/bin
- make -j"$(nproc)"
- cd ${toolchain_path}
-
- ls -l ${toolchain_binary}
- ${toolchain_binary} --version
-) >${logfile} 2>&1
diff --git a/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.gypi b/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.gypi
deleted file mode 100644
index 05d38d0..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.gypi
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- 'variables': {
- # This should have a default value in cobalt/base.gypi. See the comment
- # there for acceptable values for this variable.
- 'javascript_engine': 'mozjs',
- 'cobalt_enable_jit': 1,
- },
- 'target_defaults': {
- 'default_configuration': 'linux-x64x11-clang-3-3_debug',
- 'configurations': {
- 'linux-x64x11-clang-3-3_debug': {
- 'inherit_from': ['debug_base'],
- },
- 'linux-x64x11-clang-3-3_devel': {
- 'inherit_from': ['devel_base'],
- },
- 'linux-x64x11-clang-3-3_qa': {
- 'inherit_from': ['qa_base'],
- },
- 'linux-x64x11-clang-3-3_gold': {
- 'inherit_from': ['gold_base'],
- },
- }, # end of configurations
- },
-
- 'includes': [
- 'compiler_flags.gypi',
- '../gyp_configuration.gypi',
- ],
-}
diff --git a/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.py b/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.py
deleted file mode 100644
index 7efd522..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/gyp_configuration.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Starboard Linux X64 X11 Clang 3.6 platform configuration for gyp_cobalt."""
-
-import logging
-import os
-import subprocess
-import sys
-
-# Import the shared Linux platform configuration.
-sys.path.append(
- os.path.realpath(
- os.path.join(
- os.path.dirname(__file__), os.pardir, os.pardir, os.pardir,
- 'shared')))
-# pylint: disable=import-self,g-import-not-at-top
-import gyp_configuration as shared_configuration
-import gyp_utils
-
-
-class PlatformConfig(shared_configuration.PlatformConfig):
- """Starboard Linux platform configuration."""
-
- def __init__(self, platform, asan_enabled_by_default=False):
- super(PlatformConfig, self).__init__(
- platform, asan_enabled_by_default, goma_supports_compiler=False)
-
- script_path = os.path.dirname(os.path.realpath(__file__))
- # Run the script that ensures clang 3.3 is installed.
- subprocess.call(
- os.path.join(script_path, 'download_clang.sh'), cwd=script_path)
-
- def GetEnvironmentVariables(self):
- env_variables = super(PlatformConfig, self).GetEnvironmentVariables()
- toolchain_bin_dir = os.path.join(gyp_utils.GetToolchainsDir(),
- 'x86_64-linux-gnu-clang-3.3', 'llvm',
- 'Release+Asserts', 'bin')
- env_variables.update({
- 'CC': os.path.join(toolchain_bin_dir, 'clang'),
- 'CXX': os.path.join(toolchain_bin_dir, 'clang++'),
- })
- return env_variables
-
-
-def CreatePlatformConfig():
- try:
- return PlatformConfig('linux-x64x11-clang-3-3')
- except RuntimeError as e:
- logging.critical(e)
- return None
diff --git a/src/starboard/linux/x64x11/clang/3.3/starboard_platform.gyp b/src/starboard/linux/x64x11/clang/3.3/starboard_platform.gyp
deleted file mode 100644
index 71a6d38..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/starboard_platform.gyp
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-{
- 'includes': [
- '../starboard_platform.gyp',
- ],
-}
diff --git a/src/starboard/linux/x64x11/clang/3.3/thread_types_public.h b/src/starboard/linux/x64x11/clang/3.3/thread_types_public.h
deleted file mode 100644
index d9310bd..0000000
--- a/src/starboard/linux/x64x11/clang/3.3/thread_types_public.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_LINUX_X64X11_CLANG_3_3_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_CLANG_3_3_THREAD_TYPES_PUBLIC_H_
-
-#include "starboard/linux/x64x11/thread_types_public.h"
-
-#endif // STARBOARD_LINUX_X64X11_CLANG_3_3_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/libraries.gypi b/src/starboard/linux/x64x11/libraries.gypi
index 60a0f7e..f2c94d0 100644
--- a/src/starboard/linux/x64x11/libraries.gypi
+++ b/src/starboard/linux/x64x11/libraries.gypi
@@ -19,7 +19,6 @@
'-lGLESv2',
'-lX11',
'-lXcomposite',
- '-lXext',
'-lXrender',
],
},
diff --git a/src/starboard/linux/x64x11/mse2016/atomic_public.h b/src/starboard/linux/x64x11/mse2016/atomic_public.h
deleted file mode 100644
index 889c4c2..0000000
--- a/src/starboard/linux/x64x11/mse2016/atomic_public.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/linux/x64x11/atomic_public.h"
diff --git a/src/starboard/linux/x64x11/mse2016/configuration_public.h b/src/starboard/linux/x64x11/mse2016/configuration_public.h
deleted file mode 100644
index 49d5f8a..0000000
--- a/src/starboard/linux/x64x11/mse2016/configuration_public.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// The Starboard configuration for Desktop X86 Linux. Other devices will have
-// specific Starboard implementations, even if they ultimately are running some
-// version of Linux.
-
-// Other source files should never include this header directly, but should
-// include the generic "starboard/configuration.h" instead.
-
-#ifndef STARBOARD_LINUX_X64X11_MSE2016_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_MSE2016_CONFIGURATION_PUBLIC_H_
-
-// Include the Linux configuration that's common between all x64x11 Linuxes.
-#include "starboard/linux/x64x11/configuration_public.h"
-
-#endif // STARBOARD_LINUX_X64X11_MSE2016_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/mse2016/gyp_configuration.gypi b/src/starboard/linux/x64x11/mse2016/gyp_configuration.gypi
deleted file mode 100644
index 75362de..0000000
--- a/src/starboard/linux/x64x11/mse2016/gyp_configuration.gypi
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2017 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- 'variables': {
- 'cobalt_media_source_2016': 1,
- },
- 'target_defaults': {
- 'default_configuration': 'linux-x64x11-mse2016_debug',
- 'configurations': {
- 'linux-x64x11-mse2016_debug': {
- 'inherit_from': ['debug_base'],
- },
- 'linux-x64x11-mse2016_devel': {
- 'inherit_from': ['devel_base'],
- },
- 'linux-x64x11-mse2016_qa': {
- 'inherit_from': ['qa_base'],
- },
- 'linux-x64x11-mse2016_gold': {
- 'inherit_from': ['gold_base'],
- },
- }, # end of configurations
- },
-
- 'includes': [
- '../gyp_configuration.gypi',
- ],
-}
diff --git a/src/starboard/linux/x64x11/mse2016/gyp_configuration.py b/src/starboard/linux/x64x11/mse2016/gyp_configuration.py
deleted file mode 100644
index ec9d0e5..0000000
--- a/src/starboard/linux/x64x11/mse2016/gyp_configuration.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Starboard Linux X64 X11 MSE2016 platform configuration for gyp_cobalt."""
-
-import logging
-import os
-import sys
-
-# Import the shared platform configuration.
-sys.path.append(os.path.realpath(os.path.join(
- os.path.dirname(__file__), os.pardir, os.pardir, 'shared')))
-import gyp_configuration
-
-
-def CreatePlatformConfig():
- try:
- return gyp_configuration.PlatformConfig('linux-x64x11-mse2016')
- except RuntimeError as e:
- logging.critical(e)
- return None
diff --git a/src/starboard/linux/x64x11/mse2016/starboard_platform.gyp b/src/starboard/linux/x64x11/mse2016/starboard_platform.gyp
deleted file mode 100644
index d64fb48..0000000
--- a/src/starboard/linux/x64x11/mse2016/starboard_platform.gyp
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-{
- 'includes': [
- '../starboard_platform.gypi'
- ],
- 'targets': [
- {
- 'target_name': 'starboard_platform',
- 'type': 'static_library',
- 'sources': [
- '<@(starboard_platform_sources)',
- ],
- 'defines': [
- # This must be defined when building Starboard, and must not when
- # building Starboard client code.
- 'STARBOARD_IMPLEMENTATION',
- ],
- 'dependencies': [
- '<@(starboard_platform_dependencies)',
- ],
- },
- ],
-}
diff --git a/src/starboard/linux/x64x11/mse2016/thread_types_public.h b/src/starboard/linux/x64x11/mse2016/thread_types_public.h
deleted file mode 100644
index 04d844d..0000000
--- a/src/starboard/linux/x64x11/mse2016/thread_types_public.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/linux/x64x11/thread_types_public.h"
diff --git a/src/starboard/player.h b/src/starboard/player.h
index a58b683..0226d8b 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -399,8 +399,13 @@
SB_EXPORT void SbPlayerWriteSample(
SbPlayer player,
SbMediaType sample_type,
+#if SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
+ const void* const* sample_buffers,
+ const int* sample_buffer_sizes,
+#else // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
const void** sample_buffers,
int* sample_buffer_sizes,
+#endif // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
int number_of_sample_buffers,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
diff --git a/src/starboard/raspi/shared/application_dispmanx.h b/src/starboard/raspi/shared/application_dispmanx.h
index d08c406..a3469c2 100644
--- a/src/starboard/raspi/shared/application_dispmanx.h
+++ b/src/starboard/raspi/shared/application_dispmanx.h
@@ -61,6 +61,11 @@
Event* WaitForSystemEventWithTimeout(SbTime duration) SB_OVERRIDE;
void WakeSystemEventWait() SB_OVERRIDE;
+#if SB_API_VERSION >= SB_PRELOAD_API_VERSION
+ bool IsStartImmediate() SB_OVERRIDE { return !HasPreloadSwitch(); }
+ bool IsPreloadImmediate() SB_OVERRIDE { return HasPreloadSwitch(); }
+#endif // SB_API_VERSION >= SB_PRELOAD_API_VERSION
+
private:
// Returns whether DISPMANX has been initialized.
bool IsDispmanxInitialized() { return display_ != NULL; }
diff --git a/src/starboard/raspi/shared/gyp_configuration.gypi b/src/starboard/raspi/shared/gyp_configuration.gypi
index 1e1f4cf..5123449 100644
--- a/src/starboard/raspi/shared/gyp_configuration.gypi
+++ b/src/starboard/raspi/shared/gyp_configuration.gypi
@@ -122,7 +122,6 @@
'-lEGL',
'-lGLESv2',
'-lpthread',
- '-lpulse',
'-lrt',
'-lopenmaxil',
'-lbcm_host',
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.cc b/src/starboard/raspi/shared/open_max/video_decoder.cc
index f0e3909..7c96b7d 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.cc
+++ b/src/starboard/raspi/shared/open_max/video_decoder.cc
@@ -67,7 +67,9 @@
SB_DCHECK(SbThreadIsValid(thread_));
}
-void VideoDecoder::WriteInputBuffer(const InputBuffer& input_buffer) {
+void VideoDecoder::WriteInputBuffer(
+ const scoped_refptr<InputBuffer>& input_buffer) {
+ SB_DCHECK(input_buffer);
SB_DCHECK(host_ != NULL);
queue_.Put(new Event(input_buffer));
@@ -133,7 +135,7 @@
component.Start();
- InputBuffer current_buffer;
+ scoped_refptr<InputBuffer> current_buffer;
int offset = 0;
for (;;) {
@@ -158,13 +160,13 @@
filled_buffers_.push(buffer);
}
- if (current_buffer.is_valid()) {
- int size = static_cast<int>(current_buffer.size());
+ if (current_buffer) {
+ int size = static_cast<int>(current_buffer->size());
while (offset < size) {
int written = component.WriteData(
- current_buffer.data() + offset, size - offset,
+ current_buffer->data() + offset, size - offset,
OpenMaxComponent::kDataNonEOS,
- current_buffer.pts() * kSbTimeSecond / kSbMediaTimeSecond);
+ current_buffer->pts() * kSbTimeSecond / kSbMediaTimeSecond);
SB_DCHECK(written >= 0);
offset += written;
if (written == 0) {
@@ -172,7 +174,7 @@
}
}
if (offset == size) {
- current_buffer = InputBuffer();
+ current_buffer = NULL;
offset = 0;
} else {
SbThreadSleep(kSbTimeMillisecond);
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.h b/src/starboard/raspi/shared/open_max/video_decoder.h
index fa950fe..444d778 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.h
+++ b/src/starboard/raspi/shared/open_max/video_decoder.h
@@ -17,6 +17,7 @@
#include <queue>
+#include "starboard/common/ref_counted.h"
#include "starboard/log.h"
#include "starboard/media.h"
#include "starboard/mutex.h"
@@ -46,7 +47,8 @@
~VideoDecoder() SB_OVERRIDE;
void SetHost(Host* host) SB_OVERRIDE;
- void WriteInputBuffer(const InputBuffer& input_buffer) SB_OVERRIDE;
+ void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
+ SB_OVERRIDE;
void WriteEndOfStream() SB_OVERRIDE;
void Reset() SB_OVERRIDE;
@@ -56,11 +58,11 @@
explicit Event(const Type type) : type(type) {
SB_DCHECK(type != kWriteInputBuffer);
}
- explicit Event(const InputBuffer& input_buffer)
+ explicit Event(const scoped_refptr<InputBuffer>& input_buffer)
: type(kWriteInputBuffer), input_buffer(input_buffer) {}
Type type;
- InputBuffer input_buffer;
+ scoped_refptr<InputBuffer> input_buffer;
};
bool TryToDeliverOneFrame();
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
index 16bc1c5..12531ab 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.cc
@@ -70,9 +70,10 @@
output_cb_ = output_cb;
}
-void AudioDecoder::Decode(const InputBuffer& input_buffer,
+void AudioDecoder::Decode(const scoped_refptr<InputBuffer>& input_buffer,
const Closure& consumed_cb) {
SB_DCHECK(BelongsToCurrentThread());
+ SB_DCHECK(input_buffer);
SB_DCHECK(output_cb_.is_valid());
SB_CHECK(codec_context_ != NULL);
@@ -85,17 +86,17 @@
AVPacket packet;
av_init_packet(&packet);
- packet.data = const_cast<uint8_t*>(input_buffer.data());
- packet.size = input_buffer.size();
+ packet.data = const_cast<uint8_t*>(input_buffer->data());
+ packet.size = input_buffer->size();
avcodec_get_frame_defaults(av_frame_);
int frame_decoded = 0;
int result =
avcodec_decode_audio4(codec_context_, av_frame_, &frame_decoded, &packet);
- if (result != input_buffer.size() || frame_decoded != 1) {
+ if (result != input_buffer->size() || frame_decoded != 1) {
// TODO: Consider fill it with silence.
SB_DLOG(WARNING) << "avcodec_decode_audio4() failed with result: " << result
- << " with input buffer size: " << input_buffer.size()
+ << " with input buffer size: " << input_buffer->size()
<< " and frame decoded: " << frame_decoded;
return;
}
@@ -108,7 +109,7 @@
if (decoded_audio_size > 0) {
scoped_refptr<DecodedAudio> decoded_audio = new DecodedAudio(
codec_context_->channels, GetSampleType(), GetStorageType(),
- input_buffer.pts(),
+ input_buffer->pts(),
codec_context_->channels * av_frame_->nb_samples *
starboard::media::GetBytesPerSample(GetSampleType()));
if (GetStorageType() == kSbMediaAudioFrameStorageTypeInterleaved) {
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
index 40bd9c8..7cc62fd 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder.h
@@ -17,6 +17,7 @@
#include <queue>
+#include "starboard/common/ref_counted.h"
#include "starboard/media.h"
#include "starboard/shared/ffmpeg/ffmpeg_common.h"
#include "starboard/shared/internal_only.h"
@@ -37,7 +38,7 @@
~AudioDecoder() SB_OVERRIDE;
void Initialize(const Closure& output_cb) SB_OVERRIDE;
- void Decode(const InputBuffer& input_buffer,
+ void Decode(const scoped_refptr<InputBuffer>& input_buffer,
const Closure& consumed_cb) SB_OVERRIDE;
void WriteEndOfStream() SB_OVERRIDE;
scoped_refptr<DecodedAudio> Read() SB_OVERRIDE;
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
index 98a8680..5c08757 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -125,7 +125,9 @@
host_ = host;
}
-void VideoDecoder::WriteInputBuffer(const InputBuffer& input_buffer) {
+void VideoDecoder::WriteInputBuffer(
+ const scoped_refptr<InputBuffer>& input_buffer) {
+ SB_DCHECK(input_buffer);
SB_DCHECK(queue_.Poll().type == kInvalid);
SB_DCHECK(host_ != NULL);
@@ -194,9 +196,9 @@
// Send |input_buffer| to ffmpeg and try to decode one frame.
AVPacket packet;
av_init_packet(&packet);
- packet.data = const_cast<uint8_t*>(event.input_buffer.data());
- packet.size = event.input_buffer.size();
- packet.pts = event.input_buffer.pts();
+ packet.data = const_cast<uint8_t*>(event.input_buffer->data());
+ packet.size = event.input_buffer->size();
+ packet.pts = event.input_buffer->pts();
codec_context_->reordered_opaque = packet.pts;
DecodePacket(&packet);
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h
index 3daf19e..a89e8f9 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.h
@@ -15,6 +15,7 @@
#ifndef STARBOARD_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
#define STARBOARD_SHARED_FFMPEG_FFMPEG_VIDEO_DECODER_H_
+#include "starboard/common/ref_counted.h"
#include "starboard/log.h"
#include "starboard/media.h"
#include "starboard/queue.h"
@@ -41,7 +42,8 @@
~VideoDecoder() SB_OVERRIDE;
void SetHost(Host* host) SB_OVERRIDE;
- void WriteInputBuffer(const InputBuffer& input_buffer) SB_OVERRIDE;
+ void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
+ SB_OVERRIDE;
void WriteEndOfStream() SB_OVERRIDE;
void Reset() SB_OVERRIDE;
@@ -58,13 +60,13 @@
struct Event {
EventType type;
// |input_buffer| is only used when |type| is kWriteInputBuffer.
- InputBuffer input_buffer;
+ scoped_refptr<InputBuffer> input_buffer;
explicit Event(EventType type = kInvalid) : type(type) {
SB_DCHECK(type != kWriteInputBuffer);
}
- explicit Event(InputBuffer input_buffer)
+ explicit Event(const scoped_refptr<InputBuffer>& input_buffer)
: type(kWriteInputBuffer), input_buffer(input_buffer) {}
};
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.cc b/src/starboard/shared/libvpx/vpx_video_decoder.cc
index 14727f9..d6dbf97 100644
--- a/src/starboard/shared/libvpx/vpx_video_decoder.cc
+++ b/src/starboard/shared/libvpx/vpx_video_decoder.cc
@@ -49,7 +49,9 @@
host_ = host;
}
-void VideoDecoder::WriteInputBuffer(const InputBuffer& input_buffer) {
+void VideoDecoder::WriteInputBuffer(
+ const scoped_refptr<InputBuffer>& input_buffer) {
+ SB_DCHECK(input_buffer);
SB_DCHECK(queue_.Poll().type == kInvalid);
SB_DCHECK(host_ != NULL);
@@ -171,8 +173,10 @@
}
}
-void VideoDecoder::DecodeOneBuffer(const InputBuffer& input_buffer) {
- const SbMediaVideoSampleInfo* sample_info = input_buffer.video_sample_info();
+void VideoDecoder::DecodeOneBuffer(
+ const scoped_refptr<InputBuffer>& input_buffer) {
+ SB_DCHECK(input_buffer);
+ const SbMediaVideoSampleInfo* sample_info = input_buffer->video_sample_info();
SB_DCHECK(sample_info);
if (!context_ || sample_info->frame_width != current_frame_width_ ||
sample_info->frame_height != current_frame_height_) {
@@ -184,9 +188,9 @@
SB_DCHECK(context_);
- SbMediaTime pts = input_buffer.pts();
- vpx_codec_err_t status = vpx_codec_decode(context_.get(), input_buffer.data(),
- input_buffer.size(), &pts, 0);
+ SbMediaTime pts = input_buffer->pts();
+ vpx_codec_err_t status = vpx_codec_decode(
+ context_.get(), input_buffer->data(), input_buffer->size(), &pts, 0);
if (status != VPX_CODEC_OK) {
SB_DLOG(ERROR) << "vpx_codec_decode() failed, status=" << status;
ReportError();
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.h b/src/starboard/shared/libvpx/vpx_video_decoder.h
index 50b39ce..9eb2f5a 100644
--- a/src/starboard/shared/libvpx/vpx_video_decoder.h
+++ b/src/starboard/shared/libvpx/vpx_video_decoder.h
@@ -15,6 +15,7 @@
#ifndef STARBOARD_SHARED_LIBVPX_VPX_VIDEO_DECODER_H_
#define STARBOARD_SHARED_LIBVPX_VPX_VIDEO_DECODER_H_
+#include "starboard/common/ref_counted.h"
#include "starboard/log.h"
#include "starboard/media.h"
#include "starboard/queue.h"
@@ -44,7 +45,8 @@
~VideoDecoder() SB_OVERRIDE;
void SetHost(Host* host) SB_OVERRIDE;
- void WriteInputBuffer(const InputBuffer& input_buffer) SB_OVERRIDE;
+ void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
+ SB_OVERRIDE;
void WriteEndOfStream() SB_OVERRIDE;
void Reset() SB_OVERRIDE;
@@ -59,13 +61,13 @@
struct Event {
EventType type;
// |input_buffer| is only used when |type| is kWriteInputBuffer.
- InputBuffer input_buffer;
+ scoped_refptr<InputBuffer> input_buffer;
explicit Event(EventType type = kInvalid) : type(type) {
SB_DCHECK(type != kWriteInputBuffer);
}
- explicit Event(InputBuffer input_buffer)
+ explicit Event(const scoped_refptr<InputBuffer>& input_buffer)
: type(kWriteInputBuffer), input_buffer(input_buffer) {}
};
@@ -79,7 +81,7 @@
// thread is not running.
void InitializeCodec();
void TeardownCodec();
- void DecodeOneBuffer(const InputBuffer& input_buffer);
+ void DecodeOneBuffer(const scoped_refptr<InputBuffer>& input_buffer);
SbDecodeTarget GetCurrentDecodeTarget() SB_OVERRIDE;
diff --git a/src/starboard/shared/media_session/playback_state.h b/src/starboard/shared/media_session/playback_state.h
new file mode 100644
index 0000000..feeed87
--- /dev/null
+++ b/src/starboard/shared/media_session/playback_state.h
@@ -0,0 +1,30 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_MEDIA_SESSION_PLAYBACK_STATE_H_
+#define STARBOARD_SHARED_MEDIA_SESSION_PLAYBACK_STATE_H_
+
+namespace starboard {
+namespace shared {
+namespace media_session {
+
+enum PlaybackState { kPlaying = 0, kPaused = 1, kNone = 2 };
+
+void UpdateActiveSessionPlatformPlaybackState(PlaybackState state);
+
+} // namespace media_session
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_MEDIA_SESSION_PLAYBACK_STATE_H_
diff --git a/src/starboard/shared/media_session/stub_playback_state.cc b/src/starboard/shared/media_session/stub_playback_state.cc
new file mode 100644
index 0000000..e4ae5bf
--- /dev/null
+++ b/src/starboard/shared/media_session/stub_playback_state.cc
@@ -0,0 +1,30 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/log.h"
+
+#include "starboard/shared/media_session/playback_state.h"
+
+namespace starboard {
+namespace shared {
+namespace media_session {
+
+void UpdateActiveSessionPlatformPlaybackState(PlaybackState state) {
+ SB_UNREFERENCED_PARAMETER(state);
+ SB_NOTIMPLEMENTED();
+}
+
+} // namespace media_session
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc
index 1a4bf89..194adc1 100644
--- a/src/starboard/shared/starboard/application.cc
+++ b/src/starboard/shared/starboard/application.cc
@@ -14,6 +14,8 @@
#include "starboard/shared/starboard/application.h"
+#include <string>
+
#include "starboard/atomic.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/condition_variable.h"
@@ -31,6 +33,7 @@
namespace {
const char kPreloadSwitch[] = "preload";
+const char kLinkSwitch[] = "link";
// Dispatches an event of |type| with |data| to the system event handler,
// calling |destructor| on |data| when finished dispatching. Does all
@@ -63,6 +66,7 @@
reinterpret_cast<SbAtomicPtr>(reinterpret_cast<void*>(NULL)),
reinterpret_cast<SbAtomicPtr>(this)));
SB_DCHECK(!old_instance);
+ SB_UNREFERENCED_PARAMETER(old_instance);
}
Application::~Application() {
@@ -76,24 +80,27 @@
SbMemoryDeallocate(start_link_);
}
+int Application::Run(int argc, char** argv, const char* link_data) {
+ Initialize();
+ command_line_.reset(new CommandLine(argc, argv));
+ if (link_data) {
+ SetStartLink(link_data);
+ }
+
+ return RunLoop();
+}
+
int Application::Run(int argc, char** argv) {
Initialize();
command_line_.reset(new CommandLine(argc, argv));
- if (IsPreloadImmediate()) {
- DispatchPreload();
- } else if (IsStartImmediate()) {
- DispatchStart();
- }
-
- for (;;) {
- if (!DispatchNextEvent()) {
- break;
+ if (command_line_->HasSwitch(kLinkSwitch)) {
+ std::string value = command_line_->GetSwitchValue(kLinkSwitch);
+ if (!value.empty()) {
+ SetStartLink(value.c_str());
}
}
- CallTeardownCallbacks();
- Teardown();
- return error_level_;
+ return RunLoop();
}
CommandLine* Application::GetCommandLine() {
@@ -122,6 +129,12 @@
Inject(event);
}
+void Application::Link(const char *link_data) {
+ SB_DCHECK(link_data) << "You must call Link with link_data.";
+ Inject(new Event(kSbEventTypeLink, SbStringDuplicate(link_data),
+ SbMemoryDeallocate));
+}
+
SbEventId Application::Schedule(SbEventCallback callback,
void* context,
SbTimeMonotonic delay) {
@@ -336,6 +349,25 @@
return new Event(type, start_data, &DeleteDestructor<SbEventStartData>);
}
+int Application::RunLoop() {
+ SB_DCHECK(command_line_);
+ if (IsPreloadImmediate()) {
+ DispatchPreload();
+ } else if (IsStartImmediate()) {
+ DispatchStart();
+ }
+
+ for (;;) {
+ if (!DispatchNextEvent()) {
+ break;
+ }
+ }
+
+ CallTeardownCallbacks();
+ Teardown();
+ return error_level_;
+}
+
} // namespace starboard
} // namespace shared
} // namespace starboard
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h
index c70bcfb..2d1569d 100644
--- a/src/starboard/shared/starboard/application.h
+++ b/src/starboard/shared/starboard/application.h
@@ -155,6 +155,7 @@
// Runs the application with the current thread as the Main Starboard Thread,
// blocking until application exit. This method will dispatch all appropriate
// initialization and teardown events. Returns the resulting error level.
+ int Run(int argc, char** argv, const char* link_data);
int Run(int argc, char** argv);
// Retrieves the CommandLine for the application.
@@ -202,6 +203,12 @@
// appropriate for the current state. May be called from an external thread.
void Stop(int error_level);
+ // Injects a link event to the application with the given |link_data|, which
+ // must be a null-terminated string. Makes a copy of |link_data|, so it only
+ // has to live over the lifetime of the call to Link. May be called from an
+ // external thread.
+ void Link(const char* link_data);
+
// Schedules an event into the event queue. May be called from an external
// thread.
SbEventId Schedule(SbEventCallback callback,
@@ -357,6 +364,9 @@
// command line and deep link.
Event* CreateInitialEvent(SbEventType type);
+ // Internal workhorse of the main run loop.
+ int RunLoop();
+
// The single application instance.
static Application* g_instance;
diff --git a/src/starboard/shared/starboard/localized_strings.cc b/src/starboard/shared/starboard/localized_strings.cc
index e25e5af..ec68964 100644
--- a/src/starboard/shared/starboard/localized_strings.cc
+++ b/src/starboard/shared/starboard/localized_strings.cc
@@ -71,7 +71,7 @@
char* buffer_pos = buffer;
while (bytes_to_read > 0) {
int max_bytes_to_read = static_cast<int>(
- std::min(static_cast<int64_t>(kSbInt32Min), bytes_to_read));
+ std::min(static_cast<int64_t>(kSbInt32Max), bytes_to_read));
int bytes_read = file.Read(buffer_pos, max_bytes_to_read);
if (bytes_read < 0) {
SB_DLOG(ERROR) << "Read from i18n file failed.";
diff --git a/src/starboard/shared/starboard/media/mime_type_test.cc b/src/starboard/shared/starboard/media/mime_type_test.cc
index e8847d7..6a9fe7a 100644
--- a/src/starboard/shared/starboard/media/mime_type_test.cc
+++ b/src/starboard/shared/starboard/media/mime_type_test.cc
@@ -198,8 +198,8 @@
TEST(MimeTypeTest, GetParamFloatValueWithIndex) {
MimeType mime_type("video/mp4; name0=123; name1=123.4");
- EXPECT_FLOAT_EQ(123., mime_type.GetParamFloatValue(0));
- EXPECT_FLOAT_EQ(123.4, mime_type.GetParamFloatValue(1));
+ EXPECT_FLOAT_EQ(123.f, mime_type.GetParamFloatValue(0));
+ EXPECT_FLOAT_EQ(123.4f, mime_type.GetParamFloatValue(1));
}
TEST(MimeTypeTest, GetParamStringValueWithIndex) {
diff --git a/src/starboard/shared/starboard/player/closure.h b/src/starboard/shared/starboard/player/closure.h
index 96e2b4e..3ae7bae 100644
--- a/src/starboard/shared/starboard/player/closure.h
+++ b/src/starboard/shared/starboard/player/closure.h
@@ -117,6 +117,23 @@
return Closure(new FunctorImpl(func, obj, param));
}
+template <typename C, typename Param>
+inline Closure Bind(void (C::*func)(const Param&), C* obj, const Param& param) {
+ class FunctorImpl : public Closure::Functor {
+ public:
+ FunctorImpl(void (C::*func)(const Param&), C* obj, const Param& param)
+ : func_(func), obj_(obj), param_(param) {}
+
+ void Run() SB_OVERRIDE { ((*obj_).*func_)(param_); }
+
+ private:
+ void (C::*func_)(const Param&);
+ C* obj_;
+ Param param_;
+ };
+ return Closure(new FunctorImpl(func, obj, param));
+}
+
template <typename C, typename Param1, typename Param2>
inline Closure Bind(void (C::*func)(Param1, Param2),
C* obj,
diff --git a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
index dadbe57..f3159e6 100644
--- a/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_decoder_internal.h
@@ -15,8 +15,7 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_DECODER_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_DECODER_INTERNAL_H_
-#include <vector>
-
+#include "starboard/common/ref_counted.h"
#include "starboard/media.h"
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/closure.h"
@@ -52,7 +51,7 @@
// |consumed_cb|.
// Note that |consumed_cb| is always called asynchronously on the calling job
// queue.
- virtual void Decode(const InputBuffer& input_buffer,
+ virtual void Decode(const scoped_refptr<InputBuffer>& input_buffer,
const Closure& consumed_cb) = 0;
// Notice the object that there is no more input data unless Reset() is
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
index 29fc319..598f725 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.cc
@@ -115,12 +115,14 @@
}
}
-void AudioRendererImpl::WriteSample(const InputBuffer& input_buffer) {
+void AudioRendererImpl::WriteSample(
+ const scoped_refptr<InputBuffer>& input_buffer) {
SB_DCHECK(BelongsToCurrentThread());
+ SB_DCHECK(input_buffer);
SB_DCHECK(can_accept_more_data_);
if (eos_state_.load() >= kEOSWrittenToDecoder) {
- SB_LOG(ERROR) << "Appending audio sample at " << input_buffer.pts()
+ SB_LOG(ERROR) << "Appending audio sample at " << input_buffer->pts()
<< " after EOS reached.";
return;
}
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
index f908fd8..d9278da 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h
@@ -52,7 +52,7 @@
const SbMediaAudioHeader& audio_header);
~AudioRendererImpl() SB_OVERRIDE;
- void WriteSample(const InputBuffer& input_buffer) SB_OVERRIDE;
+ void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) SB_OVERRIDE;
void WriteEndOfStream() SB_OVERRIDE;
void Play() SB_OVERRIDE;
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
index 5737d57..517c3ef 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_impl_internal_test.cc
@@ -71,11 +71,11 @@
GetDefaultAudioHeader()));
}
- void WriteSample(InputBuffer input_buffer) {
- ASSERT_TRUE(input_buffer.is_valid());
+ void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) {
+ ASSERT_TRUE(input_buffer != NULL);
ASSERT_FALSE(consumed_cb_.is_valid());
- buffers_in_decoder_.insert(input_buffer.data());
+ buffers_in_decoder_.insert(input_buffer->data());
EXPECT_CALL(*audio_decoder_, Decode(input_buffer, _))
.WillOnce(SaveArg<1>(&consumed_cb_));
audio_renderer_->WriteSample(input_buffer);
@@ -111,11 +111,11 @@
job_queue_.RunUntilIdle();
}
- InputBuffer CreateInputBuffer(SbMediaTime pts) {
+ scoped_refptr<InputBuffer> CreateInputBuffer(SbMediaTime pts) {
const int kInputBufferSize = 4;
- return InputBuffer(kSbMediaTypeAudio, DeallocateSampleCB, NULL, this,
- SbMemoryAllocate(kInputBufferSize), kInputBufferSize,
- pts, NULL, NULL);
+ return new InputBuffer(kSbMediaTypeAudio, DeallocateSampleCB, NULL, this,
+ SbMemoryAllocate(kInputBufferSize), kInputBufferSize,
+ pts, NULL, NULL);
}
scoped_refptr<DecodedAudio> CreateDecodedAudio(SbMediaTime pts, int frames) {
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
index ccb12a7..1c192c1 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
@@ -15,8 +15,7 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_H_
-#include <vector>
-
+#include "starboard/common/ref_counted.h"
#include "starboard/media.h"
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
@@ -32,7 +31,7 @@
public:
virtual ~AudioRenderer() {}
- virtual void WriteSample(const InputBuffer& input_buffer) = 0;
+ virtual void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) = 0;
virtual void WriteEndOfStream() = 0;
virtual void Play() = 0;
virtual void Pause() = 0;
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 556c96c..a57c6ac 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -160,8 +160,10 @@
return true;
}
-bool FilterBasedPlayerWorkerHandler::WriteSample(InputBuffer input_buffer,
- bool* written) {
+bool FilterBasedPlayerWorkerHandler::WriteSample(
+ const scoped_refptr<InputBuffer>& input_buffer,
+ bool* written) {
+ SB_DCHECK(input_buffer);
SB_DCHECK(job_queue_->BelongsToCurrentThread());
SB_DCHECK(written != NULL);
@@ -171,7 +173,7 @@
*written = true;
- if (input_buffer.sample_type() == kSbMediaTypeAudio) {
+ if (input_buffer->sample_type() == kSbMediaTypeAudio) {
if (audio_renderer_->IsEndOfStreamWritten()) {
SB_LOG(WARNING) << "Try to write audio sample after EOS is reached";
} else {
@@ -180,11 +182,11 @@
return true;
}
- if (input_buffer.drm_info()) {
+ if (input_buffer->drm_info()) {
if (!SbDrmSystemIsValid(drm_system_)) {
return false;
}
- if (drm_system_->Decrypt(&input_buffer) == SbDrmSystemPrivate::kRetry) {
+ if (drm_system_->Decrypt(input_buffer) == SbDrmSystemPrivate::kRetry) {
*written = false;
return true;
}
@@ -192,7 +194,7 @@
audio_renderer_->WriteSample(input_buffer);
}
} else {
- SB_DCHECK(input_buffer.sample_type() == kSbMediaTypeVideo);
+ SB_DCHECK(input_buffer->sample_type() == kSbMediaTypeVideo);
if (video_renderer_->IsEndOfStreamWritten()) {
SB_LOG(WARNING) << "Try to write video sample after EOS is reached";
} else {
@@ -200,11 +202,11 @@
*written = false;
return true;
}
- if (input_buffer.drm_info()) {
+ if (input_buffer->drm_info()) {
if (!SbDrmSystemIsValid(drm_system_)) {
return false;
}
- if (drm_system_->Decrypt(&input_buffer) == SbDrmSystemPrivate::kRetry) {
+ if (drm_system_->Decrypt(input_buffer) == SbDrmSystemPrivate::kRetry) {
*written = false;
return true;
}
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
index 610c4e1..0ec1a3d 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
@@ -60,7 +60,8 @@
GetPlayerStateCB get_player_state_cb,
UpdatePlayerStateCB update_player_state_cb) SB_OVERRIDE;
bool Seek(SbMediaTime seek_to_pts, int ticket) SB_OVERRIDE;
- bool WriteSample(InputBuffer input_buffer, bool* written) SB_OVERRIDE;
+ bool WriteSample(const scoped_refptr<InputBuffer>& input_buffer,
+ bool* written) SB_OVERRIDE;
bool WriteEndOfStream(SbMediaType sample_type) SB_OVERRIDE;
bool SetPause(bool pause) SB_OVERRIDE;
#if SB_API_VERSION >= 4
diff --git a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
index d1726c2..4558d8e 100644
--- a/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
+++ b/src/starboard/shared/starboard/player/filter/mock_audio_decoder.h
@@ -19,6 +19,7 @@
#include "testing/gmock/include/gmock/gmock.h"
+#include "starboard/common/ref_counted.h"
#include "starboard/media.h"
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/closure.h"
@@ -43,7 +44,7 @@
samples_per_second_(sample_per_second) {}
MOCK_METHOD1(Initialize, void(const Closure&));
- MOCK_METHOD2(Decode, void(const InputBuffer&, const Closure&));
+ MOCK_METHOD2(Decode, void(const scoped_refptr<InputBuffer>&, const Closure&));
MOCK_METHOD0(WriteEndOfStream, void());
MOCK_METHOD0(Read, scoped_refptr<DecodedAudio>());
MOCK_METHOD0(Reset, void());
diff --git a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
index 0d3728d..f4bc6f6 100644
--- a/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/stub_player_components_impl.cc
@@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/shared/starboard/player/filter/player_components.h"
-
#include <queue>
+#include "starboard/common/ref_counted.h"
+#include "starboard/log.h"
#include "starboard/shared/starboard/player/closure.h"
#include "starboard/shared/starboard/player/filter/audio_renderer_impl_internal.h"
+#include "starboard/shared/starboard/player/filter/player_components.h"
#include "starboard/shared/starboard/player/filter/video_renderer_impl_internal.h"
#include "starboard/shared/starboard/player/job_queue.h"
@@ -40,17 +41,21 @@
} // namespace
-class StubAudioDecoder : public AudioDecoder, JobQueue::JobOwner {
+class StubAudioDecoder : public AudioDecoder, private JobQueue::JobOwner {
public:
explicit StubAudioDecoder(const SbMediaAudioHeader& audio_header)
: sample_type_(GetSupportedSampleType()),
audio_header_(audio_header),
stream_ended_(false) {}
+
void Initialize(const Closure& output_cb) SB_OVERRIDE {
output_cb_ = output_cb;
}
- void Decode(const InputBuffer& input_buffer,
+
+ void Decode(const scoped_refptr<InputBuffer>& input_buffer,
const Closure& consumed_cb) SB_OVERRIDE {
+ SB_DCHECK(input_buffer);
+
// Values to represent what kind of dummy audio to fill the decoded audio
// we produce with.
enum FillType {
@@ -60,13 +65,18 @@
// Can be set locally to fill with different types.
const FillType fill_type = kSilence;
- if (last_input_buffer_.is_valid()) {
- SbMediaTime diff = input_buffer.pts() - last_input_buffer_.pts();
+ if (last_input_buffer_) {
+ SbMediaTime diff = input_buffer->pts() - last_input_buffer_->pts();
+ SB_DCHECK(diff >= 0);
size_t sample_size =
GetSampleType() == kSbMediaAudioSampleTypeInt16 ? 2 : 4;
size_t size = diff * GetSamplesPerSecond() * sample_size *
audio_header_.number_of_channels / kSbMediaTimeSecond;
- decoded_audios_.push(new DecodedAudio(input_buffer.pts(), size));
+ size += size % (sample_size * audio_header_.number_of_channels);
+
+ decoded_audios_.push(new DecodedAudio(audio_header_.number_of_channels,
+ GetSampleType(), GetStorageType(),
+ input_buffer->pts(), size));
if (fill_type == kSilence) {
SbMemorySet(decoded_audios_.back()->buffer(), 0, size);
@@ -83,22 +93,31 @@
}
}
}
+ Schedule(output_cb_);
}
- last_input_buffer_ = input_buffer;
Schedule(consumed_cb);
- Schedule(output_cb_);
+ last_input_buffer_ = input_buffer;
}
+
void WriteEndOfStream() SB_OVERRIDE {
- if (last_input_buffer_.is_valid()) {
+ if (last_input_buffer_) {
// There won't be a next pts, so just guess that the decoded size is
// 4 times the encoded size.
- decoded_audios_.push(new DecodedAudio(last_input_buffer_.pts(),
- 4 * last_input_buffer_.size()));
+ size_t fake_size = 4 * last_input_buffer_->size();
+ size_t sample_size =
+ GetSampleType() == kSbMediaAudioSampleTypeInt16 ? 2 : 4;
+ fake_size += fake_size % (sample_size * audio_header_.number_of_channels);
+
+ decoded_audios_.push(new DecodedAudio(
+ audio_header_.number_of_channels, GetSampleType(), GetStorageType(),
+ last_input_buffer_->pts(), fake_size));
+ Schedule(output_cb_);
}
decoded_audios_.push(new DecodedAudio());
stream_ended_ = true;
Schedule(output_cb_);
}
+
scoped_refptr<DecodedAudio> Read() SB_OVERRIDE {
scoped_refptr<DecodedAudio> result;
if (!decoded_audios_.empty()) {
@@ -107,43 +126,44 @@
}
return result;
}
+
void Reset() SB_OVERRIDE {
while (!decoded_audios_.empty()) {
decoded_audios_.pop();
}
stream_ended_ = false;
- last_input_buffer_ = InputBuffer();
+ last_input_buffer_ = NULL;
CancelPendingJobs();
}
SbMediaAudioSampleType GetSampleType() const SB_OVERRIDE {
return sample_type_;
}
+ SbMediaAudioFrameStorageType GetStorageType() const SB_OVERRIDE {
+ return kSbMediaAudioFrameStorageTypeInterleaved;
+ }
int GetSamplesPerSecond() const SB_OVERRIDE {
return audio_header_.samples_per_second;
}
- bool CanAcceptMoreData() const SB_OVERRIDE {
- return !stream_ended_ && decoded_audios_.size() <= kMaxDecodedAudiosSize;
- }
private:
- static const kMaxDecodedAudiosSize = 64;
-
Closure output_cb_;
SbMediaAudioSampleType sample_type_;
SbMediaAudioHeader audio_header_;
bool stream_ended_;
std::queue<scoped_refptr<DecodedAudio> > decoded_audios_;
- InputBuffer last_input_buffer_;
+ scoped_refptr<InputBuffer> last_input_buffer_;
};
class StubVideoDecoder : public HostedVideoDecoder {
public:
StubVideoDecoder() : host_(NULL) {}
- void WriteInputBuffer(const InputBuffer& input_buffer) SB_OVERRIDE {
+ void WriteInputBuffer(const scoped_refptr<InputBuffer>& input_buffer)
+ SB_OVERRIDE {
+ SB_DCHECK(input_buffer);
SB_DCHECK(host_ != NULL);
host_->OnDecoderStatusUpdate(
- kNeedMoreInput, VideoFrame::CreateEmptyFrame(input_buffer.pts()));
+ kNeedMoreInput, VideoFrame::CreateEmptyFrame(input_buffer->pts()));
}
void WriteEndOfStream() SB_OVERRIDE {
SB_DCHECK(host_ != NULL);
@@ -177,8 +197,7 @@
new StubAudioDecoder(audio_parameters.audio_header);
StubVideoDecoder* video_decoder = new StubVideoDecoder();
AudioRendererImpl* audio_renderer =
- new AudioRendererImpl(audio_parameters.job_queue,
- scoped_ptr<AudioDecoder>(audio_decoder).Pass(),
+ new AudioRendererImpl(scoped_ptr<AudioDecoder>(audio_decoder).Pass(),
audio_parameters.audio_header);
VideoRendererImpl* video_renderer = new VideoRendererImpl(
scoped_ptr<HostedVideoDecoder>(video_decoder).Pass());
diff --git a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
index 6dcce32..a8c8952 100644
--- a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
@@ -15,6 +15,7 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_DECODER_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_DECODER_INTERNAL_H_
+#include "starboard/common/ref_counted.h"
#include "starboard/player.h"
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
@@ -35,7 +36,8 @@
virtual ~VideoDecoder() {}
// Send encoded video frame stored in |input_buffer| to decode.
- virtual void WriteInputBuffer(const InputBuffer& input_buffer) = 0;
+ virtual void WriteInputBuffer(
+ const scoped_refptr<InputBuffer>& input_buffer) = 0;
// Note that there won't be more input data unless Reset() is called.
// OnDecoderStatusUpdate will still be called on Host during flushing until
// the |frame| is an EOS frame.
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
index fb8e940..ffd6aca 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
@@ -34,11 +34,13 @@
decoder_->SetHost(this);
}
-void VideoRendererImpl::WriteSample(const InputBuffer& input_buffer) {
+void VideoRendererImpl::WriteSample(
+ const scoped_refptr<InputBuffer>& input_buffer) {
SB_DCHECK(thread_checker_.CalledOnValidThread());
+ SB_DCHECK(input_buffer);
if (end_of_stream_written_) {
- SB_LOG(ERROR) << "Appending video sample at " << input_buffer.pts()
+ SB_LOG(ERROR) << "Appending video sample at " << input_buffer->pts()
<< " after EOS reached.";
return;
}
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
index e0ca1a2..b40365e 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
@@ -17,7 +17,7 @@
#include <list>
-#include "starboard/common/scoped_ptr.h"
+#include "starboard/common/ref_counted.h"
#include "starboard/log.h"
#include "starboard/media.h"
#include "starboard/mutex.h"
@@ -44,7 +44,7 @@
int GetDroppedFrames() const SB_OVERRIDE { return dropped_frames_; }
- void WriteSample(const InputBuffer& input_buffer) SB_OVERRIDE;
+ void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) SB_OVERRIDE;
void WriteEndOfStream() SB_OVERRIDE;
void Seek(SbMediaTime seek_to_pts) SB_OVERRIDE;
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
index df3beef..cffa6de 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -15,7 +15,7 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_H_
-#include "starboard/common/scoped_ptr.h"
+#include "starboard/common/ref_counted.h"
#include "starboard/log.h"
#include "starboard/media.h"
#include "starboard/mutex.h"
@@ -36,7 +36,7 @@
virtual ~VideoRenderer() {}
virtual int GetDroppedFrames() const = 0;
- virtual void WriteSample(const InputBuffer& input_buffer) = 0;
+ virtual void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) = 0;
virtual void WriteEndOfStream() = 0;
virtual void Seek(SbMediaTime seek_to_pts) = 0;
virtual scoped_refptr<VideoFrame> GetCurrentFrame(SbMediaTime media_time) = 0;
diff --git a/src/starboard/shared/starboard/player/input_buffer_internal.cc b/src/starboard/shared/starboard/player/input_buffer_internal.cc
index 9c44224..968f002 100644
--- a/src/starboard/shared/starboard/player/input_buffer_internal.cc
+++ b/src/starboard/shared/starboard/player/input_buffer_internal.cc
@@ -15,9 +15,7 @@
#include "starboard/shared/starboard/player/input_buffer_internal.h"
#include <numeric>
-#include <vector>
-#include "starboard/atomic.h"
#include "starboard/log.h"
#include "starboard/memory.h"
@@ -26,171 +24,6 @@
namespace starboard {
namespace player {
-class InputBuffer::ReferenceCountedBuffer {
- public:
- ReferenceCountedBuffer(SbMediaType sample_type,
- SbPlayerDeallocateSampleFunc deallocate_sample_func,
- SbPlayer player,
- void* context,
- const void* sample_buffer,
- int sample_buffer_size,
- SbMediaTime sample_pts,
- const SbMediaVideoSampleInfo* video_sample_info,
- const SbDrmSampleInfo* sample_drm_info)
- : ref_count_(0),
- sample_type_(sample_type),
- deallocate_sample_func_(deallocate_sample_func),
- player_(player),
- context_(context),
- data_(static_cast<const uint8_t*>(sample_buffer)),
- size_(sample_buffer_size),
- pts_(sample_pts) {
- SB_DCHECK(deallocate_sample_func);
- TryToAssignVideoSampleInfo(video_sample_info);
- TryToAssignDrmSampleInfo(sample_drm_info);
- }
-
- ReferenceCountedBuffer(SbMediaType sample_type,
- SbPlayerDeallocateSampleFunc deallocate_sample_func,
- SbPlayer player,
- void* context,
- const void** sample_buffers,
- int* sample_buffer_sizes,
- int number_of_sample_buffers,
- SbMediaTime sample_pts,
- const SbMediaVideoSampleInfo* video_sample_info,
- const SbDrmSampleInfo* sample_drm_info)
- : ref_count_(0),
- sample_type_(sample_type),
- deallocate_sample_func_(deallocate_sample_func),
- player_(player),
- context_(context),
- pts_(sample_pts) {
- SB_DCHECK(deallocate_sample_func);
- SB_DCHECK(number_of_sample_buffers > 0);
-
- TryToAssignVideoSampleInfo(video_sample_info);
- TryToAssignDrmSampleInfo(sample_drm_info);
-
- if (number_of_sample_buffers == 1) {
- data_ = static_cast<const uint8_t*>(sample_buffers[0]);
- size_ = sample_buffer_sizes[0];
- } else if (number_of_sample_buffers > 1) {
- // TODO: This simply concatenating multi-part buffers into one large
- // buffer. It serves the purpose to test the Cobalt media code work with
- // multi-part sample buffer but we should proper implement InputBuffer to
- // ensure that the concatenating of multi-part buffers is handled inside
- // the renderers or the decoders so the SbPlayer implementation won't use
- // too much memory.
- size_ =
- std::accumulate(sample_buffer_sizes,
- sample_buffer_sizes + number_of_sample_buffers, 0);
- flattened_data_.reserve(size_);
- for (int i = 0; i < number_of_sample_buffers; ++i) {
- const uint8_t* data = static_cast<const uint8_t*>(sample_buffers[i]);
- flattened_data_.insert(flattened_data_.end(), data,
- data + sample_buffer_sizes[i]);
- }
- DeallocateSampleBuffer(sample_buffers[0]);
- data_ = flattened_data_.data();
- }
- }
-
- void AddRef() const { SbAtomicBarrier_Increment(&ref_count_, 1); }
- void Release() const {
- if (SbAtomicBarrier_Increment(&ref_count_, -1) == 0) {
- delete this;
- }
- }
-
- SbMediaType sample_type() const { return sample_type_; }
- const uint8_t* data() const { return data_; }
- int size() const { return size_; }
- SbMediaTime pts() const { return pts_; }
- const SbMediaVideoSampleInfo* video_sample_info() const {
- return has_video_sample_info_ ? &video_sample_info_ : NULL;
- }
- const SbDrmSampleInfo* drm_info() const {
- return has_drm_info_ ? &drm_info_ : NULL;
- }
- void SetDecryptedContent(const void* buffer, int size) {
- SB_DCHECK(size == size_);
- DeallocateSampleBuffer(data_);
-
- if (size > 0) {
- flattened_data_.resize(size);
- SbMemoryCopy(flattened_data_.data(), buffer, size);
- data_ = flattened_data_.data();
- } else {
- data_ = NULL;
- }
- size_ = size;
- has_drm_info_ = false;
- }
-
- private:
- ~ReferenceCountedBuffer() { DeallocateSampleBuffer(data_); }
-
- void TryToAssignVideoSampleInfo(
- const SbMediaVideoSampleInfo* video_sample_info) {
- has_video_sample_info_ = video_sample_info != NULL;
-
- if (!has_video_sample_info_) {
- return;
- }
-
- video_sample_info_ = *video_sample_info;
- if (video_sample_info_.color_metadata) {
- color_metadata_ = *video_sample_info_.color_metadata;
- video_sample_info_.color_metadata = &color_metadata_;
- } else {
- video_sample_info_.color_metadata = NULL;
- }
- }
- void TryToAssignDrmSampleInfo(const SbDrmSampleInfo* sample_drm_info) {
- has_drm_info_ = sample_drm_info != NULL;
-
- if (!has_drm_info_) {
- return;
- }
-
- SB_DCHECK(sample_drm_info->subsample_count > 0);
-
- subsamples_.assign(
- sample_drm_info->subsample_mapping,
- sample_drm_info->subsample_mapping + sample_drm_info->subsample_count);
- drm_info_ = *sample_drm_info;
- drm_info_.subsample_mapping = subsamples_.empty() ? NULL : &subsamples_[0];
- }
-
- void DeallocateSampleBuffer(const void* buffer) {
- if (deallocate_sample_func_) {
- deallocate_sample_func_(player_, context_, buffer);
- deallocate_sample_func_ = NULL;
- }
- }
-
- mutable SbAtomic32 ref_count_;
- SbMediaType sample_type_;
- SbPlayerDeallocateSampleFunc deallocate_sample_func_;
- SbPlayer player_;
- void* context_;
- const uint8_t* data_;
- int size_;
- SbMediaTime pts_;
- bool has_video_sample_info_;
- SbMediaColorMetadata color_metadata_;
- SbMediaVideoSampleInfo video_sample_info_;
- bool has_drm_info_;
- SbDrmSampleInfo drm_info_;
- std::vector<uint8_t> flattened_data_;
- std::vector<SbDrmSubSampleMapping> subsamples_;
-
- SB_DISALLOW_COPY_AND_ASSIGN(ReferenceCountedBuffer);
-};
-
-InputBuffer::InputBuffer() : buffer_(NULL) {}
-
InputBuffer::InputBuffer(SbMediaType sample_type,
SbPlayerDeallocateSampleFunc deallocate_sample_func,
SbPlayer player,
@@ -199,107 +32,121 @@
int sample_buffer_size,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
- const SbDrmSampleInfo* sample_drm_info) {
- buffer_ = new ReferenceCountedBuffer(
- sample_type, deallocate_sample_func, player, context, sample_buffer,
- sample_buffer_size, sample_pts, video_sample_info, sample_drm_info);
- buffer_->AddRef();
+ const SbDrmSampleInfo* sample_drm_info)
+ : sample_type_(sample_type),
+ deallocate_sample_func_(deallocate_sample_func),
+ player_(player),
+ context_(context),
+ data_(static_cast<const uint8_t*>(sample_buffer)),
+ size_(sample_buffer_size),
+ pts_(sample_pts) {
+ SB_DCHECK(deallocate_sample_func);
+ TryToAssignVideoSampleInfo(video_sample_info);
+ TryToAssignDrmSampleInfo(sample_drm_info);
}
InputBuffer::InputBuffer(SbMediaType sample_type,
SbPlayerDeallocateSampleFunc deallocate_sample_func,
SbPlayer player,
void* context,
- const void** sample_buffers,
- int* sample_buffer_sizes,
+ const void* const* sample_buffers,
+ const int* sample_buffer_sizes,
int number_of_sample_buffers,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
- const SbDrmSampleInfo* sample_drm_info) {
- buffer_ = new ReferenceCountedBuffer(
- sample_type, deallocate_sample_func, player, context, sample_buffers,
- sample_buffer_sizes, number_of_sample_buffers, sample_pts,
- video_sample_info, sample_drm_info);
- buffer_->AddRef();
-}
+ const SbDrmSampleInfo* sample_drm_info)
+ : sample_type_(sample_type),
+ deallocate_sample_func_(deallocate_sample_func),
+ player_(player),
+ context_(context),
+ pts_(sample_pts) {
+ SB_DCHECK(deallocate_sample_func);
+ SB_DCHECK(number_of_sample_buffers > 0);
-InputBuffer::InputBuffer(const InputBuffer& that) {
- buffer_ = that.buffer_;
- if (buffer_) {
- buffer_->AddRef();
+ TryToAssignVideoSampleInfo(video_sample_info);
+ TryToAssignDrmSampleInfo(sample_drm_info);
+
+ if (number_of_sample_buffers == 1) {
+ data_ = static_cast<const uint8_t*>(sample_buffers[0]);
+ size_ = sample_buffer_sizes[0];
+ } else if (number_of_sample_buffers > 1) {
+ // TODO: This simply concatenating multi-part buffers into one large
+ // buffer. It serves the purpose to test the Cobalt media code work with
+ // multi-part sample buffer but we should proper implement InputBuffer to
+ // ensure that the concatenating of multi-part buffers is handled inside
+ // the renderers or the decoders so the SbPlayer implementation won't use
+ // too much memory.
+ size_ = std::accumulate(sample_buffer_sizes,
+ sample_buffer_sizes + number_of_sample_buffers, 0);
+ flattened_data_.reserve(size_);
+ for (int i = 0; i < number_of_sample_buffers; ++i) {
+ const uint8_t* data = static_cast<const uint8_t*>(sample_buffers[i]);
+ flattened_data_.insert(flattened_data_.end(), data,
+ data + sample_buffer_sizes[i]);
+ }
+ DeallocateSampleBuffer(sample_buffers[0]);
+ data_ = flattened_data_.data();
}
}
InputBuffer::~InputBuffer() {
- reset();
-}
-
-InputBuffer& InputBuffer::operator=(const InputBuffer& that) {
- if (that.buffer_) {
- that.buffer_->AddRef();
- }
- if (buffer_) {
- buffer_->Release();
- }
- buffer_ = that.buffer_;
-
- return *this;
-}
-
-void InputBuffer::reset() {
- if (buffer_) {
- buffer_->Release();
- buffer_ = NULL;
- }
-}
-
-SbMediaType InputBuffer::sample_type() const {
- SB_DCHECK(buffer_);
- return buffer_->sample_type();
-}
-
-const uint8_t* InputBuffer::data() const {
- SB_DCHECK(buffer_);
- return buffer_->data();
-}
-
-int InputBuffer::size() const {
- SB_DCHECK(buffer_);
- return buffer_->size();
-}
-
-SbMediaTime InputBuffer::pts() const {
- SB_DCHECK(buffer_);
- return buffer_->pts();
-}
-
-const SbMediaVideoSampleInfo* InputBuffer::video_sample_info() const {
- SB_DCHECK(buffer_);
- return buffer_->video_sample_info();
-}
-
-const SbDrmSampleInfo* InputBuffer::drm_info() const {
- SB_DCHECK(buffer_);
- return buffer_->drm_info();
+ DeallocateSampleBuffer(data_);
}
void InputBuffer::SetDecryptedContent(const void* buffer, int size) {
- SB_DCHECK(buffer_);
- buffer_->SetDecryptedContent(buffer, size);
+ SB_DCHECK(size == size_);
+ DeallocateSampleBuffer(data_);
+
+ if (size > 0) {
+ flattened_data_.resize(size);
+ SbMemoryCopy(flattened_data_.data(), buffer, size);
+ data_ = flattened_data_.data();
+ } else {
+ data_ = NULL;
+ }
+ size_ = size;
+ has_drm_info_ = false;
}
-bool operator==(const InputBuffer& lhs, const InputBuffer& rhs) {
- if (!lhs.is_valid() && !rhs.is_valid()) {
- return true;
- }
- if (lhs.is_valid() && rhs.is_valid()) {
- return lhs.sample_type() == rhs.sample_type() && lhs.data() == rhs.data() &&
- lhs.size() == rhs.size() && lhs.pts() == rhs.pts() &&
- lhs.video_sample_info() == rhs.video_sample_info() &&
- lhs.drm_info() == rhs.drm_info();
+void InputBuffer::TryToAssignVideoSampleInfo(
+ const SbMediaVideoSampleInfo* video_sample_info) {
+ has_video_sample_info_ = video_sample_info != NULL;
+
+ if (!has_video_sample_info_) {
+ return;
}
- return false;
+ video_sample_info_ = *video_sample_info;
+ if (video_sample_info_.color_metadata) {
+ color_metadata_ = *video_sample_info_.color_metadata;
+ video_sample_info_.color_metadata = &color_metadata_;
+ } else {
+ video_sample_info_.color_metadata = NULL;
+ }
+}
+
+void InputBuffer::TryToAssignDrmSampleInfo(
+ const SbDrmSampleInfo* sample_drm_info) {
+ has_drm_info_ = sample_drm_info != NULL;
+
+ if (!has_drm_info_) {
+ return;
+ }
+
+ SB_DCHECK(sample_drm_info->subsample_count > 0);
+
+ subsamples_.assign(
+ sample_drm_info->subsample_mapping,
+ sample_drm_info->subsample_mapping + sample_drm_info->subsample_count);
+ drm_info_ = *sample_drm_info;
+ drm_info_.subsample_mapping = subsamples_.empty() ? NULL : &subsamples_[0];
+}
+
+void InputBuffer::DeallocateSampleBuffer(const void* buffer) {
+ if (deallocate_sample_func_) {
+ deallocate_sample_func_(player_, context_, buffer);
+ deallocate_sample_func_ = NULL;
+ }
}
} // namespace player
diff --git a/src/starboard/shared/starboard/player/input_buffer_internal.h b/src/starboard/shared/starboard/player/input_buffer_internal.h
index 5c45e78..05ca16a 100644
--- a/src/starboard/shared/starboard/player/input_buffer_internal.h
+++ b/src/starboard/shared/starboard/player/input_buffer_internal.h
@@ -15,6 +15,9 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_INPUT_BUFFER_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_INPUT_BUFFER_INTERNAL_H_
+#include <vector>
+
+#include "starboard/common/ref_counted.h"
#include "starboard/drm.h"
#include "starboard/media.h"
#include "starboard/player.h"
@@ -25,14 +28,9 @@
namespace starboard {
namespace player {
-// This class encapsulate a media buffer. It holds a reference-counted object
-// internally to ensure that the object of this class can be copied while the
-// underlying resources allocated is properly managed.
-// Note that pass this class as const reference doesn't guarantee that the
-// content of the internal buffer won't be changed.
-class InputBuffer {
+// This class encapsulate a media buffer.
+class InputBuffer : public RefCountedThreadSafe<InputBuffer> {
public:
- InputBuffer();
InputBuffer(SbMediaType sample_type,
SbPlayerDeallocateSampleFunc deallocate_sample_func,
SbPlayer player,
@@ -46,36 +44,50 @@
SbPlayerDeallocateSampleFunc deallocate_sample_func,
SbPlayer player,
void* context,
- const void** sample_buffers,
- int* sample_buffer_sizes,
+ const void* const* sample_buffers,
+ const int* sample_buffer_sizes,
int number_of_sample_buffers,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
const SbDrmSampleInfo* sample_drm_info);
- InputBuffer(const InputBuffer& that);
~InputBuffer();
- InputBuffer& operator=(const InputBuffer& that);
-
- bool is_valid() const { return buffer_ != NULL; }
- void reset();
-
- SbMediaType sample_type() const;
- const uint8_t* data() const;
- int size() const;
- SbMediaTime pts() const;
- const SbMediaVideoSampleInfo* video_sample_info() const;
- const SbDrmSampleInfo* drm_info() const;
+ SbMediaType sample_type() const { return sample_type_; }
+ const uint8_t* data() const { return data_; }
+ int size() const { return size_; }
+ SbMediaTime pts() const { return pts_; }
+ const SbMediaVideoSampleInfo* video_sample_info() const {
+ return has_video_sample_info_ ? &video_sample_info_ : NULL;
+ }
+ const SbDrmSampleInfo* drm_info() const {
+ return has_drm_info_ ? &drm_info_ : NULL;
+ }
void SetDecryptedContent(const void* buffer, int size);
private:
- class ReferenceCountedBuffer;
+ void TryToAssignVideoSampleInfo(
+ const SbMediaVideoSampleInfo* video_sample_info);
+ void TryToAssignDrmSampleInfo(const SbDrmSampleInfo* sample_drm_info);
+ void DeallocateSampleBuffer(const void* buffer);
- ReferenceCountedBuffer* buffer_;
+ SbMediaType sample_type_;
+ SbPlayerDeallocateSampleFunc deallocate_sample_func_;
+ SbPlayer player_;
+ void* context_;
+ const uint8_t* data_;
+ int size_;
+ SbMediaTime pts_;
+ bool has_video_sample_info_;
+ SbMediaColorMetadata color_metadata_;
+ SbMediaVideoSampleInfo video_sample_info_;
+ bool has_drm_info_;
+ SbDrmSampleInfo drm_info_;
+ std::vector<uint8_t> flattened_data_;
+ std::vector<SbDrmSubSampleMapping> subsamples_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(InputBuffer);
};
-bool operator==(const InputBuffer& lhs, const InputBuffer& rhs);
-
} // namespace player
} // namespace starboard
} // namespace shared
diff --git a/src/starboard/shared/starboard/player/player_create.cc b/src/starboard/shared/starboard/player/player_create.cc
index 5c83020..25dfe9b 100644
--- a/src/starboard/shared/starboard/player/player_create.cc
+++ b/src/starboard/shared/starboard/player/player_create.cc
@@ -17,6 +17,7 @@
#include "starboard/configuration.h"
#include "starboard/decode_target.h"
#include "starboard/log.h"
+#include "starboard/shared/media_session/playback_state.h"
#if SB_API_VERSION >= 4
#include "starboard/shared/starboard/media/media_support_internal.h"
#endif // SB_API_VERSION >= 4
@@ -24,6 +25,9 @@
#include "starboard/shared/starboard/player/player_internal.h"
#include "starboard/shared/starboard/player/player_worker.h"
+using starboard::shared::media_session::
+ UpdateActiveSessionPlatformPlaybackState;
+using starboard::shared::media_session::kPlaying;
using starboard::shared::starboard::player::filter::
FilterBasedPlayerWorkerHandler;
using starboard::shared::starboard::player::PlayerWorker;
@@ -89,6 +93,8 @@
}
#endif // SB_API_VERSION >= 4
+ UpdateActiveSessionPlatformPlaybackState(kPlaying);
+
#if SB_API_VERSION >= 4
starboard::scoped_ptr<PlayerWorker::Handler> handler(
new FilterBasedPlayerWorkerHandler(video_codec, audio_codec, drm_system,
diff --git a/src/starboard/shared/starboard/player/player_destroy.cc b/src/starboard/shared/starboard/player/player_destroy.cc
index a0f9947..e1ed31a 100644
--- a/src/starboard/shared/starboard/player/player_destroy.cc
+++ b/src/starboard/shared/starboard/player/player_destroy.cc
@@ -14,11 +14,17 @@
#include "starboard/player.h"
+#include "starboard/shared/media_session/playback_state.h"
#include "starboard/shared/starboard/player/player_internal.h"
+using starboard::shared::media_session::kNone;
+using starboard::shared::media_session::
+ UpdateActiveSessionPlatformPlaybackState;
+
void SbPlayerDestroy(SbPlayer player) {
if (!SbPlayerIsValid(player)) {
return;
}
+ UpdateActiveSessionPlatformPlaybackState(kNone);
delete player;
}
diff --git a/src/starboard/shared/starboard/player/player_internal.cc b/src/starboard/shared/starboard/player/player_internal.cc
index 5fe32f8..20268ea 100644
--- a/src/starboard/shared/starboard/player/player_internal.cc
+++ b/src/starboard/shared/starboard/player/player_internal.cc
@@ -72,8 +72,8 @@
void SbPlayerPrivate::WriteSample(
SbMediaType sample_type,
- const void** sample_buffers,
- int* sample_buffer_sizes,
+ const void* const* sample_buffers,
+ const int* sample_buffer_sizes,
int number_of_sample_buffers,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
@@ -81,10 +81,10 @@
if (sample_type == kSbMediaTypeVideo) {
++total_video_frames_;
}
- InputBuffer input_buffer(sample_type, sample_deallocate_func_, this, context_,
- sample_buffers, sample_buffer_sizes,
- number_of_sample_buffers, sample_pts,
- video_sample_info, sample_drm_info);
+ starboard::scoped_refptr<InputBuffer> input_buffer = new InputBuffer(
+ sample_type, sample_deallocate_func_, this, context_, sample_buffers,
+ sample_buffer_sizes, number_of_sample_buffers, sample_pts,
+ video_sample_info, sample_drm_info);
worker_->WriteSample(input_buffer);
}
diff --git a/src/starboard/shared/starboard/player/player_internal.h b/src/starboard/shared/starboard/player/player_internal.h
index 6eb3d4b..fdb3d09 100644
--- a/src/starboard/shared/starboard/player/player_internal.h
+++ b/src/starboard/shared/starboard/player/player_internal.h
@@ -39,8 +39,8 @@
void Seek(SbMediaTime seek_to_pts, int ticket);
void WriteSample(SbMediaType sample_type,
- const void** sample_buffers,
- int* sample_buffer_sizes,
+ const void* const* sample_buffers,
+ const int* sample_buffer_sizes,
int number_of_sample_buffers,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
diff --git a/src/starboard/shared/starboard/player/player_set_playback_rate.cc b/src/starboard/shared/starboard/player/player_set_playback_rate.cc
index 7928293..aaf96d1 100644
--- a/src/starboard/shared/starboard/player/player_set_playback_rate.cc
+++ b/src/starboard/shared/starboard/player/player_set_playback_rate.cc
@@ -15,8 +15,14 @@
#include "starboard/player.h"
#include "starboard/log.h"
+#include "starboard/shared/media_session/playback_state.h"
#include "starboard/shared/starboard/player/player_internal.h"
+using starboard::shared::media_session::kPaused;
+using starboard::shared::media_session::kPlaying;
+using starboard::shared::media_session::
+ UpdateActiveSessionPlatformPlaybackState;
+
#if SB_API_VERSION >= 4
bool SbPlayerSetPlaybackRate(SbPlayer player, double playback_rate) {
@@ -30,6 +36,8 @@
return false;
}
player->SetPlaybackRate(playback_rate);
+ bool paused = (playback_rate == 0.0);
+ UpdateActiveSessionPlatformPlaybackState(paused ? kPaused : kPlaying);
return true;
}
diff --git a/src/starboard/shared/starboard/player/player_worker.cc b/src/starboard/shared/starboard/player/player_worker.cc
index b9ba48a..38a0a25 100644
--- a/src/starboard/shared/starboard/player/player_worker.cc
+++ b/src/starboard/shared/starboard/player/player_worker.cc
@@ -26,6 +26,13 @@
namespace {
+// 8 ms is enough to ensure that DoWritePendingSamples() is called twice for
+// every frame in HFR.
+// TODO: Reduce this as there should be enough frames caches in the renderers.
+// Also this should be configurable for platforms with very limited video
+// backlogs.
+const SbTimeMonotonic kWritePendingSampleDelay = 8 * kSbTimeMillisecond;
+
struct ThreadParam {
explicit ThreadParam(PlayerWorker* player_worker)
: condition_variable(mutex), player_worker(player_worker) {}
@@ -140,8 +147,8 @@
job_queue_->Remove(write_pending_sample_closure_);
write_pending_sample_closure_.reset();
}
- pending_audio_buffer_.reset();
- pending_video_buffer_.reset();
+ pending_audio_buffer_ = NULL;
+ pending_video_buffer_ = NULL;
if (!handler_->Seek(seek_to_pts, ticket)) {
UpdatePlayerState(kSbPlayerStateError);
@@ -155,8 +162,10 @@
UpdateDecoderState(kSbMediaTypeVideo, kSbPlayerDecoderStateNeedsData);
}
-void PlayerWorker::DoWriteSample(InputBuffer input_buffer) {
+void PlayerWorker::DoWriteSample(
+ const scoped_refptr<InputBuffer>& input_buffer) {
SB_DCHECK(job_queue_->BelongsToCurrentThread());
+ SB_DCHECK(input_buffer);
if (player_state_ == kSbPlayerStateInitialized ||
player_state_ == kSbPlayerStateEndOfStream ||
@@ -167,10 +176,10 @@
return;
}
- if (input_buffer.sample_type() == kSbMediaTypeAudio) {
- SB_DCHECK(!pending_audio_buffer_.is_valid());
+ if (input_buffer->sample_type() == kSbMediaTypeAudio) {
+ SB_DCHECK(!pending_audio_buffer_);
} else {
- SB_DCHECK(!pending_video_buffer_.is_valid());
+ SB_DCHECK(!pending_video_buffer_);
}
bool written;
bool result = handler_->WriteSample(input_buffer, &written);
@@ -179,10 +188,10 @@
return;
}
if (written) {
- UpdateDecoderState(input_buffer.sample_type(),
+ UpdateDecoderState(input_buffer->sample_type(),
kSbPlayerDecoderStateNeedsData);
} else {
- if (input_buffer.sample_type() == kSbMediaTypeAudio) {
+ if (input_buffer->sample_type() == kSbMediaTypeAudio) {
pending_audio_buffer_ = input_buffer;
} else {
pending_video_buffer_ = input_buffer;
@@ -190,7 +199,8 @@
if (!write_pending_sample_closure_.is_valid()) {
write_pending_sample_closure_ =
Bind(&PlayerWorker::DoWritePendingSamples, this);
- job_queue_->Schedule(write_pending_sample_closure_);
+ job_queue_->Schedule(write_pending_sample_closure_,
+ kWritePendingSampleDelay);
}
}
}
@@ -200,10 +210,10 @@
SB_DCHECK(write_pending_sample_closure_.is_valid());
write_pending_sample_closure_.reset();
- if (pending_audio_buffer_.is_valid()) {
+ if (pending_audio_buffer_) {
DoWriteSample(common::ResetAndReturn(&pending_audio_buffer_));
}
- if (pending_video_buffer_.is_valid()) {
+ if (pending_video_buffer_) {
DoWriteSample(common::ResetAndReturn(&pending_video_buffer_));
}
}
@@ -223,9 +233,9 @@
}
if (sample_type == kSbMediaTypeAudio) {
- SB_DCHECK(!pending_audio_buffer_.is_valid());
+ SB_DCHECK(!pending_audio_buffer_);
} else {
- SB_DCHECK(!pending_video_buffer_.is_valid());
+ SB_DCHECK(!pending_video_buffer_);
}
if (!handler_->WriteEndOfStream(sample_type)) {
diff --git a/src/starboard/shared/starboard/player/player_worker.h b/src/starboard/shared/starboard/player/player_worker.h
index eeade17..a1d9333 100644
--- a/src/starboard/shared/starboard/player/player_worker.h
+++ b/src/starboard/shared/starboard/player/player_worker.h
@@ -15,6 +15,7 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_PLAYER_WORKER_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_PLAYER_WORKER_H_
+#include "starboard/common/ref_counted.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/log.h"
#include "starboard/media.h"
@@ -75,7 +76,8 @@
GetPlayerStateCB get_player_state_cb,
UpdatePlayerStateCB update_player_state_cb) = 0;
virtual bool Seek(SbMediaTime seek_to_pts, int ticket) = 0;
- virtual bool WriteSample(InputBuffer input_buffer, bool* written) = 0;
+ virtual bool WriteSample(const scoped_refptr<InputBuffer>& input_buffer,
+ bool* written) = 0;
virtual bool WriteEndOfStream(SbMediaType sample_type) = 0;
virtual bool SetPause(bool pause) = 0;
#if SB_API_VERSION >= 4
@@ -106,7 +108,7 @@
Bind(&PlayerWorker::DoSeek, this, seek_to_pts, ticket));
}
- void WriteSample(InputBuffer input_buffer) {
+ void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) {
job_queue_->Schedule(
Bind(&PlayerWorker::DoWriteSample, this, input_buffer));
}
@@ -165,7 +167,7 @@
void RunLoop();
void DoInit();
void DoSeek(SbMediaTime seek_to_pts, int ticket);
- void DoWriteSample(InputBuffer input_buffer);
+ void DoWriteSample(const scoped_refptr<InputBuffer>& input_buffer);
void DoWritePendingSamples();
void DoWriteEndOfStream(SbMediaType sample_type);
#if SB_API_VERSION >= 4 || SB_IS(PLAYER_PUNCHED_OUT)
@@ -192,8 +194,8 @@
int ticket_;
SbPlayerState player_state_;
- InputBuffer pending_audio_buffer_;
- InputBuffer pending_video_buffer_;
+ scoped_refptr<InputBuffer> pending_audio_buffer_;
+ scoped_refptr<InputBuffer> pending_video_buffer_;
Closure write_pending_sample_closure_;
};
diff --git a/src/starboard/shared/starboard/player/player_write_sample.cc b/src/starboard/shared/starboard/player/player_write_sample.cc
index a92797b..5fd3ca5 100644
--- a/src/starboard/shared/starboard/player/player_write_sample.cc
+++ b/src/starboard/shared/starboard/player/player_write_sample.cc
@@ -21,8 +21,13 @@
void SbPlayerWriteSample(SbPlayer player,
SbMediaType sample_type,
+#if SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
+ const void* const* sample_buffers,
+ const int* sample_buffer_sizes,
+#else // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
const void** sample_buffers,
int* sample_buffer_sizes,
+#endif // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
int number_of_sample_buffers,
SbMediaTime sample_pts,
const SbMediaVideoSampleInfo* video_sample_info,
diff --git a/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc b/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
index 34a9b16..f84e3dc 100644
--- a/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
+++ b/src/starboard/shared/stub/media_can_play_mime_and_key_system.cc
@@ -16,5 +16,7 @@
SbMediaSupportType SbMediaCanPlayMimeAndKeySystem(const char* mime,
const char* key_system) {
+ SB_UNREFERENCED_PARAMETER(mime);
+ SB_UNREFERENCED_PARAMETER(key_system);
return kSbMediaSupportTypeNotSupported;
}
diff --git a/src/starboard/shared/stub/media_get_audio_configuration.cc b/src/starboard/shared/stub/media_get_audio_configuration.cc
index c2e9d8a..b28c9d1 100644
--- a/src/starboard/shared/stub/media_get_audio_configuration.cc
+++ b/src/starboard/shared/stub/media_get_audio_configuration.cc
@@ -17,5 +17,7 @@
bool SbMediaGetAudioConfiguration(
int output_index,
SbMediaAudioConfiguration* out_configuration) {
+ SB_UNREFERENCED_PARAMETER(output_index);
+ SB_UNREFERENCED_PARAMETER(out_configuration);
return false;
}
diff --git a/src/starboard/shared/stub/player_create.cc b/src/starboard/shared/stub/player_create.cc
index 0a0bf62..a91e304 100644
--- a/src/starboard/shared/stub/player_create.cc
+++ b/src/starboard/shared/stub/player_create.cc
@@ -30,7 +30,7 @@
void* /*context*/
#if SB_API_VERSION >= 4
,
- SbPlayerOutputMode output_mode,
+ SbPlayerOutputMode /*output_mode*/,
SbDecodeTargetGraphicsContextProvider* /*provider*/
#elif SB_API_VERSION >= 3
,
diff --git a/src/starboard/shared/stub/player_write_sample.cc b/src/starboard/shared/stub/player_write_sample.cc
index 1fd2d52..0450efd 100644
--- a/src/starboard/shared/stub/player_write_sample.cc
+++ b/src/starboard/shared/stub/player_write_sample.cc
@@ -18,12 +18,18 @@
void SbPlayerWriteSample(SbPlayer /*player*/,
SbMediaType /*sample_type*/,
+#if SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
+ const void* const* /*sample_buffers*/,
+ const int* /*sample_buffer_sizes*/,
+#else // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
const void** /*sample_buffers*/,
int* /*sample_buffer_sizes*/,
+#endif // SB_API_VERSION >= SB_PLAYER_WRITE_SAMPLE_EXTRA_CONST_API_VERSION
int /*number_of_sample_buffers*/,
SbMediaTime /*sample_pts*/,
const SbMediaVideoSampleInfo* /*video_sample_info*/,
- const SbDrmSampleInfo* /*sample_drm_info*/) {}
+ const SbDrmSampleInfo* /*sample_drm_info*/) {
+}
#else // SB_API_VERSION >= 4
diff --git a/src/starboard/shared/uwp/application_uwp.cc b/src/starboard/shared/uwp/application_uwp.cc
index f7c44e1..6aa337e 100644
--- a/src/starboard/shared/uwp/application_uwp.cc
+++ b/src/starboard/shared/uwp/application_uwp.cc
@@ -83,7 +83,7 @@
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
-// Parses a starboard: URI scheme by splitting args at ';' boundries.
+// Parses a starboard: URI scheme by splitting args at ';' boundaries.
std::vector<std::string> ParseStarboardUri(const std::string& uri) {
std::vector<std::string> result;
result.push_back(GetArgvZero());
@@ -210,8 +210,7 @@
App() : previously_activated_(false) {}
// IFrameworkView methods.
- virtual void Initialize(
- CoreApplicationView^ applicationView) {
+ virtual void Initialize(CoreApplicationView^ applicationView) {
SbAudioSinkPrivate::Initialize();
CoreApplication::Suspending +=
ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
@@ -313,10 +312,10 @@
}
} else if (args->Kind == ActivationKind::DialReceiver) {
if (!previously_activated_) {
- DialReceiverActivatedEventArgs ^ dial_args =
- dynamic_cast<DialReceiverActivatedEventArgs ^>(args);
+ DialReceiverActivatedEventArgs^ dial_args =
+ dynamic_cast<DialReceiverActivatedEventArgs^>(args);
SB_CHECK(dial_args);
- Platform::String ^ arguments = dial_args->Arguments;
+ Platform::String^ arguments = dial_args->Arguments;
std::string activation_args =
kYouTubeTVurl + sbwin32::platformStringToString(arguments);
SB_DLOG(INFO) << "Dial Activation url: " << activation_args;
@@ -558,11 +557,15 @@
SB_CHECK(LOBYTE(wsaData.wVersion) == kWinSockVersionMajor &&
HIBYTE(wsaData.wVersion) == kWinSockVersionMinor);
+ HRESULT hr = MFStartup(MF_VERSION);
+ SB_DCHECK(SUCCEEDED(hr));
+
starboard::shared::win32::RegisterMainThread();
auto direct3DApplicationSource = ref new Direct3DApplicationSource();
CoreApplication::Run(direct3DApplicationSource);
+ MFShutdown();
WSACleanup();
return main_return_value;
diff --git a/src/starboard/shared/uwp/cobalt/cobalt_platform.gyp b/src/starboard/shared/uwp/cobalt/cobalt_platform.gyp
index 9da1070..e7206c0 100644
--- a/src/starboard/shared/uwp/cobalt/cobalt_platform.gyp
+++ b/src/starboard/shared/uwp/cobalt/cobalt_platform.gyp
@@ -21,8 +21,16 @@
'target_name': 'cobalt_platform',
'type': 'static_library',
'sources': [
+ 'xb1_media_session_client.cc',
+ 'xb1_media_session_client.h',
+ 'xb1_media_session_updates.cc',
+ 'xb1_media_session_button_press.cc',
+ 'xb1_media_session_button_press.h',
'xhr_modify_headers.cc',
],
+ 'dependencies': [
+ '<(DEPTH)/cobalt/media_session/media_session.gyp:media_session',
+ ],
'msvs_settings': {
'VCCLCompilerTool': {
'AdditionalOptions': [
diff --git a/src/starboard/shared/uwp/window_internal.cc b/src/starboard/shared/uwp/window_internal.cc
index 0b34b01..5363628 100644
--- a/src/starboard/shared/uwp/window_internal.cc
+++ b/src/starboard/shared/uwp/window_internal.cc
@@ -25,9 +25,7 @@
// 1080 video, but perhaps 4k UI where applicable.
SbWindowPrivate::SbWindowPrivate(const SbWindowOptions* /*options*/)
: width(1920),
- height(1080),
- output_width(1920),
- output_height(1080) {
+ height(1080) {
egl_native_window_ = reinterpret_cast<EGLNativeWindowType>(
starboard::shared::uwp::ApplicationUwp::Get()->GetCoreWindow().Get());
}
diff --git a/src/starboard/shared/uwp/window_internal.h b/src/starboard/shared/uwp/window_internal.h
index ef0777e..583774b 100644
--- a/src/starboard/shared/uwp/window_internal.h
+++ b/src/starboard/shared/uwp/window_internal.h
@@ -25,16 +25,6 @@
explicit SbWindowPrivate(const SbWindowOptions* options);
~SbWindowPrivate();
- // Wait for the next video out vblank event.
- void WaitForVBlank();
-
- // Get the process time of the latest video out vblank event.
- SbTime GetVBlankProcessTime();
-
- // Get the video out refresh rate with the provided pointer. Return value
- // indicates success.
- bool GetRefreshRate(uint64_t* refresh_rate);
-
EGLNativeWindowType egl_native_window() const { return egl_native_window_; }
// The width of this window.
@@ -43,25 +33,8 @@
// The height of this window.
int height;
- // The actual output resolution width.
- int output_width;
-
- // The actual output resolution height.
- int output_height;
-
private:
EGLNativeWindowType egl_native_window_;
-
- // Open and Initialize the video output port.
- void SetupVideo();
-
- // Close the video output port.
- void ShutdownVideo();
-
- // TODO: Ensure this gets called when the output resolution may have changed,
- // such as when resuming after suspend.
- // Retrieve the width and height from the video output resolution.
- void RefreshOutputResolution();
};
#endif // STARBOARD_SHARED_UWP_WINDOW_INTERNAL_H_
diff --git a/src/starboard/starboard.gyp b/src/starboard/starboard.gyp
index c7de30b..83c284b 100644
--- a/src/starboard/starboard.gyp
+++ b/src/starboard/starboard.gyp
@@ -59,6 +59,7 @@
'types.h',
'user.h',
'window.h',
+ '<(DEPTH)/starboard/shared/media_session/playback_state.h',
# Include private headers, if present.
'<!@(python "<(DEPTH)/starboard/tools/find_private_files.py" "<(DEPTH)" "*.h")',
],
diff --git a/src/starboard/stub/application_stub.cc b/src/starboard/stub/application_stub.cc
index 20614d9..c54bff5 100644
--- a/src/starboard/stub/application_stub.cc
+++ b/src/starboard/stub/application_stub.cc
@@ -42,6 +42,7 @@
shared::starboard::Application::Event*
ApplicationStub::WaitForSystemEventWithTimeout(SbTime time) {
+ SB_UNREFERENCED_PARAMETER(time);
return NULL;
}
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp
index 7dfd774..a95ca89 100644
--- a/src/starboard/stub/starboard_platform.gyp
+++ b/src/starboard/stub/starboard_platform.gyp
@@ -24,6 +24,7 @@
'<(DEPTH)/starboard/shared/starboard/event_schedule.cc',
'<(DEPTH)/starboard/shared/starboard/file_mode_string_to_flags.cc',
'<(DEPTH)/starboard/shared/starboard/log_message.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/stub_player_components_impl.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.cc',
'<(DEPTH)/starboard/shared/stub/accessibility_get_display_settings.cc',
'<(DEPTH)/starboard/shared/stub/accessibility_get_text_to_speech_settings.cc',
@@ -145,8 +146,8 @@
'<(DEPTH)/starboard/shared/stub/socket_create.cc',
'<(DEPTH)/starboard/shared/stub/socket_destroy.cc',
'<(DEPTH)/starboard/shared/stub/socket_free_resolution.cc',
- '<(DEPTH)/starboard/shared/stub/socket_get_last_error.cc',
'<(DEPTH)/starboard/shared/stub/socket_get_interface_address.cc',
+ '<(DEPTH)/starboard/shared/stub/socket_get_last_error.cc',
'<(DEPTH)/starboard/shared/stub/socket_get_local_address.cc',
'<(DEPTH)/starboard/shared/stub/socket_get_local_interface_address.cc',
'<(DEPTH)/starboard/shared/stub/socket_is_connected.cc',
diff --git a/src/starboard/win/console/starboard_platform.gyp b/src/starboard/win/console/starboard_platform.gyp
index ac1558d..343eec3 100644
--- a/src/starboard/win/console/starboard_platform.gyp
+++ b/src/starboard/win/console/starboard_platform.gyp
@@ -23,12 +23,12 @@
'../shared/system_get_path.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.h',
+ '<(DEPTH)/starboard/shared/starboard/system_request_pause.cc',
+ '<(DEPTH)/starboard/shared/starboard/system_request_stop.cc',
+ '<(DEPTH)/starboard/shared/starboard/system_request_suspend.cc',
+ '<(DEPTH)/starboard/shared/starboard/system_request_unpause.cc',
'<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
'<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
- '<(DEPTH)/starboard/shared/stub/system_request_pause.cc',
- '<(DEPTH)/starboard/shared/stub/system_request_stop.cc',
- '<(DEPTH)/starboard/shared/stub/system_request_suspend.cc',
- '<(DEPTH)/starboard/shared/stub/system_request_unpause.cc',
'<(DEPTH)/starboard/shared/stub/window_create.cc',
'<(DEPTH)/starboard/shared/stub/window_destroy.cc',
'<(DEPTH)/starboard/shared/stub/window_get_platform_handle.cc',
diff --git a/src/starboard/win/shared/gyp_configuration.gypi b/src/starboard/win/shared/gyp_configuration.gypi
index cee97a6..32823bc 100644
--- a/src/starboard/win/shared/gyp_configuration.gypi
+++ b/src/starboard/win/shared/gyp_configuration.gypi
@@ -161,6 +161,14 @@
'EnableCOMDATFolding' : '2', # OPT:ICF
},
},
+ 'msvs_disabled_warnings': [
+ # Unreferenced argument.
+ # Often variables are only referenced in DCHECKs.
+ 4100,
+ # Unreferenced variable.
+ # Often variables are only referenced in DCHECKs.
+ 4189,
+ ],
},
'msvs_gold': {
'inherit_from': ['gold_base', 'msvs_base'],
@@ -177,6 +185,14 @@
'EnableCOMDATFolding' : '2', # OPT:ICF
},
},
+ 'msvs_disabled_warnings': [
+ # Unreferenced argument.
+ # Often variables are only referenced in DCHECKs.
+ 4100,
+ # Unreferenced variable.
+ # Often variables are only referenced in DCHECKs.
+ 4189,
+ ],
},
},
'defines': [
@@ -224,7 +240,7 @@
'MinimalRebuild': 'false',
# Treat warnings as errors.
- 'WarnAsError': 'false',
+ 'WarnAsError': 'true',
# Enable some warnings, even those that are disabled by default.
# See https://msdn.microsoft.com/en-us/library/23k5d385.aspx
@@ -234,7 +250,6 @@
'/errorReport:none', # Don't send error reports to MS.
'/permissive-', # Visual C++ conformance mode.
'/FS', # Force sync PDB updates for parallel compile.
- '/w14389', # Turn on warnings for signed/unsigned mismatch.
],
},
'VCLinkerTool': {
@@ -267,13 +282,18 @@
# Triggers in many legitimate cases, like branching on a constant declared
# in type traits.
4127,
+ # 4244 (Level 2) - Implicit conversion from float to int
+ # 4244 (Level 3) - Implicit conversion from int to something smaller
+ # than int.
+ # 4244 (Level 4) - Implicit conversion of types, which may result in
+ # data loss.
+ 4244,
# Class has virtual functions, but destructor is not virtual.
# Far less useful than in GCC because doesn't take into account the fact
# that destructor is not public.
4265,
- # no function prototype given: converting '()' to '(void)'.
- # We do not care.
- 4255,
+ # Inconsistent DLL linkage
+ 4273,
# cast truncates constant value.
# We do not care.
4310,
diff --git a/src/starboard/win/shared/starboard_platform.gypi b/src/starboard/win/shared/starboard_platform.gypi
index 7c80fad..7307c9a 100644
--- a/src/starboard/win/shared/starboard_platform.gypi
+++ b/src/starboard/win/shared/starboard_platform.gypi
@@ -306,8 +306,8 @@
'__WRL_NO_DEFAULT_LIB__',
],
'dependencies': [
- 'convert_i18n_data'
- ]
+ 'convert_i18n_data',
+ ],
},
{
'target_name': 'convert_i18n_data',
diff --git a/src/testing/gtest.gyp b/src/testing/gtest.gyp
index 888ce5f..5cd741d 100644
--- a/src/testing/gtest.gyp
+++ b/src/testing/gtest.gyp
@@ -27,7 +27,6 @@
'gtest/include/gtest/internal/gtest-string.h',
'gtest/include/gtest/internal/gtest-tuple.h',
'gtest/include/gtest/internal/gtest-type-util.h',
- 'gtest/src/gtest-all.cc',
'gtest/src/gtest-death-test.cc',
'gtest/src/gtest-filepath.cc',
'gtest/src/gtest-internal-inl.h',
@@ -40,9 +39,6 @@
'multiprocess_func_list.h',
'platform_test.h',
],
- 'sources!': [
- 'gtest/src/gtest-all.cc', # Not needed by our build.
- ],
'include_dirs': [
'gtest',
'gtest/include',
diff --git a/src/third_party/freetype2/freetype2_cobalt.gyp b/src/third_party/freetype2/freetype2_cobalt.gyp
index 1ec9f02..0381b78 100644
--- a/src/third_party/freetype2/freetype2_cobalt.gyp
+++ b/src/third_party/freetype2/freetype2_cobalt.gyp
@@ -1,68 +1,79 @@
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
- 'variables': {
- 'ft2_dir': '<(DEPTH)/third_party/freetype2',
- },
- 'targets': [
- {
- 'target_name': 'freetype2',
- 'type': 'static_library',
- 'toolsets': ['target'],
- 'sources': [
- '<(ft2_dir)/src/autofit/autofit.c',
- '<(ft2_dir)/src/base/ftbase.c',
- '<(ft2_dir)/src/base/ftbbox.c',
- '<(ft2_dir)/src/base/ftbitmap.c',
- '<(ft2_dir)/src/base/ftfntfmt.c',
- '<(ft2_dir)/src/base/ftfstype.c',
- '<(ft2_dir)/src/base/ftgasp.c',
- '<(ft2_dir)/src/base/ftglyph.c',
- '<(ft2_dir)/src/base/ftinit.c',
- '<(ft2_dir)/src/base/ftlcdfil.c',
- '<(ft2_dir)/src/base/ftmm.c',
- '<(ft2_dir)/src/base/ftstroke.c',
- '<(ft2_dir)/src/base/ftsystem.c',
- '<(ft2_dir)/src/base/fttype1.c',
- '<(ft2_dir)/src/cff/cff.c',
- '<(ft2_dir)/src/gzip/ftgzip.c',
- '<(ft2_dir)/src/pshinter/pshinter.c',
- '<(ft2_dir)/src/psnames/psnames.c',
- '<(ft2_dir)/src/raster/raster.c',
- '<(ft2_dir)/src/sfnt/sfnt.c',
- '<(ft2_dir)/src/smooth/smooth.c',
- '<(ft2_dir)/src/truetype/truetype.c',
- ],
- 'defines': [
- 'FT_CONFIG_OPTION_SYSTEM_ZLIB',
- 'FT2_BUILD_LIBRARY',
- 'FT_CONFIG_CONFIG_H="ftconfig.h"',
- 'FT_CONFIG_MODULES_H="ftmodule.h"',
- 'FT_CONFIG_OPTIONS_H="ftoption.h"',
- ],
- 'include_dirs': [
- '<(ft2_dir)/include_cobalt',
- '<(ft2_dir)/include',
- ],
- 'dependencies': [
- '<(DEPTH)/third_party/libpng/libpng.gyp:libpng',
- '<(DEPTH)/third_party/zlib/zlib.gyp:zlib',
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [
- '<(ft2_dir)/include_cobalt',
- '<(ft2_dir)/include',
- ],
- 'defines': [
- 'FT_CONFIG_OPTION_SYSTEM_ZLIB',
- 'FT_CONFIG_CONFIG_H="ftconfig.h"',
- 'FT_CONFIG_MODULES_H="ftmodule.h"',
- 'FT_CONFIG_OPTIONS_H="ftoption.h"',
- ],
- },
- 'msvs_disabled_warnings': [4146],
- },
- ], # targets
-}
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'ft2_dir': '<(DEPTH)/third_party/freetype2',
+ },
+ 'targets': [
+ {
+ 'target_name': 'freetype2',
+ 'type': 'static_library',
+ 'toolsets': ['target'],
+ 'sources': [
+ '<(ft2_dir)/src/autofit/autofit.c',
+ '<(ft2_dir)/src/base/ftbase.c',
+ '<(ft2_dir)/src/base/ftbbox.c',
+ '<(ft2_dir)/src/base/ftbitmap.c',
+ '<(ft2_dir)/src/base/ftfntfmt.c',
+ '<(ft2_dir)/src/base/ftfstype.c',
+ '<(ft2_dir)/src/base/ftgasp.c',
+ '<(ft2_dir)/src/base/ftglyph.c',
+ '<(ft2_dir)/src/base/ftinit.c',
+ '<(ft2_dir)/src/base/ftlcdfil.c',
+ '<(ft2_dir)/src/base/ftmm.c',
+ '<(ft2_dir)/src/base/ftstroke.c',
+ '<(ft2_dir)/src/base/ftsystem.c',
+ '<(ft2_dir)/src/base/fttype1.c',
+ '<(ft2_dir)/src/cff/cff.c',
+ '<(ft2_dir)/src/gzip/ftgzip.c',
+ '<(ft2_dir)/src/pshinter/pshinter.c',
+ '<(ft2_dir)/src/psnames/psnames.c',
+ '<(ft2_dir)/src/raster/raster.c',
+ '<(ft2_dir)/src/sfnt/sfnt.c',
+ '<(ft2_dir)/src/smooth/smooth.c',
+ '<(ft2_dir)/src/truetype/truetype.c',
+ ],
+ 'defines': [
+ 'FT_CONFIG_OPTION_SYSTEM_ZLIB',
+ 'FT2_BUILD_LIBRARY',
+ 'FT_CONFIG_CONFIG_H="ftconfig.h"',
+ 'FT_CONFIG_MODULES_H="ftmodule.h"',
+ 'FT_CONFIG_OPTIONS_H="ftoption.h"',
+ ],
+ 'include_dirs': [
+ '<(ft2_dir)/include_cobalt',
+ '<(ft2_dir)/include',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/third_party/libpng/libpng.gyp:libpng',
+ '<(DEPTH)/third_party/zlib/zlib.gyp:zlib',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(ft2_dir)/include_cobalt',
+ '<(ft2_dir)/include',
+ ],
+ 'defines': [
+ 'FT_CONFIG_OPTION_SYSTEM_ZLIB',
+ 'FT_CONFIG_CONFIG_H="ftconfig.h"',
+ 'FT_CONFIG_MODULES_H="ftmodule.h"',
+ 'FT_CONFIG_OPTIONS_H="ftoption.h"',
+ ],
+ },
+ 'msvs_disabled_warnings': [
+ # Level 1 - Formal parameter 'number' is different from declaration.
+ 4028,
+ # Level 1 - Incompatible types conversion.
+ 4133,
+ # Level 2 - Unary minus operator applied to unsigned type; result is
+ # still unsigned.
+ 4146,
+ # Level 1 - Conversion from 'type1' to 'type2' of a greater size.
+ # Typically when 32-bit value is assigned to a 64-bit pointer value.
+ 4312,
+ ],
+ },
+ ], # targets
+}
diff --git a/src/third_party/harfbuzz-ng/harfbuzz.gyp b/src/third_party/harfbuzz-ng/harfbuzz.gyp
index ae2b33c..68d9a6d 100644
--- a/src/third_party/harfbuzz-ng/harfbuzz.gyp
+++ b/src/third_party/harfbuzz-ng/harfbuzz.gyp
@@ -150,7 +150,7 @@
# 4267: on amd64. size_t -> int, size_t -> unsigned int
# 4334: '<<' : result of 32-bit shift implicitly converted to 64
# bits (was 64-bit shift intended?)
- ['actual_target_arch=="win"', {
+ ['target_arch=="win"', {
'msvs_disabled_warnings': [4267, 4334],
}],
],
diff --git a/src/third_party/icu/icu.gyp b/src/third_party/icu/icu.gyp
index bad1c71..e89f9b7 100644
--- a/src/third_party/icu/icu.gyp
+++ b/src/third_party/icu/icu.gyp
@@ -10,16 +10,7 @@
'use_system_icu%': 0,
'icu_use_data_file_flag%': 0,
'want_separate_host_toolset%': 0,
- 'conditions': [
- # On Windows MSVS's library archive tool won't create an empty
- # library given zero object input. Therefore we set target type as
- # none. On other platforms use static_library.
- ['actual_target_arch=="win"', {
- 'icudata_target_type': 'none',
- }, {
- 'icudata_target_type': 'static_library',
- }],
- ],
+ 'icudata_target_type': 'static_library',
},
'target_defaults': {
'direct_dependent_settings': {
@@ -105,7 +96,7 @@
'source/common',
'source/i18n',
],
- 'msvs_disabled_warnings': [4005, 4068, 4355, 4996, 4267],
+ 'msvs_disabled_warnings': [4005, 4068, 4244, 4355, 4996, 4267],
},
'conditions': [
['use_system_icu==0 or want_separate_host_toolset==1', {
@@ -301,18 +292,11 @@
'-fno-builtin-sin',
],
}],
- ['OS=="lb_shell" or OS=="starboard"', {
+ ['OS=="starboard"', {
'defines': [
'U_HAVE_NL_LANGINFO_CODESET=0',
'U_HAVE_NL_LANGINFO=0'
],
- }],
- ['OS=="lb_shell"', {
- 'dependencies': [
- '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
- ],
- }],
- ['OS=="starboard"', {
'dependencies': [
'<(DEPTH)/starboard/starboard.gyp:starboard',
],
@@ -455,11 +439,6 @@
'-frtti',
],
}],
- ['OS=="lb_shell"', {
- 'dependencies': [
- '<(lbshell_root)/build/projects/posix_emulation.gyp:posix_emulation',
- ],
- }],
['OS=="starboard"', {
'dependencies': [
'<(DEPTH)/starboard/starboard.gyp:starboard',
diff --git a/src/third_party/libjpeg/jerror.c b/src/third_party/libjpeg/jerror.c
index 88a1434..cf7ac72 100644
--- a/src/third_party/libjpeg/jerror.c
+++ b/src/third_party/libjpeg/jerror.c
@@ -34,7 +34,7 @@
#include "starboard/system.h"
#define sprintf SbStringFormatUnsafeF
// Applications should not leave the standard error handler registered.
-#define exit(x) SbSystemBreakIntoDebugger
+#define exit(x) SbSystemBreakIntoDebugger(x)
#endif
#ifndef EXIT_FAILURE /* define exit() codes if not provided */
diff --git a/src/third_party/libpng/libpng.gyp b/src/third_party/libpng/libpng.gyp
index 2a20b6b..990cf87 100644
--- a/src/third_party/libpng/libpng.gyp
+++ b/src/third_party/libpng/libpng.gyp
@@ -60,6 +60,10 @@
'export_dependent_settings': [
'../zlib/zlib.gyp:zlib',
],
+ 'msvs_disabled_warnings': [
+ # Level 1 (but documentation says 3) - incompatible type conversion.
+ 4133,
+ ],
'conditions': [
['OS!="win"', {'product_name': 'png'}],
['OS=="win"', {
diff --git a/src/third_party/libxml/libxml.gyp b/src/third_party/libxml/libxml.gyp
index a1aaadd..86fe4a4 100644
--- a/src/third_party/libxml/libxml.gyp
+++ b/src/third_party/libxml/libxml.gyp
@@ -240,6 +240,20 @@
'src/include',
],
},
+ 'msvs_disabled_warnings': [
+ # Disable unimportant 'unused variable' warning.
+ # signed/unsigned comparison.
+ 4018,
+ # TODO(jschuh): http://crbug.com/167187 size_t -> int
+ 4267,
+ # TODO(brucedawson): http://crbug.com/554200 fix C4311 warnings
+ # C4311 is a VS 2015 64-bit warning for pointer truncation
+ 4311,
+ # Conversion from long (possibly 32-bit) to void*
+ 4312,
+ # Uninitialized local variable used.
+ 4700
+ ],
'conditions': [
['OS=="starboard" or OS=="lb_shell"', {
'dependencies!': [
@@ -260,22 +274,11 @@
# in chrome. On linux, this is picked up by transitivity from
# pkg-config output from build/linux/system.gyp.
['OS=="mac" or OS=="android"', {'defines': ['_REENTRANT']}],
- ['OS=="win"', {
+ ['target_arch=="win"', {
'product_name': 'libxml2',
- # Disable unimportant 'unused variable' warning.
- # TODO(jschuh): http://crbug.com/167187 size_t -> int
- # TODO(brucedawson): http://crbug.com/554200 fix C4311 warnings
- # C4311 is a VS 2015 64-bit warning for pointer truncation
- 'msvs_disabled_warnings': [ 4018, 4267, 4311, ],
}, { # else: OS!="win"
'product_name': 'xml2',
}],
- ['actual_target_arch=="win"', {
- # For Cobalt on Windows
- # 4018 - signed/unsigned comparison.
- # 4700 - uninitialized local variable used.
- 'msvs_disabled_warnings': [ 4018, 4700 ],
- }],
['clang == 1', {
'cflags': [
# libxml passes `const unsigned char*` through `const char*`.
diff --git a/src/third_party/mozjs-45/mozjs-45.gyp b/src/third_party/mozjs-45/mozjs-45.gyp
index 3cd5233..f331e80 100644
--- a/src/third_party/mozjs-45/mozjs-45.gyp
+++ b/src/third_party/mozjs-45/mozjs-45.gyp
@@ -104,7 +104,7 @@
}],
# TODO: Remove once ps4 configuration todos are addressed.
- ['target_arch == "ps4" or actual_target_arch == "ps4" or sb_target_platform == "ps4"', {
+ ['target_arch == "ps4" or sb_target_platform == "ps4"', {
'common_defines': [
'JS_CPU_X64=1',
'JS_CODEGEN_X64=1',
@@ -185,7 +185,7 @@
],
}],
# TODO: Remove "* == ps4" once ps4 configuration todos are addressed.
- ['target_arch == "x64" or target_arch == "ps4" or actual_target_arch == "ps4" or sb_target_platform == "ps4"', {
+ ['target_arch == "x64" or target_arch == "ps4" or sb_target_platform == "ps4"', {
'sources': [
'js/src/jit/x64/Assembler-x64.cpp',
'js/src/jit/x64/Bailouts-x64.cpp',
diff --git a/src/third_party/mozjs/mozjs.gyp b/src/third_party/mozjs/mozjs.gyp
index 0de26f2..9ba6a4b 100644
--- a/src/third_party/mozjs/mozjs.gyp
+++ b/src/third_party/mozjs/mozjs.gyp
@@ -42,10 +42,16 @@
'msvs_disabled_warnings': [
# Level 2, Typename first seen as 'type1', but then seen as 'type2'.
4099,
+ # Level 1 - Conversion from 'type1' to 'type2' of a greater size.
+ # Typically when 32-bit value is assigned to a 64-bit pointer value.
+ 4312,
# Level 2, Possible loss of data due to type conversion.
4244,
# Level 3, Possible loss of data due to type conversion from size_t.
4267,
+ # Level 1, No suitable definition provided for explicit template
+ # instantiation request.
+ 4661,
],
# Unfortunately, there is code that generate warnings in the headers.
'direct_dependent_settings': {
diff --git a/src/third_party/openssl/openssl.gyp b/src/third_party/openssl/openssl.gyp
index 27a29c3..ba790a5 100644
--- a/src/third_party/openssl/openssl.gyp
+++ b/src/third_party/openssl/openssl.gyp
@@ -569,6 +569,10 @@
'openssl/crypto/x509v3/v3_utl.c',
'openssl/crypto/x509v3/v3err.c',
],
+ 'msvs_disabled_warnings': [
+ # Level 1 - Pointer trunction warning.
+ 4311,
+ ],
'conditions': [
['os_posix==1 and OS!="android" and OS!="lb_shell"', {
'defines': [
diff --git a/src/third_party/openssl/openssl/crypto/sha/sha512.c b/src/third_party/openssl/openssl/crypto/sha/sha512.c
index 14a8597..11aaa2b 100644
--- a/src/third_party/openssl/openssl/crypto/sha/sha512.c
+++ b/src/third_party/openssl/openssl/crypto/sha/sha512.c
@@ -357,7 +357,7 @@
: "=r"(ret) \
: "r"(a),"K"(n)); ret; })
# endif
-# elif defined(_MSC_VER)
+# elif defined(_MSC_VER) && !defined(STARBOARD)
# if defined(_WIN64) /* applies to both IA-64 and AMD64 */
# pragma intrinsic(_rotr64)
# define ROTR(a,n) _rotr64((a),n)
diff --git a/src/third_party/ots/ots.gyp b/src/third_party/ots/ots.gyp
index 2827c21..03eda8c 100644
--- a/src/third_party/ots/ots.gyp
+++ b/src/third_party/ots/ots.gyp
@@ -27,14 +27,10 @@
'dependencies': [
'../zlib/zlib.gyp:zlib',
],
- 'conditions': [
- # Disable windows ots warnings:
- # 4334: '<<' : result of 32-bit shift implicitly converted to 64
- # bits (was 64-bit shift intended?)
- ['actual_target_arch=="win"', {
- 'msvs_disabled_warnings': [ 4334 ],
- }],
- ],
+ # Disable windows ots warnings:
+ # 4334: '<<' : result of 32-bit shift implicitly converted to 64
+ # bits (was 64-bit shift intended?)
+ 'msvs_disabled_warnings': [ 4334 ],
},
],
}
diff --git a/src/third_party/protobuf/protobuf.gyp b/src/third_party/protobuf/protobuf.gyp
index e985836..4e9a299 100644
--- a/src/third_party/protobuf/protobuf.gyp
+++ b/src/third_party/protobuf/protobuf.gyp
@@ -144,7 +144,7 @@
'src/google/protobuf/stubs/mathlimits.h',
'src/google/protobuf/stubs/substitute.cc',
'src/google/protobuf/stubs/substitute.h',
- 'src/google/protobuf/stubs/singleton$.h',
+ 'src/google/protobuf/stubs/singleton.h',
'src/google/protobuf/text_format.cc',
'src/google/protobuf/text_format.h',
'src/google/protobuf/timestamp.pb.cc',
diff --git a/src/third_party/protobuf/src/google/protobuf/stubs/strutil.cc b/src/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
index 296694c..688fabd 100644
--- a/src/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
+++ b/src/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
@@ -48,6 +48,7 @@
#include <google/protobuf/stubs/stl_util.h>
+#if !defined(STARBOARD)
#ifdef _WIN32
// MSVC has only _snprintf, not snprintf.
//
@@ -60,7 +61,8 @@
// occurs with some input values, not all. In any case, _snprintf does the
// right thing, so we use it.
#define snprintf _snprintf
-#endif
+#endif // _WIN32
+#endif // !defined(STARBOARD)
namespace google {
namespace protobuf {
diff --git a/src/third_party/skia/include/core/SkPixelRef.h b/src/third_party/skia/include/core/SkPixelRef.h
index 02d696e..abf5682 100644
--- a/src/third_party/skia/include/core/SkPixelRef.h
+++ b/src/third_party/skia/include/core/SkPixelRef.h
@@ -247,7 +247,8 @@
* not be created with the given config), or this PixelRef does not support deep
* copies.
*/
- virtual SkPixelRef* deepCopy(SkColorType colortype, const SkIRect* subset) {
+ virtual SkPixelRef* deepCopy(SkColorType /*colortype*/,
+ const SkIRect* /*subset*/) {
return NULL;
}
diff --git a/src/third_party/skia/src/ports/SkFontHost_FreeType.cpp b/src/third_party/skia/src/ports/SkFontHost_FreeType.cpp
index b0f8e10..4499dac 100644
--- a/src/third_party/skia/src/ports/SkFontHost_FreeType.cpp
+++ b/src/third_party/skia/src/ports/SkFontHost_FreeType.cpp
@@ -15,6 +15,7 @@
#include "SkFloatingPoint.h"
#include "SkFontHost.h"
#include "SkFontHost_FreeType_common.h"
+#include "SkFontStyle.h"
#include "SkGlyph.h"
#include "SkMask.h"
#include "SkMaskGamma.h"
@@ -26,6 +27,7 @@
#include "SkString.h"
#include "SkTemplates.h"
#include "SkThread.h"
+#include "SkTSearch.h"
#if defined(STARBOARD)
#include "starboard/log.h"
@@ -1703,8 +1705,56 @@
return false;
}
- int tempStyle = SkTypeface::kNormal;
+ int weight = SkFontStyle::kNormal_Weight;
if (face->style_flags & FT_STYLE_FLAG_BOLD) {
+ weight = SkFontStyle::kBold_Weight;
+ }
+
+ PS_FontInfoRec psFontInfo;
+ TT_OS2* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face, ft_sfnt_os2));
+ if (os2 && os2->version != 0xffff) {
+ weight = os2->usWeightClass;
+ } else if (0 == FT_Get_PS_Font_Info(face, &psFontInfo) && psFontInfo.weight) {
+ static const struct {
+ char const * const name;
+ int const weight;
+ } commonWeights [] = {
+ // There are probably more common names, but these are known to exist.
+ { "all", SkFontStyle::kNormal_Weight }, // Multiple Masters usually default to normal.
+ { "black", SkFontStyle::kBlack_Weight },
+ { "bold", SkFontStyle::kBold_Weight },
+ { "book", (SkFontStyle::kNormal_Weight + SkFontStyle::kLight_Weight)/2 },
+ { "demi", SkFontStyle::kSemiBold_Weight },
+ { "demibold", SkFontStyle::kSemiBold_Weight },
+ { "extra", SkFontStyle::kExtraBold_Weight },
+ { "extrabold", SkFontStyle::kExtraBold_Weight },
+ { "extralight", SkFontStyle::kExtraLight_Weight },
+ { "hairline", SkFontStyle::kThin_Weight },
+ { "heavy", SkFontStyle::kBlack_Weight },
+ { "light", SkFontStyle::kLight_Weight },
+ { "medium", SkFontStyle::kMedium_Weight },
+ { "normal", SkFontStyle::kNormal_Weight },
+ { "plain", SkFontStyle::kNormal_Weight },
+ { "regular", SkFontStyle::kNormal_Weight },
+ { "roman", SkFontStyle::kNormal_Weight },
+ { "semibold", SkFontStyle::kSemiBold_Weight },
+ { "standard", SkFontStyle::kNormal_Weight },
+ { "thin", SkFontStyle::kThin_Weight },
+ { "ultra", SkFontStyle::kExtraBold_Weight },
+ { "ultrabold", SkFontStyle::kExtraBold_Weight },
+ { "ultralight", SkFontStyle::kExtraLight_Weight },
+ };
+ int const index = SkStrLCSearch(&commonWeights[0].name, SK_ARRAY_COUNT(commonWeights),
+ psFontInfo.weight, sizeof(commonWeights[0]));
+ if (index >= 0) {
+ weight = commonWeights[index].weight;
+ } else {
+ SkDEBUGF(("Do not know weight for: %s (%s) \n", face->family_name, psFontInfo.weight));
+ }
+ }
+
+ int tempStyle = SkTypeface::kNormal;
+ if (weight > 500) {
tempStyle |= SkTypeface::kBold;
}
if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
diff --git a/src/tools/gyp/pylib/gyp/generator/ninja.py b/src/tools/gyp/pylib/gyp/generator/ninja.py
index 0a1887d..c8b973a 100755
--- a/src/tools/gyp/pylib/gyp/generator/ninja.py
+++ b/src/tools/gyp/pylib/gyp/generator/ninja.py
@@ -408,11 +408,17 @@
assert targets == filter(None, targets), targets
if len(targets) == 0:
return None
- if len(targets) > 1:
- stamp = self.GypPathToUniqueOutput(name + '.stamp')
- targets = self.ninja.build(stamp, 'stamp', targets)
- self.ninja.newline()
- return targets[0]
+ if len(targets) == 1:
+ return targets[0]
+
+ stamp = self.GypPathToUniqueOutput(name + '.stamp')
+ try:
+ raise NotImplementedError() # TODO: Implement the abstract toolchain.
+ except NotImplementedError:
+ # Fall back to the legacy toolchain.
+ self.ninja.build(stamp, 'stamp', targets)
+ self.ninja.newline()
+ return stamp
def WriteSpec(self, spec, config_name, generator_flags):
"""The main entry point for NinjaWriter: write the build rules for a spec.
@@ -520,7 +526,8 @@
self.GypPathToNinja(f) for f in sources if f.endswith(self.obj_ext)
]
- if self.flavor in microsoft_flavors and self.target.type == 'static_library':
+ if (self.flavor in microsoft_flavors and
+ self.target.type == 'static_library'):
self.target.component_objs = link_deps
# Write out a link step, if needed.
@@ -755,17 +762,21 @@
# Renormalize with the separator character of the os on which ninja will run
dst = self.path_module.normpath(dst)
- output = self.ninja.build(dst, 'copy', src, order_only=prebuild)
- if self.is_mac_bundle:
- # gyp has mac_bundle_resources to copy things into a bundle's
- # Resources folder, but there's no built-in way to copy files to other
- # places in the bundle. Hence, some targets use copies for this. Check
- # if this file is copied into the current bundle, and if so add it to
- # the bundle depends so that dependent targets get rebuilt if the copy
- # input changes.
- if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()):
- mac_bundle_depends.append(dst)
- return output
+ try:
+ raise NotImplementedError() # TODO: Implement the abstract toolchain.
+ except NotImplementedError:
+ # Fall back to the legacy toolchain.
+ self.ninja.build(dst, 'copy', src, order_only=prebuild)
+ if self.is_mac_bundle:
+ # gyp has mac_bundle_resources to copy things into a bundle's
+ # Resources folder, but there's no built-in way to copy files to other
+ # places in the bundle. Hence, some targets use copies for this. Check
+ # if this file is copied into the current bundle, and if so add it to
+ # the bundle depends so that dependent targets get rebuilt if the copy
+ # input changes.
+ if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()):
+ mac_bundle_depends.append(dst)
+ return [dst]
def WriteCopies(self, copies, prebuild, mac_bundle_depends):
outputs = []
@@ -847,157 +858,166 @@
def WriteSources(self, config_name, config, sources, predepends,
precompiled_header, spec):
"""Write build rules to compile all of |sources|."""
- if self.toolset == 'host':
- self.ninja.variable('ar', '$ar_host')
- self.ninja.variable('cc', '$cc_host')
- self.ninja.variable('cxx', '$cxx_host')
- self.ninja.variable('ld', '$ld_host')
- extra_defines = []
- if self.flavor == 'mac':
- cflags = self.xcode_settings.GetCflags(config_name)
- cflags_c = self.xcode_settings.GetCflagsC(config_name)
- cflags_cc = self.xcode_settings.GetCflagsCC(config_name)
- cflags_objc = ['$cflags_c'] + \
- self.xcode_settings.GetCflagsObjC(config_name)
- cflags_objcc = ['$cflags_cc'] + \
- self.xcode_settings.GetCflagsObjCC(config_name)
- elif GetToolchainOrNone(self.flavor):
- cflags = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetCflags(config_name)
- cflags_c = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetCflagsC(config_name)
- cflags_cc = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetCflagsCC(config_name)
- extra_defines = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetDefines(config_name)
- obj = 'obj'
- if self.toolset != 'target':
- obj += '.' + self.toolset
- pdbpath = os.path.normpath(
- os.path.join(obj, self.base_dir, self.name + '.pdb'))
- self.WriteVariableList('pdbname', [pdbpath])
- self.WriteVariableList('pchprefix', [self.name])
- else:
- cflags = config.get('cflags', [])
- cflags_c = config.get('cflags_c', [])
- cflags_cc = config.get('cflags_cc', [])
+ try:
+ raise NotImplementedError() # TODO: Implement the abstract toolchain.
+ except NotImplementedError:
+ # Fall back to the legacy toolchain.
- cflags_host = config.get('cflags_host', cflags)
- cflags_c_host = config.get('cflags_c_host', cflags_c)
- cflags_cc_host = config.get('cflags_cc_host', cflags_cc)
+ if self.toolset == 'host':
+ self.ninja.variable('ar', '$ar_host')
+ self.ninja.variable('cc', '$cc_host')
+ self.ninja.variable('cxx', '$cxx_host')
+ self.ninja.variable('ld', '$ld_host')
- defines = config.get('defines', []) + extra_defines
- if GetToolchainOrNone(self.flavor):
- self.WriteVariableList('defines', [
- GetToolchainOrNone(self.flavor).Define(d) for d in defines
- ])
- else:
- self.WriteVariableList('defines',
- [Define(d, self.flavor) for d in defines])
- if GetToolchainOrNone(self.flavor):
- self.WriteVariableList('rcflags', [
- QuoteShellArgument(self.ExpandSpecial(f), self.flavor)
- for f in GetToolchainOrNone(self.flavor).GetCompilerSettings()
- .GetRcFlags(config_name, self.GypPathToNinja)
- ])
-
- include_dirs = config.get('include_dirs', [])
- include_dirs += config.get('include_dirs_' + self.toolset, [])
-
- if GetToolchainOrNone(self.flavor):
- include_dirs = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().ProcessIncludeDirs(
- include_dirs, config_name)
- self.WriteVariableList('includes', [
- '/I' + GetToolchainOrNone(self.flavor).QuoteForRspFile(
- self.GypPathToNinja(i)) for i in include_dirs
- ])
- else:
- self.WriteVariableList('includes', [
- QuoteShellArgument('-I' + self.GypPathToNinja(i), self.flavor)
- for i in include_dirs
- ])
-
- pch_commands = precompiled_header.GetPchBuildCommands()
- if self.flavor == 'mac':
- self.WriteVariableList('cflags_pch_c',
- [precompiled_header.GetInclude('c')])
- self.WriteVariableList('cflags_pch_cc',
- [precompiled_header.GetInclude('cc')])
- self.WriteVariableList('cflags_pch_objc',
- [precompiled_header.GetInclude('m')])
- self.WriteVariableList('cflags_pch_objcc',
- [precompiled_header.GetInclude('mm')])
-
- self.WriteVariableList('cflags', map(self.ExpandSpecial, cflags))
- self.WriteVariableList('cflags_c', map(self.ExpandSpecial, cflags_c))
- self.WriteVariableList('cflags_cc', map(self.ExpandSpecial, cflags_cc))
-
- self.WriteVariableList('cflags_host', map(self.ExpandSpecial, cflags_host))
- self.WriteVariableList('cflags_c_host',
- map(self.ExpandSpecial, cflags_c_host))
- self.WriteVariableList('cflags_cc_host',
- map(self.ExpandSpecial, cflags_cc_host))
-
- if self.flavor == 'mac':
- self.WriteVariableList('cflags_objc', map(self.ExpandSpecial,
- cflags_objc))
- self.WriteVariableList('cflags_objcc',
- map(self.ExpandSpecial, cflags_objcc))
- self.ninja.newline()
- outputs = []
- for source in sources:
- filename, ext = os.path.splitext(source)
- ext = ext[1:]
- obj_ext = self.obj_ext
- if ext in ('cc', 'cpp', 'cxx'):
- command = 'cxx'
- elif ext == 'c' or (ext == 'S' and self.flavor != 'win'):
- command = 'cc'
- elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files.
- command = 'cc_s'
- elif (self.flavor == 'win' and ext == 'asm' and GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetArch(config_name) == 'x86' and
- not GetToolchainOrNone(
- self.flavor).GetCompilerSettings().HasExplicitAsmRules(spec)):
- # Asm files only get auto assembled for x86 (not x64).
- command = 'asm'
- # Add the _asm suffix as msvs is capable of handling .cc and
- # .asm files of the same name without collision.
- obj_ext = '_asm.obj'
- elif self.flavor == 'mac' and ext == 'm':
- command = 'objc'
- elif self.flavor == 'mac' and ext == 'mm':
- command = 'objcxx'
- elif self.flavor in microsoft_flavors and ext == 'rc':
- # TODO: Starboardize this.
- command = 'rc'
- obj_ext = '.res'
+ extra_defines = []
+ if self.flavor == 'mac':
+ cflags = self.xcode_settings.GetCflags(config_name)
+ cflags_c = self.xcode_settings.GetCflagsC(config_name)
+ cflags_cc = self.xcode_settings.GetCflagsCC(config_name)
+ cflags_objc = ['$cflags_c'] + \
+ self.xcode_settings.GetCflagsObjC(config_name)
+ cflags_objcc = ['$cflags_cc'] + \
+ self.xcode_settings.GetCflagsObjCC(config_name)
+ elif GetToolchainOrNone(self.flavor):
+ cflags = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetCflags(config_name)
+ cflags_c = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetCflagsC(config_name)
+ cflags_cc = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetCflagsCC(config_name)
+ extra_defines = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetDefines(config_name)
+ obj = 'obj'
+ if self.toolset != 'target':
+ obj += '.' + self.toolset
+ pdbpath = os.path.normpath(
+ os.path.join(obj, self.base_dir, self.name + '.pdb'))
+ self.WriteVariableList('pdbname', [pdbpath])
+ self.WriteVariableList('pchprefix', [self.name])
else:
- # Ignore unhandled extensions.
- continue
- if self.toolset != 'target':
- command += '_' + self.toolset
+ cflags = config.get('cflags', [])
+ cflags_c = config.get('cflags_c', [])
+ cflags_cc = config.get('cflags_cc', [])
- input = self.GypPathToNinja(source)
- output = self.GypPathToUniqueOutput(filename + obj_ext)
- implicit = precompiled_header.GetObjDependencies([input], [output])
- variables = []
+ cflags_host = config.get('cflags_host', cflags)
+ cflags_c_host = config.get('cflags_c_host', cflags_c)
+ cflags_cc_host = config.get('cflags_cc_host', cflags_cc)
+
+ defines = config.get('defines', []) + extra_defines
if GetToolchainOrNone(self.flavor):
- variables, output, implicit = precompiled_header.GetFlagsModifications(
- input, output, implicit, command, cflags_c, cflags_cc,
- self.ExpandSpecial)
- self.ninja.build(
- output,
- command,
- input,
- implicit=[gch for _, _, gch in implicit],
- order_only=predepends,
- variables=variables)
- outputs.append(output)
+ self.WriteVariableList('defines', [
+ GetToolchainOrNone(self.flavor).Define(d) for d in defines
+ ])
+ else:
+ self.WriteVariableList('defines',
+ [Define(d, self.flavor) for d in defines])
+ if GetToolchainOrNone(self.flavor):
+ self.WriteVariableList('rcflags', [
+ QuoteShellArgument(self.ExpandSpecial(f), self.flavor)
+ for f in GetToolchainOrNone(self.flavor).GetCompilerSettings()
+ .GetRcFlags(config_name, self.GypPathToNinja)
+ ])
- self.WritePchTargets(pch_commands)
+ include_dirs = config.get('include_dirs', [])
+ include_dirs += config.get('include_dirs_' + self.toolset, [])
+
+ if GetToolchainOrNone(self.flavor):
+ include_dirs = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().ProcessIncludeDirs(
+ include_dirs, config_name)
+ self.WriteVariableList('includes', [
+ '/I' + GetToolchainOrNone(self.flavor).QuoteForRspFile(
+ self.GypPathToNinja(i)) for i in include_dirs
+ ])
+ else:
+ self.WriteVariableList('includes', [
+ QuoteShellArgument('-I' + self.GypPathToNinja(i), self.flavor)
+ for i in include_dirs
+ ])
+
+ pch_commands = precompiled_header.GetPchBuildCommands()
+ if self.flavor == 'mac':
+ self.WriteVariableList('cflags_pch_c',
+ [precompiled_header.GetInclude('c')])
+ self.WriteVariableList('cflags_pch_cc',
+ [precompiled_header.GetInclude('cc')])
+ self.WriteVariableList('cflags_pch_objc',
+ [precompiled_header.GetInclude('m')])
+ self.WriteVariableList('cflags_pch_objcc',
+ [precompiled_header.GetInclude('mm')])
+
+ self.WriteVariableList('cflags', map(self.ExpandSpecial, cflags))
+ self.WriteVariableList('cflags_c', map(self.ExpandSpecial, cflags_c))
+ self.WriteVariableList('cflags_cc', map(self.ExpandSpecial, cflags_cc))
+
+ self.WriteVariableList('cflags_host', map(self.ExpandSpecial,
+ cflags_host))
+ self.WriteVariableList('cflags_c_host',
+ map(self.ExpandSpecial, cflags_c_host))
+ self.WriteVariableList('cflags_cc_host',
+ map(self.ExpandSpecial, cflags_cc_host))
+
+ if self.flavor == 'mac':
+ self.WriteVariableList('cflags_objc',
+ map(self.ExpandSpecial, cflags_objc))
+ self.WriteVariableList('cflags_objcc',
+ map(self.ExpandSpecial, cflags_objcc))
+ self.ninja.newline()
+
+ outputs = []
+ for source in sources:
+ filename, ext = os.path.splitext(source)
+ ext = ext[1:]
+ obj_ext = self.obj_ext
+ if ext in ('cc', 'cpp', 'cxx'):
+ command = 'cxx'
+ elif ext == 'c' or (ext == 'S' and self.flavor != 'win'):
+ command = 'cc'
+ elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files.
+ command = 'cc_s'
+ elif (self.flavor == 'win' and ext == 'asm' and GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetArch(config_name) == 'x86' and
+ not GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().HasExplicitAsmRules(spec)):
+ # Asm files only get auto assembled for x86 (not x64).
+ command = 'asm'
+ # Add the _asm suffix as msvs is capable of handling .cc and
+ # .asm files of the same name without collision.
+ obj_ext = '_asm.obj'
+ elif self.flavor == 'mac' and ext == 'm':
+ command = 'objc'
+ elif self.flavor == 'mac' and ext == 'mm':
+ command = 'objcxx'
+ elif self.flavor in microsoft_flavors and ext == 'rc':
+ # TODO: Starboardize this.
+ command = 'rc'
+ obj_ext = '.res'
+ else:
+ # Ignore unhandled extensions.
+ continue
+ if self.toolset != 'target':
+ command += '_' + self.toolset
+
+ input = self.GypPathToNinja(source)
+ output = self.GypPathToUniqueOutput(filename + obj_ext)
+ implicit = precompiled_header.GetObjDependencies([input], [output])
+ variables = []
+ if GetToolchainOrNone(self.flavor):
+ (variables, output,
+ implicit) = precompiled_header.GetFlagsModifications(
+ input, output, implicit, command, cflags_c, cflags_cc,
+ self.ExpandSpecial)
+ self.ninja.build(
+ output,
+ command,
+ input,
+ implicit=[gch for _, _, gch in implicit],
+ order_only=predepends,
+ variables=variables)
+ outputs.append(output)
+
+ self.WritePchTargets(pch_commands)
self.ninja.newline()
return outputs
@@ -1027,180 +1047,192 @@
def WriteLink(self, spec, config_name, config, link_deps):
"""Write out a link step. Fills out target.binary. """
- command = {
- 'executable': 'link',
- 'loadable_module': 'solink_module',
- 'shared_library': 'solink',
- }[spec['type']]
+ try:
+ raise NotImplementedError() # TODO: Implement the abstract toolchain.
+ except NotImplementedError:
+ # Fall back to the legacy toolchain.
- implicit_deps = set()
- order_only_deps = set()
- solibs = set()
+ command = {
+ 'executable': 'link',
+ 'loadable_module': 'solink_module',
+ 'shared_library': 'solink',
+ }[spec['type']]
- if 'dependencies' in spec:
- # Two kinds of dependencies:
- # - Linkable dependencies (like a .a or a .so): add them to the link line.
- # - Non-linkable dependencies (like a rule that generates a file
- # and writes a stamp file): add them to implicit_deps or order_only_deps
- extra_link_deps = []
- for dep in spec['dependencies']:
- target = self.target_outputs.get(dep)
- if not target:
- continue
- linkable = target.Linkable()
- # TODO: Starboardize.
- if linkable:
- if (self.flavor in microsoft_flavors and target.component_objs and
- GetToolchainOrNone(self.flavor).GetCompilerSettings()
- .IsUseLibraryDependencyInputs(config_name)):
- extra_link_deps.extend(target.component_objs)
- elif (self.flavor in (microsoft_flavors + ['ps3']) and
- target.import_lib):
- extra_link_deps.append(target.import_lib)
- elif target.UsesToc(self.flavor):
- solibs.add(target.binary)
- implicit_deps.add(target.binary + '.TOC')
- else:
- extra_link_deps.append(target.binary)
+ implicit_deps = set()
+ order_only_deps = set()
+ solibs = set()
- final_output = target.FinalOutput()
- if not linkable or final_output != target.binary:
- order_only_deps.add(final_output)
+ if 'dependencies' in spec:
+ # Two kinds of dependencies:
+ # - Linkable dependencies (like a .a or a .so): add them to the link
+ # line.
+ # - Non-linkable dependencies (like a rule that generates a file
+ # and writes a stamp file): add them to implicit_deps or
+ # order_only_deps
+ extra_link_deps = []
+ for dep in spec['dependencies']:
+ target = self.target_outputs.get(dep)
+ if not target:
+ continue
+ linkable = target.Linkable()
+ # TODO: Starboardize.
+ if linkable:
+ if (self.flavor in microsoft_flavors and target.component_objs and
+ GetToolchainOrNone(self.flavor).GetCompilerSettings()
+ .IsUseLibraryDependencyInputs(config_name)):
+ extra_link_deps.extend(target.component_objs)
+ elif (self.flavor in (microsoft_flavors + ['ps3']) and
+ target.import_lib):
+ extra_link_deps.append(target.import_lib)
+ elif target.UsesToc(self.flavor):
+ solibs.add(target.binary)
+ implicit_deps.add(target.binary + '.TOC')
+ else:
+ extra_link_deps.append(target.binary)
- # dedup the extra link deps while preserving order
- seen = set()
- extra_link_deps = [
- x for x in extra_link_deps if x not in seen and not seen.add(x)
- ]
+ final_output = target.FinalOutput()
+ if not linkable or final_output != target.binary:
+ order_only_deps.add(final_output)
- link_deps.extend(extra_link_deps)
+ # dedup the extra link deps while preserving order
+ seen = set()
+ extra_link_deps = [
+ x for x in extra_link_deps if x not in seen and not seen.add(x)
+ ]
- extra_bindings = []
- if self.is_mac_bundle:
- output = self.ComputeMacBundleBinaryOutput()
- else:
- output = self.ComputeOutput(spec)
- extra_bindings.append(('postbuilds', self.GetPostbuildCommand(
- spec, output, output)))
+ link_deps.extend(extra_link_deps)
- if self.flavor == 'mac':
- ldflags = self.xcode_settings.GetLdflags(
- config_name,
- self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
- self.GypPathToNinja)
- elif GetToolchainOrNone(self.flavor):
- libflags = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetLibFlags(
- config_name, self.GypPathToNinja)
- self.WriteVariableList(
- 'libflags', gyp.common.uniquer(map(self.ExpandSpecial, libflags)))
- is_executable = spec['type'] == 'executable'
- manifest_name = self.GypPathToUniqueOutput(
- self.ComputeOutputFileName(spec))
- ldflags, manifest_files = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetLdFlags(config_name, **{
- 'gyp_path_to_ninja': self.GypPathToNinja,
- 'expand_special': self.ExpandSpecial,
- 'manifest_name': manifest_name,
- 'is_executable': is_executable
- })
- self.WriteVariableList('manifests', manifest_files)
- else:
- ldflags = config.get('ldflags', [])
- ldflags_host = config.get('ldflags_host', ldflags)
-
- self.WriteVariableList('ldflags',
- gyp.common.uniquer(map(self.ExpandSpecial, ldflags)))
- if ('ldflags_host' in locals()):
- self.WriteVariableList(
- 'ldflags_host',
- gyp.common.uniquer(map(self.ExpandSpecial, ldflags_host)))
-
- if self.toolset == 'host':
- libs = spec.get('libraries_host', [])
- libs.extend(config.get('libraries_host', []))
- else:
- libs = spec.get('libraries', [])
- libs.extend(config.get('libraries', []))
-
- libraries = gyp.common.uniquer(map(self.ExpandSpecial, libs))
-
- if self.flavor == 'mac':
- libraries = self.xcode_settings.AdjustLibraries(libraries)
- elif GetToolchainOrNone(self.flavor):
- libraries = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().ProcessLibraries(libraries)
- self.WriteVariableList('libs', libraries)
-
- self.target.binary = output
-
- if command in ('solink', 'solink_module'):
- extra_bindings.append(('soname', os.path.split(output)[1]))
- extra_bindings.append(('lib',
- gyp.common.EncodePOSIXShellArgument(output)))
- # TODO: Starboardize.
- if self.flavor in microsoft_flavors:
- extra_bindings.append(('dll', output))
- if '/NOENTRY' not in ldflags:
- self.target.import_lib = output + '.lib'
- extra_bindings.append(('implibflag',
- '/IMPLIB:%s' % self.target.import_lib))
- output = [output, self.target.import_lib]
- elif self.flavor in ['ps3']:
- # Tell Ninja we'll be generating a .sprx and a stub library.
- # Bind the variable '$prx' to our output binary so we can
- # refer to it in the linker rules.
- prx_output = output
- prx_output_base, prx_output_ext = os.path.splitext(prx_output)
- assert prx_output_ext == '.sprx'
-
- extra_bindings.append(('prx', output))
- # TODO: Figure out how to suppress the "removal" warning
- # generated from the prx generator when we remove a function.
- # For now, we'll just delete the 'verlog.txt' file before linking.
- # Bind it here so we can refer to it as $verlog in the PS3 solink rule.
- verlog = output.replace(prx_output_ext, '_verlog.txt')
- extra_bindings.append(('verlog', verlog))
- self.target.import_lib = output.replace(prx_output_ext, '_stub.a')
- output = [prx_output, self.target.import_lib]
-
- # For PRXs, we need to convert any c++ exports into C. This is done
- # with an "export pickup" step that runs over the object files
- # and produces a new .c file. That .c file should be compiled and linked
- # into the PRX.
- gen_files_dir = os.path.join(
- self.ExpandSpecial(
- generator_default_variables['SHARED_INTERMEDIATE_DIR']), 'prx')
-
- export_pickup_output = os.path.join(
- gen_files_dir, os.path.basename(prx_output_base) + '.prx_export.c')
- prx_export_obj_file = export_pickup_output[:-2] + '.o'
- self.ninja.build(
- export_pickup_output,
- 'prx_export_pickup',
- link_deps,
- implicit=list(implicit_deps),
- order_only=list(order_only_deps))
-
- self.ninja.build(prx_export_obj_file, 'cc', export_pickup_output)
- link_deps.append(prx_export_obj_file)
-
+ extra_bindings = []
+ if self.is_mac_bundle:
+ output = self.ComputeMacBundleBinaryOutput()
else:
- output = [output, output + '.TOC']
+ output = self.ComputeOutput(spec)
+ extra_bindings.append(('postbuilds', self.GetPostbuildCommand(
+ spec, output, output)))
- if len(solibs):
- extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs)))
+ if self.flavor == 'mac':
+ ldflags = self.xcode_settings.GetLdflags(
+ config_name,
+ self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
+ self.GypPathToNinja)
+ elif GetToolchainOrNone(self.flavor):
+ libflags = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetLibFlags(
+ config_name, self.GypPathToNinja)
+ self.WriteVariableList(
+ 'libflags', gyp.common.uniquer(map(self.ExpandSpecial, libflags)))
+ is_executable = spec['type'] == 'executable'
+ manifest_name = self.GypPathToUniqueOutput(
+ self.ComputeOutputFileName(spec))
+ ldflags, manifest_files = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetLdFlags(
+ config_name, **{
+ 'gyp_path_to_ninja': self.GypPathToNinja,
+ 'expand_special': self.ExpandSpecial,
+ 'manifest_name': manifest_name,
+ 'is_executable': is_executable
+ })
+ self.WriteVariableList('manifests', manifest_files)
+ else:
+ ldflags = config.get('ldflags', [])
+ ldflags_host = config.get('ldflags_host', ldflags)
- if self.toolset != 'target':
- command += '_' + self.toolset
+ self.WriteVariableList(
+ 'ldflags', gyp.common.uniquer(map(self.ExpandSpecial, ldflags)))
+ if ('ldflags_host' in locals()):
+ self.WriteVariableList(
+ 'ldflags_host',
+ gyp.common.uniquer(map(self.ExpandSpecial, ldflags_host)))
- self.ninja.build(
- output,
- command,
- link_deps,
- implicit=list(implicit_deps),
- order_only=list(order_only_deps),
- variables=extra_bindings)
+ if self.toolset == 'host':
+ libs = spec.get('libraries_host', [])
+ libs.extend(config.get('libraries_host', []))
+ else:
+ libs = spec.get('libraries', [])
+ libs.extend(config.get('libraries', []))
+
+ libraries = gyp.common.uniquer(map(self.ExpandSpecial, libs))
+
+ if self.flavor == 'mac':
+ libraries = self.xcode_settings.AdjustLibraries(libraries)
+ elif GetToolchainOrNone(self.flavor):
+ libraries = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().ProcessLibraries(libraries)
+ self.WriteVariableList('libs', libraries)
+
+ self.target.binary = output
+
+ if command in ('solink', 'solink_module'):
+ extra_bindings.append(('soname', os.path.split(output)[1]))
+ extra_bindings.append(('lib',
+ gyp.common.EncodePOSIXShellArgument(output)))
+ # TODO: Starboardize.
+ if self.flavor in microsoft_flavors:
+ extra_bindings.append(('dll', output))
+ if '/NOENTRY' not in ldflags:
+ self.target.import_lib = output + '.lib'
+ extra_bindings.append(('implibflag',
+ '/IMPLIB:%s' % self.target.import_lib))
+ output = [output, self.target.import_lib]
+ elif self.flavor in ['ps3']:
+ # Tell Ninja we'll be generating a .sprx and a stub library.
+ # Bind the variable '$prx' to our output binary so we can
+ # refer to it in the linker rules.
+ prx_output = output
+ prx_output_base, prx_output_ext = os.path.splitext(prx_output)
+ assert prx_output_ext == '.sprx'
+
+ extra_bindings.append(('prx', output))
+ # TODO: Figure out how to suppress the "removal" warning
+ # generated from the prx generator when we remove a function.
+ # For now, we'll just delete the 'verlog.txt' file before linking.
+ # Bind it here so we can refer to it as $verlog in the PS3 solink
+ # rule.
+ verlog = output.replace(prx_output_ext, '_verlog.txt')
+ extra_bindings.append(('verlog', verlog))
+ self.target.import_lib = output.replace(prx_output_ext, '_stub.a')
+ output = [prx_output, self.target.import_lib]
+
+ # For PRXs, we need to convert any c++ exports into C. This is done
+ # with an "export pickup" step that runs over the object files
+ # and produces a new .c file. That .c file should be compiled and
+ # linked into the PRX.
+ gen_files_dir = os.path.join(
+ self.ExpandSpecial(
+ generator_default_variables['SHARED_INTERMEDIATE_DIR']),
+ 'prx')
+
+ export_pickup_output = os.path.join(
+ gen_files_dir,
+ os.path.basename(prx_output_base) + '.prx_export.c')
+ prx_export_obj_file = export_pickup_output[:-2] + '.o'
+ self.ninja.build(
+ export_pickup_output,
+ 'prx_export_pickup',
+ link_deps,
+ implicit=list(implicit_deps),
+ order_only=list(order_only_deps))
+
+ self.ninja.build(prx_export_obj_file, 'cc', export_pickup_output)
+ link_deps.append(prx_export_obj_file)
+
+ else:
+ output = [output, output + '.TOC']
+
+ if len(solibs):
+ extra_bindings.append(('solibs',
+ gyp.common.EncodePOSIXShellList(solibs)))
+
+ if self.toolset != 'target':
+ command += '_' + self.toolset
+
+ self.ninja.build(
+ output,
+ command,
+ link_deps,
+ implicit=list(implicit_deps),
+ order_only=list(order_only_deps),
+ variables=extra_bindings)
def WriteTarget(self, spec, config_name, config, link_deps, compile_deps):
if spec['type'] == 'none':
@@ -1209,34 +1241,40 @@
self.target.binary = compile_deps
elif spec['type'] == 'static_library':
self.target.binary = self.ComputeOutput(spec)
- variables = []
- if GetToolchainOrNone(self.flavor):
- libflags = GetToolchainOrNone(
- self.flavor).GetCompilerSettings().GetLibFlags(
- config_name, self.GypPathToNinja)
- # TODO: Starboardize libflags vs libtool_flags.
- variables.append(('libflags', ' '.join(libflags)))
- postbuild = self.GetPostbuildCommand(spec, self.target.binary,
- self.target.binary)
- if postbuild:
- variables.append(('postbuilds', postbuild))
- if self.xcode_settings:
- variables.append(('libtool_flags',
- self.xcode_settings.GetLibtoolflags(config_name)))
- # TODO: Starboardize.
- if (self.flavor not in (['mac'] + microsoft_flavors) and
- not self.is_standalone_static_library):
- command = 'alink_thin'
- else:
- command = 'alink'
- if self.toolset != 'target':
- command += '_' + self.toolset
- self.ninja.build(
- self.target.binary,
- command,
- link_deps,
- order_only=compile_deps,
- variables=variables)
+
+ try:
+ raise NotImplementedError() # TODO: Implement the abstract toolchain.
+ except NotImplementedError:
+ # Fall back to the legacy toolchain.
+
+ variables = []
+ if GetToolchainOrNone(self.flavor):
+ libflags = GetToolchainOrNone(
+ self.flavor).GetCompilerSettings().GetLibFlags(
+ config_name, self.GypPathToNinja)
+ # TODO: Starboardize libflags vs libtool_flags.
+ variables.append(('libflags', ' '.join(libflags)))
+ postbuild = self.GetPostbuildCommand(spec, self.target.binary,
+ self.target.binary)
+ if postbuild:
+ variables.append(('postbuilds', postbuild))
+ if self.xcode_settings:
+ variables.append(('libtool_flags',
+ self.xcode_settings.GetLibtoolflags(config_name)))
+ # TODO: Starboardize.
+ if (self.flavor not in (['mac'] + microsoft_flavors) and
+ not self.is_standalone_static_library):
+ command = 'alink_thin'
+ else:
+ command = 'alink'
+ if self.toolset != 'target':
+ command += '_' + self.toolset
+ self.ninja.build(
+ self.target.binary,
+ command,
+ link_deps,
+ order_only=compile_deps,
+ variables=variables)
else:
self.WriteLink(spec, config_name, config, link_deps)
return self.target.binary
@@ -1687,579 +1725,591 @@
OpenOutput(os.path.join(toplevel_build, 'build.ninja')), width=120)
case_sensitive_filesystem = True
- # Put build-time support tools in out/{config_name}.
- gyp.common.CopyTool(flavor, toplevel_build)
-
- # Grab make settings for CC/CXX.
- # The rules are
- # - The priority from low to high is gcc/g++, the 'make_global_settings' in
- # gyp, the environment variable.
- # - If there is no 'make_global_settings' for CC.host/CXX.host or
- # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
- # to cc/cxx.
- if (flavor in sony_flavors and is_windows):
- cc = 'cl.exe'
- cxx = 'cl.exe'
- ld = 'link.exe'
- gyp.msvs_emulation.GenerateEnvironmentFiles(toplevel_build, generator_flags,
- OpenOutput)
- ld_host = '$ld'
- elif GetToolchainOrNone(flavor):
- # TODO: starboardize.
- cc = 'cl.exe'
- cxx = 'cl.exe'
- ld = 'link.exe'
- GetToolchainOrNone(flavor).GenerateEnvironmentFiles(
- toplevel_build, generator_flags, OpenOutput)
- ld_host = '$ld'
- else:
- cc = 'gcc'
- cxx = 'g++'
- ld = '$cxx'
- ld_host = '$cxx_host'
-
- cc_host = None
- cxx_host = None
- cc_host_global_setting = None
- cxx_host_global_setting = None
-
build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
make_global_settings = data[build_file].get('make_global_settings', [])
- build_to_root = InvertRelativePath(build_dir)
- for key, value in make_global_settings:
- if key == 'CC':
- cc = os.path.join(build_to_root, value)
- if key == 'CXX':
- cxx = os.path.join(build_to_root, value)
- if key == 'LD':
- ld = os.path.join(build_to_root, value)
- if key == 'CC.host':
- cc_host = os.path.join(build_to_root, value)
- cc_host_global_setting = value
- if key == 'CXX.host':
- cxx_host = os.path.join(build_to_root, value)
- cxx_host_global_setting = value
- if key == 'LD.host':
- ld_host = os.path.join(build_to_root, value)
- flock = 'flock'
- if flavor == 'mac':
- flock = './gyp-mac-tool flock'
- cc = GetEnvironFallback(['CC_target', 'CC'], cc)
- master_ninja.variable('cc', cc)
- cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx)
- master_ninja.variable('cxx', cxx)
- ld = GetEnvironFallback(['LD_target', 'LD'], ld)
- rc = GetEnvironFallback(['RC'], 'rc.exe')
+ try:
+ raise NotImplementedError() # TODO: Implement the abstract toolchain.
+ except NotImplementedError:
+ # Fall back to the legacy toolchain.
- if not cc_host:
- cc_host = cc
- if not cxx_host:
- cxx_host = cxx
+ # Put build-time support tools in out/{config_name}.
+ gyp.common.CopyTool(flavor, toplevel_build)
- # gyp-win-tool wrappers have a winpython only flock implementation.
- if sys.platform == 'cygwin':
- python_exec = '$python'
- else:
- python_exec = sys.executable
+ # Grab make settings for CC/CXX.
+ # The rules are
+ # - The priority from low to high is gcc/g++, the 'make_global_settings' in
+ # gyp, the environment variable.
+ # - If there is no 'make_global_settings' for CC.host/CXX.host or
+ # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
+ # to cc/cxx.
+ if (flavor in sony_flavors and is_windows):
+ cc = 'cl.exe'
+ cxx = 'cl.exe'
+ ld = 'link.exe'
+ gyp.msvs_emulation.GenerateEnvironmentFiles(toplevel_build,
+ generator_flags, OpenOutput)
+ ld_host = '$ld'
+ elif GetToolchainOrNone(flavor):
+ # TODO: starboardize.
+ cc = 'cl.exe'
+ cxx = 'cl.exe'
+ ld = 'link.exe'
+ GetToolchainOrNone(flavor).GenerateEnvironmentFiles(
+ toplevel_build, generator_flags, OpenOutput)
+ ld_host = '$ld'
+ else:
+ cc = 'gcc'
+ cxx = 'g++'
+ ld = '$cxx'
+ ld_host = '$cxx_host'
- ar_flags = ''
- if flavor in microsoft_flavors:
- master_ninja.variable('ld', ld)
- master_ninja.variable('ar', os.environ.get('AR', 'ar'))
- master_ninja.variable('rc', rc)
- master_ninja.variable('asm', 'ml.exe')
- master_ninja.variable('mt', 'mt.exe')
- master_ninja.variable('use_dep_database', '1')
- elif flavor in sony_flavors:
- # Require LD to be set.
- master_ninja.variable('ld', os.environ.get('LD'))
- master_ninja.variable('ar', os.environ.get('AR', 'ar'))
- if flavor in ['ps3']:
- master_ninja.variable('prx_export_pickup',
- os.environ['PRX_EXPORT_PICKUP'])
- ar_flags = os.environ.get('ARFLAGS', 'rcs')
- master_ninja.variable('arFlags', ar_flags)
- # On the PS3, when we use ps3snarl.exe with a response file, we cannot
- # pass it flags (like 'rcs'), so ARFLAGS is likely set to '' for this
- # platform. In that case, do not append the thin archive 'T' flag
- # to the flags string.
- # Likewise for PS4, but using orbis-snarl.exe
- thin_flag_to_add = ''
- if len(ar_flags) >= 1 and ar_flags.find('T') == -1:
- thin_flag_to_add = 'T'
- master_ninja.variable('arThinFlags', ar_flags + thin_flag_to_add)
+ cc_host = None
+ cxx_host = None
+ cc_host_global_setting = None
+ cxx_host_global_setting = None
- else:
- master_ninja.variable('ld', ld)
- master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], 'ar'))
- ar_flags = os.environ.get('ARFLAGS', 'rcs')
- master_ninja.variable('arFlags', ar_flags)
- thin_flag_to_add = ''
- if ar_flags.find('T') == -1:
- thin_flag_to_add = 'T'
- master_ninja.variable('arThinFlags', ar_flags + thin_flag_to_add)
- master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], 'ar'))
- cc_host = GetEnvironFallback(['CC_host'], cc_host)
- cxx_host = GetEnvironFallback(['CXX_host'], cxx_host)
- ld_host = GetEnvironFallback(['LD_host'], ld_host)
- arflags_host = GetEnvironFallback(['ARFLAGS_host'], ar_flags)
- arthinflags_host = GetEnvironFallback(['ARTHINFLAGS_host'], arflags_host)
+ build_to_root = InvertRelativePath(build_dir)
+ for key, value in make_global_settings:
+ if key == 'CC':
+ cc = os.path.join(build_to_root, value)
+ if key == 'CXX':
+ cxx = os.path.join(build_to_root, value)
+ if key == 'LD':
+ ld = os.path.join(build_to_root, value)
+ if key == 'CC.host':
+ cc_host = os.path.join(build_to_root, value)
+ cc_host_global_setting = value
+ if key == 'CXX.host':
+ cxx_host = os.path.join(build_to_root, value)
+ cxx_host_global_setting = value
+ if key == 'LD.host':
+ ld_host = os.path.join(build_to_root, value)
- # The environment variable could be used in 'make_global_settings', like
- # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here.
- if '$(CC)' in cc_host and cc_host_global_setting:
- cc_host = cc_host_global_setting.replace('$(CC)', cc)
- if '$(CXX)' in cxx_host and cxx_host_global_setting:
- cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx)
- master_ninja.variable('cc_host', cc_host)
- master_ninja.variable('cxx_host', cxx_host)
- master_ninja.variable('arFlags_host', arflags_host)
- master_ninja.variable('arThinFlags_host', arthinflags_host)
- master_ninja.variable('ld_host', ld_host)
+ flock = 'flock'
+ if flavor == 'mac':
+ flock = './gyp-mac-tool flock'
+ cc = GetEnvironFallback(['CC_target', 'CC'], cc)
+ master_ninja.variable('cc', cc)
+ cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx)
+ master_ninja.variable('cxx', cxx)
+ ld = GetEnvironFallback(['LD_target', 'LD'], ld)
+ rc = GetEnvironFallback(['RC'], 'rc.exe')
- if sys.platform == 'cygwin':
- python_path = cygpath.to_nt('/cygdrive/c/python_27_amd64/files/python.exe')
- else:
- python_path = 'python'
- master_ninja.variable('python', python_path)
- master_ninja.newline()
+ if not cc_host:
+ cc_host = cc
+ if not cxx_host:
+ cxx_host = cxx
- master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks())
- master_ninja.newline()
+ # gyp-win-tool wrappers have a winpython only flock implementation.
+ if sys.platform == 'cygwin':
+ python_exec = '$python'
+ else:
+ python_exec = sys.executable
- if flavor not in microsoft_flavors:
- if flavor in sony_flavors:
- # uca := Unnamed Console A
- dep_format = 'snc' if (flavor in ['ps3']) else 'uca'
+ ar_flags = ''
+ if flavor in microsoft_flavors:
+ master_ninja.variable('ld', ld)
+ master_ninja.variable('ar', os.environ.get('AR', 'ar'))
+ master_ninja.variable('rc', rc)
+ master_ninja.variable('asm', 'ml.exe')
+ master_ninja.variable('mt', 'mt.exe')
+ master_ninja.variable('use_dep_database', '1')
+ elif flavor in sony_flavors:
+ # Require LD to be set.
+ master_ninja.variable('ld', os.environ.get('LD'))
+ master_ninja.variable('ar', os.environ.get('AR', 'ar'))
+ if flavor in ['ps3']:
+ master_ninja.variable('prx_export_pickup',
+ os.environ['PRX_EXPORT_PICKUP'])
+ ar_flags = os.environ.get('ARFLAGS', 'rcs')
+ master_ninja.variable('arFlags', ar_flags)
+ # On the PS3, when we use ps3snarl.exe with a response file, we cannot
+ # pass it flags (like 'rcs'), so ARFLAGS is likely set to '' for this
+ # platform. In that case, do not append the thin archive 'T' flag
+ # to the flags string.
+ # Likewise for PS4, but using orbis-snarl.exe
+ thin_flag_to_add = ''
+ if len(ar_flags) >= 1 and ar_flags.find('T') == -1:
+ thin_flag_to_add = 'T'
+ master_ninja.variable('arThinFlags', ar_flags + thin_flag_to_add)
+
+ else:
+ master_ninja.variable('ld', ld)
+ master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], 'ar'))
+ ar_flags = os.environ.get('ARFLAGS', 'rcs')
+ master_ninja.variable('arFlags', ar_flags)
+ thin_flag_to_add = ''
+ if ar_flags.find('T') == -1:
+ thin_flag_to_add = 'T'
+ master_ninja.variable('arThinFlags', ar_flags + thin_flag_to_add)
+ master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], 'ar'))
+ cc_host = GetEnvironFallback(['CC_host'], cc_host)
+ cxx_host = GetEnvironFallback(['CXX_host'], cxx_host)
+ ld_host = GetEnvironFallback(['LD_host'], ld_host)
+ arflags_host = GetEnvironFallback(['ARFLAGS_host'], ar_flags)
+ arthinflags_host = GetEnvironFallback(['ARTHINFLAGS_host'], arflags_host)
+
+ # The environment variable could be used in 'make_global_settings', like
+ # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here.
+ if '$(CC)' in cc_host and cc_host_global_setting:
+ cc_host = cc_host_global_setting.replace('$(CC)', cc)
+ if '$(CXX)' in cxx_host and cxx_host_global_setting:
+ cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx)
+ master_ninja.variable('cc_host', cc_host)
+ master_ninja.variable('cxx_host', cxx_host)
+ master_ninja.variable('arFlags_host', arflags_host)
+ master_ninja.variable('arThinFlags_host', arthinflags_host)
+ master_ninja.variable('ld_host', ld_host)
+
+ if sys.platform == 'cygwin':
+ python_path = cygpath.to_nt(
+ '/cygdrive/c/python_27_amd64/files/python.exe')
+ else:
+ python_path = 'python'
+ master_ninja.variable('python', python_path)
+ master_ninja.newline()
+
+ master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks())
+ master_ninja.newline()
+
+ if flavor not in microsoft_flavors:
+ if flavor in sony_flavors:
+ # uca := Unnamed Console A
+ dep_format = 'snc' if (flavor in ['ps3']) else 'uca'
+ master_ninja.rule(
+ 'cc',
+ description='CC $out',
+ command=('$cc @$out.rsp'),
+ rspfile='$out.rsp',
+ rspfile_content=('-c $in -o $out '
+ '-MMD $defines $includes $cflags $cflags_c '
+ '$cflags_pch_c'),
+ depfile='$out_no_ext.d',
+ deps='gcc',
+ depformat=dep_format)
+ master_ninja.rule(
+ 'cxx',
+ description='CXX $out',
+ command=('$cxx @$out.rsp'),
+ rspfile='$out.rsp',
+ rspfile_content=('-c $in -o $out '
+ '-MMD $defines $includes $cflags $cflags_cc '
+ '$cflags_pch_cc'),
+ depfile='$out_no_ext.d',
+ deps='gcc',
+ depformat=dep_format)
+ else:
+ master_ninja.rule(
+ 'cc',
+ description='CC $out',
+ command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
+ '$cflags_pch_c -c $in -o $out'),
+ deps='gcc',
+ depfile='$out.d')
+ master_ninja.rule(
+ 'cc_s',
+ description='CC $out',
+ command=('$cc $defines $includes $cflags $cflags_c '
+ '$cflags_pch_c -c $in -o $out'))
+ master_ninja.rule(
+ 'cxx',
+ description='CXX $out',
+ command=(
+ '$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
+ '$cflags_pch_cc -c $in -o $out'),
+ deps='gcc',
+ depfile='$out.d')
+
+ else:
+ cc_command = ('$cc /nologo /showIncludes /FC '
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
+ cxx_command = ('$cxx /nologo /showIncludes /FC '
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
master_ninja.rule(
'cc',
description='CC $out',
- command=('$cc @$out.rsp'),
+ command=cc_command,
+ deps='msvc',
rspfile='$out.rsp',
- rspfile_content=('-c $in -o $out '
- '-MMD $defines $includes $cflags $cflags_c '
- '$cflags_pch_c'),
- depfile='$out_no_ext.d',
- deps='gcc',
- depformat=dep_format)
+ rspfile_content='$defines $includes $cflags $cflags_c')
master_ninja.rule(
'cxx',
description='CXX $out',
- command=('$cxx @$out.rsp'),
+ command=cxx_command,
+ deps='msvc',
rspfile='$out.rsp',
- rspfile_content=('-c $in -o $out '
- '-MMD $defines $includes $cflags $cflags_cc '
- '$cflags_pch_cc'),
- depfile='$out_no_ext.d',
- deps='gcc',
- depformat=dep_format)
+ rspfile_content='$defines $includes $cflags $cflags_cc')
+
+ master_ninja.rule(
+ 'rc',
+ description='RC $in',
+ # Note: $in must be last otherwise rc.exe complains.
+ command=('%s gyp-win-tool rc-wrapper '
+ '$arch $rc $defines $includes $rcflags /fo$out $in' %
+ python_exec))
+ master_ninja.rule(
+ 'asm',
+ description='ASM $in',
+ command=(
+ '%s gyp-win-tool asm-wrapper '
+ '$arch $asm $defines $includes /c /Fo $out $in' % python_exec))
+
+ if flavor not in (['mac'] + microsoft_flavors):
+ alink_command = 'rm -f $out && $ar $arFlags $out @$out.rsp'
+ # TODO: Use rcsT on Linux only.
+ alink_thin_command = 'rm -f $out && $ar $arThinFlags $out @$out.rsp'
+
+ ld_cmd = '$ld'
+
+ if flavor in sony_flavors and is_windows:
+ alink_command = 'cmd.exe /c ' + alink_command
+ alink_thin_command = 'cmd.exe /c ' + alink_thin_command
+ ld_cmd = '%s gyp-win-tool link-wrapper $arch $ld' % python_exec
+
+ master_ninja.rule(
+ 'alink',
+ description='AR $out',
+ command=alink_command,
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline')
+ master_ninja.rule(
+ 'alink_thin',
+ description='AR $out',
+ command=alink_thin_command,
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline')
+
+ if flavor in ['ps3']:
+ # TODO: Can we suppress the warnings from verlog.txt rather than
+ # rm'ing it?
+ ld_cmd = 'rm -f $verlog && ' + ld_cmd
+ if is_windows:
+ ld_cmd = 'cmd.exe /c ' + ld_cmd
+
+ prx_flags = '--oformat=fsprx --prx-with-runtime --zgenprx -zgenstub'
+ master_ninja.rule(
+ 'solink',
+ description='LINK(PRX) $lib',
+ restat=True,
+ command=ld_cmd + ' @$prx.rsp',
+ rspfile='$prx.rsp',
+ rspfile_content='$ldflags %s -o $prx $in $libs' % prx_flags,
+ pool='link_pool')
+ master_ninja.rule(
+ 'prx_export_pickup',
+ description='PRX-EXPORT-PICKUP $out',
+ command='$prx_export_pickup --output-src=$out $in')
+
+ else: # Assume it is a Linux platform
+ # This allows targets that only need to depend on $lib's API to declare
+ # an order-only dependency on $lib.TOC and avoid relinking such
+ # downstream dependencies when $lib changes only in non-public ways.
+ # The resulting string leaves an uninterpolated %{suffix} which
+ # is used in the final substitution below.
+ mtime_preserving_solink_base = (
+ 'if [ ! -e $lib -o ! -e ${lib}.TOC ]; then %(solink)s && '
+ '%(extract_toc)s > ${lib}.TOC; else %(solink)s && %(extract_toc)s '
+ '> ${lib}.tmp && if ! cmp -s ${lib}.tmp ${lib}.TOC; then mv '
+ '${lib}.tmp ${lib}.TOC ; fi; fi' % {
+ 'solink': (
+ ld_cmd +
+ ' -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s'),
+ 'extract_toc': ('{ readelf -d ${lib} | grep SONAME ; '
+ 'nm -gD -f p ${lib} | cut -f1-2 -d\' \'; }')
+ })
+
+ master_ninja.rule(
+ 'solink',
+ description='SOLINK $lib',
+ restat=True,
+ command=(mtime_preserving_solink_base % {
+ 'suffix':
+ '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive '
+ '$libs'
+ }))
+ master_ninja.rule(
+ 'solink_module',
+ description='SOLINK(module) $lib',
+ restat=True,
+ command=(mtime_preserving_solink_base % {
+ 'suffix': '-Wl,--start-group $in $solibs -Wl,--end-group $libs'
+ }))
+
+ if flavor in sony_flavors:
+ # PS3 and PS4 linkers don't know about rpath.
+ rpath = ''
+ else:
+ rpath = r'-Wl,-rpath=\$$ORIGIN/lib'
+
+ master_ninja.rule(
+ 'link',
+ description='LINK $out',
+ command=(ld_cmd + ' @$out.rsp'),
+ rspfile='$out.rsp',
+ rspfile_content=('$ldflags -o $out %s -Wl,--start-group $in $solibs '
+ '-Wl,--end-group $libs' % rpath),
+ pool='link_pool')
+ elif flavor in microsoft_flavors:
+ master_ninja.rule(
+ 'alink',
+ description='LIB $out',
+ command=(
+ '%s gyp-win-tool link-wrapper $arch '
+ '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % python_exec),
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline $libflags')
+ dlldesc = 'LINK(DLL) $dll'
+ dllcmd = ('%s gyp-win-tool link-wrapper $arch '
+ '$ld /nologo $implibflag /DLL /OUT:$dll '
+ '/PDB:$dll.pdb @$dll.rsp' % python_exec)
+ if not flavor in microsoft_flavors:
+ # XB1 doesn't need a manifest.
+ dllcmd += (
+ ' && %s gyp-win-tool manifest-wrapper $arch '
+ '$mt -nologo -manifest $manifests -out:$dll.manifest' % python_exec)
+ master_ninja.rule(
+ 'solink',
+ description=dlldesc,
+ command=dllcmd,
+ rspfile='$dll.rsp',
+ rspfile_content='$libs $in_newline $ldflags',
+ restat=True)
+ master_ninja.rule(
+ 'solink_module',
+ description=dlldesc,
+ command=dllcmd,
+ rspfile='$dll.rsp',
+ rspfile_content='$libs $in_newline $ldflags',
+ restat=True)
+ # Note that ldflags goes at the end so that it has the option of
+ # overriding default settings earlier in the command line.
+ if flavor == 'win':
+ link_command = ('%s gyp-win-tool link-wrapper $arch '
+ '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp && '
+ '%s gyp-win-tool manifest-wrapper $arch '
+ '$mt -nologo -manifest $manifests -out:$out.manifest' %
+ (python_exec, python_exec))
+ else:
+ assert flavor in microsoft_flavors
+ # XB1 doesn't need a manifest.
+ link_command = ('%s gyp-win-tool link-wrapper $arch '
+ '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %
+ (python_exec))
+
+ master_ninja.rule(
+ 'link',
+ description='LINK $out',
+ command=link_command,
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline $libs $ldflags',
+ pool='link_pool')
else:
master_ninja.rule(
- 'cc',
- description='CC $out',
- command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
- '$cflags_pch_c -c $in -o $out'),
- deps='gcc',
+ 'objc',
+ description='OBJC $out',
+ command=(
+ '$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
+ '$cflags_pch_objc -c $in -o $out'),
depfile='$out.d')
master_ninja.rule(
- 'cc_s',
- description='CC $out',
- command=('$cc $defines $includes $cflags $cflags_c '
- '$cflags_pch_c -c $in -o $out'))
- master_ninja.rule(
- 'cxx',
- description='CXX $out',
- command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
- '$cflags_pch_cc -c $in -o $out'),
- deps='gcc',
+ 'objcxx',
+ description='OBJCXX $out',
+ command=(
+ '$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc '
+ '$cflags_pch_objcc -c $in -o $out'),
depfile='$out.d')
-
- else:
- cc_command = ('$cc /nologo /showIncludes /FC '
- '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
- cxx_command = ('$cxx /nologo /showIncludes /FC '
- '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
- master_ninja.rule(
- 'cc',
- description='CC $out',
- command=cc_command,
- deps='msvc',
- rspfile='$out.rsp',
- rspfile_content='$defines $includes $cflags $cflags_c')
- master_ninja.rule(
- 'cxx',
- description='CXX $out',
- command=cxx_command,
- deps='msvc',
- rspfile='$out.rsp',
- rspfile_content='$defines $includes $cflags $cflags_cc')
-
- master_ninja.rule(
- 'rc',
- description='RC $in',
- # Note: $in must be last otherwise rc.exe complains.
- command=(
- '%s gyp-win-tool rc-wrapper '
- '$arch $rc $defines $includes $rcflags /fo$out $in' % python_exec))
- master_ninja.rule(
- 'asm',
- description='ASM $in',
- command=('%s gyp-win-tool asm-wrapper '
- '$arch $asm $defines $includes /c /Fo $out $in' % python_exec))
-
- if flavor not in (['mac'] + microsoft_flavors):
- alink_command = 'rm -f $out && $ar $arFlags $out @$out.rsp'
- # TODO: Use rcsT on Linux only.
- alink_thin_command = 'rm -f $out && $ar $arThinFlags $out @$out.rsp'
-
- ld_cmd = '$ld'
-
- if flavor in sony_flavors and is_windows:
- alink_command = 'cmd.exe /c ' + alink_command
- alink_thin_command = 'cmd.exe /c ' + alink_thin_command
- ld_cmd = '%s gyp-win-tool link-wrapper $arch $ld' % python_exec
-
- master_ninja.rule(
- 'alink',
- description='AR $out',
- command=alink_command,
- rspfile='$out.rsp',
- rspfile_content='$in_newline')
- master_ninja.rule(
- 'alink_thin',
- description='AR $out',
- command=alink_thin_command,
- rspfile='$out.rsp',
- rspfile_content='$in_newline')
-
- if flavor in ['ps3']:
- # TODO: Can we suppress the warnings from verlog.txt rather than
- # rm'ing it?
- ld_cmd = 'rm -f $verlog && ' + ld_cmd
- if is_windows:
- ld_cmd = 'cmd.exe /c ' + ld_cmd
-
- prx_flags = '--oformat=fsprx --prx-with-runtime --zgenprx -zgenstub'
master_ninja.rule(
- 'solink',
- description='LINK(PRX) $lib',
- restat=True,
- command=ld_cmd + ' @$prx.rsp',
- rspfile='$prx.rsp',
- rspfile_content='$ldflags %s -o $prx $in $libs' % prx_flags,
- pool='link_pool')
- master_ninja.rule(
- 'prx_export_pickup',
- description='PRX-EXPORT-PICKUP $out',
- command='$prx_export_pickup --output-src=$out $in')
+ 'alink',
+ description='LIBTOOL-STATIC $out, POSTBUILDS',
+ command='rm -f $out && '
+ './gyp-mac-tool filter-libtool libtool $libtool_flags '
+ '-static -o $out $in'
+ '$postbuilds')
- else: # Assume it is a Linux platform
- # This allows targets that only need to depend on $lib's API to declare an
- # order-only dependency on $lib.TOC and avoid relinking such downstream
- # dependencies when $lib changes only in non-public ways.
- # The resulting string leaves an uninterpolated %{suffix} which
- # is used in the final substitution below.
+ # Record the public interface of $lib in $lib.TOC. See the corresponding
+ # comment in the posix section above for details.
mtime_preserving_solink_base = (
- 'if [ ! -e $lib -o ! -e ${lib}.TOC ]; then '
- '%(solink)s && %(extract_toc)s > ${lib}.TOC; else '
+ 'if [ ! -e $lib -o ! -e ${lib}.TOC ] || '
+ # Always force dependent targets to relink if this library
+ # reexports something. Handling this correctly would require
+ # recursive TOC dumping but this is rare in practice, so punt.
+ 'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then '
+ '%(solink)s && %(extract_toc)s > ${lib}.TOC; '
+ 'else '
'%(solink)s && %(extract_toc)s > ${lib}.tmp && '
- 'if ! cmp -s ${lib}.tmp ${lib}.TOC; then mv ${lib}.tmp ${lib}.TOC ; '
- 'fi; fi' % {
- 'solink':
- (ld_cmd +
- ' -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s'),
- 'extract_toc': ('{ readelf -d ${lib} | grep SONAME ; '
- 'nm -gD -f p ${lib} | cut -f1-2 -d\' \'; }')
+ 'if ! cmp -s ${lib}.tmp ${lib}.TOC; then '
+ 'mv ${lib}.tmp ${lib}.TOC ; '
+ 'fi; '
+ 'fi' % {
+ 'solink': '$ld -shared $ldflags -o $lib %(suffix)s',
+ 'extract_toc':
+ '{ otool -l $lib | grep LC_ID_DYLIB -A 5; '
+ 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'
})
+ # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to
+ # pass -bundle -single_module here (for osmesa.so).
master_ninja.rule(
'solink',
- description='SOLINK $lib',
+ description='SOLINK $lib, POSTBUILDS',
restat=True,
command=(mtime_preserving_solink_base % {
- 'suffix':
- '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive '
- '$libs'
+ 'suffix': '$in $solibs $libs$postbuilds'
}))
master_ninja.rule(
'solink_module',
- description='SOLINK(module) $lib',
+ description='SOLINK(module) $lib, POSTBUILDS',
restat=True,
command=(mtime_preserving_solink_base % {
- 'suffix': '-Wl,--start-group $in $solibs -Wl,--end-group $libs'
+ 'suffix': '$in $solibs $libs$postbuilds'
}))
- if flavor in sony_flavors:
- # PS3 and PS4 linkers don't know about rpath.
- rpath = ''
+ master_ninja.rule(
+ 'link',
+ description='LINK $out, POSTBUILDS',
+ command=('$ld $ldflags -o $out '
+ '$in $solibs $libs$postbuilds'),
+ pool='link_pool')
+ master_ninja.rule(
+ 'infoplist',
+ description='INFOPLIST $out',
+ command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && '
+ 'plutil -convert xml1 $out $out'))
+ master_ninja.rule(
+ 'mac_tool',
+ description='MACTOOL $mactool_cmd $in',
+ command='$env ./gyp-mac-tool $mactool_cmd $in $out')
+ master_ninja.rule(
+ 'package_framework',
+ description='PACKAGE FRAMEWORK $out, POSTBUILDS',
+ command='./gyp-mac-tool package-framework $out $version$postbuilds '
+ '&& touch $out')
+ if flavor in microsoft_flavors:
+ master_ninja.rule(
+ 'stamp',
+ description='STAMP $out',
+ command='%s gyp-win-tool stamp $out' % python_exec)
+ master_ninja.rule(
+ 'copy',
+ description='COPY $in $out',
+ command='%s gyp-win-tool recursive-mirror $in $out' % python_exec)
+ elif sys.platform in ['cygwin', 'win32']:
+ master_ninja.rule(
+ 'stamp',
+ description='STAMP $out',
+ command='$python gyp-win-tool stamp $out')
+ master_ninja.rule(
+ 'copy',
+ description='COPY $in $out',
+ command='$python gyp-win-tool recursive-mirror $in $out')
else:
- rpath = r'-Wl,-rpath=\$$ORIGIN/lib'
+ master_ninja.rule(
+ 'stamp', description='STAMP $out', command='${postbuilds}touch $out')
+ master_ninja.rule(
+ 'copy',
+ description='COPY $in $out',
+ command='rm -rf $out && cp -af $in $out')
+ master_ninja.newline()
- master_ninja.rule(
- 'link',
- description='LINK $out',
- command=(ld_cmd + ' @$out.rsp'),
- rspfile='$out.rsp',
- rspfile_content=('$ldflags -o $out %s -Wl,--start-group $in $solibs '
- '-Wl,--end-group $libs' % rpath),
- pool='link_pool')
- elif flavor in microsoft_flavors:
- master_ninja.rule(
- 'alink',
- description='LIB $out',
- command=('%s gyp-win-tool link-wrapper $arch '
- '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % python_exec),
- rspfile='$out.rsp',
- rspfile_content='$in_newline $libflags')
- dlldesc = 'LINK(DLL) $dll'
- dllcmd = ('%s gyp-win-tool link-wrapper $arch '
- '$ld /nologo $implibflag /DLL /OUT:$dll '
- '/PDB:$dll.pdb @$dll.rsp' % python_exec)
- if not flavor in microsoft_flavors:
- # XB1 doesn't need a manifest.
- dllcmd += (
- ' && %s gyp-win-tool manifest-wrapper $arch '
- '$mt -nologo -manifest $manifests -out:$dll.manifest' % python_exec)
- master_ninja.rule(
- 'solink',
- description=dlldesc,
- command=dllcmd,
- rspfile='$dll.rsp',
- rspfile_content='$libs $in_newline $ldflags',
- restat=True)
- master_ninja.rule(
- 'solink_module',
- description=dlldesc,
- command=dllcmd,
- rspfile='$dll.rsp',
- rspfile_content='$libs $in_newline $ldflags',
- restat=True)
- # Note that ldflags goes at the end so that it has the option of
- # overriding default settings earlier in the command line.
- if flavor == 'win':
- link_command = ('%s gyp-win-tool link-wrapper $arch '
- '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp && '
- '%s gyp-win-tool manifest-wrapper $arch '
- '$mt -nologo -manifest $manifests -out:$out.manifest' %
- (python_exec, python_exec))
- else:
- assert flavor in microsoft_flavors
- # XB1 doesn't need a manifest.
+ # Output host building rules
+ if is_windows:
+ cc_command = ('$cc /nologo /showIncludes /FC '
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
+ cxx_command = ('$cxx /nologo /showIncludes /FC '
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
+ master_ninja.rule(
+ 'cc_host',
+ description='CC_HOST $out',
+ command=cc_command,
+ deps='msvc',
+ rspfile='$out.rsp',
+ rspfile_content='$defines $includes $cflags_host $cflags_c_host')
+ master_ninja.rule(
+ 'cxx_host',
+ description='CXX_HOST $out',
+ command=cxx_command,
+ deps='msvc',
+ rspfile='$out.rsp',
+ rspfile_content='$defines $includes $cflags_host $cflags_cc_host')
+
+ master_ninja.rule(
+ 'alink_host',
+ description='LIB_HOST $out',
+ command=(
+ '%s gyp-win-tool link-wrapper $arch '
+ '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % python_exec),
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline $libflags_host')
+
+ master_ninja.rule(
+ 'alink_thin_host',
+ description='LIB_HOST $out',
+ command=(
+ '%s gyp-win-tool link-wrapper $arch '
+ '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % python_exec),
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline $libflags_host')
+
link_command = ('%s gyp-win-tool link-wrapper $arch '
'$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %
(python_exec))
- master_ninja.rule(
- 'link',
- description='LINK $out',
- command=link_command,
- rspfile='$out.rsp',
- rspfile_content='$in_newline $libs $ldflags',
- pool='link_pool')
- else:
- master_ninja.rule(
- 'objc',
- description='OBJC $out',
- command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
- '$cflags_pch_objc -c $in -o $out'),
- depfile='$out.d')
- master_ninja.rule(
- 'objcxx',
- description='OBJCXX $out',
- command=(
- '$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc '
- '$cflags_pch_objcc -c $in -o $out'),
- depfile='$out.d')
- master_ninja.rule(
- 'alink',
- description='LIBTOOL-STATIC $out, POSTBUILDS',
- command='rm -f $out && '
- './gyp-mac-tool filter-libtool libtool $libtool_flags '
- '-static -o $out $in'
- '$postbuilds')
+ master_ninja.rule(
+ 'link_host',
+ description='LINK_HOST $out',
+ command=link_command,
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline $libs $ldflags',
+ pool='link_pool')
+ else:
+ cc_command = 'bash -c "$cc_host @$out.rsp"'
+ cxx_command = 'bash -c "$cxx_host @$out.rsp"'
+ master_ninja.rule(
+ 'cc_host',
+ description='CC_HOST $out',
+ command=cc_command,
+ rspfile='$out.rsp',
+ rspfile_content=('-MMD -MF $out.d $defines $includes $cflags_host '
+ '$cflags_c_host $cflags_pch_c -c $in -o $out'),
+ depfile='$out.d')
+ master_ninja.rule(
+ 'cxx_host',
+ description='CXX_HOST $out',
+ command=cxx_command,
+ rspfile='$out.rsp',
+ rspfile_content=('-MMD -MF $out.d $defines $includes $cflags_host '
+ '$cflags_cc_host $cflags_pch_cc -c $in -o $out'),
+ depfile='$out.d')
- # Record the public interface of $lib in $lib.TOC. See the corresponding
- # comment in the posix section above for details.
- mtime_preserving_solink_base = (
- 'if [ ! -e $lib -o ! -e ${lib}.TOC ] || '
- # Always force dependent targets to relink if this library
- # reexports something. Handling this correctly would require
- # recursive TOC dumping but this is rare in practice, so punt.
- 'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then '
- '%(solink)s && %(extract_toc)s > ${lib}.TOC; '
- 'else '
- '%(solink)s && %(extract_toc)s > ${lib}.tmp && '
- 'if ! cmp -s ${lib}.tmp ${lib}.TOC; then '
- 'mv ${lib}.tmp ${lib}.TOC ; '
- 'fi; '
- 'fi' % {
- 'solink': '$ld -shared $ldflags -o $lib %(suffix)s',
- 'extract_toc':
- '{ otool -l $lib | grep LC_ID_DYLIB -A 5; '
- 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'
- })
+ alink_command = 'rm -f $out && $ar_host $arFlags_host $out @$out.rsp'
+ alink_thin_command = ('rm -f $out && $ar_host $arThinFlags_host $out '
+ '@$out.rsp')
- # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
- # -bundle -single_module here (for osmesa.so).
- master_ninja.rule(
- 'solink',
- description='SOLINK $lib, POSTBUILDS',
- restat=True,
- command=(mtime_preserving_solink_base % {
- 'suffix': '$in $solibs $libs$postbuilds'
- }))
- master_ninja.rule(
- 'solink_module',
- description='SOLINK(module) $lib, POSTBUILDS',
- restat=True,
- command=(mtime_preserving_solink_base % {
- 'suffix': '$in $solibs $libs$postbuilds'
- }))
-
- master_ninja.rule(
- 'link',
- description='LINK $out, POSTBUILDS',
- command=('$ld $ldflags -o $out '
- '$in $solibs $libs$postbuilds'),
- pool='link_pool')
- master_ninja.rule(
- 'infoplist',
- description='INFOPLIST $out',
- command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && '
- 'plutil -convert xml1 $out $out'))
- master_ninja.rule(
- 'mac_tool',
- description='MACTOOL $mactool_cmd $in',
- command='$env ./gyp-mac-tool $mactool_cmd $in $out')
- master_ninja.rule(
- 'package_framework',
- description='PACKAGE FRAMEWORK $out, POSTBUILDS',
- command='./gyp-mac-tool package-framework $out $version$postbuilds '
- '&& touch $out')
- if flavor in microsoft_flavors:
- master_ninja.rule(
- 'stamp',
- description='STAMP $out',
- command='%s gyp-win-tool stamp $out' % python_exec)
- master_ninja.rule(
- 'copy',
- description='COPY $in $out',
- command='%s gyp-win-tool recursive-mirror $in $out' % python_exec)
- elif sys.platform in ['cygwin', 'win32']:
- master_ninja.rule(
- 'stamp',
- description='STAMP $out',
- command='$python gyp-win-tool stamp $out')
- master_ninja.rule(
- 'copy',
- description='COPY $in $out',
- command='$python gyp-win-tool recursive-mirror $in $out')
- else:
- master_ninja.rule(
- 'stamp', description='STAMP $out', command='${postbuilds}touch $out')
- master_ninja.rule(
- 'copy',
- description='COPY $in $out',
- command='rm -rf $out && cp -af $in $out')
- master_ninja.newline()
-
- # Output host building rules
- if is_windows:
- cc_command = ('$cc /nologo /showIncludes /FC '
- '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
- cxx_command = ('$cxx /nologo /showIncludes /FC '
- '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
- master_ninja.rule(
- 'cc_host',
- description='CC_HOST $out',
- command=cc_command,
- deps='msvc',
- rspfile='$out.rsp',
- rspfile_content='$defines $includes $cflags_host $cflags_c_host')
- master_ninja.rule(
- 'cxx_host',
- description='CXX_HOST $out',
- command=cxx_command,
- deps='msvc',
- rspfile='$out.rsp',
- rspfile_content='$defines $includes $cflags_host $cflags_cc_host')
-
- master_ninja.rule(
- 'alink_host',
- description='LIB_HOST $out',
- command=('%s gyp-win-tool link-wrapper $arch '
- '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % python_exec),
- rspfile='$out.rsp',
- rspfile_content='$in_newline $libflags_host')
-
- master_ninja.rule(
- 'alink_thin_host',
- description='LIB_HOST $out',
- command=('%s gyp-win-tool link-wrapper $arch '
- '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % python_exec),
- rspfile='$out.rsp',
- rspfile_content='$in_newline $libflags_host')
-
- link_command = ('%s gyp-win-tool link-wrapper $arch '
- '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %
- (python_exec))
-
- master_ninja.rule(
- 'link_host',
- description='LINK_HOST $out',
- command=link_command,
- rspfile='$out.rsp',
- rspfile_content='$in_newline $libs $ldflags',
- pool='link_pool')
- else:
- cc_command = 'bash -c "$cc_host @$out.rsp"'
- cxx_command = 'bash -c "$cxx_host @$out.rsp"'
- master_ninja.rule(
- 'cc_host',
- description='CC_HOST $out',
- command=cc_command,
- rspfile='$out.rsp',
- rspfile_content=('-MMD -MF $out.d $defines $includes $cflags_host '
- '$cflags_c_host $cflags_pch_c -c $in -o $out'),
- depfile='$out.d')
- master_ninja.rule(
- 'cxx_host',
- description='CXX_HOST $out',
- command=cxx_command,
- rspfile='$out.rsp',
- rspfile_content=('-MMD -MF $out.d $defines $includes $cflags_host '
- '$cflags_cc_host $cflags_pch_cc -c $in -o $out'),
- depfile='$out.d')
-
- alink_command = 'rm -f $out && $ar_host $arFlags_host $out @$out.rsp'
- alink_thin_command = ('rm -f $out && $ar_host $arThinFlags_host $out '
- '@$out.rsp')
-
- master_ninja.rule(
- 'alink_host',
- description='AR_HOST $out',
- command='bash -c "' + alink_command + '"',
- rspfile='$out.rsp',
- rspfile_content='$in_newline')
- master_ninja.rule(
- 'alink_thin_host',
- description='AR_HOST $out',
- command='bash -c "' + alink_thin_command + '"',
- rspfile='$out.rsp',
- rspfile_content='$in_newline')
- beginlinkinlibs = ''
- endlinkinlibs = ''
- if is_linux:
- beginlinkinlibs = '-Wl,--start-group'
- endlinkinlibs = '-Wl,--end-group'
- rpath = '-Wl,-rpath=\$$ORIGIN/lib'
- master_ninja.rule(
- 'link_host',
- description='LINK_HOST $out',
- command=('bash -c "$ld_host $ldflags_host -o $out %s '
- '%s $in $solibs %s $libs"' % (rpath, beginlinkinlibs,
- endlinkinlibs)))
+ master_ninja.rule(
+ 'alink_host',
+ description='AR_HOST $out',
+ command='bash -c "' + alink_command + '"',
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline')
+ master_ninja.rule(
+ 'alink_thin_host',
+ description='AR_HOST $out',
+ command='bash -c "' + alink_thin_command + '"',
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline')
+ beginlinkinlibs = ''
+ endlinkinlibs = ''
+ if is_linux:
+ beginlinkinlibs = '-Wl,--start-group'
+ endlinkinlibs = '-Wl,--end-group'
+ rpath = '-Wl,-rpath=\$$ORIGIN/lib'
+ master_ninja.rule(
+ 'link_host',
+ description='LINK_HOST $out',
+ command=('bash -c "$ld_host $ldflags_host -o $out %s '
+ '%s $in $solibs %s $libs"' % (rpath, beginlinkinlibs,
+ endlinkinlibs)))
all_targets = set()
for build_file in params['build_files']: