diff --git a/.gitignore b/.gitignore index 5ba7c07..719b6b94 100644 --- a/.gitignore +++ b/.gitignore
@@ -89,6 +89,7 @@ /chrome/browser/extensions/default_extensions/chromeos /chrome/browser/google/linkdoctor_internal /chrome/browser/internal +/chrome/browser/media/engagement_internal /chrome/browser/performance_monitor/performance_monitor.xml /chrome/browser/protector/internal /chrome/browser/resources/chromeos/quickoffice
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index e2b46c45..2de9436 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -260,6 +260,89 @@ } IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest, + NonPersistentWebNotificationOptionsReflection) { + ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest()); + + // First, test the default values. + + std::string script_result; + ASSERT_TRUE(RunScript("DisplayNonPersistentNotification('Title', {})", + &script_result)); + EXPECT_EQ("ok", script_result); + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(false /* is_persistent */); + ASSERT_EQ(1u, notifications.size()); + + // We don't use the notification's direction or language, hence we don't check + // those properties here. + const message_center::Notification& default_notification = notifications[0]; + EXPECT_EQ("Title", base::UTF16ToUTF8(default_notification.title())); + EXPECT_EQ("", base::UTF16ToUTF8(default_notification.message())); + EXPECT_TRUE(default_notification.image().IsEmpty()); + EXPECT_TRUE(default_notification.icon().IsEmpty()); + EXPECT_TRUE(default_notification.small_image().IsEmpty()); + EXPECT_FALSE(default_notification.renotify()); + EXPECT_FALSE(default_notification.silent()); + EXPECT_FALSE(default_notification.never_timeout()); + EXPECT_EQ(0u, default_notification.buttons().size()); + + // Verifies that the notification's default timestamp is set in the last 30 + // seconds. This number has no significance, but it needs to be significantly + // high to avoid flakiness in the test. + EXPECT_NEAR(default_notification.timestamp().ToJsTime(), + base::Time::Now().ToJsTime(), 30 * 1000); + + // Now, test the non-default values. + + ASSERT_TRUE(RunScript(R"(DisplayNonPersistentNotification('Title', { + body: 'Contents', + tag: 'replace-id', + dir: 'rtl', + lang: 'nl-NL', + image: 'icon.png', + icon: 'icon.png', + badge: 'icon.png', + timestamp: 621046800000, + renotify: true, + silent: true, + requireInteraction: true, + data: [ + { property: 'value' } + ] + }))", + &script_result)); + EXPECT_EQ("ok", script_result); + + notifications = GetDisplayedNotifications(false /* is_persistent */); + ASSERT_EQ(2u, notifications.size()); + + // We don't use the notification's direction or language, hence we don't check + // those properties here. + const message_center::Notification& all_options_notification = + notifications[1]; + EXPECT_EQ("Title", base::UTF16ToUTF8(all_options_notification.title())); + EXPECT_EQ("Contents", base::UTF16ToUTF8(all_options_notification.message())); + // The js-provided tag should be part of the id. + EXPECT_FALSE(all_options_notification.id().find("replace-id") == + std::string::npos); +#if !defined(OS_MACOSX) + EXPECT_FALSE(all_options_notification.image().IsEmpty()); + EXPECT_EQ(kIconWidth, all_options_notification.image().Width()); + EXPECT_EQ(kIconHeight, all_options_notification.image().Height()); +#endif + EXPECT_FALSE(all_options_notification.icon().IsEmpty()); + EXPECT_EQ(kIconWidth, all_options_notification.icon().Width()); + EXPECT_EQ(kIconHeight, all_options_notification.icon().Height()); + EXPECT_TRUE(all_options_notification.small_image().IsEmpty()); + EXPECT_TRUE(all_options_notification.renotify()); + EXPECT_TRUE(all_options_notification.silent()); + EXPECT_TRUE(all_options_notification.never_timeout()); + EXPECT_DOUBLE_EQ(kNotificationTimestamp, + all_options_notification.timestamp().ToJsTime()); +} + +IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest, WebNotificationOptionsReflection) { ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest()); @@ -274,7 +357,8 @@ GetDisplayedNotifications(true /* is_persistent */); ASSERT_EQ(1u, notifications.size()); - // We don't use or check the notification's direction and language. + // We don't use the notification's direction or language, hence we don't check + // those properties here. const message_center::Notification& default_notification = notifications[0]; EXPECT_EQ("Some title", base::UTF16ToUTF8(default_notification.title())); EXPECT_EQ("", base::UTF16ToUTF8(default_notification.message())); @@ -301,7 +385,8 @@ notifications = GetDisplayedNotifications(true /* is_persistent */); ASSERT_EQ(2u, notifications.size()); - // We don't use or check the notification's direction and language. + // We don't use the notification's direction or language, hence we don't check + // those properties here. const message_center::Notification& all_options_notification = notifications[1]; EXPECT_EQ("Title", base::UTF16ToUTF8(all_options_notification.title())); @@ -877,3 +962,95 @@ // notification should be shown without an image. EXPECT_TRUE(notifications[0].image().IsEmpty()); } + +class PlatformNotificationServiceMojoEnabledBrowserTest + : public PlatformNotificationServiceBrowserTest { + public: + // InProcessBrowserTest overrides. + void SetUpInProcessBrowserTestFixture() override { + scoped_feature_list_.InitWithFeatures({features::kNotificationsWithMojo}, + {}); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceMojoEnabledBrowserTest, + NonPersistentWebNotificationOptionsReflection) { + ASSERT_NO_FATAL_FAILURE(GrantNotificationPermissionForTest()); + + // First, test the default values. + + std::string script_result; + { + // This closure ensures the notification has been shown before we check it. + // TODO(crbug.com/595685): We can dispense with this closure once the show + // event is implemented via mojo. + base::RunLoop run_loop; + display_service_tester_->SetNotificationAddedClosure( + run_loop.QuitClosure()); + + ASSERT_TRUE(RunScript( + "DisplayNonPersistentNotificationWithoutWaitingForEvent('Title')", + &script_result)); + EXPECT_EQ("sync-ok", script_result); + + run_loop.Run(); + } + + std::vector<message_center::Notification> notifications = + GetDisplayedNotifications(false /* is_persistent */); + ASSERT_EQ(1u, notifications.size()); + + // We don't use the notification's direction or language, hence we don't check + // those properties here. + const message_center::Notification& default_notification = notifications[0]; + EXPECT_EQ("Title", base::UTF16ToUTF8(default_notification.title())); + EXPECT_EQ("", base::UTF16ToUTF8(default_notification.message())); + EXPECT_TRUE(default_notification.image().IsEmpty()); + EXPECT_TRUE(default_notification.icon().IsEmpty()); + EXPECT_TRUE(default_notification.small_image().IsEmpty()); + EXPECT_FALSE(default_notification.renotify()); + EXPECT_FALSE(default_notification.silent()); + EXPECT_FALSE(default_notification.never_timeout()); + EXPECT_EQ(0u, default_notification.buttons().size()); + // TODO(https://crbug.com/595685): Test the default notification timestamp. + + // Now, test the non-default values. + + { + // This closure ensures the notification has been shown before we check it. + // TODO(crbug.com/595685): We can dispense with this closure once the show + // event is implemented via mojo. + base::RunLoop run_loop; + display_service_tester_->SetNotificationAddedClosure( + run_loop.QuitClosure()); + ASSERT_TRUE(RunScript( + R"(DisplayNonPersistentNotificationWithoutWaitingForEvent('Title2', { + body: 'Contents', + tag: 'replace-id', + dir: 'rtl', + lang: 'nl-NL', + image: 'icon.png', + icon: 'icon.png', + badge: 'icon.png', + timestamp: 621046800000, + renotify: true, + silent: true, + requireInteraction: true, + data: [ + { property: 'value' } + ] + }))", + &script_result)); + EXPECT_EQ("sync-ok", script_result); + + run_loop.Run(); + } + + notifications = GetDisplayedNotifications(false /* is_persistent */); + ASSERT_EQ(2u, notifications.size()); + + // TODO(https://crbug.com/595685): Test the rest of the properties. +}
diff --git a/chrome/test/data/notifications/platform_notification_service.html b/chrome/test/data/notifications/platform_notification_service.html index 1a7f347..a504667e 100644 --- a/chrome/test/data/notifications/platform_notification_service.html +++ b/chrome/test/data/notifications/platform_notification_service.html
@@ -21,6 +21,8 @@ }); } + // Instantiates a new non-persistent notification with the given |title| + // and |options| and forwards the notification shown or error event. function DisplayNonPersistentNotification(title, options) { const notification = new Notification(title, options || {}); notification.addEventListener('show', e => @@ -29,6 +31,14 @@ domAutomationController.send('could not show notification')); } + // Instantiates a new non-persistent notification with the given |title| + // and |options| and then forwards script result 'sync-ok', without + // waiting for a notification shown or error event. + function DisplayNonPersistentNotificationWithoutWaitingForEvent(title, options) { + const notification = new Notification(title, options || {}); + domAutomationController.send('sync-ok'); + } + // Renews the registered Service Worker registration for this page, then // displays a notification on the activated ServiceWorkerRegistration. function DisplayPersistentNotification(title, options) {
diff --git a/content/browser/notifications/blink_notification_service_impl.cc b/content/browser/notifications/blink_notification_service_impl.cc index eca495e..cabdf3e 100644 --- a/content/browser/notifications/blink_notification_service_impl.cc +++ b/content/browser/notifications/blink_notification_service_impl.cc
@@ -80,15 +80,27 @@ return; PlatformNotificationData platform_notification_data; platform_notification_data.title = title; + + // TODO(https://crbug.com/595685): Generate a GUID in the + // NotificationIdGenerator instead. + static int request_id = 0; + request_id++; + + std::string notification_id = + notification_context_->notification_id_generator() + ->GenerateForNonPersistentNotification( + origin_.GetURL(), platform_notification_data.tag, request_id, + render_process_id_); + // TODO(crbug.com/595685): Plumb through the rest of the notification data and // the notification resources from blink. // Using base::Unretained is safe because Service() returns a singleton. BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::BindOnce(&PlatformNotificationService::DisplayNotification, - base::Unretained(Service()), browser_context_, "", - origin_.GetURL(), platform_notification_data, - NotificationResources())); + base::Unretained(Service()), browser_context_, + notification_id, origin_.GetURL(), + platform_notification_data, NotificationResources())); } } // namespace content
diff --git a/ios/chrome/browser/web/early_page_script_perftest.mm b/ios/chrome/browser/web/early_page_script_perftest.mm index 7694882a..d6e588ae 100644 --- a/ios/chrome/browser/web/early_page_script_perftest.mm +++ b/ios/chrome/browser/web/early_page_script_perftest.mm
@@ -42,7 +42,8 @@ }; // Tests injection time into a bare web view. -TEST_F(EarlyPageScriptPerfTest, BareWebViewInjection) { +// TODO(crbug.com/796149): Reenable it. +TEST_F(EarlyPageScriptPerfTest, FLAKY_BareWebViewInjection) { RepeatTimedRuns("Bare web view injection", ^base::TimeDelta(int) { base::ElapsedTimer timer;
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-outside.html b/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-outside.html index ae07b7e5..999ce3c 100644 --- a/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-outside.html +++ b/third_party/WebKit/LayoutTests/media/controls/modern/singletap-on-outside.html
@@ -12,18 +12,11 @@ video.addEventListener('playing', t.step_func(() => { // Single tap in the top right hand corner const coordinates = - coordinatesOutsideElement(mediaControlsOverlayPlayButton(video)); + coordinatesOutsideElement(mediaControlsOverlayPlayButtonInternal(video)); singleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1); }), { once: true }); - video.addEventListener('pause', t.unreached_func()); - - video.addEventListener('webkitfullscreenchange', t.unreached_func()); - - video.ontimeupdate = t.step_func(() => { - if (video.currentTime > 0) - t.done(); - }); + video.addEventListener('pause', t.step_func_done(), { once: true }); video.play(); });
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/slow-doubletap.html b/third_party/WebKit/LayoutTests/media/controls/modern/slow-doubletap.html index 3ee7af4..8f0471e2 100644 --- a/third_party/WebKit/LayoutTests/media/controls/modern/slow-doubletap.html +++ b/third_party/WebKit/LayoutTests/media/controls/modern/slow-doubletap.html
@@ -8,23 +8,23 @@ <script> async_test(t => { const video = document.querySelector('video'); + let didPause = false; video.onplaying = t.step_func(() => { - // Double tap in the top right hand corner - const coordinates = - coordinatesOutsideElement(mediaControlsOverlayPlayButton(video)); - doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1, 400); - }); - - video.addEventListener('pause', t.unreached_func()); - - video.addEventListener('webkitfullscreenchange', t.unreached_func()); - - video.ontimeupdate = t.step_func(() => { - if (video.currentTime > 0) + if (didPause) { t.done(); + } else { + // Double tap in the top right hand corner + const coordinates = + coordinatesOutsideElement(mediaControlsOverlayPlayButton(video)); + doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1, 400); + } }); + video.addEventListener('pause', t.step_func(() => { + didPause = true; + }), { once: true }); + video.play(); }); </script>
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/tap-to-hide-controls.html b/third_party/WebKit/LayoutTests/media/controls/modern/tap-to-hide-controls.html deleted file mode 100644 index 3b50eca..0000000 --- a/third_party/WebKit/LayoutTests/media/controls/modern/tap-to-hide-controls.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<html> -<title>Test that the controls are hidden if they are tapped</title> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<script src="../../media-controls.js"></script> -<video controls width=400 src="../../content/60_sec_video.webm"></video> -<script> -async_test(t => { - // This number comes from MediaControlOverlayPlayButtonElement.cpp. - const doubleTapTimeoutMs = 301; - const video = document.querySelector('video'); - - video.addEventListener('playing', t.step_func(() => { - assert_true(isControlsPanelVisible(video)); - - // Single tap in the top right hand corner - const c = coordinatesOutsideElement(mediaControlsOverlayPlayButton(video)); - singleTapAtCoordinates(c[0] + 1, c[1] + 1, t.step_func(() => { - // Wait for the tap to expire. - setTimeout(t.step_func_done(() => { - assert_false(isControlsPanelVisible(video)); - }), doubleTapTimeoutMs); - })); - }), { once: true }); - - video.play(); -}); -</script> -</html>i
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js index d41010aa..ed9b82d 100644 --- a/third_party/WebKit/LayoutTests/media/media-controls.js +++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -319,7 +319,7 @@ ]); } -function singleTapAtCoordinates(xPos, yPos, callback) { +function singleTapAtCoordinates(xPos, yPos) { chrome.gpuBenchmarking.pointerActionSequence([ { source: 'mouse', @@ -328,7 +328,7 @@ { name: 'pointerUp' } ] } - ], callback); + ]); } function enableDoubleTapToJumpForTest(t) {
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp index 4b5bf7ff..e4cb3e9 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -714,14 +714,6 @@ panel_->MakeOpaque(); } -void MediaControlsImpl::MakeOpaqueFromPointerEvent() { - if (IsVisible()) - return; - - MakeOpaque(); - pointer_event_did_show_controls_ = true; -} - void MediaControlsImpl::MakeTransparent() { // Only hide the cursor if the controls are enabled. if (MediaElement().ShouldShowControls()) @@ -1002,28 +994,6 @@ download_iph_manager_->UpdateInProductHelp(); } -void MediaControlsImpl::MaybeToggleControlsFromTap() { - if (MediaElement().paused()) - return; - - // If the controls are visible we should try to hide them unless they should - // be kept around for another reason. If the controls are not visible then - // show them and start the timer to automatically hide them. If a pointer - // event showed the controls in this batch of events then we should not hiden - // the controls. - if (IsVisible() && !pointer_event_did_show_controls_) { - MakeTransparent(); - } else { - MakeOpaque(); - if (ShouldHideMediaControls(kIgnoreWaitForTimer)) { - keep_showing_until_timer_fires_ = true; - StartHideMediaControlsTimer(); - } - - pointer_event_did_show_controls_ = false; - } -} - void MediaControlsImpl::DefaultEventHandler(Event* event) { HTMLDivElement::DefaultEventHandler(event); @@ -1045,7 +1015,7 @@ // Touch events are treated differently to avoid fake mouse events to trigger // random behavior. The expect behaviour for touch is that a tap will show the // controls and they will hide when the timer to hide fires. - if (is_touch_event && !IsModern()) { + if (is_touch_event) { if (event->type() != EventTypeNames::gesturetap) return; @@ -1071,7 +1041,7 @@ if (!ContainsRelatedTarget(event)) { is_mouse_over_controls_ = true; if (!MediaElement().paused()) { - MakeOpaqueFromPointerEvent(); + MakeOpaque(); StartHideMediaControlsIfNecessary(); } } @@ -1086,21 +1056,10 @@ return; } - if (event->type() == EventTypeNames::click) { - MaybeToggleControlsFromTap(); - return; - } - - // The pointer event has finished so we should clear the bit. - if (event->type() == EventTypeNames::mouseout) { - pointer_event_did_show_controls_ = false; - return; - } - if (event->type() == EventTypeNames::pointermove) { // When we get a mouse move, show the media controls, and start a timer // that will hide the media controls after a 3 seconds without a mouse move. - MakeOpaqueFromPointerEvent(); + MakeOpaque(); if (ShouldHideMediaControls(kIgnoreVideoHover)) StartHideMediaControlsTimer(); return;
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h index ee003f40..9b11473 100644 --- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h +++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
@@ -157,8 +157,6 @@ }; ControlsState State() const; - void MaybeToggleControlsFromTap(); - private: // MediaControlsMediaEventListener is a component that is listening to events // and calling the appropriate callback on MediaControlsImpl. The object is @@ -200,7 +198,6 @@ void InitializeControls(); void MakeOpaque(); - void MakeOpaqueFromPointerEvent(); void MakeTransparent(); bool IsVisible() const; @@ -319,8 +316,6 @@ bool keep_showing_until_timer_fires_ : 1; - bool pointer_event_did_show_controls_ = false; - Member<MediaDownloadInProductHelpManager> download_iph_manager_; };
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp index e479c0c..eaf4026 100644 --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
@@ -20,7 +20,6 @@ #include "public/platform/Platform.h" #include "public/platform/TaskType.h" #include "public/platform/WebSize.h" -#include "public/platform/WebTraceLocation.h" namespace { @@ -36,8 +35,11 @@ (y >= (rect.top() - margin)) && (y <= (rect.bottom() + margin))); } -// The delay between two taps to be recognized as a double tap gesture. -constexpr WTF::TimeDelta kDoubleTapDelay = TimeDelta::FromMilliseconds(300); +// The delay if a touch is outside the internal button. +constexpr WTF::TimeDelta kOutsideTouchDelay = TimeDelta::FromMilliseconds(300); + +// The delay if a touch is inside the internal button. +constexpr WTF::TimeDelta kInsideTouchDelay = TimeDelta::FromMilliseconds(0); // The number of seconds to jump when double tapping. constexpr int kNumberOfSecondsToJump = 10; @@ -183,13 +185,22 @@ left_jump_arrow_->Show(); } +void MediaControlOverlayPlayButtonElement::HandlePlayPauseEvent( + Event* event, + WTF::TimeDelta delay) { + event->SetDefaultHandled(); + + if (tap_timer_.IsActive()) + return; + + tap_timer_.StartOneShot(delay, FROM_HERE); +} + void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) { if (event->type() == EventTypeNames::click) { - event->SetDefaultHandled(); - // Double tap to navigate should only be available on modern controls. if (!MediaControlsImpl::IsModern() || !event->IsMouseEvent()) { - MaybePlayPause(); + HandlePlayPauseEvent(event, kInsideTouchDelay); return; } @@ -198,7 +209,7 @@ // TODO(beccahughes): Move to PointerEvent. MouseEvent* mouse_event = ToMouseEvent(event); if (!mouse_event->HasPosition()) { - MaybePlayPause(); + HandlePlayPauseEvent(event, kInsideTouchDelay); return; } @@ -207,14 +218,12 @@ if (IsPointInRect(*internal_button_->getBoundingClientRect(), kInnerButtonTouchPaddingSize, mouse_event->clientX(), mouse_event->clientY())) { - MaybePlayPause(); + HandlePlayPauseEvent(event, kInsideTouchDelay); } else if (!tap_timer_.IsActive()) { // If there was not a previous touch and this was outside of the button - // then we should toggle visibility with a small unnoticeable delay in - // case their is a second tap. - if (tap_timer_.IsActive()) - return; - tap_timer_.StartOneShot(kDoubleTapDelay, BLINK_FROM_HERE); + // then we should play/pause but with a small unnoticeable delay to allow + // for a secondary tap. + HandlePlayPauseEvent(event, kOutsideTouchDelay); } else { // Cancel the play pause event. tap_timer_.Stop(); @@ -256,7 +265,11 @@ } void MediaControlOverlayPlayButtonElement::TapTimerFired(TimerBase*) { - GetMediaControls().MaybeToggleControlsFromTap(); + std::unique_ptr<UserGestureIndicator> user_gesture_scope = + Frame::NotifyUserActivation(GetDocument().GetFrame(), + UserGestureToken::kNewGesture); + + MaybePlayPause(); } void MediaControlOverlayPlayButtonElement::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h index 66a0e212..f5961a35 100644 --- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h +++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.h
@@ -78,6 +78,8 @@ void MaybePlayPause(); void MaybeJump(int); + void HandlePlayPauseEvent(Event*, WTF::TimeDelta); + TaskRunnerTimer<MediaControlOverlayPlayButtonElement> tap_timer_; Member<HTMLDivElement> internal_button_;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index e94b789..b364a52 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -21,7 +21,10 @@ "graphics/cpu/arm/WebGLImageConversionNEON.h", ] -blink_platform_msa_files = [ "graphics/cpu/mips/WebGLImageConversionMSA.h" ] +blink_platform_msa_files = [ + "audio/cpu/mips/VectorMathMSA.h", + "graphics/cpu/mips/WebGLImageConversionMSA.h", +] blink_platform_sse_files = [ "audio/cpu/x86/VectorMathSSE.h", @@ -515,6 +518,7 @@ "audio/VectorMathScalar.h", "audio/android/FFTFrameOpenMAXDLAndroid.cpp", "audio/cpu/arm/VectorMathNEON.h", + "audio/cpu/mips/VectorMathMSA.h", "audio/cpu/x86/VectorMathSSE.h", "audio/cpu/x86/VectorMathX86.h", "audio/ffmpeg/FFTFrameFFMPEG.cpp",
diff --git a/third_party/WebKit/Source/platform/audio/VectorMath.cpp b/third_party/WebKit/Source/platform/audio/VectorMath.cpp index 2950177..1380a55 100644 --- a/third_party/WebKit/Source/platform/audio/VectorMath.cpp +++ b/third_party/WebKit/Source/platform/audio/VectorMath.cpp
@@ -35,18 +35,14 @@ #include "platform/audio/mac/VectorMathMac.h" #elif WTF_CPU_ARM_NEON #include "platform/audio/cpu/arm/VectorMathNEON.h" +#elif HAVE_MIPS_MSA_INTRINSICS +#include "platform/audio/cpu/mips/VectorMathMSA.h" #elif defined(ARCH_CPU_X86_FAMILY) #include "platform/audio/cpu/x86/VectorMathX86.h" #else #include "platform/audio/VectorMathScalar.h" #endif -#if HAVE_MIPS_MSA_INTRINSICS -#include "platform/cpu/mips/CommonMacrosMSA.h" -#endif - -#include <algorithm> - namespace blink { namespace VectorMath { @@ -56,6 +52,8 @@ namespace Impl = Mac; #elif WTF_CPU_ARM_NEON namespace Impl = NEON; +#elif HAVE_MIPS_MSA_INTRINSICS +namespace Impl = MSA; #elif defined(ARCH_CPU_X86_FAMILY) namespace Impl = X86; #else @@ -63,77 +61,6 @@ #endif } // namespace -void Vsma(const float* source_p, - int source_stride, - const float* scale, - float* dest_p, - int dest_stride, - size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS - int n = frames_to_process; - - if ((source_stride == 1) && (dest_stride == 1)) { - float* destPCopy = dest_p; - v4f32 vScale; - v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; - v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; - FloatInt scaleVal; - - scaleVal.floatVal = *scale; - vScale = (v4f32)__msa_fill_w(scaleVal.intVal); - - for (; n >= 32; n -= 32) { - LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, - vSrc7); - LD_SP8(destPCopy, 4, vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, - vDst7); - VSMA4(vSrc0, vSrc1, vSrc2, vSrc3, vDst0, vDst1, vDst2, vDst3, vScale); - VSMA4(vSrc4, vSrc5, vSrc6, vSrc7, vDst4, vDst5, vDst6, vDst7, vScale); - ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); - } - } - - frames_to_process = n; -#endif - - Impl::Vsma(source_p, source_stride, scale, dest_p, dest_stride, - frames_to_process); -} - -void Vsmul(const float* source_p, - int source_stride, - const float* scale, - float* dest_p, - int dest_stride, - size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS - int n = frames_to_process; - - if ((source_stride == 1) && (dest_stride == 1)) { - v4f32 vScale; - v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; - v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; - FloatInt scaleVal; - - scaleVal.floatVal = *scale; - vScale = (v4f32)__msa_fill_w(scaleVal.intVal); - - for (; n >= 32; n -= 32) { - LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, - vSrc7); - VSMUL4(vSrc0, vSrc1, vSrc2, vSrc3, vDst0, vDst1, vDst2, vDst3, vScale); - VSMUL4(vSrc4, vSrc5, vSrc6, vSrc7, vDst4, vDst5, vDst6, vDst7, vScale); - ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); - } - } - - frames_to_process = n; -#endif - - Impl::Vsmul(source_p, source_stride, scale, dest_p, dest_stride, - frames_to_process); -} - void Vadd(const float* source1p, int source_stride1, const float* source2p, @@ -141,136 +68,10 @@ float* dest_p, int dest_stride, size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS - int n = frames_to_process; - - if ((source_stride1 == 1) && (source_stride2 == 1) && (dest_stride == 1)) { - v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6, - vSrc1P7; - v4f32 vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, vSrc2P6, - vSrc2P7; - v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; - - for (; n >= 32; n -= 32) { - LD_SP8(source1p, 4, vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, - vSrc1P6, vSrc1P7); - LD_SP8(source2p, 4, vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, - vSrc2P6, vSrc2P7); - ADD4(vSrc1P0, vSrc2P0, vSrc1P1, vSrc2P1, vSrc1P2, vSrc2P2, vSrc1P3, - vSrc2P3, vDst0, vDst1, vDst2, vDst3); - ADD4(vSrc1P4, vSrc2P4, vSrc1P5, vSrc2P5, vSrc1P6, vSrc2P6, vSrc1P7, - vSrc2P7, vDst4, vDst5, vDst6, vDst7); - ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); - } - } - - frames_to_process = n; -#endif - Impl::Vadd(source1p, source_stride1, source2p, source_stride2, dest_p, dest_stride, frames_to_process); } -void Vmul(const float* source1p, - int source_stride1, - const float* source2p, - int source_stride2, - float* dest_p, - int dest_stride, - size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS - int n = frames_to_process; - - if ((source_stride1 == 1) && (source_stride2 == 1) && (dest_stride == 1)) { - v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6, - vSrc1P7; - v4f32 vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, vSrc2P6, - vSrc2P7; - v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; - - for (; n >= 32; n -= 32) { - LD_SP8(source1p, 4, vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, - vSrc1P6, vSrc1P7); - LD_SP8(source2p, 4, vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, - vSrc2P6, vSrc2P7); - MUL4(vSrc1P0, vSrc2P0, vSrc1P1, vSrc2P1, vSrc1P2, vSrc2P2, vSrc1P3, - vSrc2P3, vDst0, vDst1, vDst2, vDst3); - MUL4(vSrc1P4, vSrc2P4, vSrc1P5, vSrc2P5, vSrc1P6, vSrc2P6, vSrc1P7, - vSrc2P7, vDst4, vDst5, vDst6, vDst7); - ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); - } - } - - frames_to_process = n; -#endif - - Impl::Vmul(source1p, source_stride1, source2p, source_stride2, dest_p, - dest_stride, frames_to_process); -} - -void Zvmul(const float* real1p, - const float* imag1p, - const float* real2p, - const float* imag2p, - float* real_dest_p, - float* imag_dest_p, - size_t frames_to_process) { - Impl::Zvmul(real1p, imag1p, real2p, imag2p, real_dest_p, imag_dest_p, - frames_to_process); -} - -void Vsvesq(const float* source_p, - int source_stride, - float* sum_p, - size_t frames_to_process) { - float sum = 0; - - Impl::Vsvesq(source_p, source_stride, &sum, frames_to_process); - - DCHECK(sum_p); - *sum_p = sum; -} - -void Vmaxmgv(const float* source_p, - int source_stride, - float* max_p, - size_t frames_to_process) { - float max = 0; - -#if HAVE_MIPS_MSA_INTRINSICS - int n = frames_to_process; - - if (source_stride == 1) { - v4f32 vMax = { - 0, - }; - v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; - const v16i8 vSignBitMask = (v16i8)__msa_fill_w(0x7FFFFFFF); - - for (; n >= 32; n -= 32) { - LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, - vSrc7); - AND_W4_SP(vSrc0, vSrc1, vSrc2, vSrc3, vSignBitMask); - VMAX_W4_SP(vSrc0, vSrc1, vSrc2, vSrc3, vMax); - AND_W4_SP(vSrc4, vSrc5, vSrc6, vSrc7, vSignBitMask); - VMAX_W4_SP(vSrc4, vSrc5, vSrc6, vSrc7, vMax); - } - - max = std::max(max, vMax[0]); - max = std::max(max, vMax[1]); - max = std::max(max, vMax[2]); - max = std::max(max, vMax[3]); - } - - frames_to_process = n; -#endif - - Impl::Vmaxmgv(source_p, source_stride, &max, frames_to_process); - - DCHECK(max_p); - *max_p = max; -} - void Vclip(const float* source_p, int source_stride, const float* low_threshold_p, @@ -290,38 +91,80 @@ DCHECK_LE(low_threshold, high_threshold); #endif -#if HAVE_MIPS_MSA_INTRINSICS - int n = frames_to_process; - - if ((source_stride == 1) && (dest_stride == 1)) { - v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; - v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; - v4f32 vLowThr, vHighThr; - FloatInt lowThr, highThr; - - lowThr.floatVal = low_threshold; - highThr.floatVal = high_threshold; - vLowThr = (v4f32)__msa_fill_w(lowThr.intVal); - vHighThr = (v4f32)__msa_fill_w(highThr.intVal); - - for (; n >= 32; n -= 32) { - LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, - vSrc7); - VCLIP4(vSrc0, vSrc1, vSrc2, vSrc3, vLowThr, vHighThr, vDst0, vDst1, vDst2, - vDst3); - VCLIP4(vSrc4, vSrc5, vSrc6, vSrc7, vLowThr, vHighThr, vDst4, vDst5, vDst6, - vDst7); - ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); - } - } - - frames_to_process = n; -#endif - Impl::Vclip(source_p, source_stride, &low_threshold, &high_threshold, dest_p, dest_stride, frames_to_process); } +void Vmaxmgv(const float* source_p, + int source_stride, + float* max_p, + size_t frames_to_process) { + float max = 0; + + Impl::Vmaxmgv(source_p, source_stride, &max, frames_to_process); + + DCHECK(max_p); + *max_p = max; +} + +void Vmul(const float* source1p, + int source_stride1, + const float* source2p, + int source_stride2, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + Impl::Vmul(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, frames_to_process); +} + +void Vsma(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + const float k = *scale; + + Impl::Vsma(source_p, source_stride, &k, dest_p, dest_stride, + frames_to_process); +} + +void Vsmul(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + const float k = *scale; + + Impl::Vsmul(source_p, source_stride, &k, dest_p, dest_stride, + frames_to_process); +} + +void Vsvesq(const float* source_p, + int source_stride, + float* sum_p, + size_t frames_to_process) { + float sum = 0; + + Impl::Vsvesq(source_p, source_stride, &sum, frames_to_process); + + DCHECK(sum_p); + *sum_p = sum; +} + +void Zvmul(const float* real1p, + const float* imag1p, + const float* real2p, + const float* imag2p, + float* real_dest_p, + float* imag_dest_p, + size_t frames_to_process) { + Impl::Zvmul(real1p, imag1p, real2p, imag2p, real_dest_p, imag_dest_p, + frames_to_process); +} + } // namespace VectorMath } // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/cpu/mips/VectorMathMSA.h b/third_party/WebKit/Source/platform/audio/cpu/mips/VectorMathMSA.h new file mode 100644 index 0000000..5754575c --- /dev/null +++ b/third_party/WebKit/Source/platform/audio/cpu/mips/VectorMathMSA.h
@@ -0,0 +1,232 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VectorMathMSA_h +#define VectorMathMSA_h + +#include <algorithm> + +#include "platform/audio/VectorMathScalar.h" +#include "platform/cpu/mips/CommonMacrosMSA.h" + +namespace blink { +namespace VectorMath { +namespace MSA { + +static ALWAYS_INLINE void Vadd(const float* source1p, + int source_stride1, + const float* source2p, + int source_stride2, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) { + v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6, + vSrc1P7; + v4f32 vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, vSrc2P6, + vSrc2P7; + v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; + + for (; n >= 32; n -= 32) { + LD_SP8(source1p, 4, vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, + vSrc1P6, vSrc1P7); + LD_SP8(source2p, 4, vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, + vSrc2P6, vSrc2P7); + ADD4(vSrc1P0, vSrc2P0, vSrc1P1, vSrc2P1, vSrc1P2, vSrc2P2, vSrc1P3, + vSrc2P3, vDst0, vDst1, vDst2, vDst3); + ADD4(vSrc1P4, vSrc2P4, vSrc1P5, vSrc2P5, vSrc1P6, vSrc2P6, vSrc1P7, + vSrc2P7, vDst4, vDst5, vDst6, vDst7); + ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); + } + } + + Scalar::Vadd(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, n); +} + +static ALWAYS_INLINE void Vclip(const float* source_p, + int source_stride, + const float* low_threshold_p, + const float* high_threshold_p, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1 && dest_stride == 1) { + v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; + v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; + v4f32 vLowThr, vHighThr; + FloatInt lowThr, highThr; + + lowThr.floatVal = *low_threshold_p; + highThr.floatVal = *high_threshold_p; + vLowThr = (v4f32)__msa_fill_w(lowThr.intVal); + vHighThr = (v4f32)__msa_fill_w(highThr.intVal); + + for (; n >= 32; n -= 32) { + LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, + vSrc7); + VCLIP4(vSrc0, vSrc1, vSrc2, vSrc3, vLowThr, vHighThr, vDst0, vDst1, vDst2, + vDst3); + VCLIP4(vSrc4, vSrc5, vSrc6, vSrc7, vLowThr, vHighThr, vDst4, vDst5, vDst6, + vDst7); + ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); + } + } + + Scalar::Vclip(source_p, source_stride, low_threshold_p, high_threshold_p, + dest_p, dest_stride, n); +} + +static ALWAYS_INLINE void Vmaxmgv(const float* source_p, + int source_stride, + float* max_p, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1) { + v4f32 vMax = { + 0, + }; + v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; + const v16i8 vSignBitMask = (v16i8)__msa_fill_w(0x7FFFFFFF); + + for (; n >= 32; n -= 32) { + LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, + vSrc7); + AND_W4_SP(vSrc0, vSrc1, vSrc2, vSrc3, vSignBitMask); + VMAX_W4_SP(vSrc0, vSrc1, vSrc2, vSrc3, vMax); + AND_W4_SP(vSrc4, vSrc5, vSrc6, vSrc7, vSignBitMask); + VMAX_W4_SP(vSrc4, vSrc5, vSrc6, vSrc7, vMax); + } + + *max_p = std::max(*max_p, vMax[0]); + *max_p = std::max(*max_p, vMax[1]); + *max_p = std::max(*max_p, vMax[2]); + *max_p = std::max(*max_p, vMax[3]); + } + + Scalar::Vmaxmgv(source_p, source_stride, max_p, n); +} + +static ALWAYS_INLINE void Vmul(const float* source1p, + int source_stride1, + const float* source2p, + int source_stride2, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) { + v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6, + vSrc1P7; + v4f32 vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, vSrc2P6, + vSrc2P7; + v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; + + for (; n >= 32; n -= 32) { + LD_SP8(source1p, 4, vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, + vSrc1P6, vSrc1P7); + LD_SP8(source2p, 4, vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, + vSrc2P6, vSrc2P7); + MUL4(vSrc1P0, vSrc2P0, vSrc1P1, vSrc2P1, vSrc1P2, vSrc2P2, vSrc1P3, + vSrc2P3, vDst0, vDst1, vDst2, vDst3); + MUL4(vSrc1P4, vSrc2P4, vSrc1P5, vSrc2P5, vSrc1P6, vSrc2P6, vSrc1P7, + vSrc2P7, vDst4, vDst5, vDst6, vDst7); + ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); + } + } + + Scalar::Vmul(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, n); +} + +static ALWAYS_INLINE void Vsma(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1 && dest_stride == 1) { + float* destPCopy = dest_p; + v4f32 vScale; + v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; + v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; + FloatInt scaleVal; + + scaleVal.floatVal = *scale; + vScale = (v4f32)__msa_fill_w(scaleVal.intVal); + + for (; n >= 32; n -= 32) { + LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, + vSrc7); + LD_SP8(destPCopy, 4, vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, + vDst7); + VSMA4(vSrc0, vSrc1, vSrc2, vSrc3, vDst0, vDst1, vDst2, vDst3, vScale); + VSMA4(vSrc4, vSrc5, vSrc6, vSrc7, vDst4, vDst5, vDst6, vDst7, vScale); + ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); + } + } + + Scalar::Vsma(source_p, source_stride, scale, dest_p, dest_stride, n); +} + +static ALWAYS_INLINE void Vsmul(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1 && dest_stride == 1) { + v4f32 vScale; + v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; + v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; + FloatInt scaleVal; + + scaleVal.floatVal = *scale; + vScale = (v4f32)__msa_fill_w(scaleVal.intVal); + + for (; n >= 32; n -= 32) { + LD_SP8(source_p, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, + vSrc7); + VSMUL4(vSrc0, vSrc1, vSrc2, vSrc3, vDst0, vDst1, vDst2, vDst3, vScale); + VSMUL4(vSrc4, vSrc5, vSrc6, vSrc7, vDst4, vDst5, vDst6, vDst7, vScale); + ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); + } + } + + Scalar::Vsmul(source_p, source_stride, scale, dest_p, dest_stride, n); +} + +static ALWAYS_INLINE void Vsvesq(const float* source_p, + int source_stride, + float* sum_p, + size_t frames_to_process) { + Scalar::Vsvesq(source_p, source_stride, sum_p, n); +} + +static ALWAYS_INLINE void Zvmul(const float* real1p, + const float* imag1p, + const float* real2p, + const float* imag2p, + float* real_dest_p, + float* imag_dest_p, + size_t frames_to_process) { + Scalar::Zvmul(real1p, imag1p, real2p, imag2p, real_dest_p, imag_dest_p, + frames_to_process); +} + +} // namespace MSA +} // namespace VectorMath +} // namespace blink + +#endif // VectorMathMSA_h