summaryrefslogtreecommitdiffstats
path: root/gfx/layers
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers')
-rw-r--r--gfx/layers/BuildConstants.h7
-rw-r--r--gfx/layers/CanvasDrawEventRecorder.cpp114
-rw-r--r--gfx/layers/CanvasDrawEventRecorder.h24
-rw-r--r--gfx/layers/FrameMetrics.cpp10
-rw-r--r--gfx/layers/FrameMetrics.h12
-rw-r--r--gfx/layers/ImageContainer.cpp4
-rw-r--r--gfx/layers/ImageContainer.h14
-rw-r--r--gfx/layers/NativeLayerCA.h22
-rw-r--r--gfx/layers/NativeLayerCA.mm212
-rw-r--r--gfx/layers/PersistentBufferProvider.cpp7
-rw-r--r--gfx/layers/RemoteTextureMap.cpp100
-rw-r--r--gfx/layers/RemoteTextureMap.h8
-rw-r--r--gfx/layers/SurfacePool.h2
-rw-r--r--gfx/layers/SurfacePoolCA.h2
-rw-r--r--gfx/layers/SurfacePoolCA.mm21
-rw-r--r--gfx/layers/apz/src/APZCTreeManager.cpp56
-rw-r--r--gfx/layers/apz/src/APZCTreeManager.h9
-rw-r--r--gfx/layers/apz/src/APZUpdater.cpp30
-rw-r--r--gfx/layers/apz/src/AsyncPanZoomController.cpp46
-rw-r--r--gfx/layers/apz/src/AsyncPanZoomController.h2
-rw-r--r--gfx/layers/apz/src/AutoscrollAnimation.cpp2
-rw-r--r--gfx/layers/apz/src/GenericScrollAnimation.cpp9
-rw-r--r--gfx/layers/apz/src/GestureEventListener.cpp87
-rw-r--r--gfx/layers/apz/src/GestureEventListener.h3
-rw-r--r--gfx/layers/apz/test/gtest/TestGestureDetector.cpp236
-rw-r--r--gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js14
-rw-r--r--gfx/layers/apz/test/mochitest/apz_test_utils.js4
-rw-r--r--gfx/layers/apz/test/mochitest/browser.toml8
-rw-r--r--gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js2
-rw-r--r--gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js1
-rw-r--r--gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_basic_scrollend.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_browser_test_utils.js2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1346632.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1414336.html6
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_bug1695598.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_content_response_timeout.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_displayport_expiry.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_fullscreen.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_fixed.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_key_scroll.html4
-rw-r--r--gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_touch_action_regions.html2
-rw-r--r--gfx/layers/apz/test/mochitest/helper_zoomed_pan.html4
-rw-r--r--gfx/layers/apz/test/mochitest/test_smoothness.html2
-rw-r--r--gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html4
-rw-r--r--gfx/layers/apz/test/reftest/reftest.list18
-rw-r--r--gfx/layers/apz/testutil/APZTestData.h6
-rw-r--r--gfx/layers/apz/util/APZCCallbackHelper.cpp3
-rw-r--r--gfx/layers/apz/util/APZEventState.cpp2
-rw-r--r--gfx/layers/client/TextureClient.cpp10
-rw-r--r--gfx/layers/client/TextureRecorded.cpp5
-rw-r--r--gfx/layers/client/TextureRecorded.h3
-rw-r--r--gfx/layers/ipc/CanvasChild.cpp164
-rw-r--r--gfx/layers/ipc/CanvasChild.h20
-rw-r--r--gfx/layers/ipc/CanvasTranslator.cpp32
-rw-r--r--gfx/layers/ipc/CanvasTranslator.h3
-rw-r--r--gfx/layers/ipc/CompositorManagerChild.cpp11
-rw-r--r--gfx/layers/ipc/LayersMessageUtils.h2
-rw-r--r--gfx/layers/ipc/PCanvas.ipdl6
-rw-r--r--gfx/layers/ipc/VideoBridgeParent.cpp5
-rw-r--r--gfx/layers/moz.build4
-rw-r--r--gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp1
-rw-r--r--gfx/layers/wr/AsyncImagePipelineManager.cpp3
-rw-r--r--gfx/layers/wr/WebRenderBridgeParent.cpp10
-rw-r--r--gfx/layers/wr/WebRenderImageHost.cpp13
-rw-r--r--gfx/layers/wr/WebRenderScrollData.cpp16
-rw-r--r--gfx/layers/wr/WebRenderScrollData.h13
83 files changed, 1131 insertions, 365 deletions
diff --git a/gfx/layers/BuildConstants.h b/gfx/layers/BuildConstants.h
index 6db150d136..cebdd35371 100644
--- a/gfx/layers/BuildConstants.h
+++ b/gfx/layers/BuildConstants.h
@@ -52,6 +52,13 @@ constexpr bool kIsAndroid =
false;
#endif
+constexpr bool kIsDmd =
+#ifdef MOZ_DMD
+ true;
+#else
+ false;
+#endif
+
} // namespace mozilla
#endif // BUILD_CONSTANTS_H_
diff --git a/gfx/layers/CanvasDrawEventRecorder.cpp b/gfx/layers/CanvasDrawEventRecorder.cpp
index 1bf928b816..af143bf5cb 100644
--- a/gfx/layers/CanvasDrawEventRecorder.cpp
+++ b/gfx/layers/CanvasDrawEventRecorder.cpp
@@ -8,6 +8,11 @@
#include <string.h>
+#include "mozilla/dom/WorkerCommon.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerRef.h"
+#include "mozilla/dom/WorkerRunnable.h"
+#include "mozilla/layers/TextureRecorded.h"
#include "mozilla/layers/SharedSurfacesChild.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "RecordedCanvasEventImpl.h"
@@ -34,7 +39,9 @@ static Maybe<ShmemAndHandle> CreateAndMapShmem(size_t aSize) {
return Some(ShmemAndHandle{shmem.forget(), std::move(shmemHandle)});
}
-CanvasDrawEventRecorder::CanvasDrawEventRecorder() {
+CanvasDrawEventRecorder::CanvasDrawEventRecorder(
+ dom::ThreadSafeWorkerRef* aWorkerRef)
+ : mWorkerRef(aWorkerRef), mIsOnWorker(!!aWorkerRef) {
mDefaultBufferSize = ipc::SharedMemory::PageAlignedSize(
StaticPrefs::gfx_canvas_remote_default_buffer_size());
mMaxDefaultBuffers = StaticPrefs::gfx_canvas_remote_max_default_buffers();
@@ -43,7 +50,10 @@ CanvasDrawEventRecorder::CanvasDrawEventRecorder() {
mDropBufferOnZero = mDropBufferLimit;
}
+CanvasDrawEventRecorder::~CanvasDrawEventRecorder() { MOZ_ASSERT(!mWorkerRef); }
+
bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
+ TextureType aWebglTextureType,
gfx::BackendType aBackendType,
UniquePtr<Helpers> aHelpers) {
NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder);
@@ -95,7 +105,7 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
return false;
}
- if (!mHelpers->InitTranslator(aTextureType, aBackendType,
+ if (!mHelpers->InitTranslator(aTextureType, aWebglTextureType, aBackendType,
std::move(header->handle),
std::move(bufferHandles), mDefaultBufferSize,
std::move(readerSem), std::move(writerSem))) {
@@ -317,6 +327,106 @@ void CanvasDrawEventRecorder::CheckAndSignalReader() {
} while (true);
}
+void CanvasDrawEventRecorder::DetachResources() {
+ NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder);
+
+ DrawEventRecorderPrivate::DetachResources();
+
+ {
+ auto lockedPendingDeletions = mPendingDeletions.Lock();
+ mWorkerRef = nullptr;
+ }
+}
+
+void CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder) {
+ if (!mWorkerRef) {
+ MOZ_RELEASE_ASSERT(
+ !mIsOnWorker,
+ "QueueProcessPendingDeletionsLocked called after worker shutdown!");
+
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked",
+ [self = std::move(aRecorder)]() { self->ProcessPendingDeletions(); }));
+ return;
+ }
+
+ if (!NS_IsMainThread()) {
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "CanvasDrawEventRecorder::QueueProcessPendingDeletionsLocked",
+ [self = std::move(aRecorder)]() mutable {
+ self->QueueProcessPendingDeletions(std::move(self));
+ }));
+ return;
+ }
+
+ class ProcessPendingRunnable final : public dom::WorkerRunnable {
+ public:
+ ProcessPendingRunnable(dom::WorkerPrivate* aWorkerPrivate,
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder)
+ : dom::WorkerRunnable(aWorkerPrivate),
+ mRecorder(std::move(aRecorder)) {}
+
+ bool WorkerRun(JSContext*, dom::WorkerPrivate*) override {
+ RefPtr<CanvasDrawEventRecorder> recorder = std::move(mRecorder);
+ recorder->ProcessPendingDeletions();
+ return true;
+ }
+
+ private:
+ RefPtr<CanvasDrawEventRecorder> mRecorder;
+ };
+
+ auto task = MakeRefPtr<ProcessPendingRunnable>(mWorkerRef->Private(),
+ std::move(aRecorder));
+ if (NS_WARN_IF(!task->Dispatch())) {
+ MOZ_CRASH("ProcessPendingRunnable leaked!");
+ }
+}
+
+void CanvasDrawEventRecorder::QueueProcessPendingDeletions(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder) {
+ auto lockedPendingDeletions = mPendingDeletions.Lock();
+ if (lockedPendingDeletions->empty()) {
+ // We raced to handle the deletions, and something got there first.
+ return;
+ }
+
+ QueueProcessPendingDeletionsLocked(std::move(aRecorder));
+}
+
+void CanvasDrawEventRecorder::AddPendingDeletion(
+ std::function<void()>&& aPendingDeletion) {
+ PendingDeletionsVector pendingDeletions;
+
+ {
+ auto lockedPendingDeletions = mPendingDeletions.Lock();
+ bool wasEmpty = lockedPendingDeletions->empty();
+ lockedPendingDeletions->emplace_back(std::move(aPendingDeletion));
+
+ MOZ_RELEASE_ASSERT(!mIsOnWorker || mWorkerRef,
+ "AddPendingDeletion called after worker shutdown!");
+
+ // If we are not on the owning thread, we must queue an event to run the
+ // deletions, if we transitioned from empty to non-empty.
+ if ((mWorkerRef && !mWorkerRef->Private()->IsOnCurrentThread()) ||
+ (!mWorkerRef && !NS_IsMainThread())) {
+ if (wasEmpty) {
+ RefPtr<CanvasDrawEventRecorder> self(this);
+ QueueProcessPendingDeletionsLocked(std::move(self));
+ }
+ return;
+ }
+
+ // Otherwise, we can just run all of them right now.
+ pendingDeletions.swap(*lockedPendingDeletions);
+ }
+
+ for (const auto& pendingDeletion : pendingDeletions) {
+ pendingDeletion();
+ }
+}
+
void CanvasDrawEventRecorder::StoreSourceSurfaceRecording(
gfx::SourceSurface* aSurface, const char* aReason) {
NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder);
diff --git a/gfx/layers/CanvasDrawEventRecorder.h b/gfx/layers/CanvasDrawEventRecorder.h
index a4b1261cfb..c9eacf27ac 100644
--- a/gfx/layers/CanvasDrawEventRecorder.h
+++ b/gfx/layers/CanvasDrawEventRecorder.h
@@ -21,6 +21,10 @@ namespace mozilla {
using EventType = gfx::RecordedEvent::EventType;
+namespace dom {
+class ThreadSafeWorkerRef;
+}
+
namespace layers {
typedef mozilla::ipc::SharedMemoryBasic::Handle Handle;
@@ -31,7 +35,8 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CanvasDrawEventRecorder, final)
- CanvasDrawEventRecorder();
+ explicit CanvasDrawEventRecorder(dom::ThreadSafeWorkerRef* aWorkerRef);
+ ~CanvasDrawEventRecorder() override;
enum class State : uint32_t {
Processing,
@@ -68,6 +73,7 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
virtual ~Helpers() = default;
virtual bool InitTranslator(TextureType aTextureType,
+ TextureType aWebglTextureType,
gfx::BackendType aBackendType,
Handle&& aReadHandle,
nsTArray<Handle>&& aBufferHandles,
@@ -89,8 +95,8 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
virtual bool RestartReader() = 0;
};
- bool Init(TextureType aTextureType, gfx::BackendType aBackendType,
- UniquePtr<Helpers> aHelpers);
+ bool Init(TextureType aTextureType, TextureType aWebglTextureType,
+ gfx::BackendType aBackendType, UniquePtr<Helpers> aHelpers);
/**
* Record an event for processing by the CanvasParent's CanvasTranslator.
@@ -98,6 +104,10 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
*/
void RecordEvent(const gfx::RecordedEvent& aEvent) final;
+ void DetachResources() final;
+
+ void AddPendingDeletion(std::function<void()>&& aPendingDeletion) override;
+
void StoreSourceSurfaceRecording(gfx::SourceSurface* aSurface,
const char* aReason) final;
@@ -134,6 +144,11 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
void CheckAndSignalReader();
+ void QueueProcessPendingDeletions(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder);
+ void QueueProcessPendingDeletionsLocked(
+ RefPtr<CanvasDrawEventRecorder>&& aRecorder);
+
size_t mDefaultBufferSize;
size_t mMaxDefaultBuffers;
uint32_t mMaxSpinCount;
@@ -173,6 +188,9 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
+
+ RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
+ bool mIsOnWorker = false;
};
} // namespace layers
diff --git a/gfx/layers/FrameMetrics.cpp b/gfx/layers/FrameMetrics.cpp
index 5d82b7f295..86fdd5ffd6 100644
--- a/gfx/layers/FrameMetrics.cpp
+++ b/gfx/layers/FrameMetrics.cpp
@@ -147,12 +147,10 @@ CSSSize FrameMetrics::CalculateCompositedSizeInCssPixels(
return aCompositionBounds.Size() / aZoom;
}
-std::pair<bool, CSSPoint> FrameMetrics::ApplyAbsoluteScrollUpdateFrom(
- const ScrollPositionUpdate& aUpdate) {
- CSSPoint oldVisualOffset = GetVisualScrollOffset();
+bool FrameMetrics::ApplyScrollUpdateFrom(const ScrollPositionUpdate& aUpdate) {
// In applying a main-thread scroll update, try to preserve the relative
// offset between the visual and layout viewports.
- CSSPoint relativeOffset = oldVisualOffset - GetLayoutScrollOffset();
+ CSSPoint relativeOffset = GetVisualScrollOffset() - GetLayoutScrollOffset();
MOZ_ASSERT(IsRootContent() || relativeOffset == CSSPoint());
// We need to set the two offsets together, otherwise a subsequent
// RecalculateLayoutViewportOffset() could see divergent layout and
@@ -160,7 +158,7 @@ std::pair<bool, CSSPoint> FrameMetrics::ApplyAbsoluteScrollUpdateFrom(
bool offsetChanged = SetLayoutScrollOffset(aUpdate.GetDestination());
offsetChanged |=
ClampAndSetVisualScrollOffset(aUpdate.GetDestination() + relativeOffset);
- return {offsetChanged, GetVisualScrollOffset() - oldVisualOffset};
+ return offsetChanged;
}
CSSPoint FrameMetrics::ApplyRelativeScrollUpdateFrom(
@@ -168,7 +166,7 @@ CSSPoint FrameMetrics::ApplyRelativeScrollUpdateFrom(
MOZ_ASSERT(aUpdate.GetType() == ScrollUpdateType::Relative);
CSSPoint origin = GetVisualScrollOffset();
CSSPoint delta = (aUpdate.GetDestination() - aUpdate.GetSource());
- ClampAndSetVisualScrollOffset(origin + delta);
+ SetVisualScrollOffset(origin + delta);
return GetVisualScrollOffset() - origin;
}
diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h
index 6b7a41bf25..5d13d36703 100644
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -243,11 +243,9 @@ struct FrameMetrics {
}
/*
- * Returns true if the layout scroll offset or visual scroll offset changed
- * and returns the visual scroll offset change delta.
+ * Returns true if the layout scroll offset or visual scroll offset changed.
*/
- std::pair<bool, CSSPoint> ApplyAbsoluteScrollUpdateFrom(
- const ScrollPositionUpdate& aUpdate);
+ bool ApplyScrollUpdateFrom(const ScrollPositionUpdate& aUpdate);
/**
* Applies the relative scroll offset update contained in aOther to the
@@ -893,6 +891,12 @@ struct ScrollMetadata {
mScrollUpdates.AppendElements(std::move(aUpdates));
}
+ void PrependUpdates(const nsTArray<ScrollPositionUpdate>& aUpdates) {
+ MOZ_ASSERT(!aUpdates.IsEmpty());
+
+ mScrollUpdates.InsertElementsAt(0, aUpdates);
+ }
+
private:
FrameMetrics mMetrics;
diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp
index 8a4c03f5a2..bdedccf56d 100644
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -34,7 +34,7 @@
#include "nsProxyRelease.h"
#include "nsISupportsUtils.h" // for NS_IF_ADDREF
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
# include "MacIOSurfaceImage.h"
#endif
@@ -563,7 +563,7 @@ ImageContainer::GetD3D11YCbCrRecycleAllocator(
}
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
already_AddRefed<MacIOSurfaceRecycleAllocator>
ImageContainer::GetMacIOSurfaceRecycleAllocator() {
RecursiveMutexAutoLock lock(mRecursiveMutex);
diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h
index 253ba417eb..6fa12cf195 100644
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -63,7 +63,7 @@ class MemoryOrShmem;
class D3D11RecycleAllocator;
class D3D11YCbCrRecycleAllocator;
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
class MacIOSurfaceRecycleAllocator;
#endif
class SurfaceDescriptorBuffer;
@@ -80,7 +80,7 @@ class GLImage;
class SharedRGBImage;
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureImage;
-#elif defined(XP_MACOSX)
+#elif defined(XP_DARWIN)
class MacIOSurfaceImage;
#elif MOZ_WIDGET_GTK
class DMABUFSurfaceImage;
@@ -159,7 +159,7 @@ class Image {
#ifdef MOZ_WIDGET_ANDROID
virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
virtual MacIOSurfaceImage* AsMacIOSurfaceImage() { return nullptr; }
#endif
virtual PlanarYCbCrImage* AsPlanarYCbCrImage() { return nullptr; }
@@ -191,8 +191,8 @@ class Image {
virtual ~Image() = default;
mozilla::EnumeratedArray<mozilla::layers::LayersBackend,
- mozilla::layers::LayersBackend::LAYERS_LAST,
- UniquePtr<ImageBackendData>>
+ UniquePtr<ImageBackendData>,
+ size_t(mozilla::layers::LayersBackend::LAYERS_LAST)>
mBackendData;
void* mImplData;
@@ -530,7 +530,7 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
KnowsCompositor* aKnowsCompositor);
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
already_AddRefed<MacIOSurfaceRecycleAllocator>
GetMacIOSurfaceRecycleAllocator();
#endif
@@ -618,7 +618,7 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
RefPtr<D3D11YCbCrRecycleAllocator> mD3D11YCbCrRecycleAllocator
MOZ_GUARDED_BY(mRecursiveMutex);
#endif
-#ifdef XP_MACOSX
+#ifdef XP_DARWIN
RefPtr<MacIOSurfaceRecycleAllocator> mMacIOSurfaceRecycleAllocator
MOZ_GUARDED_BY(mRecursiveMutex);
#endif
diff --git a/gfx/layers/NativeLayerCA.h b/gfx/layers/NativeLayerCA.h
index 1424c1251f..b41ac36c23 100644
--- a/gfx/layers/NativeLayerCA.h
+++ b/gfx/layers/NativeLayerCA.h
@@ -6,7 +6,7 @@
#ifndef mozilla_layers_NativeLayerCA_h
#define mozilla_layers_NativeLayerCA_h
-#include <IOSurface/IOSurface.h>
+#include <IOSurface/IOSurfaceRef.h>
#include <deque>
#include <unordered_map>
@@ -39,7 +39,9 @@ class RenderMacIOSurfaceTextureHost;
namespace layers {
+#ifdef XP_MACOSX
class NativeLayerRootSnapshotterCA;
+#endif
class SurfacePoolHandleCA;
enum class VideoLowPowerType {
@@ -102,8 +104,10 @@ class NativeLayerRootCA : public NativeLayerRoot {
bool CommitToScreen() override;
void CommitOffscreen();
+#ifdef XP_MACOSX
void OnNativeLayerRootSnapshotterDestroyed(
NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter);
+#endif
// Enters a mode during which CommitToScreen(), when called on a non-main
// thread, will not apply any updates to the CALayer tree.
@@ -139,7 +143,7 @@ class NativeLayerRootCA : public NativeLayerRoot {
void SetWindowIsFullscreen(bool aFullscreen);
- VideoLowPowerType CheckVideoLowPower(const MutexAutoLock& aProofOfLock);
+ VideoLowPowerType CheckVideoLowPower();
protected:
explicit NativeLayerRootCA(CALayer* aLayer);
@@ -149,7 +153,8 @@ class NativeLayerRootCA : public NativeLayerRoot {
explicit Representation(CALayer* aRootCALayer);
~Representation();
void Commit(WhichRepresentation aRepresentation,
- const nsTArray<RefPtr<NativeLayerCA>>& aSublayers);
+ const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
+ bool aWindowIsFullscreen);
CALayer* mRootCALayer = nullptr; // strong
bool mMutatedLayerStructure = false;
};
@@ -160,7 +165,9 @@ class NativeLayerRootCA : public NativeLayerRoot {
Mutex mMutex MOZ_UNANNOTATED; // protects all other fields
Representation mOnscreenRepresentation;
Representation mOffscreenRepresentation;
+#ifdef XP_MACOSX
NativeLayerRootSnapshotterCA* mWeakSnapshotter = nullptr;
+#endif
nsTArray<RefPtr<NativeLayerCA>> mSublayers; // in z-order
float mBackingScale = 1.0f;
bool mMutated = false;
@@ -188,6 +195,7 @@ class NativeLayerRootCA : public NativeLayerRoot {
class RenderSourceNLRS;
+#ifdef XP_MACOSX
class NativeLayerRootSnapshotterCA final : public NativeLayerRootSnapshotter {
public:
static UniquePtr<NativeLayerRootSnapshotterCA> Create(
@@ -217,6 +225,7 @@ class NativeLayerRootSnapshotterCA final : public NativeLayerRootSnapshotter {
RefPtr<RenderSourceNLRS> mSnapshot;
CARenderer* mRenderer = nullptr; // strong
};
+#endif
// NativeLayerCA wraps a CALayer and lets you draw to it. It ensures that only
// fully-drawn frames make their way to the screen, by maintaining a swap chain
@@ -260,6 +269,8 @@ class NativeLayerCA : public NativeLayer {
void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
+ void SetRootWindowIsFullscreen(bool aFullscreen);
+
protected:
friend class NativeLayerRootCA;
@@ -324,7 +335,8 @@ class NativeLayerCA : public NativeLayer {
Maybe<SurfaceWithInvalidRegion> GetUnusedSurfaceAndCleanUp(
const MutexAutoLock& aProofOfLock);
- bool IsVideo(const MutexAutoLock& aProofOfLock);
+ bool IsVideo();
+ bool IsVideoAndLocked(const MutexAutoLock& aProofOfLock);
bool ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock);
bool HasExtent() const { return mHasExtent; }
void SetHasExtent(bool aHasExtent) { mHasExtent = aHasExtent; }
@@ -468,10 +480,10 @@ class NativeLayerCA : public NativeLayer {
bool mSurfaceIsFlipped = false;
CFTypeRefPtr<CGColorRef> mColor;
const bool mIsOpaque = false;
+ bool mRootWindowIsFullscreen = false;
bool mSpecializeVideo = false;
bool mHasExtent = false;
bool mIsDRM = false;
- bool mIsTextureHostVideo = false;
#ifdef NIGHTLY_BUILD
// Track the consistency of our caller's API usage. Layers that are drawn
diff --git a/gfx/layers/NativeLayerCA.mm b/gfx/layers/NativeLayerCA.mm
index bd0b50e91b..42a889184e 100644
--- a/gfx/layers/NativeLayerCA.mm
+++ b/gfx/layers/NativeLayerCA.mm
@@ -5,10 +5,12 @@
#include "mozilla/layers/NativeLayerCA.h"
-#import <AppKit/NSAnimationContext.h>
-#import <AppKit/NSColor.h>
+#ifdef XP_MACOSX
+# import <AppKit/NSAnimationContext.h>
+# import <AppKit/NSColor.h>
+# import <OpenGL/gl.h>
+#endif
#import <AVFoundation/AVFoundation.h>
-#import <OpenGL/gl.h>
#import <QuartzCore/QuartzCore.h>
#include <algorithm>
@@ -19,7 +21,11 @@
#include "gfxUtils.h"
#include "GLBlitHelper.h"
-#include "GLContextCGL.h"
+#ifdef XP_MACOSX
+# include "GLContextCGL.h"
+#else
+# include "GLContextEAGL.h"
+#endif
#include "GLContextProvider.h"
#include "MozFramebuffer.h"
#include "mozilla/gfx/Swizzle.h"
@@ -45,7 +51,9 @@ using gfx::IntSize;
using gfx::Matrix4x4;
using gfx::SurfaceFormat;
using gl::GLContext;
+#ifdef XP_MACOSX
using gl::GLContextCGL;
+#endif
static Maybe<Telemetry::LABELS_GFX_MACOS_VIDEO_LOW_POWER>
VideoLowPowerTypeToTelemetryType(VideoLowPowerType aVideoLowPower) {
@@ -150,13 +158,23 @@ class AsyncReadbackBufferNLRS
// protection, see bug 1585523.
struct MOZ_STACK_CLASS AutoCATransaction final {
AutoCATransaction() {
+#ifdef XP_MACOSX
[NSAnimationContext beginGrouping];
+#else
+ [CATransaction begin];
+#endif
// By default, mutating a CALayer property triggers an animation which
// smoothly transitions the property to the new value. We don't need these
// animations, and this call turns them off:
[CATransaction setDisableActions:YES];
}
- ~AutoCATransaction() { [NSAnimationContext endGrouping]; }
+ ~AutoCATransaction() {
+#ifdef XP_MACOSX
+ [NSAnimationContext endGrouping];
+#else
+ [CATransaction commit];
+#endif
+ }
};
/* static */ already_AddRefed<NativeLayerRootCA>
@@ -178,9 +196,9 @@ static CALayer* MakeOffscreenRootCALayer() {
// down).
AutoCATransaction transaction;
CALayer* layer = [CALayer layer];
- layer.position = NSZeroPoint;
- layer.bounds = NSZeroRect;
- layer.anchorPoint = NSZeroPoint;
+ layer.position = CGPointZero;
+ layer.bounds = CGRectZero;
+ layer.anchorPoint = CGPointZero;
layer.contentsGravity = kCAGravityTopLeft;
layer.masksToBounds = YES;
layer.geometryFlipped = YES;
@@ -226,6 +244,7 @@ void NativeLayerRootCA::AppendLayer(NativeLayer* aLayer) {
mSublayers.AppendElement(layerCA);
layerCA->SetBackingScale(mBackingScale);
+ layerCA->SetRootWindowIsFullscreen(mWindowIsFullscreen);
ForAllRepresentations(
[&](Representation& r) { r.mMutatedLayerStructure = true; });
}
@@ -257,6 +276,7 @@ void NativeLayerRootCA::SetLayers(
RefPtr<NativeLayerCA> layerCA = layer->AsNativeLayerCA();
MOZ_RELEASE_ASSERT(layerCA);
layerCA->SetBackingScale(mBackingScale);
+ layerCA->SetRootWindowIsFullscreen(mWindowIsFullscreen);
layersCA.AppendElement(std::move(layerCA));
}
@@ -306,47 +326,48 @@ bool NativeLayerRootCA::CommitToScreen() {
return false;
}
- mOnscreenRepresentation.Commit(WhichRepresentation::ONSCREEN, mSublayers);
+ mOnscreenRepresentation.Commit(WhichRepresentation::ONSCREEN, mSublayers,
+ mWindowIsFullscreen);
mCommitPending = false;
+ }
- if (StaticPrefs::gfx_webrender_debug_dump_native_layer_tree_to_file()) {
- static uint32_t sFrameID = 0;
- uint32_t frameID = sFrameID++;
-
- NSString* dirPath =
- [NSString stringWithFormat:@"%@/Desktop/nativelayerdumps-%d",
- NSHomeDirectory(), getpid()];
- if ([NSFileManager.defaultManager createDirectoryAtPath:dirPath
- withIntermediateDirectories:YES
- attributes:nil
- error:nullptr]) {
- NSString* filename =
- [NSString stringWithFormat:@"frame-%d.html", frameID];
- NSString* filePath = [dirPath stringByAppendingPathComponent:filename];
- DumpLayerTreeToFile([filePath UTF8String]);
- } else {
- NSLog(@"Failed to create directory %@", dirPath);
- }
+ if (StaticPrefs::gfx_webrender_debug_dump_native_layer_tree_to_file()) {
+ static uint32_t sFrameID = 0;
+ uint32_t frameID = sFrameID++;
+
+ NSString* dirPath =
+ [NSString stringWithFormat:@"%@/Desktop/nativelayerdumps-%d",
+ NSHomeDirectory(), getpid()];
+ if ([NSFileManager.defaultManager createDirectoryAtPath:dirPath
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:nullptr]) {
+ NSString* filename =
+ [NSString stringWithFormat:@"frame-%d.html", frameID];
+ NSString* filePath = [dirPath stringByAppendingPathComponent:filename];
+ DumpLayerTreeToFile([filePath UTF8String]);
+ } else {
+ NSLog(@"Failed to create directory %@", dirPath);
}
+ }
- // Decide if we are going to emit telemetry about video low power on this
- // commit.
- static const int32_t TELEMETRY_COMMIT_PERIOD =
- StaticPrefs::gfx_core_animation_low_power_telemetry_frames_AtStartup();
- mTelemetryCommitCount =
- (mTelemetryCommitCount + 1) % TELEMETRY_COMMIT_PERIOD;
- if (mTelemetryCommitCount == 0) {
- // Figure out if we are hitting video low power mode.
- VideoLowPowerType videoLowPower = CheckVideoLowPower(lock);
- EmitTelemetryForVideoLowPower(videoLowPower);
- }
+ // Decide if we are going to emit telemetry about video low power on this
+ // commit.
+ static const int32_t TELEMETRY_COMMIT_PERIOD =
+ StaticPrefs::gfx_core_animation_low_power_telemetry_frames_AtStartup();
+ mTelemetryCommitCount = (mTelemetryCommitCount + 1) % TELEMETRY_COMMIT_PERIOD;
+ if (mTelemetryCommitCount == 0) {
+ // Figure out if we are hitting video low power mode.
+ VideoLowPowerType videoLowPower = CheckVideoLowPower();
+ EmitTelemetryForVideoLowPower(videoLowPower);
}
return true;
}
UniquePtr<NativeLayerRootSnapshotter> NativeLayerRootCA::CreateSnapshotter() {
+#ifdef XP_MACOSX
MutexAutoLock lock(mMutex);
MOZ_RELEASE_ASSERT(!mWeakSnapshotter,
"No NativeLayerRootSnapshotter for this NativeLayerRoot "
@@ -358,18 +379,24 @@ UniquePtr<NativeLayerRootSnapshotter> NativeLayerRootCA::CreateSnapshotter() {
mWeakSnapshotter = cr.get();
}
return cr;
+#else
+ return nullptr;
+#endif
}
+#ifdef XP_MACOSX
void NativeLayerRootCA::OnNativeLayerRootSnapshotterDestroyed(
NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter) {
MutexAutoLock lock(mMutex);
MOZ_RELEASE_ASSERT(mWeakSnapshotter == aNativeLayerRootSnapshotter);
mWeakSnapshotter = nullptr;
}
+#endif
void NativeLayerRootCA::CommitOffscreen() {
MutexAutoLock lock(mMutex);
- mOffscreenRepresentation.Commit(WhichRepresentation::OFFSCREEN, mSublayers);
+ mOffscreenRepresentation.Commit(WhichRepresentation::OFFSCREEN, mSublayers,
+ mWindowIsFullscreen);
}
template <typename F>
@@ -394,7 +421,8 @@ NativeLayerRootCA::Representation::~Representation() {
void NativeLayerRootCA::Representation::Commit(
WhichRepresentation aRepresentation,
- const nsTArray<RefPtr<NativeLayerCA>>& aSublayers) {
+ const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
+ bool aWindowIsFullscreen) {
bool mustRebuild = mMutatedLayerStructure;
if (!mustRebuild) {
// Check which type of update we need to do, if any.
@@ -439,7 +467,7 @@ void NativeLayerRootCA::Representation::Commit(
mustRebuild |= layer->WillUpdateAffectLayers(aRepresentation);
layer->ApplyChanges(aRepresentation, NativeLayerCA::UpdateType::All);
CALayer* caLayer = layer->UnderlyingCALayer(aRepresentation);
- if (!caLayer.masksToBounds || !NSIsEmptyRect(caLayer.bounds)) {
+ if (!caLayer.masksToBounds || !CGRectIsEmpty(caLayer.bounds)) {
// This layer has an extent. If it didn't before, we need to rebuild.
mustRebuild |= !layer->HasExtent();
layer->SetHasExtent(true);
@@ -472,6 +500,7 @@ void NativeLayerRootCA::Representation::Commit(
mMutatedLayerStructure = false;
}
+#ifdef XP_MACOSX
/* static */ UniquePtr<NativeLayerRootSnapshotterCA>
NativeLayerRootSnapshotterCA::Create(NativeLayerRootCA* aLayerRoot,
CALayer* aRootCALayer) {
@@ -498,6 +527,7 @@ NativeLayerRootSnapshotterCA::Create(NativeLayerRootCA* aLayerRoot,
new NativeLayerRootSnapshotterCA(aLayerRoot, std::move(gl),
aRootCALayer));
}
+#endif
void NativeLayerRootCA::DumpLayerTreeToFile(const char* aPath) {
MutexAutoLock lock(mMutex);
@@ -519,7 +549,15 @@ void NativeLayerRootCA::DumpLayerTreeToFile(const char* aPath) {
}
void NativeLayerRootCA::SetWindowIsFullscreen(bool aFullscreen) {
- mWindowIsFullscreen = aFullscreen;
+ MutexAutoLock lock(mMutex);
+
+ if (mWindowIsFullscreen != aFullscreen) {
+ mWindowIsFullscreen = aFullscreen;
+
+ for (auto layer : mSublayers) {
+ layer->SetRootWindowIsFullscreen(mWindowIsFullscreen);
+ }
+ }
}
/* static */ bool IsCGColorOpaqueBlack(CGColorRef aColor) {
@@ -541,8 +579,7 @@ void NativeLayerRootCA::SetWindowIsFullscreen(bool aFullscreen) {
return components[componentCount - 1] >= 1.0f;
}
-VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower(
- const MutexAutoLock& aProofOfLock) {
+VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower() {
// This deteremines whether the current layer contents qualify for the
// macOS Core Animation video low power mode. Those requirements are
// summarized at
@@ -572,7 +609,7 @@ VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower(
secondCALayer = topCALayer;
topCALayer = topLayer->UnderlyingCALayer(WhichRepresentation::ONSCREEN);
- topLayerIsVideo = topLayer->IsVideo(aProofOfLock);
+ topLayerIsVideo = topLayer->IsVideo();
if (topLayerIsVideo) {
++videoLayerCount;
}
@@ -641,6 +678,7 @@ VideoLowPowerType NativeLayerRootCA::CheckVideoLowPower(
return VideoLowPowerType::LowPower;
}
+#ifdef XP_MACOSX
NativeLayerRootSnapshotterCA::NativeLayerRootSnapshotterCA(
NativeLayerRootCA* aLayerRoot, RefPtr<GLContext>&& aGL,
CALayer* aRootCALayer)
@@ -779,6 +817,7 @@ NativeLayerRootSnapshotterCA::CreateAsyncReadbackBuffer(const IntSize& aSize) {
LOCAL_GL_STREAM_READ);
return MakeAndAddRef<AsyncReadbackBufferNLRS>(mGL, aSize, bufferHandle);
}
+#endif
NativeLayerCA::NativeLayerCA(const IntSize& aSize, bool aIsOpaque,
SurfacePoolHandleCA* aSurfacePoolHandle)
@@ -796,8 +835,9 @@ NativeLayerCA::NativeLayerCA(bool aIsOpaque)
mIsOpaque(aIsOpaque) {
#ifdef NIGHTLY_BUILD
if (StaticPrefs::gfx_core_animation_specialize_video_log()) {
- NSLog(@"VIDEO_LOG: NativeLayerCA: %p is being created to host an external "
- @"image, which may force a video layer rebuild.",
+ NSLog(@"VIDEO_LOG: NativeLayerCA: %p is being created to host video, which "
+ @"will force a video "
+ @"layer rebuild.",
this);
}
#endif
@@ -824,7 +864,7 @@ NativeLayerCA::~NativeLayerCA() {
if (mHasEverAttachExternalImage &&
StaticPrefs::gfx_core_animation_specialize_video_log()) {
NSLog(@"VIDEO_LOG: ~NativeLayerCA: %p is being destroyed after hosting "
- @"an external image.",
+ @"video.",
this);
}
#endif
@@ -862,9 +902,6 @@ void NativeLayerCA::AttachExternalImage(wr::RenderTextureHost* aExternalImage) {
return;
}
- // Determine if TextureHost is a video surface.
- mIsTextureHostVideo = gfx::Info(mTextureHost->GetFormat())->isYuv;
-
gfx::IntSize oldSize = mSize;
mSize = texture->GetSize(0);
bool changedSizeAndDisplayRect = (mSize != oldSize);
@@ -896,15 +933,18 @@ void NativeLayerCA::AttachExternalImage(wr::RenderTextureHost* aExternalImage) {
});
}
-bool NativeLayerCA::IsVideo(const MutexAutoLock& aProofOfLock) {
- // If we have a texture host, we've checked to see if it's providing video.
- // And if we don't have a texture host, it isn't video, so we just check
- // the value we've computed.
- return mIsTextureHostVideo;
+bool NativeLayerCA::IsVideo() {
+ // Anything with a texture host is considered a video source.
+ return mTextureHost;
+}
+
+bool NativeLayerCA::IsVideoAndLocked(const MutexAutoLock& aProofOfLock) {
+ // Anything with a texture host is considered a video source.
+ return mTextureHost;
}
bool NativeLayerCA::ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock) {
- if (!IsVideo(aProofOfLock)) {
+ if (!IsVideoAndLocked(aProofOfLock)) {
// Only videos are eligible.
return false;
}
@@ -934,7 +974,49 @@ bool NativeLayerCA::ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock) {
return true;
}
- return StaticPrefs::gfx_core_animation_specialize_video();
+ // Beyond this point, we return true if-and-only-if we think we can achieve
+ // the power-saving "detached mode" of the macOS compositor.
+
+ if (!StaticPrefs::gfx_core_animation_specialize_video()) {
+ // Pref must be set.
+ return false;
+ }
+
+ if (pixelFormat != kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange &&
+ pixelFormat != kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
+ // The video is not in one of the formats that qualifies for detachment.
+ return false;
+ }
+
+ // It will only detach if we're fullscreen.
+ return mRootWindowIsFullscreen;
+}
+
+void NativeLayerCA::SetRootWindowIsFullscreen(bool aFullscreen) {
+ if (mRootWindowIsFullscreen == aFullscreen) {
+ return;
+ }
+
+ MutexAutoLock lock(mMutex);
+
+ mRootWindowIsFullscreen = aFullscreen;
+
+ bool oldSpecializeVideo = mSpecializeVideo;
+ mSpecializeVideo = ShouldSpecializeVideo(lock);
+ bool changedSpecializeVideo = (mSpecializeVideo != oldSpecializeVideo);
+
+ if (changedSpecializeVideo) {
+#ifdef NIGHTLY_BUILD
+ if (StaticPrefs::gfx_core_animation_specialize_video_log()) {
+ NSLog(@"VIDEO_LOG: SetRootWindowIsFullscreen: %p is forcing a video "
+ @"layer rebuild.",
+ this);
+ }
+#endif
+
+ ForAllRepresentations(
+ [&](Representation& r) { r.mMutatedSpecializeVideo = true; });
+ }
}
void NativeLayerCA::SetSurfaceIsFlipped(bool aIsFlipped) {
@@ -1328,8 +1410,6 @@ void NativeLayerCA::NotifySurfaceReady() {
mInProgressSurface,
"NotifySurfaceReady called without preceding call to NextSurface");
- mIsTextureHostVideo = false;
-
if (mInProgressLockedIOSurface) {
mInProgressLockedIOSurface->Unlock(false);
mInProgressLockedIOSurface = nullptr;
@@ -1385,7 +1465,7 @@ void NativeLayerCA::ForAllRepresentations(F aFn) {
NativeLayerCA::UpdateType NativeLayerCA::HasUpdate(
WhichRepresentation aRepresentation) {
MutexAutoLock lock(mMutex);
- return GetRepresentation(aRepresentation).HasUpdate(IsVideo(lock));
+ return GetRepresentation(aRepresentation).HasUpdate(IsVideoAndLocked(lock));
}
/* static */
@@ -1430,7 +1510,7 @@ bool NativeLayerCA::ApplyChanges(WhichRepresentation aRepresentation,
.ApplyChanges(aUpdate, mSize, mIsOpaque, mPosition, mTransform,
mDisplayRect, mClipRect, mBackingScale, mSurfaceIsFlipped,
mSamplingFilter, mSpecializeVideo, surface, mColor, mIsDRM,
- IsVideo(lock));
+ IsVideo());
}
CALayer* NativeLayerCA::UnderlyingCALayer(WhichRepresentation aRepresentation) {
@@ -1457,8 +1537,10 @@ static NSString* NSStringForOSType(OSType type) {
CFRelease(surfaceValues);
if (aBuffer) {
+#ifdef XP_MACOSX
CGColorSpaceRef colorSpace = CVImageBufferGetColorSpace(aBuffer);
NSLog(@"ColorSpace is %@.\n", colorSpace);
+#endif
CFDictionaryRef bufferAttachments =
CVBufferGetAttachments(aBuffer, kCVAttachmentMode_ShouldPropagate);
@@ -1512,7 +1594,7 @@ bool NativeLayerCA::Representation::EnqueueSurface(IOSurfaceRef aSurfaceRef) {
return false;
}
-#ifdef NIGHTLY_BUILD
+#if defined(NIGHTLY_BUILD) && defined(XP_MACOSX)
if (StaticPrefs::gfx_core_animation_specialize_video_check_color_space()) {
// Ensure the resulting pixel buffer has a color space. If it doesn't, then
// modify the surface and create the buffer again.
@@ -1764,10 +1846,10 @@ bool NativeLayerCA::Representation::ApplyChanges(
mOpaquenessTintLayer.contentsGravity = kCAGravityTopLeft;
if (aIsOpaque) {
mOpaquenessTintLayer.backgroundColor =
- [[[NSColor greenColor] colorWithAlphaComponent:0.5] CGColor];
+ CGColorCreateGenericRGB(0, 1, 0, 0.5);
} else {
mOpaquenessTintLayer.backgroundColor =
- [[[NSColor redColor] colorWithAlphaComponent:0.5] CGColor];
+ CGColorCreateGenericRGB(1, 0, 0, 0.5);
}
[mWrappingCALayer addSublayer:mOpaquenessTintLayer];
} else if (!shouldTintOpaqueness && mOpaquenessTintLayer) {
diff --git a/gfx/layers/PersistentBufferProvider.cpp b/gfx/layers/PersistentBufferProvider.cpp
index 0e02501a4a..d79c8cdca1 100644
--- a/gfx/layers/PersistentBufferProvider.cpp
+++ b/gfx/layers/PersistentBufferProvider.cpp
@@ -663,14 +663,15 @@ PersistentBufferProviderShared::BorrowSnapshot(gfx::DrawTarget* aTarget) {
if (mDrawTarget) {
auto back = GetTexture(mBack);
- MOZ_ASSERT(back && back->IsLocked());
+ if (NS_WARN_IF(!back) || NS_WARN_IF(!back->IsLocked())) {
+ return nullptr;
+ }
mSnapshot = back->BorrowSnapshot();
return do_AddRef(mSnapshot);
}
auto front = GetTexture(mFront);
- if (!front || front->IsLocked()) {
- MOZ_ASSERT(false);
+ if (NS_WARN_IF(!front) || NS_WARN_IF(front->IsLocked())) {
return nullptr;
}
diff --git a/gfx/layers/RemoteTextureMap.cpp b/gfx/layers/RemoteTextureMap.cpp
index fa0cfd33f5..3fe3b13deb 100644
--- a/gfx/layers/RemoteTextureMap.cpp
+++ b/gfx/layers/RemoteTextureMap.cpp
@@ -369,7 +369,11 @@ void RemoteTextureMap::PushTexture(
aTextureId, aTextureHost, std::move(aTextureData),
std::move(aResourceWrapper));
- MOZ_ASSERT(owner->mLatestTextureId < aTextureId);
+ MOZ_ASSERT(owner->mLatestPushedTextureId < aTextureId);
+ if (owner->mLatestPushedTextureId < aTextureId) {
+ owner->mLatestPushedTextureId = aTextureId;
+ }
+ MOZ_ASSERT(owner->mLatestUsingTextureId < aTextureId);
owner->mWaitingTextureDataHolders.push_back(std::move(textureData));
@@ -898,9 +902,9 @@ void RemoteTextureMap::UpdateTexture(const MonitorAutoLock& aProofOfLock,
const RemoteTextureId aTextureId) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aOwner);
- MOZ_ASSERT(aTextureId >= aOwner->mLatestTextureId);
+ MOZ_ASSERT(aTextureId >= aOwner->mLatestUsingTextureId);
- if (aTextureId == aOwner->mLatestTextureId) {
+ if (aTextureId == aOwner->mLatestUsingTextureId) {
// No need to update texture.
return;
}
@@ -913,7 +917,7 @@ void RemoteTextureMap::UpdateTexture(const MonitorAutoLock& aProofOfLock,
}
MOZ_RELEASE_ASSERT(front->mTextureHost);
aOwner->mLatestTextureHost = front->mTextureHost;
- aOwner->mLatestTextureId = front->mTextureId;
+ aOwner->mLatestUsingTextureId = front->mTextureId;
UniquePtr<TextureDataHolder> holder = std::move(front);
aOwner->mWaitingTextureDataHolders.pop_front();
@@ -962,10 +966,42 @@ void RemoteTextureMap::GetAllRenderingReadyCallbacks(
MOZ_ASSERT(aOwner->mRenderingReadyCallbackHolders.empty());
}
+bool RemoteTextureMap::WaitForRemoteTextureOwner(
+ RemoteTextureHostWrapper* aTextureHostWrapper) {
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ MOZ_ASSERT(aTextureHostWrapper);
+
+ const auto& ownerId = aTextureHostWrapper->mOwnerId;
+ const auto& forPid = aTextureHostWrapper->mForPid;
+
+ MonitorAutoLock lock(mMonitor);
+
+ auto* owner = GetTextureOwner(lock, ownerId, forPid);
+ // If there is no texture owner yet, then we might need to wait for one to
+ // be created, if allowed. If so, we must also wait for an initial texture
+ // host to be created so we can use it.
+ if (!owner || (!owner->mLatestTextureHost &&
+ owner->mWaitingTextureDataHolders.empty())) {
+ const TimeDuration timeout = TimeDuration::FromMilliseconds(10000);
+ while (!owner || (!owner->mLatestTextureHost &&
+ owner->mWaitingTextureDataHolders.empty())) {
+ if (owner && (owner->mIsContextLost || owner->mDeferUnregister)) {
+ // If the context was lost, no further updates are expected.
+ return false;
+ }
+ CVStatus status = mMonitor.Wait(timeout);
+ if (status == CVStatus::Timeout) {
+ return false;
+ }
+ owner = GetTextureOwner(lock, ownerId, forPid);
+ }
+ }
+ return true;
+}
+
bool RemoteTextureMap::GetRemoteTexture(
RemoteTextureHostWrapper* aTextureHostWrapper,
- std::function<void(const RemoteTextureInfo&)>&& aReadyCallback,
- bool aWaitForRemoteTextureOwner) {
+ std::function<void(const RemoteTextureInfo&)>&& aReadyCallback) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(aTextureHostWrapper);
@@ -983,27 +1019,8 @@ bool RemoteTextureMap::GetRemoteTexture(
MonitorAutoLock lock(mMonitor);
auto* owner = GetTextureOwner(lock, ownerId, forPid);
- // If there is no texture owner yet, then we might need to wait for one to
- // be created, if allowed. If so, we must also wait for an initial texture
- // host to be created so we can use it.
- if (!owner || (aWaitForRemoteTextureOwner && !owner->mLatestTextureHost &&
- owner->mWaitingTextureDataHolders.empty())) {
- if (!aWaitForRemoteTextureOwner) {
- return false;
- }
- const TimeDuration timeout = TimeDuration::FromMilliseconds(10000);
- while (!owner || (!owner->mLatestTextureHost &&
- owner->mWaitingTextureDataHolders.empty())) {
- if (owner && (owner->mIsContextLost || owner->mDeferUnregister)) {
- // If the context was lost, no further updates are expected.
- return false;
- }
- CVStatus status = mMonitor.Wait(timeout);
- if (status == CVStatus::Timeout) {
- return false;
- }
- owner = GetTextureOwner(lock, ownerId, forPid);
- }
+ if (!owner) {
+ return false;
}
UpdateTexture(lock, owner, textureId);
@@ -1014,7 +1031,7 @@ bool RemoteTextureMap::GetRemoteTexture(
return false;
}
- if (textureId == owner->mLatestTextureId) {
+ if (textureId == owner->mLatestUsingTextureId) {
MOZ_ASSERT(owner->mLatestTextureHost);
MOZ_ASSERT(owner->mLatestTextureHost->GetSize() == size);
if (owner->mLatestTextureHost->GetSize() != size) {
@@ -1034,7 +1051,7 @@ bool RemoteTextureMap::GetRemoteTexture(
}
// Update mRemoteTextureHost
- if (textureId == owner->mLatestTextureId) {
+ if (textureId == owner->mLatestUsingTextureId) {
const auto key = std::pair(forPid, textureId);
auto it = mRemoteTextureHostWrapperHolders.find(key);
if (it != mRemoteTextureHostWrapperHolders.end() &&
@@ -1195,16 +1212,9 @@ bool RemoteTextureMap::CheckRemoteTextureReady(
return true;
}
- if (it->second->mRemoteTextureHost) {
+ if (owner->mLatestPushedTextureId >= aInfo.mTextureId) {
return true;
}
- MOZ_ASSERT(!it->second->mRemoteTextureHost);
-
- // Check if RemoteTextureId is as expected.
- if (!owner->mRenderingReadyCallbackHolders.empty()) {
- auto& front = owner->mRenderingReadyCallbackHolders.front();
- MOZ_RELEASE_ASSERT(aInfo.mTextureId >= front->mTextureId);
- }
auto callbackHolder = MakeUnique<RenderingReadyCallbackHolder>(
aInfo.mTextureId, std::move(aCallback));
@@ -1234,9 +1244,8 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) {
}
const TimeDuration timeout = TimeDuration::FromMilliseconds(1000);
- TextureHost* remoteTexture = it->second->mRemoteTextureHost;
- while (!remoteTexture) {
+ while (owner->mLatestPushedTextureId < aInfo.mTextureId) {
CVStatus status = mMonitor.Wait(timeout);
if (status == CVStatus::Timeout) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
@@ -1251,14 +1260,11 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) {
return false;
}
- remoteTexture = it->second->mRemoteTextureHost;
- if (!remoteTexture) {
- auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
- // When owner is alreay unregistered, remote texture will not be pushed.
- if (!owner || owner->mIsContextLost) {
- // This could happen with IPC abnormal shutdown
- return false;
- }
+ auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
+ // When owner is alreay unregistered, remote texture will not be pushed.
+ if (!owner || owner->mIsContextLost) {
+ // This could happen with IPC abnormal shutdown
+ return false;
}
}
diff --git a/gfx/layers/RemoteTextureMap.h b/gfx/layers/RemoteTextureMap.h
index a60bfd4c3c..8aee1c6f7d 100644
--- a/gfx/layers/RemoteTextureMap.h
+++ b/gfx/layers/RemoteTextureMap.h
@@ -304,13 +304,14 @@ class RemoteTextureMap {
void NotifyContextRestored(const RemoteTextureOwnerIdSet& aOwnerIds,
const base::ProcessId aForPid);
+ bool WaitForRemoteTextureOwner(RemoteTextureHostWrapper* aTextureHostWrapper);
+
// Get remote texture's TextureHost for RemoteTextureHostWrapper.
//
// return true when aReadyCallback will be called.
bool GetRemoteTexture(
RemoteTextureHostWrapper* aTextureHostWrapper,
- std::function<void(const RemoteTextureInfo&)>&& aReadyCallback,
- bool aWaitForRemoteTextureOwner = false);
+ std::function<void(const RemoteTextureInfo&)>&& aReadyCallback);
bool WaitForTxn(const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid, RemoteTextureTxnType aTxnType,
@@ -403,7 +404,8 @@ class RemoteTextureMap {
std::deque<UniquePtr<RenderingReadyCallbackHolder>>
mRenderingReadyCallbackHolders;
- RemoteTextureId mLatestTextureId = {0};
+ RemoteTextureId mLatestPushedTextureId = {0};
+ RemoteTextureId mLatestUsingTextureId = {0};
CompositableTextureHostRef mLatestTextureHost;
CompositableTextureHostRef mLatestRenderedTextureHost;
// Holds compositable refs to TextureHosts of RenderTextureHosts that are
diff --git a/gfx/layers/SurfacePool.h b/gfx/layers/SurfacePool.h
index eecb398d85..6be3718af5 100644
--- a/gfx/layers/SurfacePool.h
+++ b/gfx/layers/SurfacePool.h
@@ -31,7 +31,7 @@ class SurfacePool {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SurfacePool);
-#if defined(XP_MACOSX) || defined(MOZ_WAYLAND)
+#if defined(XP_DARWIN) || defined(MOZ_WAYLAND)
static RefPtr<SurfacePool> Create(size_t aPoolSizeLimit);
#endif
diff --git a/gfx/layers/SurfacePoolCA.h b/gfx/layers/SurfacePoolCA.h
index 97344f7d06..265782df9e 100644
--- a/gfx/layers/SurfacePoolCA.h
+++ b/gfx/layers/SurfacePoolCA.h
@@ -6,7 +6,7 @@
#ifndef mozilla_layers_SurfacePoolCA_h
#define mozilla_layers_SurfacePoolCA_h
-#include <IOSurface/IOSurface.h>
+#include <IOSurface/IOSurfaceRef.h>
#include <deque>
#include <unordered_map>
diff --git a/gfx/layers/SurfacePoolCA.mm b/gfx/layers/SurfacePoolCA.mm
index 47b2663ed7..4e012350f0 100644
--- a/gfx/layers/SurfacePoolCA.mm
+++ b/gfx/layers/SurfacePoolCA.mm
@@ -6,6 +6,7 @@
#include "mozilla/layers/SurfacePoolCA.h"
#import <CoreVideo/CVPixelBuffer.h>
+#include <IOSurface/IOSurfaceTypes.h>
#include <algorithm>
#include <unordered_set>
@@ -16,7 +17,12 @@
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPrefs_gfx.h"
-#include "GLContextCGL.h"
+#ifdef XP_MACOSX
+# include "GLContextCGL.h"
+#else
+# include "GLContextEAGL.h"
+#endif
+
#include "MozFramebuffer.h"
#include "ScopedGLHelpers.h"
@@ -28,7 +34,11 @@ using gfx::IntRect;
using gfx::IntRegion;
using gfx::IntSize;
using gl::GLContext;
+#ifdef XP_MACOSX
using gl::GLContextCGL;
+#else
+using gl::GLContextEAGL;
+#endif
/* static */ RefPtr<SurfacePool> SurfacePool::Create(size_t aPoolSizeLimit) {
return new SurfacePoolCA(aPoolSizeLimit);
@@ -306,8 +316,13 @@ Maybe<GLuint> SurfacePoolCA::LockedPool::GetFramebufferForSurface(
"Framebuffer creation", GRAPHICS_TileAllocation,
nsPrintfCString("%dx%d", entry.mSize.width, entry.mSize.height));
+#ifdef XP_MACOSX
RefPtr<GLContextCGL> cgl = GLContextCGL::Cast(aGL);
MOZ_RELEASE_ASSERT(cgl, "Unexpected GLContext type");
+#else
+ RefPtr<GLContextEAGL> eagl = GLContextEAGL::Cast(aGL);
+ MOZ_RELEASE_ASSERT(eagl, "Unexpected GLContext type");
+#endif
if (!aGL->MakeCurrent()) {
// Context may have been destroyed.
@@ -318,10 +333,14 @@ Maybe<GLuint> SurfacePoolCA::LockedPool::GetFramebufferForSurface(
{
const gl::ScopedBindTexture bindTex(aGL, tex,
LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+#ifdef XP_MACOSX
CGLTexImageIOSurface2D(cgl->GetCGLContext(), LOCAL_GL_TEXTURE_RECTANGLE_ARB,
LOCAL_GL_RGBA, entry.mSize.width, entry.mSize.height,
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
entry.mIOSurface.get(), 0);
+#else
+ MOZ_CRASH("unimplemented");
+#endif
}
auto fb =
diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp
index d28392b716..ef3cde3596 100644
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -62,6 +62,8 @@
mozilla::LazyLogModule mozilla::layers::APZCTreeManager::sLog("apz.manager");
#define APZCTM_LOG(...) \
MOZ_LOG(APZCTreeManager::sLog, LogLevel::Debug, (__VA_ARGS__))
+#define APZCTM_LOGV(...) \
+ MOZ_LOG(APZCTreeManager::sLog, LogLevel::Verbose, (__VA_ARGS__))
static mozilla::LazyLogModule sApzKeyLog("apz.key");
#define APZ_KEY_LOG(...) MOZ_LOG(sApzKeyLog, LogLevel::Debug, (__VA_ARGS__))
@@ -83,10 +85,10 @@ typedef CompositorBridgeParent::LayerTreeState LayerTreeState;
struct APZCTreeManager::TreeBuildingState {
TreeBuildingState(LayersId aRootLayersId, bool aIsFirstPaint,
LayersId aOriginatingLayersId, APZTestData* aTestData,
- uint32_t aPaintSequence)
+ uint32_t aPaintSequence, bool aIsTestLoggingEnabled)
: mIsFirstPaint(aIsFirstPaint),
mOriginatingLayersId(aOriginatingLayersId),
- mPaintLogger(aTestData, aPaintSequence) {
+ mPaintLogger(aTestData, aPaintSequence, aIsTestLoggingEnabled) {
CompositorBridgeParent::CallWithIndirectShadowTree(
aRootLayersId, [this](LayerTreeState& aState) -> void {
mCompositorController = aState.GetCompositorController();
@@ -158,6 +160,9 @@ struct APZCTreeManager::TreeBuildingState {
// cumulative EventRegionsOverride flags from the reflayers, and is used to
// apply them to descendant layers.
std::stack<EventRegionsOverride> mOverrideFlags;
+
+ // Wether the APZC correspoinding to the originating LayersId was updated.
+ bool mOriginatingLayersIdUpdated = false;
};
class APZCTreeManager::CheckerboardFlushObserver : public nsIObserver {
@@ -391,8 +396,7 @@ void APZCTreeManager::SetAllowedTouchBehavior(
uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aValues) {
if (!APZThreadUtils::IsControllerThread()) {
APZThreadUtils::RunOnControllerThread(
- NewRunnableMethod<uint64_t,
- StoreCopyPassByLRef<nsTArray<TouchBehaviorFlags>>>(
+ NewRunnableMethod<uint64_t, nsTArray<TouchBehaviorFlags>>(
"layers::APZCTreeManager::SetAllowedTouchBehavior", this,
&APZCTreeManager::SetAllowedTouchBehavior, aInputBlockId,
aValues.Clone()));
@@ -420,9 +424,11 @@ void APZCTreeManager::SetBrowserGestureResponse(
mInputQueue->SetBrowserGestureResponse(aInputBlockId, aResponse);
}
-void APZCTreeManager::UpdateHitTestingTree(
- const WebRenderScrollDataWrapper& aRoot, bool aIsFirstPaint,
- LayersId aOriginatingLayersId, uint32_t aPaintSequenceNumber) {
+APZCTreeManager::OriginatingLayersIdUpdated
+APZCTreeManager::UpdateHitTestingTree(const WebRenderScrollDataWrapper& aRoot,
+ bool aIsFirstPaint,
+ LayersId aOriginatingLayersId,
+ uint32_t aPaintSequenceNumber) {
AssertOnUpdaterThread();
RecursiveMutexAutoLock lock(mTreeLock);
@@ -430,7 +436,8 @@ void APZCTreeManager::UpdateHitTestingTree(
// For testing purposes, we log some data to the APZTestData associated with
// the layers id that originated this update.
APZTestData* testData = nullptr;
- if (StaticPrefs::apz_test_logging_enabled()) {
+ const bool testLoggingEnabled = StaticPrefs::apz_test_logging_enabled();
+ if (testLoggingEnabled) {
MutexAutoLock lock(mTestDataLock);
UniquePtr<APZTestData> ptr = MakeUnique<APZTestData>();
auto result =
@@ -440,7 +447,7 @@ void APZCTreeManager::UpdateHitTestingTree(
}
TreeBuildingState state(mRootLayersId, aIsFirstPaint, aOriginatingLayersId,
- testData, aPaintSequenceNumber);
+ testData, aPaintSequenceNumber, testLoggingEnabled);
// We do this business with collecting the entire tree into an array because
// otherwise it's very hard to determine which APZC instances need to be
@@ -730,6 +737,8 @@ void APZCTreeManager::UpdateHitTestingTree(
mRootNode->Dump(" ");
}
SendSubtreeTransformsToChromeMainThread(nullptr);
+
+ return OriginatingLayersIdUpdated{state.mOriginatingLayersIdUpdated};
}
void APZCTreeManager::UpdateFocusState(LayersId aRootLayerTreeId,
@@ -763,7 +772,7 @@ void APZCTreeManager::SampleForWebRender(const Maybe<VsyncId>& aVsyncId,
controller->ScheduleRenderOnCompositorThread(
wr::RenderReasons::ANIMATED_PROPERTY);
}
- APZCTM_LOG(
+ APZCTM_LOGV(
"APZCTreeManager(%p)::SampleForWebRender, want more composites: %d\n",
this, (activeAnimations && controller));
@@ -1231,6 +1240,10 @@ HitTestingTreeNode* APZCTreeManager::PrepareNodeForLayer(
"Found APZC %p for layer %p with identifiers %" PRIx64 " %" PRId64 "\n",
apzc.get(), aLayer.GetLayer(), uint64_t(guid.mLayersId), guid.mScrollId);
+ if (aLayersId == aState.mOriginatingLayersId) {
+ aState.mOriginatingLayersIdUpdated = true;
+ }
+
// If we haven't encountered a layer already with the same metrics, then we
// need to do the full reuse-or-make-an-APZC algorithm, which is contained
// inside the block below.
@@ -1522,6 +1535,11 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
}
case MOUSE_INPUT: {
MouseInput& mouseInput = aEvent.AsMouseInput();
+ MOZ_LOG(APZCTreeManager::sLog,
+ mouseInput.mType == MouseInput::MOUSE_MOVE ? LogLevel::Verbose
+ : LogLevel::Debug,
+ ("Received mouse input type %d at %s\n", (int)mouseInput.mType,
+ ToString(mouseInput.mOrigin).c_str()));
mouseInput.mHandledByAPZ = true;
SetCurrentMousePosition(mouseInput.mOrigin);
@@ -1613,6 +1631,9 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
// Do this before early return for Fission hit testing.
ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
+ APZCTM_LOG("Received wheel input at %s with delta (%f, %f)\n",
+ ToString(wheelInput.mOrigin).c_str(), wheelInput.mDeltaX,
+ wheelInput.mDeltaY);
state.mHit = GetTargetAPZC(wheelInput.mOrigin);
wheelInput.mHandledByAPZ = WillHandleInput(wheelInput);
@@ -1674,6 +1695,9 @@ APZEventResult APZCTreeManager::ReceiveInputEvent(
// Do this before early return for Fission hit testing.
PanGestureInput& panInput = aEvent.AsPanGestureInput();
+ APZCTM_LOG("Received pan gesture input type %d at %s with delta %s\n",
+ (int)panInput.mType, ToString(panInput.mPanStartPoint).c_str(),
+ ToString(panInput.mPanDisplacement).c_str());
state.mHit = GetTargetAPZC(panInput.mPanStartPoint);
panInput.mHandledByAPZ = WillHandleInput(panInput);
@@ -2021,6 +2045,18 @@ APZEventResult APZCTreeManager::InputHandlingState::Finish(
void APZCTreeManager::ProcessTouchInput(InputHandlingState& aState,
MultiTouchInput& aInput) {
+ APZCTM_LOG("Received touch input type %d with touch points [%s]\n",
+ (int)aInput.mType,
+ [&] {
+ nsCString result;
+ for (const auto& touch : aInput.mTouches) {
+ result.AppendPrintf("%s",
+ ToString(touch.mScreenPoint).c_str());
+ }
+ return result;
+ }()
+ .get());
+
aInput.mHandledByAPZ = true;
nsTArray<TouchBehaviorFlags> touchBehaviors;
HitTestingTreeNodeAutoLock hitScrollbarNode;
diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h
index ff9bba51ca..71d35fd5a6 100644
--- a/gfx/layers/apz/src/APZCTreeManager.h
+++ b/gfx/layers/apz/src/APZCTreeManager.h
@@ -190,10 +190,13 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
* this layer update. Note that every child
* process' layer subtree has its own sequence
* numbers.
+ * @return OriginatingLayersIdUpdated whether the given
+ * |aOriginatingLayersId|'s data was processed.
*/
- void UpdateHitTestingTree(const WebRenderScrollDataWrapper& aRoot,
- bool aIsFirstPaint, LayersId aOriginatingLayersId,
- uint32_t aPaintSequenceNumber);
+ enum class OriginatingLayersIdUpdated : bool { No, Yes };
+ OriginatingLayersIdUpdated UpdateHitTestingTree(
+ const WebRenderScrollDataWrapper& aRoot, bool aIsFirstPaint,
+ LayersId aOriginatingLayersId, uint32_t aPaintSequenceNumber);
/**
* Called when webrender is enabled, from the sampler thread. This function
diff --git a/gfx/layers/apz/src/APZUpdater.cpp b/gfx/layers/apz/src/APZUpdater.cpp
index 2bbad6e1a7..2f1b551f3a 100644
--- a/gfx/layers/apz/src/APZUpdater.cpp
+++ b/gfx/layers/apz/src/APZUpdater.cpp
@@ -191,14 +191,38 @@ void APZUpdater::UpdateScrollDataAndTreeState(
auto isFirstPaint = aScrollData.IsFirstPaint();
auto paintSequenceNumber = aScrollData.GetPaintSequenceNumber();
+ auto previous = self->mScrollData.find(aOriginatingLayersId);
+ // If there's the previous scroll data which hasn't yet been
+ // processed, we need to merge the previous scroll position updates
+ // into the latest one.
+ if (previous != self->mScrollData.end()) {
+ WebRenderScrollData& previousData = previous->second;
+ if (previousData.GetWasUpdateSkipped()) {
+ MOZ_ASSERT(previousData.IsFirstPaint());
+ aScrollData.PrependUpdates(previousData);
+ }
+ }
+
self->mScrollData[aOriginatingLayersId] = std::move(aScrollData);
auto root = self->mScrollData.find(aRootLayerTreeId);
if (root == self->mScrollData.end()) {
return;
}
- self->mApz->UpdateHitTestingTree(
- WebRenderScrollDataWrapper(*self, &(root->second)),
- isFirstPaint, aOriginatingLayersId, paintSequenceNumber);
+ if ((self->mApz->UpdateHitTestingTree(
+ WebRenderScrollDataWrapper(*self, &(root->second)),
+ isFirstPaint, aOriginatingLayersId, paintSequenceNumber) ==
+ APZCTreeManager::OriginatingLayersIdUpdated::No) &&
+ isFirstPaint) {
+ // If the given |aOriginatingLayersId| data wasn't used for
+ // updating, it's likly that the parent process hasn't yet
+ // received the LayersId as "ReferentId", thus we need to process
+ // it in a subsequent update where we got the "ReferentId".
+ //
+ // NOTE: We restrict the above previous scroll data prepending to
+ // the first paint case, otherwise the cumulative scroll data may
+ // be exploded if we have never received the "ReferenceId".
+ self->mScrollData[aOriginatingLayersId].SetWasUpdateSkipped();
+ }
}));
}
diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp
index 342375c019..edbd2ecffa 100644
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -106,6 +106,10 @@ static mozilla::LazyLogModule sApzCtlLog("apz.controller");
APZC_LOG("%p(%s scrollId=%" PRIu64 "): " fmt, (apzc), \
(apzc)->IsRootContent() ? "root" : "subframe", \
(apzc)->GetScrollId(), ##__VA_ARGS__)
+#define APZC_LOGV_DETAIL(fmt, apzc, ...) \
+ APZC_LOGV("%p(%s scrollId=%" PRIu64 "): " fmt, (apzc), \
+ (apzc)->IsRootContent() ? "root" : "subframe", \
+ (apzc)->GetScrollId(), ##__VA_ARGS__)
#define APZC_LOG_FM_COMMON(fm, prefix, level, ...) \
if (MOZ_LOG_TEST(sApzCtlLog, level)) { \
@@ -2248,6 +2252,11 @@ CSSRect AsyncPanZoomController::GetCurrentScrollRangeInCssPixels() const {
return Metrics().CalculateScrollRange();
}
+bool AsyncPanZoomController::AllowOneTouchPinch() const {
+ return StaticPrefs::apz_one_touch_pinch_enabled() &&
+ ZoomConstraintsAllowZoom();
+}
+
// Return whether or not the underlying layer can be scrolled on either axis.
bool AsyncPanZoomController::CanScroll(const InputData& aEvent) const {
ParentLayerPoint delta = GetDeltaForEvent(aEvent);
@@ -4734,7 +4743,7 @@ bool AsyncPanZoomController::UpdateAnimation(
// Even if there's no animation, if we have a scroll offset change pending due
// to the frame delay, we need to keep compositing.
if (mLastSampleTime == aSampleTime) {
- APZC_LOG_DETAIL(
+ APZC_LOGV_DETAIL(
"UpdateAnimation short-circuit, animation=%p, pending frame-delayed "
"offset=%d\n",
this, mAnimation.get(), HavePendingFrameDelayedOffset());
@@ -4754,8 +4763,8 @@ bool AsyncPanZoomController::UpdateAnimation(
// so that e.g. a main-thread animation can stay in sync with user-driven
// scrolling or a compositor animation.
bool needComposite = SampleCompositedAsyncTransform(aProofOfLock);
- APZC_LOG_DETAIL("UpdateAnimation needComposite=%d mAnimation=%p\n", this,
- needComposite, mAnimation.get());
+ APZC_LOGV_DETAIL("UpdateAnimation needComposite=%d mAnimation=%p\n", this,
+ needComposite, mAnimation.get());
TimeDuration sampleTimeDelta = aSampleTime - mLastSampleTime;
mLastSampleTime = aSampleTime;
@@ -5581,17 +5590,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(
aScrollMetadata.GetOverscrollBehavior());
}
- if (needToReclampScroll) {
- // Whenever scrollable rect or composition bounds has changed, we need to
- // re-clamp the scroll offset since it may be out of bounds. Also note that
- // we need to re-clamp before updating new scroll offsets from content since
- // we will use the last scroll offset to reflect the new offsets.
- ClampAndSetVisualScrollOffset(Metrics().GetVisualScrollOffset());
- for (auto& sampledState : mSampledState) {
- sampledState.ClampVisualScrollOffset(Metrics());
- }
- }
-
bool instantScrollMayTriggerTransform = false;
bool scrollOffsetUpdated = false;
bool smoothScrollRequested = false;
@@ -5738,20 +5736,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(
relativeDelta =
Some(Metrics().ApplyPureRelativeScrollUpdateFrom(scrollUpdate));
Metrics().RecalculateLayoutViewportOffset();
- } else if (scrollUpdate.GetType() == ScrollUpdateType::MergeableAbsolute) {
- APZC_LOG("%p mergeable updating scroll offset from %s to %s\n", this,
- ToString(Metrics().GetVisualScrollOffset()).c_str(),
- ToString(scrollUpdate.GetDestination()).c_str());
- relativeDelta =
- Some(Metrics().ApplyAbsoluteScrollUpdateFrom(scrollUpdate).second);
- Metrics().RecalculateLayoutViewportOffset();
- scrollOffsetUpdated = true;
} else {
APZC_LOG("%p updating scroll offset from %s to %s\n", this,
ToString(Metrics().GetVisualScrollOffset()).c_str(),
ToString(scrollUpdate.GetDestination()).c_str());
- auto [offsetChanged, _] =
- Metrics().ApplyAbsoluteScrollUpdateFrom(scrollUpdate);
+ bool offsetChanged = Metrics().ApplyScrollUpdateFrom(scrollUpdate);
Metrics().RecalculateLayoutViewportOffset();
if (offsetChanged || scrollUpdate.GetMode() != ScrollMode::Instant ||
@@ -5788,6 +5777,15 @@ void AsyncPanZoomController::NotifyLayersUpdated(
}
}
+ if (aIsFirstPaint || needToReclampScroll) {
+ // The scrollable rect or composition bounds may have changed in a way that
+ // makes our local scroll offset out of bounds, so clamp it.
+ ClampAndSetVisualScrollOffset(Metrics().GetVisualScrollOffset());
+ for (auto& sampledState : mSampledState) {
+ sampledState.ClampVisualScrollOffset(Metrics());
+ }
+ }
+
if (scrollOffsetUpdated) {
for (auto& sampledState : mSampledState) {
if (!didCancelAnimation && cumulativeRelativeDelta.isSome()) {
diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h
index fdc72b1971..d0c4537a66 100644
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -1305,6 +1305,8 @@ class AsyncPanZoomController {
*/
CSSRect GetCurrentScrollRangeInCssPixels() const;
+ bool AllowOneTouchPinch() const;
+
private:
/**
* Advances to the next sample, if there is one, the list of sampled states
diff --git a/gfx/layers/apz/src/AutoscrollAnimation.cpp b/gfx/layers/apz/src/AutoscrollAnimation.cpp
index 8d4b8fca10..45063ef2b4 100644
--- a/gfx/layers/apz/src/AutoscrollAnimation.cpp
+++ b/gfx/layers/apz/src/AutoscrollAnimation.cpp
@@ -17,7 +17,7 @@ namespace mozilla {
namespace layers {
// Helper function for AutoscrollAnimation::DoSample().
-// Basically copied as-is from toolkit/actors/AutoScrollChild.jsm.
+// Basically copied as-is from toolkit/actors/AutoScrollChild.sys.mjs.
static float Accelerate(ScreenCoord curr, ScreenCoord start) {
static const int speed = 12;
float val = (curr - start) / speed;
diff --git a/gfx/layers/apz/src/GenericScrollAnimation.cpp b/gfx/layers/apz/src/GenericScrollAnimation.cpp
index 04ca8c4697..62f19fab35 100644
--- a/gfx/layers/apz/src/GenericScrollAnimation.cpp
+++ b/gfx/layers/apz/src/GenericScrollAnimation.cpp
@@ -15,6 +15,9 @@
#include "ScrollAnimationMSDPhysics.h"
#include "mozilla/StaticPrefs_general.h"
+static mozilla::LazyLogModule sApzScrollAnimLog("apz.scrollanimation");
+#define GSA_LOG(...) MOZ_LOG(sApzScrollAnimLog, LogLevel::Debug, (__VA_ARGS__))
+
namespace mozilla {
namespace layers {
@@ -101,6 +104,12 @@ bool GenericScrollAnimation::DoSample(FrameMetrics& aFrameMetrics,
// then end the animation early. Note that the initial displacement could be 0
// if the compositor ran very quickly (<1ms) after the animation was created.
// When that happens we want to make sure the animation continues.
+ GSA_LOG(
+ "Sampling GenericScrollAnimation: time %f finished %d sampledDest %s "
+ "adjustedOffset %s overscroll %s\n",
+ (now - TimeStamp::ProcessCreation()).ToMilliseconds(), finished,
+ ToString(CSSPoint::FromAppUnits(sampledDest)).c_str(),
+ ToString(adjustedOffset).c_str(), ToString(overscroll).c_str());
if (!IsZero(displacement / zoom) && IsZero(adjustedOffset / zoom)) {
// Nothing more to do - end the animation.
return false;
diff --git a/gfx/layers/apz/src/GestureEventListener.cpp b/gfx/layers/apz/src/GestureEventListener.cpp
index b54674b593..4300e9ba41 100644
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -5,13 +5,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GestureEventListener.h"
-#include <algorithm> // for max
+#include <algorithm> // for max
+#include <ostream>
#include <math.h> // for fabsf
#include <stddef.h> // for size_t
#include "AsyncPanZoomController.h" // for AsyncPanZoomController
#include "InputBlockState.h" // for TouchBlockState
#include "base/task.h" // for CancelableTask, etc
#include "InputBlockState.h" // for TouchBlockState
+#include "mozilla/Assertions.h"
+#include "mozilla/EventForwards.h"
#include "mozilla/StaticPrefs_apz.h"
#include "mozilla/StaticPrefs_ui.h"
#include "nsDebug.h" // for NS_WARNING
@@ -83,8 +86,8 @@ GestureEventListener::~GestureEventListener() = default;
nsEventStatus GestureEventListener::HandleInputEvent(
const MultiTouchInput& aEvent) {
- GEL_LOG("Receiving event type %d with %zu touches in state %d\n",
- aEvent.mType, aEvent.mTouches.Length(), mState);
+ GEL_LOG("Receiving event type %d with %zu touches in state %s\n",
+ aEvent.mType, aEvent.mTouches.Length(), ToString(mState).c_str());
nsEventStatus rv = nsEventStatus_eIgnore;
@@ -175,16 +178,15 @@ nsEventStatus GestureEventListener::HandleInputTouchSingleStart() {
EnterFirstSingleTouchDown();
break;
case GESTURE_FIRST_SINGLE_TOUCH_UP:
+ // Bail out of any gesture that includes the first tap.
+ CancelLongTapTimeoutTask();
+ CancelMaxTapTimeoutTask();
if (SecondTapIsFar()) {
- // If the second tap goes down far away from the first, then bail out
- // of any gesture that includes the first tap.
- CancelLongTapTimeoutTask();
- CancelMaxTapTimeoutTask();
- mSingleTapSent = Nothing();
-
- // But still allow the second tap to participate in a gesture
+ // If the second tap goes down far away from the first,
+ // allow the second tap to participate in a gesture
// (e.g. lead to a single tap, or a double tap if an additional
// tap occurs near the same location).
+ mSingleTapSent = Nothing();
EnterFirstSingleTouchDown();
} else {
// Otherwise, reset the touch start position so that, if this turns into
@@ -225,9 +227,10 @@ nsEventStatus GestureEventListener::HandleInputTouchMultiStart() {
rv = nsEventStatus_eConsumeNoDefault;
break;
case GESTURE_FIRST_SINGLE_TOUCH_UP:
- case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
// Cancel wait for double tap
CancelMaxTapTimeoutTask();
+ [[fallthrough]];
+ case GESTURE_SECOND_SINGLE_TOUCH_DOWN:
MOZ_ASSERT(mSingleTapSent.isSome());
if (!mSingleTapSent.value()) {
TriggerSingleTapConfirmedEvent();
@@ -307,12 +310,8 @@ nsEventStatus GestureEventListener::HandleInputTouchMove() {
// If touch has moved noticeably (within StaticPrefs::apz_max_tap_time()),
// change state.
if (MoveDistanceIsLarge()) {
- CancelLongTapTimeoutTask();
- CancelMaxTapTimeoutTask();
mSingleTapSent = Nothing();
- if (!StaticPrefs::apz_one_touch_pinch_enabled()) {
- // If the one-touch-pinch feature is disabled, bail out of the double-
- // tap gesture instead.
+ if (!mAsyncPanZoomController->AllowOneTouchPinch()) {
SetState(GESTURE_NONE);
break;
}
@@ -451,7 +450,6 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() {
}
case GESTURE_SECOND_SINGLE_TOUCH_DOWN: {
- CancelMaxTapTimeoutTask();
MOZ_ASSERT(mSingleTapSent.isSome());
mAsyncPanZoomController->HandleGestureEvent(CreateTapEvent(
mLastTouchInput, mSingleTapSent.value()
@@ -535,7 +533,9 @@ nsEventStatus GestureEventListener::HandleInputTouchCancel() {
}
void GestureEventListener::HandleInputTimeoutLongTap() {
- GEL_LOG("Running long-tap timeout task in state %d\n", mState);
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+ GEL_LOG("Running long-tap timeout task in state %s\n",
+ ToString(mState).c_str());
mLongTapTimeoutTask = nullptr;
@@ -559,14 +559,15 @@ void GestureEventListener::HandleInputTimeoutLongTap() {
}
void GestureEventListener::HandleInputTimeoutMaxTap(bool aDuringFastFling) {
- GEL_LOG("Running max-tap timeout task in state %d\n", mState);
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+ GEL_LOG("Running max-tap timeout task in state %s\n",
+ ToString(mState).c_str());
mMaxTapTimeoutTask = nullptr;
if (mState == GESTURE_FIRST_SINGLE_TOUCH_DOWN) {
SetState(GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN);
- } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP ||
- mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
+ } else if (mState == GESTURE_FIRST_SINGLE_TOUCH_UP) {
MOZ_ASSERT(mSingleTapSent.isSome());
if (!aDuringFastFling && !mSingleTapSent.value()) {
TriggerSingleTapConfirmedEvent();
@@ -585,6 +586,8 @@ void GestureEventListener::TriggerSingleTapConfirmedEvent() {
}
void GestureEventListener::SetState(GestureState aState) {
+ GEL_LOG("State change from %s to %s", ToString(mState).c_str(),
+ ToString(aState).c_str());
mState = aState;
if (mState == GESTURE_NONE) {
@@ -598,10 +601,7 @@ void GestureEventListener::SetState(GestureState aState) {
}
void GestureEventListener::CancelLongTapTimeoutTask() {
- if (mState == GESTURE_SECOND_SINGLE_TOUCH_DOWN) {
- // being in this state means the task has been canceled already
- return;
- }
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
if (mLongTapTimeoutTask) {
mLongTapTimeoutTask->Cancel();
@@ -628,6 +628,8 @@ void GestureEventListener::CreateLongTapTimeoutTask() {
}
void GestureEventListener::CancelMaxTapTimeoutTask() {
+ MOZ_ASSERT(mState != GESTURE_SECOND_SINGLE_TOUCH_DOWN);
+
if (mState == GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN) {
// being in this state means the timer has just been triggered
return;
@@ -659,5 +661,40 @@ void GestureEventListener::CreateMaxTapTimeoutTask() {
std::max(0L, remainingDelay));
}
+std::ostream& operator<<(std::ostream& os,
+ GestureEventListener::GestureState aState) {
+ switch (aState) {
+ case GestureEventListener::GESTURE_NONE:
+ os << "GESTURE_NONE";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_DOWN:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN";
+ break;
+ case GestureEventListener::GESTURE_FIRST_SINGLE_TOUCH_UP:
+ os << "GESTURE_FIRST_SINGLE_TOUCH_UP";
+ break;
+ case GestureEventListener::GESTURE_SECOND_SINGLE_TOUCH_DOWN:
+ os << "GESTURE_SECOND_SINGLE_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_LONG_TOUCH_DOWN:
+ os << "GESTURE_LONG_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_MULTI_TOUCH_DOWN:
+ os << "GESTURE_MULTI_TOUCH_DOWN";
+ break;
+ case GestureEventListener::GESTURE_PINCH:
+ os << "GESTURE_PINCH";
+ break;
+ case GestureEventListener::GESTURE_ONE_TOUCH_PINCH:
+ os << "GESTURE_ONE_TOUCH_PINCH";
+ break;
+ }
+
+ return os;
+}
+
} // namespace layers
} // namespace mozilla
diff --git a/gfx/layers/apz/src/GestureEventListener.h b/gfx/layers/apz/src/GestureEventListener.h
index aa51889fdd..bf50d4f40a 100644
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -7,6 +7,7 @@
#ifndef mozilla_layers_GestureEventListener_h
#define mozilla_layers_GestureEventListener_h
+#include <iosfwd>
#include "InputData.h" // for MultiTouchInput, etc
#include "Units.h"
#include "mozilla/EventForwards.h" // for nsEventStatus
@@ -135,6 +136,8 @@ class GestureEventListener final {
GESTURE_ONE_TOUCH_PINCH
};
+ friend std::ostream& operator<<(std::ostream& os, GestureState aState);
+
/**
* These HandleInput* functions comprise input alphabet of the GEL
* finite-state machine triggering state transitions.
diff --git a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
index f244ca4dc7..8256667d6b 100644
--- a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
+++ b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp
@@ -21,12 +21,12 @@ class APZCGestureDetectorTester : public APZCBasicTester {
: APZCBasicTester(AsyncPanZoomController::USE_GESTURE_DETECTOR) {}
protected:
- FrameMetrics GetPinchableFrameMetrics() {
+ FrameMetrics GetPinchableFrameMetrics(float aZoom = 2.0f) {
FrameMetrics fm;
fm.SetCompositionBounds(ParentLayerRect(200, 200, 100, 200));
fm.SetScrollableRect(CSSRect(0, 0, 980, 1000));
fm.SetVisualScrollOffset(CSSPoint(300, 300));
- fm.SetZoom(CSSToParentLayerScale(2.0));
+ fm.SetZoom(CSSToParentLayerScale(aZoom));
// APZC only allows zooming on the root scrollable frame.
fm.SetIsRootContent(true);
// the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100
@@ -843,3 +843,235 @@ TEST_F(APZCGestureDetectorTester, LongPressWithInputQueueDelay3) {
mcc->AdvanceByMillis(1);
check.Call("post long-tap dispatch");
}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureShort) {
+ // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
+ // hold second touch down for a very short time, then move
+ // and expect a successful one touch pinch gesture
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(10);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_NE(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureLong) {
+ // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
+ // hold second touch down for a long time, then move
+ // and expect a successful one touch pinch gesture
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_NE(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureNoMoveTriggersDoubleTap) {
+ // Take less than StaticPrefs::apz_max_tap_time() until second touch down,
+ // then wait longer than StaticPrefs::apz_max_tap_time(), lift finger up
+ // and expect a successful double tap. No zooming should be performed
+ // by the one-touch pinch codepath.
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ MakeApzcZoomable();
+
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(0);
+ EXPECT_CALL(*mcc,
+ HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _, _));
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before lifting the finger
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchUp(apzc, ScreenIntPoint(10, 10), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureNonZoomablePage) {
+ // Use a non-zoomable page. Perform a tap and a touch-drag
+ // which on a zoomable page trigger a one touch pinch gesture,
+ // and expect a single tap followed by a touch-scroll
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics(1.0f));
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ const auto oldScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+ MakeApzcUnzoomable();
+
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(1);
+ EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(0);
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 100), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 100), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+
+ const auto newScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+ EXPECT_NE(newScrollOffset, oldScrollOffset);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureTimeout) {
+ // Take longer than StaticPrefs::apz_max_tap_time() until second touch down
+ // and expect no one touch pinch gesture being performed
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", true);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+
+ EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _, _))
+ .Times(1);
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time());
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+}
+
+TEST_F(APZCGestureDetectorTester, OneTouchPinchGestureDisabled) {
+ // With apz.one_touch_pinch disabled,
+ // perform one touch pinch gesture within the time threshold,
+ // and expect no zooming.
+ SCOPED_GFX_PREF_BOOL("apz.one_touch_pinch.enabled", false);
+
+ MakeApzcZoomable();
+ apzc->SetFrameMetrics(GetPinchableFrameMetrics());
+ const auto oldZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ const auto oldScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+
+ // todo: enable following EXPECT_CALLs when fixing bug 1881794
+ // EXPECT_CALL(*mcc, HandleTap(TapType::eSingleTap, _, 0, apzc->GetGuid(), _,
+ // _))
+ // .Times(1);
+ // EXPECT_CALL(*mcc, HandleTap(TapType::eDoubleTap, _, 0, apzc->GetGuid(), _,
+ // _))
+ // .Times(0);
+
+ const auto tapResult =
+ Tap(apzc, ScreenIntPoint(10, 10), TimeDuration::FromMilliseconds(10));
+ apzc->SetAllowedTouchBehavior(tapResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() - 20);
+ const auto touchResult = TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time());
+ apzc->SetAllowedTouchBehavior(touchResult.mInputBlockId,
+ {kDefaultTouchBehavior});
+
+ // We should be able to hold down the second touch as long as we like
+ // before beginning to move
+ mcc->AdvanceByMillis(StaticPrefs::apz_max_tap_time() + 100);
+ TouchMove(apzc, ScreenIntPoint(10, 50), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchMove(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ mcc->AdvanceByMillis(10);
+ TouchUp(apzc, ScreenIntPoint(10, 150), mcc->Time());
+
+ const auto newZoom = apzc->GetFrameMetrics().GetZoom().scale;
+ EXPECT_EQ(newZoom, oldZoom);
+
+ const auto newScrollOffset = apzc->GetFrameMetrics().GetVisualScrollOffset();
+ EXPECT_NE(newScrollOffset, oldScrollOffset);
+}
diff --git a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
index c290965845..1642bc147a 100644
--- a/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
@@ -498,7 +498,7 @@ async function promiseNativeTouchpadPanEventAndWaitForObserver(
return new Promise(resolve => {
var observer = {
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
if (aTopic == "touchpadpanevent") {
resolve();
}
@@ -557,7 +557,7 @@ function promiseNativePanGestureEventAndWaitForObserver(
) {
return new Promise(resolve => {
var observer = {
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
if (aTopic == "mousescrollevent") {
resolve();
}
@@ -588,7 +588,7 @@ function promiseNativeWheelAndWaitForObserver(
) {
return new Promise(resolve => {
var observer = {
- observe(aSubject, aTopic, aData) {
+ observe(aSubject, aTopic) {
if (aTopic == "mousescrollevent") {
resolve();
}
@@ -614,7 +614,7 @@ function promiseNativeWheelAndWaitForWheelEvent(
var targetWindow = windowForTarget(aTarget);
targetWindow.addEventListener(
"wheel",
- function (e) {
+ function () {
setTimeout(resolve, 0);
},
{ once: true }
@@ -1566,7 +1566,7 @@ function promiseScrollend(aTarget = window) {
function promiseTouchEnd(element, count = 1) {
return new Promise(resolve => {
var eventCount = 0;
- var counterFunction = function (e) {
+ var counterFunction = function () {
eventCount++;
if (eventCount == count) {
element.removeEventListener("touchend", counterFunction, {
@@ -1816,7 +1816,7 @@ async function panRightToLeftUpdate(aElement, aX, aY, aMultiplier) {
);
}
-async function panRightToLeftEnd(aElement, aX, aY, aMultiplier) {
+async function panRightToLeftEnd(aElement, aX, aY) {
await NativePanHandler.promiseNativePanEvent(
aElement,
aX,
@@ -1869,7 +1869,7 @@ async function panLeftToRightUpdate(aElement, aX, aY, aMultiplier) {
);
}
-async function panLeftToRightEnd(aElement, aX, aY, aMultiplier) {
+async function panLeftToRightEnd(aElement, aX, aY) {
await NativePanHandler.promiseNativePanEvent(
aElement,
aX,
diff --git a/gfx/layers/apz/test/mochitest/apz_test_utils.js b/gfx/layers/apz/test/mochitest/apz_test_utils.js
index 821c66103d..cdae7824b2 100644
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -309,7 +309,7 @@ function promiseAfterPaint() {
// occurred by the the returned promise resolves. If you want to wait
// for those repaints, consider using promiseApzFlushedRepaints instead.
function promiseOnlyApzControllerFlushedWithoutSetTimeout(aWindow = window) {
- return new Promise(function (resolve, reject) {
+ return new Promise(function (resolve) {
var repaintDone = function () {
dump("PromiseApzRepaintsFlushed: APZ flush done\n");
SpecialPowers.Services.obs.removeObserver(
@@ -518,7 +518,7 @@ function runSubtestsSeriallyInFreshWindows(aSubtests) {
if (test.onload) {
w.addEventListener(
"load",
- function (e) {
+ function () {
test.onload(w);
},
{ once: true }
diff --git a/gfx/layers/apz/test/mochitest/browser.toml b/gfx/layers/apz/test/mochitest/browser.toml
index 5432aa0ae1..67428eee23 100644
--- a/gfx/layers/apz/test/mochitest/browser.toml
+++ b/gfx/layers/apz/test/mochitest/browser.toml
@@ -19,7 +19,7 @@ support-files = ["helper_test_autoscrolling_in_oop_frame.html"]
support-files = ["helper_background_tab_load_scroll.html"]
["browser_test_background_tab_scroll.js"]
-skip-if = ["toolkit == 'android'"] # wheel events not supported on mobile
+skip-if = ["os == 'android'"] # wheel events not supported on mobile
support-files = ["helper_background_tab_scroll.html"]
["browser_test_content_response_timeout.js"]
@@ -28,7 +28,7 @@ support-files = ["helper_content_response_timeout.html"]
["browser_test_group_fission.js"]
skip-if = [
"win11_2009 && bits == 32", # intermittent failures on on win11/32
- "os == 'linux' && bits == 64", # Bug 1773830
+ "os == 'linux' && os_version == '18.04' && bits == 64", # Bug 1773830
]
support-files = [
"FissionTestHelperParent.sys.mjs",
@@ -49,7 +49,7 @@ support-files = ["helper_scroll_thumb_dragging.html"]
["browser_test_scrollbar_in_extension_popup_window.js"]
skip-if = [
"verify",
- "os == 'linux'" # Bug 1713052
+ "os == 'linux' && os_version == '18.04'" # Bug 1713052
]
["browser_test_scrolling_in_extension_popup_window.js"]
@@ -70,7 +70,7 @@ skip-if = ["os == 'win'"] # bug 1495580
support-files = ["helper_test_select_zoom.html"]
["browser_test_tab_drag_event_counts.js"]
-skip-if = ["os == 'linux'"] # No native key event support on Linux at this time (bug 1770143)
+skip-if = ["os == 'linux' && os_version == '18.04'"] # No native key event support on Linux at this time (bug 1770143)
support-files = [
"helper_test_tab_drag_event_counts.html"
]
diff --git a/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js b/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js
index 26d0ff6109..f7f83575f2 100644
--- a/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js
+++ b/gfx/layers/apz/test/mochitest/browser_test_autoscrolling_in_oop_frame.js
@@ -74,7 +74,7 @@ async function doTest() {
return new Promise(resolve => {
content.addEventListener(
"scroll",
- event => {
+ () => {
dump("Got a scroll event in the iframe\n");
resolve();
},
diff --git a/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js b/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js
index a80fd77c17..98f6ea6c29 100644
--- a/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js
+++ b/gfx/layers/apz/test/mochitest/browser_test_content_response_timeout.js
@@ -60,6 +60,7 @@ add_task(async () => {
);
await new Promise(resolve => {
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
setTimeout(resolve, 200);
});
diff --git a/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js b/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js
index 6da3f3311b..9896e628e3 100644
--- a/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js
+++ b/gfx/layers/apz/test/mochitest/browser_test_scrolling_in_extension_popup_window.js
@@ -98,7 +98,7 @@ add_task(async () => {
return new Promise(resolve => {
content.window.addEventListener(
"scroll",
- event => {
+ () => {
dump("Got a scroll event in the popup content document\n");
resolve();
},
diff --git a/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html b/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html
index 9d71fe6251..6c31859690 100644
--- a/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html
+++ b/gfx/layers/apz/test/mochitest/helper_basic_scrollend.html
@@ -19,7 +19,7 @@ const searchParams = new URLSearchParams(location.search);
async function test() {
var scrollendCount = 0;
- function onScrollend(e) {
+ function onScrollend() {
scrollendCount += 1;
}
diff --git a/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js b/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js
index ac68c9b1d4..22a072e48d 100644
--- a/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/helper_browser_test_utils.js
@@ -4,7 +4,7 @@ Services.scriptloader.loadSubScript(
this
);
-function openSelectPopup(selector = "select", win = window) {
+function openSelectPopup(selector, win = window) {
let popupShownPromise = BrowserTestUtils.waitForSelectPopupShown(win);
EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true }, win);
return popupShownPromise;
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1346632.html b/gfx/layers/apz/test/mochitest/helper_bug1346632.html
index f91f8159b5..c7f92c3810 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1346632.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1346632.html
@@ -28,7 +28,7 @@
async function test() {
var root = document.scrollingElement;
var scrollPos = root.scrollTop;
- var scrollPromise = new Promise((resolve, reject) => {
+ var scrollPromise = new Promise((resolve) => {
document.addEventListener("scroll", () => {
ok(root.scrollTop > scrollPos, "document scrolled after dragging scrollbar");
resolve();
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1414336.html b/gfx/layers/apz/test/mochitest/helper_bug1414336.html
index 636328b7e4..c0d35db401 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1414336.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1414336.html
@@ -62,14 +62,14 @@ waitUntilApzStable().then(async () => {
let target0 = window.document.getElementById("target0");
let target0_events = ["pointerdown", "pointermove"];
- target0_events.forEach((elem, index, arr) => {
+ target0_events.forEach((elem) => {
target0.addEventListener(elem, (event) => {
is(event.type, target0_events[0], "receive " + event.type + " on target0");
target0_events.shift();
}, { once: true });
});
- target0.addEventListener("pointercancel", (event) => {
+ target0.addEventListener("pointercancel", () => {
ok(false, "Shouldn't receive pointercancel when content prevents default on touchstart");
// Wait until the event is done processing before we end the subtest,
// otherwise on Android the pointer events pref is flipped back to false
@@ -81,7 +81,7 @@ waitUntilApzStable().then(async () => {
event.preventDefault();
}, { once: true });
- target0.addEventListener("pointerup", (event) => {
+ target0.addEventListener("pointerup", () => {
ok(!target0_events.length, " should receive " + target0_events + " on target0");
// Wait until the event is done processing before we end the subtest,
// otherwise on Android the pointer events pref is flipped back to false
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html b/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html
index 73badf4bc7..8534e8886b 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1502010_unconsumed_pan.html
@@ -38,7 +38,7 @@
async function test() {
var target = document.getElementById("carousel");
- target.addEventListener("pointercancel", (event) => {
+ target.addEventListener("pointercancel", () => {
ok(false, "Received pointercancel, uh-oh!");
endEventReceived = true;
setTimeout(checkForTestEnd, 0);
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html b/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html
index cc73fe99ea..b853bde04d 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1506497_touch_action_fixed_on_fixed.html
@@ -11,7 +11,7 @@
<script type="application/javascript">
async function test() {
- document.getElementById("overlay").addEventListener("touchstart", function(e) {
+ document.getElementById("overlay").addEventListener("touchstart", function() {
// no need to do anything here. Just having a non-passive touchstart
// listener will force APZ to wait for the main thread to handle the
// touch event. The bug is that the touch-action:none property on the
@@ -34,7 +34,7 @@ async function test() {
// This promise will resolve after the main thread has processed
// all the synthesized touch events.
let promiseTouchEnd = new Promise(resolve => {
- var waitForTouchEnd = function(e) {
+ var waitForTouchEnd = function() {
dump("touchend listener hit\n");
resolve();
};
diff --git a/gfx/layers/apz/test/mochitest/helper_bug1695598.html b/gfx/layers/apz/test/mochitest/helper_bug1695598.html
index fb6102e33d..7961d7ced4 100644
--- a/gfx/layers/apz/test/mochitest/helper_bug1695598.html
+++ b/gfx/layers/apz/test/mochitest/helper_bug1695598.html
@@ -19,7 +19,7 @@
let utils = SpecialPowers.getDOMWindowUtils(window);
let timeStamp = document.timeline.currentTime;
- async function sendScrollEvent(aRafTimestamp) {
+ async function sendScrollEvent() {
if (i < scrollEvents) {
if (timeStamp == document.timeline.currentTime) {
// If we are in a rAF callback at the same time stamp we've already
diff --git a/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html b/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html
index 41a0319699..c0481d01a4 100644
--- a/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html
+++ b/gfx/layers/apz/test/mochitest/helper_content_response_timeout.html
@@ -11,7 +11,7 @@ div { height: 1000vh; }
</style>
<div id='target'></div>
<script>
-window.addEventListener('wheel', (e) => {
+window.addEventListener('wheel', () => {
const timeAtStart = window.performance.now();
while (window.performance.now() - timeAtStart < 200) {
// Make a 200ms busy state.
diff --git a/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html b/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html
index 023786a270..b463e4f39c 100644
--- a/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html
+++ b/gfx/layers/apz/test/mochitest/helper_displayport_expiry.html
@@ -53,7 +53,7 @@ async function test() {
await promiseFrame();
let paintCount = 0;
- function countPaints(e) {
+ function countPaints() {
paintCount += 1;
}
diff --git a/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html b/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html
index 82f529bebd..8ebfc492f2 100644
--- a/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html
+++ b/gfx/layers/apz/test/mochitest/helper_fission_event_region_override.html
@@ -29,7 +29,7 @@ let code_for_oopif_to_run = function() {
let result = { x: e.clientX, y: e.clientY };
FissionTestHelper.fireEventInEmbedder("OOPIF:WheelData", result);
}, { passive: true });
- document.addEventListener("scroll", function(e) {
+ document.addEventListener("scroll", function() {
dump(`OOPIF got scroll to ${window.scrollX},${window.scrollY}\n`);
let result = { x: window.scrollX, y: window.scrollY };
FissionTestHelper.fireEventInEmbedder("OOPIF:Scrolled", result);
diff --git a/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html b/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
index 2911b1eaf0..5a192c9f9e 100644
--- a/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
+++ b/gfx/layers/apz/test/mochitest/helper_fission_scroll_oopif.html
@@ -66,7 +66,7 @@ let make_oopif_scrollable = function() {
FissionTestHelper.fireEventInEmbedder("OOPIF:Scrollable", result);
});
// Also register a scroll listener for when it actually gets scrolled.
- window.addEventListener("scroll", function(e) {
+ window.addEventListener("scroll", function() {
dump(`OOPIF got scroll event, now at ${window.scrollY}\n`);
let result = { y: window.scrollY };
FissionTestHelper.fireEventInEmbedder("OOPIF:Scrolled", result);
diff --git a/gfx/layers/apz/test/mochitest/helper_fullscreen.html b/gfx/layers/apz/test/mochitest/helper_fullscreen.html
index 32de4979f2..7ac443a1cc 100644
--- a/gfx/layers/apz/test/mochitest/helper_fullscreen.html
+++ b/gfx/layers/apz/test/mochitest/helper_fullscreen.html
@@ -27,7 +27,7 @@
});
}
- async function test(testDriver) {
+ async function test() {
target.requestFullscreen();
await waitForFullscreenChange();
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html b/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html
index a04b1d3e83..30a9740d24 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_deep_scene_stack.html
@@ -38,7 +38,7 @@ for (var i = 3; i < 1000; i++) {
}
document.body.appendChild(div);
-async function test(testDriver) {
+async function test() {
var config = getHitTestConfig();
var utils = config.utils;
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html
index 0f20719d46..b83b864aa2 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-2.html
@@ -45,7 +45,7 @@ async function test() {
e.stopPropagation(); // do not propagate event to |fixed| ancestor
resolve();
});
- fixed.addEventListener("click", e => {
+ fixed.addEventListener("click", () => {
// Since target's listener calls stopPropagation(), if we get here
// then the coordinates of the click event did not correspond to
// |target|, but somewhere else on |fixed|.
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html
index 2004ea9ae4..092c5b0dfa 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_fixed-3.html
@@ -72,7 +72,7 @@ async function test() {
e.stopPropagation(); // do not propagate event to ancestors
resolve();
});
- fixed.addEventListener("click", e => {
+ fixed.addEventListener("click", () => {
// Since target's listener calls stopPropagation(), if we get here
// then the coordinates of the click event did not correspond to
// |target|, but somewhere else on |fixed|.
@@ -82,7 +82,7 @@ async function test() {
todo(false, "Fixed ancestor should not be hit");
resolve();
});
- window.addEventListener("click", e => {
+ window.addEventListener("click", () => {
// Similarly, the root content document's window should not be hit.
ok(false, "Root document should not be hit");
resolve();
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html b/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html
index 530c53fd7a..3185d83bf5 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_fixed.html
@@ -53,7 +53,7 @@ async function test() {
e.stopPropagation(); // do not propagate event to |fixed| ancestor
resolve();
});
- fixed.addEventListener("click", e => {
+ fixed.addEventListener("click", () => {
// Since target's listener calls stopPropagation(), if we get here
// then the coordinates of the click event did not correspond to
// |target|, but somewhere else on |fixed|.
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html b/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html
index 0abed82156..6d9ea7bc53 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_hidden_inactive_scrollframe.html
@@ -26,7 +26,7 @@
</body>
<script type="application/javascript">
-function test(testDriver) {
+function test() {
var config = getHitTestConfig();
var utils = config.utils;
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html b/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html
index 9838a02aa9..b6128aaa87 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_iframe_perspective-2.html
@@ -44,7 +44,7 @@ async function test() {
}
});
- window.addEventListener("mousedown", event => {
+ window.addEventListener("mousedown", () => {
ok(true, "Parent document should have received mouse-down");
resolve();
});
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html
index c245258b68..c33dff3f28 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll.html
@@ -63,7 +63,7 @@ function startListeningForClickEventsInChrome() {
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
}
let chromeReceivedClick = false;
- function chromeListener(e) {
+ function chromeListener() {
chromeReceivedClick = true;
}
topWin.addEventListener("click", chromeListener);
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html
index 8aff3103dd..0bb3972c8a 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_contextmenu.html
@@ -43,7 +43,7 @@ function startListeningForContextmenuEventsInChrome() {
topWin = Services.wm.getMostRecentWindow("navigator:geckoview");
}
let chromeReceivedContextmenu = false;
- function chromeListener(e) {
+ function chromeListener() {
chromeReceivedContextmenu = true;
}
topWin.addEventListener("contextmenu", chromeListener);
@@ -95,7 +95,7 @@ async function test() {
let midGutter = 4 / deviceScale; // gutter is 8 *screen* pixels
startListeningForContextmenuEventsInChrome();
let contentReceivedContextmenu = false;
- let contentListener = function(e) {
+ let contentListener = function() {
contentReceivedContextmenu = true;
};
document.addEventListener("contextmenu", contentListener);
diff --git a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html
index 36918b3682..ff97c34bd5 100644
--- a/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_overscroll_subframe.html
@@ -84,7 +84,7 @@ async function test() {
// This makes sure we catch the case where the overscroll transform causes
// the event to incorrectly target the document.
let receivedClick = false;
- let listener = function(e) {
+ let listener = function() {
receivedClick = true;
};
document.addEventListener("click", listener);
diff --git a/gfx/layers/apz/test/mochitest/helper_key_scroll.html b/gfx/layers/apz/test/mochitest/helper_key_scroll.html
index 021e2803b7..4f574abd10 100644
--- a/gfx/layers/apz/test/mochitest/helper_key_scroll.html
+++ b/gfx/layers/apz/test/mochitest/helper_key_scroll.html
@@ -32,7 +32,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1383365
// page. This scroll is done synchronously because APZ doesn't have
// current focus state at page load.
let scrollBottomPromise = new Promise(resolve => {
- let checkBottom = function(e) {
+ let checkBottom = function() {
if (window.scrollY < window.scrollMaxY) {
return;
}
@@ -63,7 +63,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1383365
// This scroll should be asynchronous now that the focus state is up to date.
let scrollTopPromise = new Promise(resolve => {
- let checkTop = function(e) {
+ let checkTop = function() {
if (window.scrollY > 0) {
return;
}
diff --git a/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html b/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html
index 4f07db516e..c4a98ec7fa 100644
--- a/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html
+++ b/gfx/layers/apz/test/mochitest/helper_main_thread_smooth_scroll_scrollend.html
@@ -25,7 +25,7 @@
async function test() {
let scrollendCount = 0;
- window.addEventListener("scrollend", e => {
+ window.addEventListener("scrollend", () => {
scrollendCount += 1;
});
diff --git a/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html b/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html
index 17ccb3a54d..9c98ecf727 100644
--- a/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html
+++ b/gfx/layers/apz/test/mochitest/helper_minimum_scale_1_0.html
@@ -22,7 +22,7 @@
<script type="application/javascript">
const utils = SpecialPowers.getDOMWindowUtils(window);
- async function test(testDriver) {
+ async function test() {
utils.scrollToVisual(100, 0, utils.UPDATE_TYPE_MAIN_THREAD,
utils.SCROLL_MODE_INSTANT);
diff --git a/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html b/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html
index 7280a26006..1c26fafdb7 100644
--- a/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html
+++ b/gfx/layers/apz/test/mochitest/helper_no_scalable_with_initial_scale.html
@@ -22,7 +22,7 @@
<script type="application/javascript">
const utils = SpecialPowers.getDOMWindowUtils(window);
- async function test(testDriver) {
+ async function test() {
utils.scrollToVisual(100, 0, utils.UPDATE_TYPE_MAIN_THREAD,
utils.SCROLL_MODE_INSTANT);
diff --git a/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html b/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html
index 721ce7e538..755c4115e2 100644
--- a/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html
+++ b/gfx/layers/apz/test/mochitest/helper_programmatic_scroll_behavior.html
@@ -35,7 +35,7 @@ async function test() {
// trigger one scroll event, so a scroll event count of 1 indicates that a
// instant scroll was conducted.
let scrollCount = 0;
- window.addEventListener("scroll", (e) => {
+ window.addEventListener("scroll", () => {
scrollCount += 1;
});
diff --git a/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html b/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
index 6a8a09e55a..14e800a561 100644
--- a/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
+++ b/gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
@@ -293,7 +293,7 @@ function* test(testDriver) {
// waitUntilApzStable().then(runContinuation(myTest));
function runContinuation(testFunction) {
return function() {
- return new Promise(function(resolve, reject) {
+ return new Promise(function(resolve) {
var testContinuation = null;
function driveTest() {
diff --git a/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html b/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html
index 98547fb73f..0692c2f588 100644
--- a/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html
+++ b/gfx/layers/apz/test/mochitest/helper_zoomed_pan.html
@@ -42,7 +42,7 @@
x: 0,
y: 0,
dx: (width) => -computeDelta(width),
- dy: (height) => 0,
+ dy: () => 0,
expected: {
x: [OFFSET_CSS_PX, "x-offset was adjusted"],
y: [0, "y-offset was not affected"],
@@ -51,7 +51,7 @@
{
x: OFFSET_CSS_PX,
y: 0,
- dx: (width) => 0,
+ dx: () => 0,
dy: (height) => -computeDelta(height),
expected: {
x: [OFFSET_CSS_PX, "x-offset was not affected"],
diff --git a/gfx/layers/apz/test/mochitest/test_smoothness.html b/gfx/layers/apz/test/mochitest/test_smoothness.html
index 64cb8bcefa..0f2ca3219e 100644
--- a/gfx/layers/apz/test/mochitest/test_smoothness.html
+++ b/gfx/layers/apz/test/mochitest/test_smoothness.html
@@ -23,7 +23,7 @@
SimpleTest.waitForExplicitFinish();
var utils = SpecialPowers.getDOMWindowUtils(window);
- async function sendScrollEvent(aRafTimestamp) {
+ async function sendScrollEvent() {
var scrollDiv = document.getElementById("content");
if (i < scrollEvents) {
diff --git a/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html b/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
index 71147d5238..0598f1a201 100644
--- a/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
+++ b/gfx/layers/apz/test/mochitest/test_touch_listeners_impacting_wheel.html
@@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1203140
const kResponseTimeoutMs = 2 * 60 * 1000; // 2 minutes
-function takeSnapshots(e) {
+function takeSnapshots() {
// Grab some snapshots, and make sure some of them are different (i.e. check
// the page is scrolling in the compositor, concurrently with this wheel
// listener running).
@@ -69,7 +69,7 @@ async function test() {
// Ensure the div is layerized by scrolling it
await promiseMoveMouseAndScrollWheelOver(box, 10, 10);
- box.addEventListener("touchstart", function(e) {
+ box.addEventListener("touchstart", function() {
ok(false, "This should never be run");
});
box.addEventListener("wheel", takeSnapshots, { capture: false, passive: true });
diff --git a/gfx/layers/apz/test/reftest/reftest.list b/gfx/layers/apz/test/reftest/reftest.list
index 77bfff3e6e..9af67384a8 100644
--- a/gfx/layers/apz/test/reftest/reftest.list
+++ b/gfx/layers/apz/test/reftest/reftest.list
@@ -1,14 +1,14 @@
# The following tests test the async positioning of the scrollbars.
# Basic root-frame scrollbar with async scrolling
# First make sure that we are actually drawing scrollbars
-skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v.html about:blank
-skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v-ref.html about:blank
-fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
-fuzzy-if(Android,0-13,0-10) fuzzy-if(gtkWidget,1-30,4-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
-fuzzy-if(Android,0-13,0-21) fuzzy-if(gtkWidget,1-4,4-24) fuzzy-if(cocoaWidget,11-18,44-88) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
-fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
-fuzzy-if(Android,0-14,0-10) fuzzy-if(gtkWidget,1-30,12-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
-fuzzy-if(Android,0-43,0-26) fuzzy-if(gtkWidget,0-14,12-32) fuzzy-if(cocoaWidget,11-18,26-76) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
+skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) != async-scrollbar-1-v.html about:blank
+skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) != async-scrollbar-1-v-ref.html about:blank
+fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
+fuzzy-if(Android,0-13,0-10) fuzzy-if(gtkWidget,1-30,4-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
+fuzzy-if(Android,0-13,0-21) fuzzy-if(gtkWidget,1-4,4-24) fuzzy-if(cocoaWidget,11-18,44-88) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
+fuzzy-if(Android,0-5,0-6) fuzzy-if(gtkWidget,1-8,8-32) fuzzy-if(cocoaWidget,16-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
+fuzzy-if(Android,0-14,0-10) fuzzy-if(gtkWidget,1-30,12-32) fuzzy-if(cocoaWidget,14-22,20-44) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
+fuzzy-if(Android,0-43,0-26) fuzzy-if(gtkWidget,0-14,12-32) fuzzy-if(cocoaWidget,11-18,26-76) skip-if(useDrawSnapshot) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
# compositor, the border-radius ends of the scrollthumb are going to be a little
@@ -37,7 +37,7 @@ fuzzy-if(Android,0-28,0-23) fuzzy-if(!Android,0-107,0-34) pref(apz.allow_zooming
# Meta-viewport tag support
skip-if(!Android) pref(apz.allow_zooming,true) == initial-scale-1.html initial-scale-1-ref.html
-skip-if(!asyncPan) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping-ref.html
+skip-if(useDrawSnapshot) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping-ref.html
# Test that position:fixed and position:sticky elements are attached to the
# layout viewport.
diff --git a/gfx/layers/apz/testutil/APZTestData.h b/gfx/layers/apz/testutil/APZTestData.h
index e4a73c80cc..d180bbcf1d 100644
--- a/gfx/layers/apz/testutil/APZTestData.h
+++ b/gfx/layers/apz/testutil/APZTestData.h
@@ -144,10 +144,10 @@ class APZTestData {
// A helper class for logging data for a paint.
class APZPaintLogHelper {
public:
- APZPaintLogHelper(APZTestData* aTestData, SequenceNumber aPaintSequenceNumber)
+ APZPaintLogHelper(APZTestData* aTestData, SequenceNumber aPaintSequenceNumber,
+ bool aIsTestLoggingEnabled)
: mTestData(aTestData), mPaintSequenceNumber(aPaintSequenceNumber) {
- MOZ_ASSERT(!aTestData || StaticPrefs::apz_test_logging_enabled(),
- "don't call me");
+ MOZ_ASSERT(!aTestData || aIsTestLoggingEnabled, "don't call me");
}
template <typename Value>
diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp
index 9ad65ce981..508cd8e67f 100644
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -518,7 +518,8 @@ nsEventStatus APZCCallbackHelper::DispatchSynthesizedMouseEvent(
WidgetMouseEvent::eNormal);
event.mRefPoint = LayoutDeviceIntPoint::Truncate(aRefPoint.x, aRefPoint.y);
event.mButton = MouseButton::ePrimary;
- event.mButtons |= MouseButtonsFlag::ePrimaryFlag;
+ event.mButtons = aMsg == eMouseDown ? MouseButtonsFlag::ePrimaryFlag
+ : MouseButtonsFlag::eNoButtons;
event.mInputSource = dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH;
if (aMsg == eMouseLongTap) {
event.mFlags.mOnlyChromeDispatch = true;
diff --git a/gfx/layers/apz/util/APZEventState.cpp b/gfx/layers/apz/util/APZEventState.cpp
index 7384296f45..5db6a08429 100644
--- a/gfx/layers/apz/util/APZEventState.cpp
+++ b/gfx/layers/apz/util/APZEventState.cpp
@@ -240,7 +240,7 @@ void APZEventState::ProcessLongTap(PresShell* aPresShell,
false;
#elif defined(MOZ_WIDGET_ANDROID)
// On Android, GeckoView calls preventDefault() in a JSActor
- // (ContentDelegateChild.jsm) when opening context menu so that we can
+ // (ContentDelegateChild.sys.mjs) when opening context menu so that we can
// tell whether contextmenu opens in response to the contextmenu event by
// checking where preventDefault() got called.
preventDefaultResult == PreventDefaultResult::ByChrome;
diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp
index bfc20b9b08..4187e48955 100644
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -27,6 +27,7 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/ipc/CrossProcessSemaphore.h"
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
+#include "mozilla/layers/CanvasRenderer.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/ImageBridgeChild.h"
@@ -375,7 +376,8 @@ TextureData* TextureData::Create(TextureForwarder* aAllocator,
RefPtr<CanvasChild> canvasChild = aAllocator->GetCanvasChild();
if (canvasChild) {
return new RecordedTextureData(canvasChild.forget(), aSize, aFormat,
- textureType);
+ textureType,
+ layers::TexTypeForWebgl(aKnowsCompositor));
}
// If we must be remote, but there is no canvas child, then falling back
// is not possible.
@@ -746,12 +748,10 @@ void TextureClient::ReadUnlock() {
}
bool TextureClient::Lock(OpenMode aMode) {
- MOZ_ASSERT(IsValid());
- MOZ_ASSERT(!mIsLocked);
- if (!IsValid()) {
+ if (NS_WARN_IF(!IsValid())) {
return false;
}
- if (mIsLocked) {
+ if (NS_WARN_IF(mIsLocked)) {
return mOpenMode == aMode;
}
diff --git a/gfx/layers/client/TextureRecorded.cpp b/gfx/layers/client/TextureRecorded.cpp
index 7e7ee2da99..da4ca4f8f3 100644
--- a/gfx/layers/client/TextureRecorded.cpp
+++ b/gfx/layers/client/TextureRecorded.cpp
@@ -23,9 +23,10 @@ static int64_t sNextRecordedTextureId = 0;
RecordedTextureData::RecordedTextureData(
already_AddRefed<CanvasChild> aCanvasChild, gfx::IntSize aSize,
- gfx::SurfaceFormat aFormat, TextureType aTextureType)
+ gfx::SurfaceFormat aFormat, TextureType aTextureType,
+ TextureType aWebglTextureType)
: mCanvasChild(aCanvasChild), mSize(aSize), mFormat(aFormat) {
- mCanvasChild->EnsureRecorder(aSize, aFormat, aTextureType);
+ mCanvasChild->EnsureRecorder(aSize, aFormat, aTextureType, aWebglTextureType);
}
RecordedTextureData::~RecordedTextureData() {
diff --git a/gfx/layers/client/TextureRecorded.h b/gfx/layers/client/TextureRecorded.h
index d846c1fac1..56e504fb54 100644
--- a/gfx/layers/client/TextureRecorded.h
+++ b/gfx/layers/client/TextureRecorded.h
@@ -18,7 +18,8 @@ class RecordedTextureData final : public TextureData {
public:
RecordedTextureData(already_AddRefed<CanvasChild> aCanvasChild,
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
- TextureType aTextureType);
+ TextureType aTextureType,
+ TextureType aWebglTextureType = TextureType::Unknown);
void FillInfo(TextureData::Info& aInfo) const final;
diff --git a/gfx/layers/ipc/CanvasChild.cpp b/gfx/layers/ipc/CanvasChild.cpp
index 553217d82b..515463cd8e 100644
--- a/gfx/layers/ipc/CanvasChild.cpp
+++ b/gfx/layers/ipc/CanvasChild.cpp
@@ -7,6 +7,9 @@
#include "CanvasChild.h"
#include "MainThreadUtils.h"
+#include "mozilla/dom/WorkerPrivate.h"
+#include "mozilla/dom/WorkerRef.h"
+#include "mozilla/dom/WorkerRunnable.h"
#include "mozilla/gfx/CanvasManagerChild.h"
#include "mozilla/gfx/DrawTargetRecording.h"
#include "mozilla/gfx/Tools.h"
@@ -18,6 +21,7 @@
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/SourceSurfaceSharedData.h"
#include "mozilla/Maybe.h"
+#include "mozilla/Mutex.h"
#include "nsIObserverService.h"
#include "RecordedCanvasEventImpl.h"
@@ -33,9 +37,9 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
~RecorderHelpers() override = default;
- bool InitTranslator(TextureType aTextureType, gfx::BackendType aBackendType,
- Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
- uint64_t aBufferSize,
+ bool InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
+ gfx::BackendType aBackendType, Handle&& aReadHandle,
+ nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) override {
NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
@@ -43,7 +47,7 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
return false;
}
return mCanvasChild->SendInitTranslator(
- aTextureType, aBackendType, std::move(aReadHandle),
+ aTextureType, aWebglTextureType, aBackendType, std::move(aReadHandle),
std::move(aBufferHandles), aBufferSize, std::move(aReaderSem),
std::move(aWriterSem));
}
@@ -165,9 +169,104 @@ class SourceSurfaceCanvasRecording final : public gfx::SourceSurface {
bool mDetached = false;
};
-CanvasChild::CanvasChild() = default;
+class CanvasDataShmemHolder {
+ public:
+ CanvasDataShmemHolder(ipc::SharedMemoryBasic* aShmem,
+ CanvasChild* aCanvasChild)
+ : mMutex("CanvasChild::DataShmemHolder::mMutex"),
+ mShmem(aShmem),
+ mCanvasChild(aCanvasChild) {}
+
+ bool Init(dom::ThreadSafeWorkerRef* aWorkerRef) {
+ if (!aWorkerRef) {
+ return true;
+ }
-CanvasChild::~CanvasChild() = default;
+ RefPtr<dom::StrongWorkerRef> workerRef = dom::StrongWorkerRef::Create(
+ aWorkerRef->Private(), "CanvasChild::DataShmemHolder",
+ [this]() { DestroyWorker(); });
+ if (NS_WARN_IF(!workerRef)) {
+ return false;
+ }
+
+ MutexAutoLock lock(mMutex);
+ mWorkerRef = new dom::ThreadSafeWorkerRef(workerRef);
+ return true;
+ }
+
+ void Destroy() {
+ class DestroyRunnable final : public dom::WorkerRunnable {
+ public:
+ DestroyRunnable(dom::WorkerPrivate* aWorkerPrivate,
+ CanvasDataShmemHolder* aShmemHolder)
+ : dom::WorkerRunnable(aWorkerPrivate,
+ "CanvasDataShmemHolder::Destroy",
+ dom::WorkerRunnable::WorkerThread),
+ mShmemHolder(aShmemHolder) {}
+
+ bool WorkerRun(JSContext* aCx,
+ dom::WorkerPrivate* aWorkerPrivate) override {
+ mShmemHolder->Destroy();
+ return true;
+ }
+
+ void PostRun(JSContext* aCx, dom::WorkerPrivate* aWorkerPrivate,
+ bool aRunResult) override {}
+
+ bool PreDispatch(dom::WorkerPrivate* aWorkerPrivate) override {
+ return true;
+ }
+
+ void PostDispatch(dom::WorkerPrivate* aWorkerPrivate,
+ bool aDispatchResult) override {}
+
+ private:
+ CanvasDataShmemHolder* mShmemHolder;
+ };
+
+ mMutex.Lock();
+
+ if (mCanvasChild) {
+ if (mWorkerRef) {
+ if (!mWorkerRef->Private()->IsOnCurrentThread()) {
+ auto task = MakeRefPtr<DestroyRunnable>(mWorkerRef->Private(), this);
+ mMutex.Unlock();
+ task->Dispatch();
+ return;
+ }
+ } else if (!NS_IsMainThread()) {
+ mMutex.Unlock();
+ NS_DispatchToMainThread(NS_NewRunnableFunction(
+ "CanvasDataShmemHolder::Destroy", [this]() { Destroy(); }));
+ return;
+ }
+
+ mCanvasChild->ReturnDataSurfaceShmem(mShmem.forget());
+ mCanvasChild = nullptr;
+ mWorkerRef = nullptr;
+ }
+
+ mMutex.Unlock();
+ delete this;
+ }
+
+ void DestroyWorker() {
+ MutexAutoLock lock(mMutex);
+ mCanvasChild = nullptr;
+ mWorkerRef = nullptr;
+ }
+
+ private:
+ Mutex mMutex;
+ RefPtr<ipc::SharedMemoryBasic> mShmem;
+ RefPtr<CanvasChild> mCanvasChild MOZ_GUARDED_BY(mMutex);
+ RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef MOZ_GUARDED_BY(mMutex);
+};
+
+CanvasChild::CanvasChild(dom::ThreadSafeWorkerRef* aWorkerRef)
+ : mWorkerRef(aWorkerRef) {}
+
+CanvasChild::~CanvasChild() { MOZ_ASSERT(!mWorkerRef); }
static void NotifyCanvasDeviceReset() {
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
@@ -207,14 +306,15 @@ ipc::IPCResult CanvasChild::RecvBlockCanvas() {
}
void CanvasChild::EnsureRecorder(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
- TextureType aTextureType) {
+ TextureType aTextureType,
+ TextureType aWebglTextureType) {
NS_ASSERT_OWNINGTHREAD(CanvasChild);
if (!mRecorder) {
gfx::BackendType backendType =
gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
- auto recorder = MakeRefPtr<CanvasDrawEventRecorder>();
- if (!recorder->Init(aTextureType, backendType,
+ auto recorder = MakeRefPtr<CanvasDrawEventRecorder>(mWorkerRef);
+ if (!recorder->Init(aTextureType, aWebglTextureType, backendType,
MakeUnique<RecorderHelpers>(this))) {
return;
}
@@ -242,6 +342,8 @@ void CanvasChild::Destroy() {
if (CanSend()) {
Send__delete__(this);
}
+
+ mWorkerRef = nullptr;
}
bool CanvasChild::EnsureBeginTransaction() {
@@ -397,6 +499,10 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
return nullptr;
}
+ gfx::IntSize ssSize = aSurface->GetSize();
+ gfx::SurfaceFormat ssFormat = aSurface->GetFormat();
+ auto stride = ImageDataSerializer::ComputeRGBStride(ssFormat, ssSize.width);
+
// Shmem is only valid if the surface is the latest snapshot (not detached).
if (!aDetached) {
// If there is a shmem associated with this snapshot id, then we want to try
@@ -411,20 +517,22 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
if (NS_WARN_IF(!mRecorder->WaitForCheckpoint(checkpoint))) {
return nullptr;
}
- gfx::IntSize size = aSurface->GetSize();
- gfx::SurfaceFormat format = aSurface->GetFormat();
- auto stride = ImageDataSerializer::ComputeRGBStride(format, size.width);
+ auto* closure =
+ new CanvasDataShmemHolder(it->second.mSnapshotShmem, this);
+ if (NS_WARN_IF(!closure->Init(mWorkerRef))) {
+ delete closure;
+ return nullptr;
+ }
RefPtr<gfx::DataSourceSurface> dataSurface =
- gfx::Factory::CreateWrappingDataSourceSurface(shmemPtr, stride, size,
- format);
+ gfx::Factory::CreateWrappingDataSourceSurface(
+ shmemPtr, stride, ssSize, ssFormat, ReleaseDataShmemHolder,
+ closure);
return dataSurface.forget();
}
}
RecordEvent(RecordedPrepareDataForSurface(aSurface));
- gfx::IntSize ssSize = aSurface->GetSize();
- gfx::SurfaceFormat ssFormat = aSurface->GetFormat();
if (!EnsureDataSurfaceShmem(ssSize, ssFormat)) {
return nullptr;
}
@@ -435,15 +543,15 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
return nullptr;
}
+ auto* closure = new CanvasDataShmemHolder(mDataSurfaceShmem, this);
+ if (NS_WARN_IF(!closure->Init(mWorkerRef))) {
+ delete closure;
+ return nullptr;
+ }
+
mDataSurfaceShmemAvailable = false;
- struct DataShmemHolder {
- RefPtr<ipc::SharedMemoryBasic> shmem;
- RefPtr<CanvasChild> canvasChild;
- };
auto* data = static_cast<uint8_t*>(mDataSurfaceShmem->memory());
- auto* closure = new DataShmemHolder{do_AddRef(mDataSurfaceShmem), this};
- auto stride = ImageDataSerializer::ComputeRGBStride(ssFormat, ssSize.width);
RefPtr<gfx::DataSourceSurface> dataSurface =
gfx::Factory::CreateWrappingDataSourceSurface(
@@ -452,16 +560,8 @@ already_AddRefed<gfx::DataSourceSurface> CanvasChild::GetDataSurface(
}
/* static */ void CanvasChild::ReleaseDataShmemHolder(void* aClosure) {
- if (!NS_IsMainThread()) {
- NS_DispatchToMainThread(NS_NewRunnableFunction(
- "CanvasChild::ReleaseDataShmemHolder",
- [aClosure]() { ReleaseDataShmemHolder(aClosure); }));
- return;
- }
-
- auto* shmemHolder = static_cast<DataShmemHolder*>(aClosure);
- shmemHolder->canvasChild->ReturnDataSurfaceShmem(shmemHolder->shmem.forget());
- delete shmemHolder;
+ auto* shmemHolder = static_cast<CanvasDataShmemHolder*>(aClosure);
+ shmemHolder->Destroy();
}
already_AddRefed<gfx::SourceSurface> CanvasChild::WrapSurface(
diff --git a/gfx/layers/ipc/CanvasChild.h b/gfx/layers/ipc/CanvasChild.h
index c99fe50bfb..e22109f406 100644
--- a/gfx/layers/ipc/CanvasChild.h
+++ b/gfx/layers/ipc/CanvasChild.h
@@ -15,6 +15,10 @@
namespace mozilla {
+namespace dom {
+class ThreadSafeWorkerRef;
+}
+
namespace gfx {
class DrawTargetRecording;
class SourceSurface;
@@ -28,7 +32,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
public:
NS_INLINE_DECL_REFCOUNTING(CanvasChild)
- CanvasChild();
+ explicit CanvasChild(dom::ThreadSafeWorkerRef* aWorkerRef);
/**
* @returns true if remote canvas has been deactivated due to failure.
@@ -58,7 +62,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
* @params aTextureType the TextureType to create in the CanvasTranslator.
*/
void EnsureRecorder(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
- TextureType aTextureType);
+ TextureType aTextureType, TextureType aWebglTextureType);
/**
* Clean up IPDL actor.
@@ -147,6 +151,9 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
void CleanupTexture(int64_t aTextureId);
+ void ReturnDataSurfaceShmem(
+ already_AddRefed<ipc::SharedMemoryBasic> aDataSurfaceShmem);
+
protected:
void ActorDestroy(ActorDestroyReason aWhy) final;
@@ -157,14 +164,6 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
bool EnsureDataSurfaceShmem(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
- void ReturnDataSurfaceShmem(
- already_AddRefed<ipc::SharedMemoryBasic> aDataSurfaceShmem);
-
- struct DataShmemHolder {
- RefPtr<ipc::SharedMemoryBasic> shmem;
- RefPtr<CanvasChild> canvasChild;
- };
-
static void ReleaseDataShmemHolder(void* aClosure);
void DropFreeBuffersWhenDormant();
@@ -173,6 +172,7 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
static bool mDeactivated;
+ RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
RefPtr<CanvasDrawEventRecorder> mRecorder;
RefPtr<ipc::SharedMemoryBasic> mDataSurfaceShmem;
diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp
index 08150d6952..4a184f48d8 100644
--- a/gfx/layers/ipc/CanvasTranslator.cpp
+++ b/gfx/layers/ipc/CanvasTranslator.cpp
@@ -13,6 +13,7 @@
#include "mozilla/gfx/DrawTargetWebgl.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUParent.h"
+#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/BufferTexture.h"
@@ -131,15 +132,17 @@ bool CanvasTranslator::EnsureSharedContextWebgl() {
}
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
- TextureType aTextureType, gfx::BackendType aBackendType,
- Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
- uint64_t aBufferSize, CrossProcessSemaphoreHandle&& aReaderSem,
+ TextureType aTextureType, TextureType aWebglTextureType,
+ gfx::BackendType aBackendType, Handle&& aReadHandle,
+ nsTArray<Handle>&& aBufferHandles, uint64_t aBufferSize,
+ CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) {
if (mHeaderShmem) {
return IPC_FAIL(this, "RecvInitTranslator called twice.");
}
mTextureType = aTextureType;
+ mWebglTextureType = aWebglTextureType;
mBackendType = aBackendType;
mOtherPid = OtherPid();
@@ -637,7 +640,11 @@ bool CanvasTranslator::HandleExtensionEvent(int32_t aType) {
}
}
-void CanvasTranslator::BeginTransaction() { mIsInTransaction = true; }
+void CanvasTranslator::BeginTransaction() {
+ PROFILER_MARKER_TEXT("CanvasTranslator", GRAPHICS, {},
+ "CanvasTranslator::BeginTransaction"_ns);
+ mIsInTransaction = true;
+}
void CanvasTranslator::Flush() {
#if defined(XP_WIN)
@@ -728,9 +735,15 @@ bool CanvasTranslator::CheckForFreshCanvasDevice(int aLineNumber) {
NotifyDeviceChanged();
}
- RefPtr<Runnable> runnable = NS_NewRunnableFunction(
- "CanvasTranslator NotifyDeviceReset",
- []() { gfx::GPUParent::GetSingleton()->NotifyDeviceReset(); });
+ RefPtr<Runnable> runnable =
+ NS_NewRunnableFunction("CanvasTranslator NotifyDeviceReset", []() {
+ if (XRE_IsGPUProcess()) {
+ gfx::GPUParent::GetSingleton()->NotifyDeviceReset();
+ } else {
+ gfx::GPUProcessManager::Get()->OnInProcessDeviceReset(
+ /* aTrackThreshold */ false);
+ }
+ });
// It is safe to wait here because only the Compositor thread waits on us and
// the main thread doesn't wait on the compositor thread in the GPU process.
@@ -1025,6 +1038,8 @@ bool CanvasTranslator::UnlockTexture(int64_t aTextureId) {
}
bool CanvasTranslator::PresentTexture(int64_t aTextureId, RemoteTextureId aId) {
+ AUTO_PROFILER_MARKER_TEXT("CanvasTranslator", GRAPHICS, {},
+ "CanvasTranslator::PresentTexture"_ns);
auto result = mTextureInfo.find(aTextureId);
if (result == mTextureInfo.end()) {
return false;
@@ -1033,7 +1048,8 @@ bool CanvasTranslator::PresentTexture(int64_t aTextureId, RemoteTextureId aId) {
RemoteTextureOwnerId ownerId = info.mRemoteTextureOwnerId;
if (gfx::DrawTargetWebgl* webgl = info.GetDrawTargetWebgl()) {
EnsureRemoteTextureOwner(ownerId);
- if (webgl->CopyToSwapChain(aId, ownerId, mRemoteTextureOwner)) {
+ if (webgl->CopyToSwapChain(mWebglTextureType, aId, ownerId,
+ mRemoteTextureOwner)) {
return true;
}
if (mSharedContext && mSharedContext->IsContextLost()) {
diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h
index cf87b7ab53..5258e0c529 100644
--- a/gfx/layers/ipc/CanvasTranslator.h
+++ b/gfx/layers/ipc/CanvasTranslator.h
@@ -69,6 +69,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* CanvasEventRingBuffer.
*
* @param aTextureType the TextureType the translator will create
+ * @param aWebglTextureType the TextureType of any WebGL buffers
* @param aBackendType the BackendType for texture data
* @param aHeaderHandle handle for the control header
* @param aBufferHandles handles for the initial buffers for translation
@@ -77,6 +78,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
*/
ipc::IPCResult RecvInitTranslator(TextureType aTextureType,
+ TextureType aWebglTextureType,
gfx::BackendType aBackendType,
Handle&& aReadHandle,
nsTArray<Handle>&& aBufferHandles,
@@ -358,6 +360,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
UniquePtr<CrossProcessSemaphore> mWriterSemaphore;
UniquePtr<CrossProcessSemaphore> mReaderSemaphore;
TextureType mTextureType = TextureType::Unknown;
+ TextureType mWebglTextureType = TextureType::Unknown;
UniquePtr<TextureData> mReferenceTextureData;
dom::ContentParentId mContentId;
uint32_t mManagerId;
diff --git a/gfx/layers/ipc/CompositorManagerChild.cpp b/gfx/layers/ipc/CompositorManagerChild.cpp
index 0e553745d3..8d89339373 100644
--- a/gfx/layers/ipc/CompositorManagerChild.cpp
+++ b/gfx/layers/ipc/CompositorManagerChild.cpp
@@ -10,6 +10,7 @@
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorManagerParent.h"
#include "mozilla/layers/CompositorThread.h"
+#include "mozilla/gfx/CanvasShutdownManager.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/dom/ContentChild.h" // for ContentChild
@@ -67,7 +68,15 @@ bool CompositorManagerChild::Init(Endpoint<PCompositorManagerChild>&& aEndpoint,
sInstance = new CompositorManagerChild(std::move(aEndpoint), aProcessToken,
aNamespace);
sOtherPid = sInstance->OtherPid();
- return sInstance->CanSend();
+ if (!sInstance->CanSend()) {
+ return false;
+ }
+
+ // If there are any canvases waiting on the recreation of the GPUProcess or
+ // CompositorManagerChild, then we need to notify them so that they can
+ // restore their contexts.
+ gfx::CanvasShutdownManager::OnCompositorManagerRestored();
+ return true;
}
/* static */
diff --git a/gfx/layers/ipc/LayersMessageUtils.h b/gfx/layers/ipc/LayersMessageUtils.h
index d869d4ed83..a4e9557ac3 100644
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -520,7 +520,7 @@ template <>
struct ParamTraits<mozilla::ScrollUpdateType>
: public ContiguousEnumSerializerInclusive<
mozilla::ScrollUpdateType, mozilla::ScrollUpdateType::Absolute,
- mozilla::ScrollUpdateType::MergeableAbsolute> {};
+ mozilla::ScrollUpdateType::PureRelative> {};
template <>
struct ParamTraits<mozilla::ScrollMode>
diff --git a/gfx/layers/ipc/PCanvas.ipdl b/gfx/layers/ipc/PCanvas.ipdl
index 5187e61d23..59896b72cf 100644
--- a/gfx/layers/ipc/PCanvas.ipdl
+++ b/gfx/layers/ipc/PCanvas.ipdl
@@ -32,9 +32,9 @@ parent:
* each aBufferHandles' memory and the default size. aReaderSem and aWriterSem
* are handles for the semaphores to handle waiting on either side.
*/
- async InitTranslator(TextureType aTextureType, BackendType aBackendType,
- Handle aHeaderHandle, Handle[] aBufferHandles,
- uint64_t aBufferSize,
+ async InitTranslator(TextureType aTextureType, TextureType aWebglTextureType,
+ BackendType aBackendType, Handle aHeaderHandle,
+ Handle[] aBufferHandles, uint64_t aBufferSize,
CrossProcessSemaphoreHandle aReaderSem,
CrossProcessSemaphoreHandle aWriterSem);
diff --git a/gfx/layers/ipc/VideoBridgeParent.cpp b/gfx/layers/ipc/VideoBridgeParent.cpp
index 6413c27bc1..50f0549e50 100644
--- a/gfx/layers/ipc/VideoBridgeParent.cpp
+++ b/gfx/layers/ipc/VideoBridgeParent.cpp
@@ -17,9 +17,8 @@ namespace mozilla::layers {
using namespace mozilla::ipc;
using namespace mozilla::gfx;
-using VideoBridgeTable =
- EnumeratedArray<VideoBridgeSource, VideoBridgeSource::_Count,
- VideoBridgeParent*>;
+using VideoBridgeTable = EnumeratedArray<VideoBridgeSource, VideoBridgeParent*,
+ size_t(VideoBridgeSource::_Count)>;
static StaticDataMutex<VideoBridgeTable> sVideoBridgeFromProcess(
"VideoBridges");
diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build
index 1bf2e83804..384611b68b 100644
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -260,7 +260,7 @@ if CONFIG["MOZ_WAYLAND"]:
"SurfacePoolWayland.cpp",
]
-if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
EXPORTS.mozilla.layers += [
"NativeLayerCA.h",
"SurfacePoolCA.h",
@@ -458,7 +458,7 @@ DEFINES["GOOGLE_PROTOBUF_NO_RTTI"] = True
DEFINES["GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER"] = True
DEFINES["MOZ_APP_VERSION"] = CONFIG["MOZ_APP_VERSION"]
-if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+if CONFIG["MOZ_WIDGET_TOOLKIT"] in ("cocoa", "uikit"):
SOURCES += [
"opengl/MacIOSurfaceTextureClientOGL.cpp",
"opengl/MacIOSurfaceTextureHostOGL.cpp",
diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
index ee61045599..112ed7711c 100644
--- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.cpp
@@ -10,7 +10,6 @@
#include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/webrender/WebRenderAPI.h"
-#include "GLContextCGL.h"
namespace mozilla {
namespace layers {
diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp
index 464b8fb69f..8a49ffef69 100644
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -229,8 +229,7 @@ Maybe<TextureHost::ResourceUpdateOp> AsyncImagePipelineManager::UpdateImageKeys(
auto* wrapper = aTexture ? aTexture->AsRemoteTextureHostWrapper() : nullptr;
if (wrapper && !aPipeline->mImageHost->GetAsyncRef()) {
std::function<void(const RemoteTextureInfo&)> function;
- RemoteTextureMap::Get()->GetRemoteTexture(
- wrapper, std::move(function), /* aWaitForRemoteTextureOwner */ false);
+ RemoteTextureMap::Get()->GetRemoteTexture(wrapper, std::move(function));
}
if (!aTexture || aTexture->NumSubTextures() == 0) {
diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp
index 789476cb6b..83139b6af6 100644
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -141,7 +141,7 @@ void gfx_wr_set_crash_annotation(mozilla::wr::CrashAnnotation aAnnotation,
return;
}
- CrashReporter::AnnotateCrashReport(annotation, nsDependentCString(aValue));
+ CrashReporter::RecordAnnotationCString(annotation, aValue);
}
void gfx_wr_clear_crash_annotation(mozilla::wr::CrashAnnotation aAnnotation) {
@@ -150,7 +150,7 @@ void gfx_wr_clear_crash_annotation(mozilla::wr::CrashAnnotation aAnnotation) {
return;
}
- CrashReporter::RemoveCrashReportAnnotation(annotation);
+ CrashReporter::UnrecordAnnotation(annotation);
}
}
@@ -1188,7 +1188,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList(
IsRootWebRenderBridgeParent());
if (!IsRootWebRenderBridgeParent()) {
- CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aTxnURL);
+ CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
+ aTxnURL);
}
CompositorBridgeParent* cbp = GetRootCompositorBridgeParent();
@@ -1330,7 +1331,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction(
IsRootWebRenderBridgeParent());
if (!IsRootWebRenderBridgeParent()) {
- CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aTxnURL);
+ CrashReporter::RecordAnnotationNSCString(CrashReporter::Annotation::URL,
+ aTxnURL);
}
AUTO_PROFILER_TRACING_MARKER("Paint", "EmptyTransaction", GRAPHICS);
diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp
index e3bbd5d50f..5016bc30f8 100644
--- a/gfx/layers/wr/WebRenderImageHost.cpp
+++ b/gfx/layers/wr/WebRenderImageHost.cpp
@@ -198,8 +198,11 @@ void WebRenderImageHost::UseRemoteTexture() {
while (!mPendingRemoteTextureWrappers.empty()) {
auto* wrapper =
mPendingRemoteTextureWrappers.front()->AsRemoteTextureHostWrapper();
- mWaitingReadyCallback = RemoteTextureMap::Get()->GetRemoteTexture(
- wrapper, readyCallback, mWaitForRemoteTextureOwner);
+ if (mWaitForRemoteTextureOwner) {
+ RemoteTextureMap::Get()->WaitForRemoteTextureOwner(wrapper);
+ }
+ mWaitingReadyCallback =
+ RemoteTextureMap::Get()->GetRemoteTexture(wrapper, readyCallback);
MOZ_ASSERT_IF(mWaitingReadyCallback, !wrapper->IsReadyForRendering());
if (!wrapper->IsReadyForRendering()) {
break;
@@ -213,9 +216,9 @@ void WebRenderImageHost::UseRemoteTexture() {
mPendingRemoteTextureWrappers.pop_front();
MOZ_ASSERT(mPendingRemoteTextureWrappers.empty());
- std::function<void(const RemoteTextureInfo&)> function;
- RemoteTextureMap::Get()->GetRemoteTexture(wrapper, std::move(function),
- mWaitForRemoteTextureOwner);
+ if (mWaitForRemoteTextureOwner) {
+ RemoteTextureMap::Get()->WaitForRemoteTextureOwner(wrapper);
+ }
mWaitForRemoteTextureOwner = false;
}
diff --git a/gfx/layers/wr/WebRenderScrollData.cpp b/gfx/layers/wr/WebRenderScrollData.cpp
index 538df8bdef..905b7e1de0 100644
--- a/gfx/layers/wr/WebRenderScrollData.cpp
+++ b/gfx/layers/wr/WebRenderScrollData.cpp
@@ -370,6 +370,22 @@ void WebRenderScrollData::ApplyUpdates(ScrollUpdatesMap&& aUpdates,
mPaintSequenceNumber = aPaintSequenceNumber;
}
+void WebRenderScrollData::PrependUpdates(
+ const WebRenderScrollData& aPreviousData) {
+ for (auto previousMetadata : aPreviousData.mScrollMetadatas) {
+ const nsTArray<ScrollPositionUpdate>& previousUpdates =
+ previousMetadata.GetScrollUpdates();
+ if (previousUpdates.IsEmpty()) {
+ continue;
+ }
+
+ if (Maybe<size_t> index =
+ HasMetadataFor(previousMetadata.GetMetrics().GetScrollId())) {
+ mScrollMetadatas[*index].PrependUpdates(previousUpdates);
+ }
+ }
+}
+
void WebRenderScrollData::DumpSubtree(std::ostream& aOut, size_t aIndex,
const std::string& aIndent) const {
aOut << aIndent;
diff --git a/gfx/layers/wr/WebRenderScrollData.h b/gfx/layers/wr/WebRenderScrollData.h
index c575d4ca21..fd82ac93fc 100644
--- a/gfx/layers/wr/WebRenderScrollData.h
+++ b/gfx/layers/wr/WebRenderScrollData.h
@@ -276,6 +276,13 @@ class WebRenderScrollData {
void ApplyUpdates(ScrollUpdatesMap&& aUpdates, uint32_t aPaintSequenceNumber);
+ // Prepend the scroll position updates in the previous data to this data so
+ // that we can handle all scroll position updates in the proper order.
+ void PrependUpdates(const WebRenderScrollData& aPreviousData);
+
+ void SetWasUpdateSkipped() { mWasUpdateSkipped = true; }
+ bool GetWasUpdateSkipped() const { return mWasUpdateSkipped; }
+
friend struct IPC::ParamTraits<WebRenderScrollData>;
friend std::ostream& operator<<(std::ostream& aOut,
@@ -328,6 +335,12 @@ class WebRenderScrollData {
bool mIsFirstPaint;
uint32_t mPaintSequenceNumber;
+
+ // Wether this data was skipped to updated because the parent process hasn't
+ // yet gotten the referent LayersId for this data.
+ //
+ // Note this variable is not copied over IPC.
+ bool mWasUpdateSkipped = false;
};
} // namespace layers