diff options
Diffstat (limited to 'gfx/layers')
33 files changed, 600 insertions, 128 deletions
diff --git a/gfx/layers/AnimationHelper.cpp b/gfx/layers/AnimationHelper.cpp index 8cb97f19a1..ece69cd403 100644 --- a/gfx/layers/AnimationHelper.cpp +++ b/gfx/layers/AnimationHelper.cpp @@ -15,13 +15,13 @@ #include "mozilla/ServoStyleConsts.h" // for StyleComputedTimingFunction #include "mozilla/dom/AnimationEffectBinding.h" // for dom::FillMode #include "mozilla/dom/KeyframeEffectBinding.h" // for dom::IterationComposite -#include "mozilla/dom/KeyframeEffect.h" // for dom::KeyFrameEffectReadOnly -#include "mozilla/dom/Nullable.h" // for dom::Nullable -#include "mozilla/layers/APZSampler.h" // for APZSampler +#include "mozilla/dom/KeyframeEffect.h" // for dom::KeyFrameEffectReadOnly +#include "mozilla/dom/Nullable.h" // for dom::Nullable +#include "mozilla/layers/APZSampler.h" // for APZSampler #include "mozilla/AnimatedPropertyID.h" -#include "mozilla/LayerAnimationInfo.h" // for GetCSSPropertiesFor() -#include "mozilla/Maybe.h" // for Maybe<> -#include "mozilla/MotionPathUtils.h" // for ResolveMotionPath() +#include "mozilla/LayerAnimationInfo.h" // for GetCSSPropertiesFor() +#include "mozilla/Maybe.h" // for Maybe<> +#include "mozilla/MotionPathUtils.h" // for ResolveMotionPath() #include "mozilla/StyleAnimationValue.h" // for StyleAnimationValue, etc #include "nsCSSPropertyID.h" // for eCSSProperty_offset_path, etc #include "nsDisplayList.h" // for nsDisplayTransform, etc diff --git a/gfx/layers/CanvasDrawEventRecorder.cpp b/gfx/layers/CanvasDrawEventRecorder.cpp index 6140fc4ba7..8f3cd4be5c 100644 --- a/gfx/layers/CanvasDrawEventRecorder.cpp +++ b/gfx/layers/CanvasDrawEventRecorder.cpp @@ -362,11 +362,11 @@ void CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked( return; } - class ProcessPendingRunnable final : public dom::WorkerRunnable { + class ProcessPendingRunnable final : public dom::WorkerThreadRunnable { public: ProcessPendingRunnable(dom::WorkerPrivate* aWorkerPrivate, RefPtr<CanvasDrawEventRecorder>&& aRecorder) - : dom::WorkerRunnable(aWorkerPrivate), + : dom::WorkerThreadRunnable("ProcessPendingRunnable"), mRecorder(std::move(aRecorder)) {} bool WorkerRun(JSContext*, dom::WorkerPrivate*) override { @@ -381,7 +381,7 @@ void CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked( auto task = MakeRefPtr<ProcessPendingRunnable>(mWorkerRef->Private(), std::move(aRecorder)); - if (NS_WARN_IF(!task->Dispatch())) { + if (NS_WARN_IF(!task->Dispatch(mWorkerRef->Private()))) { MOZ_CRASH("ProcessPendingRunnable leaked!"); } } diff --git a/gfx/layers/GPUVideoImage.h b/gfx/layers/GPUVideoImage.h index a9bbb5950d..b511d55ccc 100644 --- a/gfx/layers/GPUVideoImage.h +++ b/gfx/layers/GPUVideoImage.h @@ -72,7 +72,9 @@ class GPUVideoImage final : public Image { gfx::ColorDepth GetColorDepth() const override { return mColorDepth; } gfx::ColorSpace2 GetColorPrimaries() const { return mColorSpace; } gfx::YUVColorSpace GetYUVColorSpace() const { return mYUVColorSpace; } - gfx::TransferFunction GetTransferFunction() const { return mTransferFunction; } + gfx::TransferFunction GetTransferFunction() const { + return mTransferFunction; + } gfx::ColorRange GetColorRange() const { return mColorRange; } Maybe<SurfaceDescriptor> GetDesc() override { diff --git a/gfx/layers/LayersTypes.cpp b/gfx/layers/LayersTypes.cpp index 81ea1aa88f..392af31862 100644 --- a/gfx/layers/LayersTypes.cpp +++ b/gfx/layers/LayersTypes.cpp @@ -91,5 +91,17 @@ GpuProcessQueryId GpuProcessQueryId::GetNext() { return GpuProcessQueryId{++sCounter}; } +std::ostream& operator<<(std::ostream& os, ScrollDirection aDirection) { + switch (aDirection) { + case ScrollDirection::eHorizontal: + os << "horizontal"; + break; + case ScrollDirection::eVertical: + os << "vertical"; + break; + } + return os; +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/LayersTypes.h b/gfx/layers/LayersTypes.h index c02851d81f..ab26523e60 100644 --- a/gfx/layers/LayersTypes.h +++ b/gfx/layers/LayersTypes.h @@ -463,6 +463,8 @@ MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint8_t, ( eHorizontal )); +std::ostream& operator<<(std::ostream& os, ScrollDirection aDirection); + using ScrollDirections = EnumSet<ScrollDirection, uint8_t>; constexpr ScrollDirections EitherScrollDirection(ScrollDirection::eVertical,ScrollDirection::eHorizontal); diff --git a/gfx/layers/ScrollableLayerGuid.cpp b/gfx/layers/ScrollableLayerGuid.cpp index 914a8ad124..42a8a4824f 100644 --- a/gfx/layers/ScrollableLayerGuid.cpp +++ b/gfx/layers/ScrollableLayerGuid.cpp @@ -8,7 +8,8 @@ #include <ostream> #include "mozilla/HashFunctions.h" // for HashGeneric -#include "nsPrintfCString.h" // for nsPrintfCString +#include "mozilla/IntegerPrintfMacros.h" +#include "nsPrintfCString.h" // for nsPrintfCString namespace mozilla { namespace layers { diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index a070340421..84b4a95b9e 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1988,6 +1988,10 @@ ParentLayerPoint AsyncPanZoomController::GetScrollWheelDelta( // Apply user-set multipliers. delta.x *= aMultiplierX; delta.y *= aMultiplierY; + APZC_LOGV( + "user-multiplied delta is %s (deltaType %d, line size %s, page size %s)", + ToString(delta).c_str(), (int)aEvent.mDeltaType, + ToString(scrollAmount).c_str(), ToString(pageScrollSize).c_str()); // For the conditions under which we allow system scroll overrides, see // WidgetWheelEvent::OverriddenDelta{X,Y}. @@ -1999,6 +2003,7 @@ ParentLayerPoint AsyncPanZoomController::GetScrollWheelDelta( aEvent.mAllowToOverrideSystemScrollSpeed) { delta.x = WidgetWheelEvent::ComputeOverriddenDelta(delta.x, false); delta.y = WidgetWheelEvent::ComputeOverriddenDelta(delta.y, true); + APZC_LOGV("overridden delta is %s", ToString(delta).c_str()); } // If this is a line scroll, and this event was part of a scroll series, then @@ -2258,6 +2263,8 @@ bool AsyncPanZoomController::AllowOneTouchPinch() const { // Return whether or not the underlying layer can be scrolled on either axis. bool AsyncPanZoomController::CanScroll(const InputData& aEvent) const { ParentLayerPoint delta = GetDeltaForEvent(aEvent); + APZC_LOGV_DETAIL("CanScroll: event delta is %s", this, + ToString(delta).c_str()); if (!delta.x && !delta.y) { return false; } @@ -2330,6 +2337,9 @@ bool AsyncPanZoomController::CanScrollWithWheel( disregardedDirection != Some(ScrollDirection::eVertical)) { return true; } + APZC_LOGV_FM(Metrics(), + "cannot scroll with wheel (disregarded direction is %s)", + ToString(disregardedDirection).c_str()); return false; } diff --git a/gfx/layers/apz/src/FocusState.cpp b/gfx/layers/apz/src/FocusState.cpp index 0230676e7e..84bf0b4570 100644 --- a/gfx/layers/apz/src/FocusState.cpp +++ b/gfx/layers/apz/src/FocusState.cpp @@ -7,6 +7,7 @@ #include "FocusState.h" #include "mozilla/Logging.h" +#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/layers/APZThreadUtils.h" static mozilla::LazyLogModule sApzFstLog("apz.focusstate"); diff --git a/gfx/layers/apz/src/InputBlockState.h b/gfx/layers/apz/src/InputBlockState.h index d65b1cb57b..d27e7ead27 100644 --- a/gfx/layers/apz/src/InputBlockState.h +++ b/gfx/layers/apz/src/InputBlockState.h @@ -501,9 +501,9 @@ class TouchBlockState : public CancelableBlockState { mIsWaitingLongTapResult = false; } - void SetWaitingLongTapResult() { + void SetWaitingLongTapResult(bool aResult) { MOZ_ASSERT(!mForLongTap); - mIsWaitingLongTapResult = true; + mIsWaitingLongTapResult = aResult; } bool IsWaitingLongTapResult() const { return mIsWaitingLongTapResult; } diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index 8ad75a9794..78b70fddf4 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -204,8 +204,8 @@ APZEventResult InputQueue::ReceiveTouchInput( } else { // If all following conditions are met, we need to wait for a content // response (again); - // 1) this is the first event bailing out from in-slop state after a - // long-tap event has been fired + // 1) this is the first touch-move event bailing out from in-slop state + // after a long-tap event has been fired // 2) there's any APZ-aware event listeners // 3) the event block hasn't yet been prevented // @@ -216,7 +216,7 @@ APZEventResult InputQueue::ReceiveTouchInput( // until a long-tap event happens, then if the user started moving their // finger, we have to wait for a content response twice, one is for // `touchstart` and one is for `touchmove`. - if (wasInSlop && + if (wasInSlop && aEvent.mType == MultiTouchInput::MULTITOUCH_MOVE && (block->WasLongTapProcessed() || block->IsWaitingLongTapResult()) && !block->IsTargetOriginallyConfirmed() && !block->ShouldDropEvents()) { INPQ_LOG( @@ -637,6 +637,12 @@ uint64_t InputQueue::InjectNewTouchBlock(AsyncPanZoomController* aTarget) { TouchBlockState* InputQueue::StartNewTouchBlock( const RefPtr<AsyncPanZoomController>& aTarget, TargetConfirmationFlags aFlags) { + if (mPrevActiveTouchBlock && mActiveTouchBlock && + mActiveTouchBlock->ForLongTap()) { + mPrevActiveTouchBlock->SetWaitingLongTapResult(false); + mPrevActiveTouchBlock = nullptr; + } + TouchBlockState* newBlock = new TouchBlockState(aTarget, aFlags, mTouchCounter); @@ -664,7 +670,7 @@ TouchBlockState* InputQueue::StartNewTouchBlockForLongTap( // touch block because if the long-tap event response prevents us from // scrolling we must stop processing any subsequent touch-move events in the // same block. - currentBlock->SetWaitingLongTapResult(); + currentBlock->SetWaitingLongTapResult(true); // We need to keep the current block alive, it will be used once after this // new touch block for long-tap was processed. diff --git a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp index 8256667d6b..f5024e8208 100644 --- a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp +++ b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp @@ -10,6 +10,7 @@ #include "APZCBasicTester.h" #include "APZTestCommon.h" #include "InputUtils.h" +#include "apz/src/InputBlockState.h" #include "mozilla/StaticPrefs_apz.h" // Note: There are additional tests that test gesture detection behaviour @@ -553,6 +554,83 @@ class APZCLongPressTester : public APZCGestureDetectorTester { apzc->AssertStateIsReset(); } + + // Tests a scenario that after a long-press event happened the original touch + // block initiated by a touch-start event and the touch block initiated by a + // long-tap event have been discarded when a new touch-start event happens. + void DoLongPressDiscardTouchBlockTest(bool aWithTouchMove) { + // Set apz.content_response_timeout > ui.click_hold_context_menus.delay and + // apz.touch_start_tolerance explicitly to match Android preferences. + SCOPED_GFX_PREF_INT("apz.content_response_timeout", 60); + SCOPED_GFX_PREF_INT("ui.click_hold_context_menus.delay", 30); + SCOPED_GFX_PREF_FLOAT("apz.touch_start_tolerance", 0.06); + + MockFunction<void(std::string checkPointName)> check; + { + InSequence s; + EXPECT_CALL(check, Call("pre long-tap dispatch")); + EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10), + 0, apzc->GetGuid(), _, _)) + .Times(1); + EXPECT_CALL(check, Call("post long-tap dispatch")); + + // If a touch-move happens while long-tap is happening, there's no + // eLongTapUp event. + if (!aWithTouchMove) { + EXPECT_CALL(*mcc, + HandleTap(TapType::eLongTapUp, LayoutDevicePoint(10, 20), 0, + apzc->GetGuid(), _, _)) + .Times(1); + } + EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10), + 0, apzc->GetGuid(), _, _)) + .Times(1); + } + + // Keep touching for a while to trigger a long tap event. + uint64_t firstTouchBlockId = + TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time()).mInputBlockId; + TouchBlockState* firstTouchBlock = + tm->GetInputQueue()->GetCurrentTouchBlock(); + EXPECT_NE(firstTouchBlock, nullptr); + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(firstTouchBlockId), + firstTouchBlock); + + // Wait for a long tap. + check.Call("pre long-tap dispatch"); + mcc->AdvanceByMillis(30); + check.Call("post long-tap dispatch"); + + // Now the current touch block is not the first touch block, it should be + // a new touch block for the long tap event. + TouchBlockState* secondTouchBlock = + tm->GetInputQueue()->GetCurrentTouchBlock(); + EXPECT_NE(secondTouchBlock, firstTouchBlock); + EXPECT_TRUE(secondTouchBlock->ForLongTap()); + uint64_t secondTouchBlockId = secondTouchBlock->GetBlockId(); + + if (aWithTouchMove) { + mcc->AdvanceByMillis(10); + TouchMove(apzc, ScreenIntPoint(10, 20), mcc->Time()); + } + + // Finish the first touch block. + mcc->AdvanceByMillis(10); + TouchUp(apzc, ScreenIntPoint(10, 20), mcc->Time()); + + // And start a new touch block. + mcc->AdvanceByMillis(10); + uint64_t newTouchBlockId = + TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time()).mInputBlockId; + + mcc->AdvanceByMillis(10); + // Now the original touch block and the touch block for long-tap should have + // been discarded from the input queue. + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(firstTouchBlockId), nullptr); + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(secondTouchBlockId), nullptr); + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(newTouchBlockId), + tm->GetInputQueue()->GetCurrentBlock()); + } }; TEST_F(APZCLongPressTester, LongPress) { @@ -563,6 +641,28 @@ TEST_F(APZCLongPressTester, LongPressPreventDefault) { DoLongPressPreventDefaultTest(kDefaultTouchBehavior); } +TEST_F(APZCLongPressTester, LongPressDiscardBlock) { + DoLongPressDiscardTouchBlockTest(true /* with touch-move */); +} + +// Similar to above LongPressDiscardBlock but APZ is waiting for responses from +// the content. +TEST_F(APZCLongPressTester, LongPressDiscardBlock2) { + MakeApzcWaitForMainThread(); + DoLongPressDiscardTouchBlockTest(true /* with touch-move */); +} + +// Similar to above LongPressDiscardBlock/LongPressDiscardBlock2 without +// touch-move events. +TEST_F(APZCLongPressTester, LongPressDiscardBlock3) { + DoLongPressDiscardTouchBlockTest(false /* without touch-move */); +} + +TEST_F(APZCLongPressTester, LongPressDiscardBlock4) { + MakeApzcWaitForMainThread(); + DoLongPressDiscardTouchBlockTest(false /* without touch-move */); +} + TEST_F(APZCGestureDetectorTester, DoubleTap) { MakeApzcWaitForMainThread(); MakeApzcZoomable(); diff --git a/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html b/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html index 99616d9834..762e1cef69 100644 --- a/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html +++ b/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html @@ -7,6 +7,12 @@ <script src="apz_test_native_event_utils.js"></script> <script src="apz_test_utils.js"></script> <script src="/tests/SimpleTest/paint_listener.js"></script> + <style> + #target { + width: 100px; + height: 100px; + } + </style> <script> async function test() { diff --git a/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe.html b/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe.html new file mode 100644 index 0000000000..21efcbd9d6 --- /dev/null +++ b/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe.html @@ -0,0 +1,146 @@ +<!DOCTYPE html> +<html> + <title>A scroll over an iframe should not terminate the wheel transaction</title> + <script type="application/javascript" src="apz_test_utils.js"></script> + <script type="application/javascript" src="apz_test_native_event_utils.js"></script> + <script src="/tests/SimpleTest/paint_listener.js"></script> +<head> +<style> +body { + height: 250vh; + width: 100%; + margin: 0; + padding: 0; +} + +#spacer { + height: 50px; + width: 100vw; + background: yellow; +} + +#subframe { + width: 80vw; + height: 60vh; +} +</style> +</head> +<body> + <div id="spacer"></div> + <iframe id="subframe"> + </iframe> +</body> +<script> +const searchParams = new URLSearchParams(location.search); + +async function scrollWithPan() { + await NativePanHandler.promiseNativePanEvent( + document.scrollingElement, + 50, + 30, + 0, + NativePanHandler.delta, + NativePanHandler.beginPhase, + ); + + await NativePanHandler.promiseNativePanEvent( + document.scrollingElement, + 50, + 30, + 0, + NativePanHandler.delta, + NativePanHandler.updatePhase, + ); + + await NativePanHandler.promiseNativePanEvent( + document.scrollingElement, + 50, + 30, + 0, + NativePanHandler.delta, + NativePanHandler.endPhase, + ); +} + +async function scrollWithWheel() { + await promiseMoveMouseAndScrollWheelOver(document.scrollingElement, 50, 30, + false, 100); +} + +async function test() { + let iframeURL = + SimpleTest.getTestFileURL("helper_scroll_over_subframe_child.html"); + + switch (searchParams.get("oop")) { + case "true": + iframeURL = iframeURL.replace(window.location.origin, "https://example.com/"); + break; + default: + break; + } + + const iframeLoadPromise = promiseOneEvent(subframe, "load", null); + subframe.src = iframeURL; + await iframeLoadPromise; + + await SpecialPowers.spawn(subframe, [], async () => { + await content.wrappedJSObject.waitUntilApzStable(); + await SpecialPowers.contentTransformsReceived(content); + }); + + let childWindowReceivedWheelEvent = false; + + window.addEventListener("message", e => { + if (e.data == "child-received-wheel-event") { + childWindowReceivedWheelEvent = true; + } + }); + + await SpecialPowers.spawn(subframe, [], () => { + let target = content.document.getElementById("target") + target.style.backgroundColor = "green"; + content.getComputedStyle(target).backgroundColor; + target.addEventListener("wheel", () => { + target.style.backgroundColor = "red"; + content.getComputedStyle(target).backgroundColor; + }); + return new Promise(resolve => resolve()); + }); + + await promiseFrame(); + + let transformEndPromise = promiseTransformEnd(); + + // Scroll over the iframe + switch (searchParams.get("scroll")) { + case "wheel": + await scrollWithWheel(); + break; + case "pan": + await scrollWithPan(); + break; + default: + ok(false, "Unsupported scroll value: " + searchParams.get("scroll")); + break; + } + + await transformEndPromise; + + // Wait an extra frame to ensure any message from the child has + // extra time to be sent to the parent. + await promiseFrame(); + + let res = await SpecialPowers.spawn(subframe, [], () => { + let target = content.document.getElementById("target") + return target.style.backgroundColor; + }); + + await promiseFrame(); + + // We should not have fired a wheel event to the element in the iframe + ok(!childWindowReceivedWheelEvent, "Child window should not receive wheel events"); + is(res, "green", "OOP iframe does not halt user scroll of parent"); +} +waitUntilApzStable().then(test).then(subtestDone, subtestFailed); +</script> +</html> diff --git a/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe_child.html b/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe_child.html new file mode 100644 index 0000000000..48f03a51d9 --- /dev/null +++ b/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe_child.html @@ -0,0 +1,29 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="/tests/SimpleTest/paint_listener.js"></script> +<script src="apz_test_utils.js"></script> +<style> +body { + margin: 0px; +} + +#target { + width: 100%; + height: 100vh; + background: blue; + overflow: scroll; +} +</style> +</head> +<body> +<div id="target"> +</div> +</body> +<script> + window.addEventListener("wheel", () => { + window.parent.postMessage("child-received-wheel-event", "*"); + }); +</script> +</html> diff --git a/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html b/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html index fe4a0784a9..c1e0351ccb 100644 --- a/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html +++ b/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html @@ -24,12 +24,12 @@ var logging_and_doubletap_prefs = [ var subtests = [ {"file": "helper_doubletap_zoom.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_img.html", "prefs": doubletap_prefs}, - {"file": "helper_doubletap_zoom_textarea.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_horizontal_center.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_bug1702464.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_large_overflow.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_fixedpos.html", "prefs": logging_and_doubletap_prefs}, {"file": "helper_doubletap_zoom_tallwide.html", "prefs": doubletap_prefs}, + {"file": "helper_doubletap_zoom_textarea.html", "prefs": doubletap_prefs}, ]; if (getPlatform() == "mac") { diff --git a/gfx/layers/apz/test/mochitest/test_group_pointerevents.html b/gfx/layers/apz/test/mochitest/test_group_pointerevents.html index 9ec03edd59..8bc0690bfc 100644 --- a/gfx/layers/apz/test/mochitest/test_group_pointerevents.html +++ b/gfx/layers/apz/test/mochitest/test_group_pointerevents.html @@ -24,14 +24,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1285070 {"file": "helper_bug1682170_pointercancel_on_touchaction_pinchzoom.html", "prefs": touch_action_prefs}, {"file": "helper_bug1719855_pointercancel_on_touchmove_after_contextmenu_prevented.html"}, + {"file": "helper_bug1285070.html"}, + {"file": "helper_bug1299195.html", "prefs": [["dom.meta-viewport.enabled", isMac]]}, ]; + if (getPlatform() != "android") { // Bug 1858610: these subtests are flaky on Android. - subtests.push( - {"file": "helper_bug1285070.html"}, - {"file": "helper_bug1299195.html", "prefs": [["dom.meta-viewport.enabled", isMac]]}, - {"file": "helper_bug1502010_unconsumed_pan.html"} - ) + subtests.push({"file": "helper_bug1502010_unconsumed_pan.html"}); } if (isApzEnabled()) { diff --git a/gfx/layers/apz/test/mochitest/test_group_wheelevents.html b/gfx/layers/apz/test/mochitest/test_group_wheelevents.html index 42ce15a247..93746b9f6f 100644 --- a/gfx/layers/apz/test/mochitest/test_group_wheelevents.html +++ b/gfx/layers/apz/test/mochitest/test_group_wheelevents.html @@ -20,6 +20,13 @@ var prefs = [ ["mousewheel.transaction.timeout", 0], ]; +var wheel_transaction_prefs = [ + ["dom.event.wheel-event-groups.enabled", true], + ["mousewheel.transaction.timeout", 10000], + ["apz.test.mac.synth_wheel_input", true], + ...getSmoothScrollPrefs("wheel"), +]; + // For helper_scroll_over_scrollbar, we need to set a pref to force // layerization of the scrollbar track to reproduce the bug being fixed. // Otherwise, the bug only manifests with overlay scrollbars on macOS, @@ -48,6 +55,10 @@ var subtests = [ prefs: [["general.smoothScroll", false], ["apz.test.mac.synth_wheel_input", true]]}, {"file": "helper_scroll_anchoring_on_wheel.html", prefs: smoothness_prefs}, + {"file": "helper_scroll_over_subframe.html?scroll=wheel", prefs: wheel_transaction_prefs}, + {"file": "helper_scroll_over_subframe.html?oop=true&scroll=wheel", prefs: wheel_transaction_prefs}, + {"file": "helper_scroll_over_subframe.html?scroll=pan", prefs: wheel_transaction_prefs}, + {"file": "helper_scroll_over_subframe.html?oop=true&scroll=pan", prefs: wheel_transaction_prefs}, ]; subtests.push(...buildRelativeScrollSmoothnessVariants("wheel", ["scrollBy", "scrollTo", "scrollTop"])); diff --git a/gfx/layers/d3d11/TextureHostWrapperD3D11.cpp b/gfx/layers/d3d11/TextureHostWrapperD3D11.cpp index 380307fcea..aa6cb49f39 100644 --- a/gfx/layers/d3d11/TextureHostWrapperD3D11.cpp +++ b/gfx/layers/d3d11/TextureHostWrapperD3D11.cpp @@ -14,6 +14,7 @@ #include "mozilla/layers/GpuProcessD3D11TextureMap.h" #include "mozilla/layers/TextureD3D11.h" #include "mozilla/layers/WebRenderTextureHost.h" +#include "mozilla/ProfilerMarkers.h" #include "mozilla/SharedThreadPool.h" namespace mozilla { @@ -236,6 +237,14 @@ RefPtr<TextureHost> TextureHostWrapperD3D11::CreateFromBufferTexture( colorDepth != gfx::ColorDepth::COLOR_8 || colorRange != gfx::ColorRange::LIMITED || chromaSubsampling != gfx::ChromaSubsampling::HALF_WIDTH_AND_HEIGHT) { + if (profiler_thread_is_being_profiled_for_markers()) { + nsPrintfCString str( + "Unsupported size(%dx%d) colorDepth %hhu colorRange %hhu " + "chromaSubsampling %hhu", + size.width, size.height, uint8_t(colorDepth), uint8_t(colorRange), + uint8_t(chromaSubsampling)); + PROFILER_MARKER_TEXT("TextureHostWrapperD3D11", GRAPHICS, {}, str); + } return nullptr; } diff --git a/gfx/layers/ipc/APZCTreeManagerChild.cpp b/gfx/layers/ipc/APZCTreeManagerChild.cpp index b7f50c1c92..5dec4ca065 100644 --- a/gfx/layers/ipc/APZCTreeManagerChild.cpp +++ b/gfx/layers/ipc/APZCTreeManagerChild.cpp @@ -31,6 +31,9 @@ void APZCTreeManagerChild::SetCompositorSession( // we're setting mCompositorSession or we're clearing it). MOZ_ASSERT(!mCompositorSession ^ !aSession); mCompositorSession = aSession; + if (mInputBridge) { + mInputBridge->SetCompositorSession(aSession); + } } void APZCTreeManagerChild::SetInputBridge(APZInputBridgeChild* aInputBridge) { @@ -143,45 +146,6 @@ void APZCTreeManagerChild::ActorDestroy(ActorDestroyReason aWhy) { mIPCOpen = false; } -mozilla::ipc::IPCResult APZCTreeManagerChild::RecvHandleTap( - const TapType& aType, const LayoutDevicePoint& aPoint, - const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, - const uint64_t& aInputBlockId, - const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { - MOZ_ASSERT(XRE_IsParentProcess()); - if (mCompositorSession && - mCompositorSession->RootLayerTreeId() == aGuid.mLayersId && - mCompositorSession->GetContentController()) { - RefPtr<GeckoContentController> controller = - mCompositorSession->GetContentController(); - controller->HandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId, - aDoubleTapToZoomMetrics); - return IPC_OK(); - } - dom::BrowserParent* tab = - dom::BrowserParent::GetBrowserParentFromLayersId(aGuid.mLayersId); - if (tab) { -#ifdef MOZ_WIDGET_ANDROID - // On Android, touch events are dispatched from the UI thread to the main - // thread using the Android priority queue. It is possible that this tap has - // made it to the GPU process and back before they have been processed. We - // must therefore dispatch this message to the same queue, otherwise the tab - // may receive the tap event before the touch events that synthesized it. - mozilla::jni::DispatchToGeckoPriorityQueue( - NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers, - ScrollableLayerGuid, uint64_t, - Maybe<DoubleTapToZoomMetrics>>( - "dom::BrowserParent::SendHandleTap", tab, - &dom::BrowserParent::SendHandleTap, aType, aPoint, aModifiers, - aGuid, aInputBlockId, aDoubleTapToZoomMetrics)); -#else - tab->SendHandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId, - aDoubleTapToZoomMetrics); -#endif - } - return IPC_OK(); -} - mozilla::ipc::IPCResult APZCTreeManagerChild::RecvNotifyPinchGesture( const PinchGestureType& aType, const ScrollableLayerGuid& aGuid, const LayoutDevicePoint& aFocusPoint, const LayoutDeviceCoord& aSpanChange, diff --git a/gfx/layers/ipc/APZCTreeManagerChild.h b/gfx/layers/ipc/APZCTreeManagerChild.h index 756677e1e3..4d79a18d5a 100644 --- a/gfx/layers/ipc/APZCTreeManagerChild.h +++ b/gfx/layers/ipc/APZCTreeManagerChild.h @@ -73,13 +73,6 @@ class APZCTreeManagerChild : public IAPZCTreeManager, void ActorDestroy(ActorDestroyReason aWhy) override; protected: - MOZ_CAN_RUN_SCRIPT_BOUNDARY - mozilla::ipc::IPCResult RecvHandleTap( - const TapType& aType, const LayoutDevicePoint& aPoint, - const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, - const uint64_t& aInputBlockId, - const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics); - mozilla::ipc::IPCResult RecvNotifyPinchGesture( const PinchGestureType& aType, const ScrollableLayerGuid& aGuid, const LayoutDevicePoint& aFocusPoint, diff --git a/gfx/layers/ipc/APZInputBridgeChild.cpp b/gfx/layers/ipc/APZInputBridgeChild.cpp index bf059143ec..f9de8575a6 100644 --- a/gfx/layers/ipc/APZInputBridgeChild.cpp +++ b/gfx/layers/ipc/APZInputBridgeChild.cpp @@ -12,6 +12,14 @@ #include "mozilla/layers/APZThreadUtils.h" #include "mozilla/layers/SynchronousTask.h" +#include "mozilla/layers/GeckoContentController.h" // for GeckoContentController +#include "mozilla/layers/DoubleTapToZoom.h" // for DoubleTapToZoomMetrics +#include "mozilla/layers/RemoteCompositorSession.h" // for RemoteCompositorSession +#include "mozilla/dom/BrowserParent.h" // for BrowserParent +#ifdef MOZ_WIDGET_ANDROID +# include "mozilla/jni/Utils.h" // for DispatchToGeckoPriorityQueue +#endif + namespace mozilla { namespace layers { @@ -31,13 +39,20 @@ RefPtr<APZInputBridgeChild> APZInputBridgeChild::Create( } APZInputBridgeChild::APZInputBridgeChild(const uint64_t& aProcessToken) - : mIsOpen(false), mProcessToken(aProcessToken) { + : mIsOpen(false), + mProcessToken(aProcessToken), + mCompositorSession(nullptr) { MOZ_ASSERT(XRE_IsParentProcess()); MOZ_ASSERT(NS_IsMainThread()); } APZInputBridgeChild::~APZInputBridgeChild() = default; +void APZInputBridgeChild::SetCompositorSession( + RemoteCompositorSession* aSession) { + mCompositorSession = aSession; +} + void APZInputBridgeChild::Open(Endpoint<PAPZInputBridgeChild>&& aEndpoint) { APZThreadUtils::AssertOnControllerThread(); @@ -176,6 +191,63 @@ APZEventResult APZInputBridgeChild::ReceiveInputEvent( return res; } +void APZInputBridgeChild::HandleTapOnMainThread( + const TapType& aType, const LayoutDevicePoint& aPoint, + const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId, + const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { + if (mCompositorSession && + mCompositorSession->RootLayerTreeId() == aGuid.mLayersId && + mCompositorSession->GetContentController()) { + RefPtr<GeckoContentController> controller = + mCompositorSession->GetContentController(); + controller->HandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId, + aDoubleTapToZoomMetrics); + return; + } + dom::BrowserParent* tab = + dom::BrowserParent::GetBrowserParentFromLayersId(aGuid.mLayersId); + if (tab) { +#ifdef MOZ_WIDGET_ANDROID + // On Android, touch events are dispatched from the UI thread to the main + // thread using the Android priority queue. It is possible that this tap has + // made it to the GPU process and back before they have been processed. We + // must therefore dispatch this message to the same queue, otherwise the tab + // may receive the tap event before the touch events that synthesized it. + mozilla::jni::DispatchToGeckoPriorityQueue( + NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers, + ScrollableLayerGuid, uint64_t, + Maybe<DoubleTapToZoomMetrics>>( + "dom::BrowserParent::SendHandleTap", tab, + &dom::BrowserParent::SendHandleTap, aType, aPoint, aModifiers, + aGuid, aInputBlockId, aDoubleTapToZoomMetrics)); +#else + tab->SendHandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId, + aDoubleTapToZoomMetrics); +#endif + } +} + +mozilla::ipc::IPCResult APZInputBridgeChild::RecvHandleTap( + const TapType& aType, const LayoutDevicePoint& aPoint, + const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId, + const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { + if (NS_IsMainThread()) { + HandleTapOnMainThread(aType, aPoint, aModifiers, aGuid, aInputBlockId, + aDoubleTapToZoomMetrics); + } else { + NS_DispatchToMainThread( + NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers, + ScrollableLayerGuid, uint64_t, + Maybe<DoubleTapToZoomMetrics>>( + "layers::APZInputBridgeChild::HandleTapOnMainThread", this, + &APZInputBridgeChild::HandleTapOnMainThread, aType, aPoint, + aModifiers, aGuid, aInputBlockId, aDoubleTapToZoomMetrics)); + } + return IPC_OK(); +} + mozilla::ipc::IPCResult APZInputBridgeChild::RecvCallInputBlockCallback( uint64_t aInputBlockId, const APZHandledResult& aHandledResult) { auto it = mInputBlockCallbacks.find(aInputBlockId); diff --git a/gfx/layers/ipc/APZInputBridgeChild.h b/gfx/layers/ipc/APZInputBridgeChild.h index dd77d95f36..4b14e3aa0d 100644 --- a/gfx/layers/ipc/APZInputBridgeChild.h +++ b/gfx/layers/ipc/APZInputBridgeChild.h @@ -10,11 +10,16 @@ #include "mozilla/layers/APZInputBridge.h" #include "mozilla/layers/PAPZInputBridgeChild.h" +#include "mozilla/layers/GeckoContentControllerTypes.h" + namespace mozilla { namespace layers { +class RemoteCompositorSession; + class APZInputBridgeChild : public PAPZInputBridgeChild, public APZInputBridge { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZInputBridgeChild, final) + using TapType = GeckoContentController_TapType; public: static RefPtr<APZInputBridgeChild> Create( @@ -23,10 +28,19 @@ class APZInputBridgeChild : public PAPZInputBridgeChild, public APZInputBridge { void Destroy(); + void SetCompositorSession(RemoteCompositorSession* aSession); + APZEventResult ReceiveInputEvent( InputData& aEvent, InputBlockCallback&& aCallback = InputBlockCallback()) override; + MOZ_CAN_RUN_SCRIPT_BOUNDARY + mozilla::ipc::IPCResult RecvHandleTap( + const TapType& aType, const LayoutDevicePoint& aPoint, + const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId, + const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics); + mozilla::ipc::IPCResult RecvCallInputBlockCallback( uint64_t aInputBlockId, const APZHandledResult& handledResult); @@ -48,8 +62,16 @@ class APZInputBridgeChild : public PAPZInputBridgeChild, public APZInputBridge { private: void Open(Endpoint<PAPZInputBridgeChild>&& aEndpoint); + MOZ_CAN_RUN_SCRIPT_BOUNDARY + void HandleTapOnMainThread( + const TapType& aType, const LayoutDevicePoint& aPoint, + const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId, + const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics); + bool mIsOpen; uint64_t mProcessToken; + MOZ_NON_OWNING_REF RemoteCompositorSession* mCompositorSession = nullptr; using InputBlockCallbackMap = std::unordered_map<uint64_t, InputBlockCallback>; diff --git a/gfx/layers/ipc/APZInputBridgeParent.cpp b/gfx/layers/ipc/APZInputBridgeParent.cpp index fcc642ff7a..475c15abca 100644 --- a/gfx/layers/ipc/APZInputBridgeParent.cpp +++ b/gfx/layers/ipc/APZInputBridgeParent.cpp @@ -16,14 +16,15 @@ namespace mozilla { namespace layers { /* static */ -RefPtr<APZInputBridgeParent> APZInputBridgeParent::Create( +APZInputBridgeParent* APZInputBridgeParent::Create( const LayersId& aLayersId, Endpoint<PAPZInputBridgeParent>&& aEndpoint) { - RefPtr<APZInputBridgeParent> parent = new APZInputBridgeParent(aLayersId); + APZInputBridgeParent* parent = new APZInputBridgeParent(aLayersId); if (!aEndpoint.Bind(parent)) { // We can't recover from this. MOZ_CRASH("Failed to bind APZInputBridgeParent to endpoint"); } + CompositorBridgeParent::SetAPZInputBridgeParent(aLayersId, parent); return parent; } @@ -31,6 +32,7 @@ APZInputBridgeParent::APZInputBridgeParent(const LayersId& aLayersId) { MOZ_ASSERT(XRE_IsGPUProcess()); MOZ_ASSERT(NS_IsMainThread()); + mLayersId = aLayersId; mTreeManager = CompositorBridgeParent::GetAPZCTreeManager(aLayersId); MOZ_ASSERT(mTreeManager); } @@ -205,6 +207,10 @@ mozilla::ipc::IPCResult APZInputBridgeParent::RecvProcessUnhandledEvent( } void APZInputBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { + StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); + CompositorBridgeParent::LayerTreeState& state = + CompositorBridgeParent::sIndirectLayerTrees[mLayersId]; + state.mApzInputBridgeParent = nullptr; // We shouldn't need it after this mTreeManager = nullptr; } diff --git a/gfx/layers/ipc/APZInputBridgeParent.h b/gfx/layers/ipc/APZInputBridgeParent.h index 71f43d092b..62e6427bb5 100644 --- a/gfx/layers/ipc/APZInputBridgeParent.h +++ b/gfx/layers/ipc/APZInputBridgeParent.h @@ -18,7 +18,7 @@ class APZInputBridgeParent : public PAPZInputBridgeParent { NS_INLINE_DECL_REFCOUNTING(APZInputBridgeParent, final) public: - static RefPtr<APZInputBridgeParent> Create( + static APZInputBridgeParent* Create( const LayersId& aLayersId, Endpoint<PAPZInputBridgeParent>&& aEndpoint); mozilla::ipc::IPCResult RecvReceiveMultiTouchInputEvent( @@ -67,6 +67,7 @@ class APZInputBridgeParent : public PAPZInputBridgeParent { private: RefPtr<IAPZCTreeManager> mTreeManager; + LayersId mLayersId; }; } // namespace layers diff --git a/gfx/layers/ipc/CanvasChild.cpp b/gfx/layers/ipc/CanvasChild.cpp index a25d5e6799..efcd520300 100644 --- a/gfx/layers/ipc/CanvasChild.cpp +++ b/gfx/layers/ipc/CanvasChild.cpp @@ -206,13 +206,11 @@ class CanvasDataShmemHolder { } void Destroy() { - class DestroyRunnable final : public dom::WorkerRunnable { + class DestroyRunnable final : public dom::WorkerThreadRunnable { public: DestroyRunnable(dom::WorkerPrivate* aWorkerPrivate, CanvasDataShmemHolder* aShmemHolder) - : dom::WorkerRunnable(aWorkerPrivate, - "CanvasDataShmemHolder::Destroy", - dom::WorkerRunnable::WorkerThread), + : dom::WorkerThreadRunnable("CanvasDataShmemHolder::Destroy"), mShmemHolder(aShmemHolder) {} bool WorkerRun(JSContext* aCx, @@ -241,8 +239,9 @@ class CanvasDataShmemHolder { if (mWorkerRef) { if (!mWorkerRef->Private()->IsOnCurrentThread()) { auto task = MakeRefPtr<DestroyRunnable>(mWorkerRef->Private(), this); + dom::WorkerPrivate* worker = mWorkerRef->Private(); mMutex.Unlock(); - task->Dispatch(); + task->Dispatch(worker); return; } } else if (!NS_IsMainThread()) { diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp index 3fd7a4c4c4..46cab838de 100644 --- a/gfx/layers/ipc/CanvasTranslator.cpp +++ b/gfx/layers/ipc/CanvasTranslator.cpp @@ -1190,23 +1190,42 @@ already_AddRefed<gfx::SourceSurface> CanvasTranslator::LookupExternalSurface( // Check if the surface descriptor describes a GPUVideo texture for which we // only have an opaque source/handle from SurfaceDescriptorRemoteDecoder to // derive the actual texture from. -static bool SDIsNullRemoteDecoder(const SurfaceDescriptor& sd) { - return sd.type() == SurfaceDescriptor::TSurfaceDescriptorGPUVideo && - sd.get_SurfaceDescriptorGPUVideo() - .get_SurfaceDescriptorRemoteDecoder() - .subdesc() - .type() == RemoteDecoderVideoSubDescriptor::Tnull_t; +static bool SDIsSupportedRemoteDecoder(const SurfaceDescriptor& sd) { + if (sd.type() != SurfaceDescriptor::TSurfaceDescriptorGPUVideo) { + return false; + } + + const auto& sdv = sd.get_SurfaceDescriptorGPUVideo(); + const auto& sdvType = sdv.type(); + if (sdvType != SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder) { + return false; + } + + const auto& sdrd = sdv.get_SurfaceDescriptorRemoteDecoder(); + const auto& subdesc = sdrd.subdesc(); + const auto& subdescType = subdesc.type(); + + if (subdescType == RemoteDecoderVideoSubDescriptor::Tnull_t || + subdescType == + RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorMacIOSurface) { + return true; + } + + return false; } already_AddRefed<gfx::SourceSurface> CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor( const SurfaceDescriptor& aDesc) { - if (!SDIsNullRemoteDecoder(aDesc)) { + if (!SDIsSupportedRemoteDecoder(aDesc)) { return nullptr; } const auto& sdrd = aDesc.get_SurfaceDescriptorGPUVideo() .get_SurfaceDescriptorRemoteDecoder(); + const auto& subdesc = sdrd.subdesc(); + const auto& subdescType = subdesc.type(); + RefPtr<VideoBridgeParent> parent = VideoBridgeParent::GetSingleton(sdrd.source()); if (!parent) { @@ -1222,9 +1241,19 @@ CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor( return nullptr; } - RefPtr<gfx::DataSourceSurface> surf = texture->GetAsSurface(); + if (subdescType == + RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorMacIOSurface) { + MOZ_ASSERT(texture->AsMacIOSurfaceTextureHost()); + return texture->GetAsSurface(); + } + + if (subdescType == RemoteDecoderVideoSubDescriptor::Tnull_t) { + RefPtr<gfx::DataSourceSurface> surf = texture->GetAsSurface(); + return surf.forget(); + } - return surf.forget(); + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + return nullptr; } void CanvasTranslator::CheckpointReached() { CheckAndSignalWriter(); } diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index 767ea47b2f..d6efb2c991 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -167,6 +167,7 @@ bool CompositorBridgeParentBase::DeallocShmem(ipc::Shmem& aShmem) { CompositorBridgeParent::LayerTreeState::LayerTreeState() : mApzcTreeManagerParent(nullptr), + mApzInputBridgeParent(nullptr), mParent(nullptr), mContentCompositorBridgeParent(nullptr) {} @@ -645,9 +646,21 @@ bool CompositorBridgeParent::DeallocPAPZCTreeManagerParent( return true; } +void CompositorBridgeParent::SetAPZInputBridgeParent( + const LayersId& aLayersId, APZInputBridgeParent* aInputBridgeParent) { + MOZ_RELEASE_ASSERT(XRE_IsGPUProcess()); + MOZ_ASSERT(NS_IsMainThread()); + StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock); + CompositorBridgeParent::LayerTreeState& state = + CompositorBridgeParent::sIndirectLayerTrees[aLayersId]; + MOZ_ASSERT(!state.mApzInputBridgeParent); + state.mApzInputBridgeParent = aInputBridgeParent; +} + void CompositorBridgeParent::AllocateAPZCTreeManagerParent( const StaticMonitorAutoLock& aProofOfLayerTreeStateLock, const LayersId& aLayersId, LayerTreeState& aState) { + MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); MOZ_ASSERT(aState.mParent == this); MOZ_ASSERT(mApzcTreeManager); MOZ_ASSERT(mApzUpdater); @@ -1713,6 +1726,15 @@ APZCTreeManagerParent* CompositorBridgeParent::GetApzcTreeManagerParentForRoot( } /* static */ +APZInputBridgeParent* CompositorBridgeParent::GetApzInputBridgeParentForRoot( + LayersId aContentLayersId) { + StaticMonitorAutoLock lock(sIndirectLayerTreesLock); + CompositorBridgeParent::LayerTreeState* state = + GetStateForRoot(aContentLayersId, lock); + return state ? state->mApzInputBridgeParent : nullptr; +} + +/* static */ GeckoContentController* CompositorBridgeParent::GetGeckoContentControllerForRoot( LayersId aContentLayersId) { diff --git a/gfx/layers/ipc/CompositorBridgeParent.h b/gfx/layers/ipc/CompositorBridgeParent.h index 0e6bd48f9a..c7cb530989 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -24,6 +24,7 @@ #include "mozilla/layers/ISurfaceAllocator.h" // for IShmemAllocator #include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/PCompositorBridgeParent.h" +#include "mozilla/layers/APZInputBridgeParent.h" #include "mozilla/webrender/WebRenderTypes.h" namespace mozilla { @@ -394,6 +395,10 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase, ~LayerTreeState(); RefPtr<GeckoContentController> mController; APZCTreeManagerParent* mApzcTreeManagerParent; + // The mApzInputBridgeParent is only populated for LayerTreeState + // objects corresponding to root LayerIds (one for each top-level + // window). + APZInputBridgeParent* mApzInputBridgeParent; RefPtr<CompositorBridgeParent> mParent; RefPtr<WebRenderBridgeParent> mWrBridge; // Pointer to the ContentCompositorBridgeParent. Used by APZCs to share @@ -438,6 +443,13 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase, LayersId aContentLayersId); /** + * Same as the GetApzcTreeManagerParentForRoot function, but returns + * the APZInputBridge for the parent process. + */ + static APZInputBridgeParent* GetApzInputBridgeParentForRoot( + LayersId aContentLayersId); + + /** * Used by the profiler to denote when a vsync occured */ static void PostInsertVsyncProfilerMarker(mozilla::TimeStamp aVsyncTimestamp); @@ -454,6 +466,9 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase, const StaticMonitorAutoLock& aProofOfLayerTreeStateLock, const LayersId& aLayersId, LayerTreeState& aLayerTreeStateToUpdate); + static void SetAPZInputBridgeParent(const LayersId& aLayersId, + APZInputBridgeParent* aInputBridgeParent); + PAPZParent* AllocPAPZParent(const LayersId& aLayersId) override; bool DeallocPAPZParent(PAPZParent* aActor) override; diff --git a/gfx/layers/ipc/PAPZCTreeManager.ipdl b/gfx/layers/ipc/PAPZCTreeManager.ipdl index a08e2cfeb1..75cb04bea6 100644 --- a/gfx/layers/ipc/PAPZCTreeManager.ipdl +++ b/gfx/layers/ipc/PAPZCTreeManager.ipdl @@ -80,10 +80,6 @@ parent: child: - async HandleTap(GeckoContentController_TapType aType, LayoutDevicePoint point, Modifiers aModifiers, - ScrollableLayerGuid aGuid, uint64_t aInputBlockId, - DoubleTapToZoomMetrics? aDoubleTapToZoomMetrics); - async NotifyPinchGesture(PinchGestureType aType, ScrollableLayerGuid aGuid, LayoutDevicePoint aFocusPoint, LayoutDeviceCoord aSpanChange, Modifiers aModifiers); diff --git a/gfx/layers/ipc/PAPZInputBridge.ipdl b/gfx/layers/ipc/PAPZInputBridge.ipdl index 7564757b28..35ca82c018 100644 --- a/gfx/layers/ipc/PAPZInputBridge.ipdl +++ b/gfx/layers/ipc/PAPZInputBridge.ipdl @@ -6,11 +6,15 @@ include "ipc/nsGUIEventIPC.h"; using mozilla::LayoutDeviceIntPoint from "Units.h"; +using mozilla::LayoutDevicePoint from "Units.h"; +using mozilla::layers::GeckoContentController_TapType from "mozilla/layers/GeckoContentControllerTypes.h"; +using mozilla::layers::DoubleTapToZoomMetrics from "mozilla/layers/DoubleTapToZoom.h"; using struct mozilla::layers::ScrollableLayerGuid from "mozilla/layers/ScrollableLayerGuid.h"; using struct mozilla::layers::APZEventResult from "mozilla/layers/APZInputBridge.h"; using struct mozilla::layers::APZHandledResult from "mozilla/layers/APZInputBridge.h"; using mozilla::EventMessage from "mozilla/EventForwards.h"; +using mozilla::Modifiers from "mozilla/EventForwards.h"; using class mozilla::MultiTouchInput from "InputData.h"; using class mozilla::MouseInput from "InputData.h"; using class mozilla::PanGestureInput from "InputData.h"; @@ -82,6 +86,10 @@ parent: child: async CallInputBlockCallback(uint64_t aInputBlockId, APZHandledResult aHandledResult); + + async HandleTap(GeckoContentController_TapType aType, LayoutDevicePoint point, + Modifiers aModifiers, ScrollableLayerGuid aGuid, + uint64_t aInputBlockId, DoubleTapToZoomMetrics? aDoubleTapToZoomMetrics); }; } // namespace gfx diff --git a/gfx/layers/ipc/RemoteContentController.cpp b/gfx/layers/ipc/RemoteContentController.cpp index 682331362b..8c6ab22acd 100644 --- a/gfx/layers/ipc/RemoteContentController.cpp +++ b/gfx/layers/ipc/RemoteContentController.cpp @@ -62,7 +62,7 @@ void RemoteContentController::RequestContentRepaint( } } -void RemoteContentController::HandleTapOnMainThread( +void RemoteContentController::HandleTapOnParentProcessMainThread( TapType aTapType, LayoutDevicePoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId, const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { @@ -78,20 +78,19 @@ void RemoteContentController::HandleTapOnMainThread( } } -void RemoteContentController::HandleTapOnCompositorThread( +void RemoteContentController::HandleTapOnGPUProcessMainThread( TapType aTapType, LayoutDevicePoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId, const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics) { MOZ_ASSERT(XRE_IsGPUProcess()); - MOZ_ASSERT(mCompositorThread->IsOnCurrentThread()); + MOZ_ASSERT(NS_IsMainThread()); - // The raw pointer to APZCTreeManagerParent is ok here because we are on - // the compositor thread. - APZCTreeManagerParent* apzctmp = - CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId); - if (apzctmp) { - Unused << apzctmp->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, - aInputBlockId, aDoubleTapToZoomMetrics); + // Send a message to the controller thread to handle the single-tap gesture. + APZInputBridgeParent* apzib = + CompositorBridgeParent::GetApzInputBridgeParentForRoot(aGuid.mLayersId); + if (apzib) { + Unused << apzib->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, + aInputBlockId, aDoubleTapToZoomMetrics); } } @@ -103,19 +102,18 @@ void RemoteContentController::HandleTap( APZThreadUtils::AssertOnControllerThread(); if (XRE_GetProcessType() == GeckoProcessType_GPU) { - if (mCompositorThread->IsOnCurrentThread()) { - HandleTapOnCompositorThread(aTapType, aPoint, aModifiers, aGuid, - aInputBlockId, aDoubleTapToZoomMetrics); + if (NS_IsMainThread()) { + HandleTapOnGPUProcessMainThread(aTapType, aPoint, aModifiers, aGuid, + aInputBlockId, aDoubleTapToZoomMetrics); } else { - // We have to send messages from the compositor thread - mCompositorThread->Dispatch( - NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers, - ScrollableLayerGuid, uint64_t, - Maybe<DoubleTapToZoomMetrics>>( - "layers::RemoteContentController::HandleTapOnCompositorThread", - this, &RemoteContentController::HandleTapOnCompositorThread, - aTapType, aPoint, aModifiers, aGuid, aInputBlockId, - aDoubleTapToZoomMetrics)); + NS_DispatchToMainThread(NewRunnableMethod<TapType, LayoutDevicePoint, + Modifiers, ScrollableLayerGuid, + uint64_t, + Maybe<DoubleTapToZoomMetrics>>( + "layers::RemoteContentController::HandleTapOnGPUProcessMainThread", + this, &RemoteContentController::HandleTapOnGPUProcessMainThread, + aTapType, aPoint, aModifiers, aGuid, aInputBlockId, + aDoubleTapToZoomMetrics)); } return; } @@ -123,8 +121,8 @@ void RemoteContentController::HandleTap( MOZ_ASSERT(XRE_IsParentProcess()); if (NS_IsMainThread()) { - HandleTapOnMainThread(aTapType, aPoint, aModifiers, aGuid, aInputBlockId, - aDoubleTapToZoomMetrics); + HandleTapOnParentProcessMainThread(aTapType, aPoint, aModifiers, aGuid, + aInputBlockId, aDoubleTapToZoomMetrics); } else { // We must be on Android, running on the Java UI thread #ifndef MOZ_WIDGET_ANDROID @@ -138,13 +136,15 @@ void RemoteContentController::HandleTap( // using NS_DispatchToMainThread would post to a different message loop, // and introduces the possibility of this tap event getting processed // out of order with respect to the touch events that synthesized it. - mozilla::jni::DispatchToGeckoPriorityQueue( - NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers, - ScrollableLayerGuid, uint64_t, - Maybe<DoubleTapToZoomMetrics>>( - "layers::RemoteContentController::HandleTapOnMainThread", this, - &RemoteContentController::HandleTapOnMainThread, aTapType, aPoint, - aModifiers, aGuid, aInputBlockId, aDoubleTapToZoomMetrics)); + mozilla::jni::DispatchToGeckoPriorityQueue(NewRunnableMethod< + TapType, LayoutDevicePoint, + Modifiers, ScrollableLayerGuid, + uint64_t, + Maybe<DoubleTapToZoomMetrics>>( + "layers::RemoteContentController::HandleTapOnParentProcessMainThread", + this, &RemoteContentController::HandleTapOnParentProcessMainThread, + aTapType, aPoint, aModifiers, aGuid, aInputBlockId, + aDoubleTapToZoomMetrics)); #endif } } diff --git a/gfx/layers/ipc/RemoteContentController.h b/gfx/layers/ipc/RemoteContentController.h index 7c2ef3789f..34f85004d2 100644 --- a/gfx/layers/ipc/RemoteContentController.h +++ b/gfx/layers/ipc/RemoteContentController.h @@ -98,12 +98,12 @@ class RemoteContentController : public GeckoContentController, nsCOMPtr<nsISerialEventTarget> mCompositorThread; bool mCanSend; - void HandleTapOnMainThread( - TapType aType, LayoutDevicePoint aPoint, Modifiers aModifiers, + void HandleTapOnParentProcessMainThread( + TapType aTapType, LayoutDevicePoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId, const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics); - void HandleTapOnCompositorThread( - TapType aType, LayoutDevicePoint aPoint, Modifiers aModifiers, + void HandleTapOnGPUProcessMainThread( + TapType aTapType, LayoutDevicePoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId, const Maybe<DoubleTapToZoomMetrics>& aDoubleTapToZoomMetrics); void NotifyPinchGestureOnCompositorThread( diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp index 5016bc30f8..3febc5872b 100644 --- a/gfx/layers/wr/WebRenderImageHost.cpp +++ b/gfx/layers/wr/WebRenderImageHost.cpp @@ -18,6 +18,7 @@ #include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/layers/WebRenderBridgeParent.h" #include "mozilla/layers/WebRenderTextureHost.h" +#include "mozilla/ProfilerMarkers.h" #include "mozilla/StaticPrefs_webgl.h" #include "nsAString.h" #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION @@ -311,12 +312,15 @@ TextureHost* WebRenderImageHost::GetAsTextureHostForComposite( // Convert YUV BufferTextureHost to TextureHostWrapperD3D11 if possible if (texture->AsBufferTextureHost()) { auto identifier = aAsyncImageManager->GetTextureFactoryIdentifier(); - const bool convertToNV12 = + const bool tryConvertToNV12 = StaticPrefs::gfx_video_convert_yuv_to_nv12_image_host_win() && identifier.mSupportsD3D11NV12 && KnowsCompositor::SupportsD3D11(identifier) && texture->GetFormat() == gfx::SurfaceFormat::YUV; - if (convertToNV12) { + if (tryConvertToNV12) { + PROFILER_MARKER_TEXT("WebRenderImageHost", GRAPHICS, {}, + "Try ConvertToNV12"_ns); + if (!mTextureAllocator) { mTextureAllocator = new TextureWrapperD3D11Allocator(); } @@ -326,6 +330,13 @@ TextureHost* WebRenderImageHost::GetAsTextureHostForComposite( if (textureWrapper) { texture = textureWrapper; } + } else if (profiler_thread_is_being_profiled_for_markers() && + StaticPrefs::gfx_video_convert_yuv_to_nv12_image_host_win() && + texture->GetFormat() == gfx::SurfaceFormat::YUV) { + nsPrintfCString str("No ConvertToNV12 D3D11 %d NV12 %d", + KnowsCompositor::SupportsD3D11(identifier), + identifier.mSupportsD3D11NV12); + PROFILER_MARKER_TEXT("WebRenderImageHost", GRAPHICS, {}, str); } } #endif |