--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -5,31 +5,33 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <math.h> // for fabsf, fabs, atan2
#include <stdint.h> // for uint32_t, uint64_t
#include <sys/types.h> // for int32_t
#include <algorithm> // for max, min
#include "AsyncPanZoomController.h" // for AsyncPanZoomController, etc
#include "Axis.h" // for AxisX, AxisY, Axis, etc
+#include "CheckerboardEvent.h" // for CheckerboardEvent
#include "Compositor.h" // for Compositor
#include "FrameMetrics.h" // for FrameMetrics, etc
#include "GestureEventListener.h" // for GestureEventListener
#include "HitTestingTreeNode.h" // for HitTestingTreeNode
#include "InputData.h" // for MultiTouchInput, etc
#include "InputBlockState.h" // for InputBlockState, TouchBlockState
#include "InputQueue.h" // for InputQueue
#include "OverscrollHandoffState.h" // for OverscrollHandoffState
#include "Units.h" // for CSSRect, CSSPoint, etc
#include "UnitTransforms.h" // for TransformTo
#include "base/message_loop.h" // for MessageLoop
#include "base/task.h" // for NewRunnableMethod, etc
#include "base/tracked.h" // for FROM_HERE
#include "gfxPrefs.h" // for gfxPrefs
#include "gfxTypes.h" // for gfxFloat
+#include "LayersLogging.h" // for print_stderr
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/BasicEvents.h" // for Modifiers, MODIFIER_*
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
#include "mozilla/EventForwards.h" // for nsEventStatus_*
#include "mozilla/Preferences.h" // for Preferences
#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitorAutoEnter, etc
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
#include "mozilla/Telemetry.h" // for Telemetry
@@ -62,23 +64,20 @@
#include "nsStyleConsts.h"
#include "nsStyleStruct.h" // for nsTimingFunction
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
#include "nsThreadUtils.h" // for NS_IsMainThread
#include "prsystem.h" // for PR_GetPhysicalMemorySize
#include "SharedMemoryBasic.h" // for SharedMemoryBasic
#include "WheelScrollAnimation.h"
-// #define APZC_ENABLE_RENDERTRACE
-
#define ENABLE_APZC_LOGGING 0
// #define ENABLE_APZC_LOGGING 1
#if ENABLE_APZC_LOGGING
-# include "LayersLogging.h"
# define APZC_LOG(...) printf_stderr("APZC: " __VA_ARGS__)
# define APZC_LOG_FM(fm, prefix, ...) \
{ std::stringstream ss; \
ss << nsPrintfCString(prefix, __VA_ARGS__).get(); \
AppendToString(ss, fm, ":", "", true); \
APZC_LOG("%s\n", ss.str().c_str()); \
}
#else
@@ -271,16 +270,19 @@ using mozilla::gfx::PointTyped;
* and the velocity fall below their thresholds, we stop oscillating.\n
* Units: screen pixels (for distance)
* screen pixels per millisecond (for velocity)
*
* \li\b apz.pan_repaint_interval
* Maximum amount of time while panning before sending a viewport change. This
* will asynchronously repaint the page. It is also forced when panning stops.
*
+ * \li\b apz.record_checkerboarding
+ * Whether or not to record detailed info on checkerboarding events.
+ *
* \li\b apz.smooth_scroll_repaint_interval
* Maximum amount of time doing a smooth scroll before sending a viewport
* change. This will asynchronously repaint the page.\n
* Units: milliseconds
*
* \li\b apz.test.logging_enabled
* Enable logging of APZ test data (see bug 961289).
*
@@ -383,28 +385,16 @@ static bool IsCloseToHorizontal(float aA
}
// As above, but for the vertical axis.
static bool IsCloseToVertical(float aAngle, float aThreshold)
{
return (fabs(aAngle - (M_PI / 2)) < aThreshold);
}
-static inline void LogRendertraceRect(const ScrollableLayerGuid& aGuid, const char* aDesc, const char* aColor, const CSSRect& aRect)
-{
-#ifdef APZC_ENABLE_RENDERTRACE
- static const TimeStamp sRenderStart = TimeStamp::Now();
- TimeDuration delta = TimeStamp::Now() - sRenderStart;
- printf_stderr("(%llu,%lu,%llu)%s RENDERTRACE %f rect %s %f %f %f %f\n",
- aGuid.mLayersId, aGuid.mPresShellId, aGuid.mScrollId,
- aDesc, delta.ToMilliseconds(), aColor,
- aRect.x, aRect.y, aRect.width, aRect.height);
-#endif
-}
-
// Counter used to give each APZC a unique id
static uint32_t sAsyncPanZoomControllerCount = 0;
TimeStamp
AsyncPanZoomController::GetFrameTime() const
{
APZCTreeManager* treeManagerLocal = GetApzcTreeManager();
return treeManagerLocal ? treeManagerLocal->GetFrameTime() : TimeStamp::Now();
@@ -2855,17 +2845,20 @@ GetDisplayPortRect(const FrameMetrics& a
void
AsyncPanZoomController::DispatchRepaintRequest(const FrameMetrics& aFrameMetrics) {
RefPtr<GeckoContentController> controller = GetGeckoContentController();
if (!controller) {
return;
}
APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this);
- LogRendertraceRect(GetGuid(), "requested displayport", "yellow", GetDisplayPortRect(aFrameMetrics));
+ if (mCheckerboardEvent) {
+ mCheckerboardEvent->UpdateRendertraceProperty(
+ CheckerboardEvent::RequestedDisplayPort, GetDisplayPortRect(aFrameMetrics));
+ }
if (NS_IsMainThread()) {
controller->RequestContentRepaint(aFrameMetrics);
} else {
NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<FrameMetrics>(
controller, &GeckoContentController::RequestContentRepaint, aFrameMetrics));
}
mExpectedGeckoMetrics = aFrameMetrics;
@@ -2963,19 +2956,22 @@ bool AsyncPanZoomController::AdvanceAnim
bool requestAnimationFrame = false;
Vector<Task*> deferredTasks;
{
ReentrantMonitorAutoEnter lock(mMonitor);
requestAnimationFrame = UpdateAnimation(aSampleTime, &deferredTasks);
- LogRendertraceRect(GetGuid(), "viewport", "red",
- CSSRect(mFrameMetrics.GetScrollOffset(),
- mFrameMetrics.CalculateCompositedSizeInCssPixels()));
+ if (mCheckerboardEvent) {
+ mCheckerboardEvent->UpdateRendertraceProperty(
+ CheckerboardEvent::UserVisible,
+ CSSRect(mFrameMetrics.GetScrollOffset(),
+ mFrameMetrics.CalculateCompositedSizeInCssPixels()));
+ }
}
// Execute any deferred tasks queued up by mAnimation's Sample() (called by
// UpdateAnimation()). This needs to be done after the monitor is released
// since the tasks are allowed to call APZCTreeManager methods which can grab
// the tree lock.
for (uint32_t i = 0; i < deferredTasks.length(); ++i) {
deferredTasks[i]->Run();
@@ -3087,16 +3083,29 @@ AsyncPanZoomController::ReportCheckerboa
return;
}
uint32_t time = (aSampleTime - mLastCheckerboardReport).ToMilliseconds();
uint32_t magnitude = GetCheckerboardMagnitude();
// TODO: make this a function of velocity
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::CHECKERBOARDED_CSSPIXELS_MS, magnitude * time);
mLastCheckerboardReport = aSampleTime;
+
+ if (!mCheckerboardEvent && gfxPrefs::APZRecordCheckerboarding()) {
+ mCheckerboardEvent = MakeUnique<CheckerboardEvent>();
+ }
+ if (mCheckerboardEvent) {
+ if (mCheckerboardEvent->RecordFrameInfo(aSampleTime, magnitude)) {
+ // This checkerboard event is done. TODO: save the info somewhere or
+ // dispatch it to telemetry or something. For now we just print it.
+ std::stringstream log(mCheckerboardEvent->GetLog());
+ print_stderr(log);
+ mCheckerboardEvent = nullptr;
+ }
+ }
}
bool AsyncPanZoomController::IsCurrentlyCheckerboarding() const {
ReentrantMonitorAutoEnter lock(mMonitor);
if (!gfxPrefs::APZAllowCheckerboarding()) {
return false;
}
@@ -3119,22 +3128,27 @@ void AsyncPanZoomController::NotifyLayer
ReentrantMonitorAutoEnter lock(mMonitor);
bool isDefault = mFrameMetrics.IsDefault();
mLastContentPaintMetrics = aLayerMetrics;
mFrameMetrics.SetScrollParentId(aLayerMetrics.GetScrollParentId());
APZC_LOG_FM(aLayerMetrics, "%p got a NotifyLayersUpdated with aIsFirstPaint=%d", this, aIsFirstPaint);
- LogRendertraceRect(GetGuid(), "page", "brown", aLayerMetrics.GetScrollableRect());
- LogRendertraceRect(GetGuid(), "painted displayport", "lightgreen",
- aLayerMetrics.GetDisplayPort() + aLayerMetrics.GetScrollOffset());
- if (!aLayerMetrics.GetCriticalDisplayPort().IsEmpty()) {
- LogRendertraceRect(GetGuid(), "painted critical displayport", "darkgreen",
- aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset());
+ if (mCheckerboardEvent) {
+ mCheckerboardEvent->UpdateRendertraceProperty(
+ CheckerboardEvent::Page, aLayerMetrics.GetScrollableRect());
+ mCheckerboardEvent->UpdateRendertraceProperty(
+ CheckerboardEvent::PaintedDisplayPort,
+ aLayerMetrics.GetDisplayPort() + aLayerMetrics.GetScrollOffset());
+ if (!aLayerMetrics.GetCriticalDisplayPort().IsEmpty()) {
+ mCheckerboardEvent->UpdateRendertraceProperty(
+ CheckerboardEvent::PaintedCriticalDisplayPort,
+ aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset());
+ }
}
bool needContentRepaint = false;
bool viewportUpdated = false;
if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().width, mFrameMetrics.GetCompositionBounds().width) &&
FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().height, mFrameMetrics.GetCompositionBounds().height)) {
// Remote content has sync'd up to the composition geometry
// change, so we can accept the viewport it's calculated.
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -47,16 +47,17 @@ class PCompositorParent;
struct AsyncTransform;
class AsyncPanZoomAnimation;
class FlingAnimation;
class InputBlockState;
class TouchBlockState;
class PanGestureBlockState;
class OverscrollHandoffChain;
class StateChangeNotificationBlocker;
+class CheckerboardEvent;
/**
* Controller for all panning and zooming logic. Any time a user input is
* detected and it must be processed in some way to affect what the user sees,
* it goes through here. Listens for any input event from InputData and can
* optionally handle WidgetGUIEvent-derived touch events, but this must be done
* on the main thread. Note that this class completely cross-platform.
*
@@ -1094,14 +1095,25 @@ public:
private:
// Extra offset to add in SampleContentTransformForFrame for testing
CSSPoint mTestAsyncScrollOffset;
// Extra zoom to include in SampleContentTransformForFrame for testing
LayerToParentLayerScale mTestAsyncZoom;
// Flag to track whether or not the APZ transform is not used. This
// flag is recomputed for every composition frame.
bool mAsyncTransformAppliedToContent;
+
+
+ /* ===================================================================
+ * The functions and members in this section are used for checkerboard
+ * recording.
+ */
+private:
+ // This is created when this APZC instance is first included as part of a
+ // composite. If a checkerboard event takes place, this is destroyed at the
+ // end of the event, and a new one is created on the next composite.
+ UniquePtr<CheckerboardEvent> mCheckerboardEvent;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_PanZoomController_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/CheckerboardEvent.cpp
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CheckerboardEvent.h"
+
+#include <algorithm> // for std::sort
+
+namespace mozilla {
+namespace layers {
+
+// Relatively arbitrary limit to prevent a perma-checkerboard event from
+// eating up gobs of memory. Ideally we shouldn't have perma-checkerboarding
+// but better to guard against it.
+#define LOG_LENGTH_LIMIT (50 * 1024)
+
+const char* CheckerboardEvent::sDescriptions[] = {
+ "page",
+ "painted critical displayport",
+ "painted displayport",
+ "requested displayport",
+ "viewport",
+};
+
+const char* CheckerboardEvent::sColors[] = {
+ "brown",
+ "darkgreen",
+ "lightgreen",
+ "yellow",
+ "red",
+};
+
+CheckerboardEvent::CheckerboardEvent()
+ : mOriginTime(TimeStamp::Now())
+ , mCheckerboardingActive(false)
+ , mLastSampleTime(mOriginTime)
+ , mFrameCount(0)
+ , mTotalPixelMs(0)
+ , mPeakPixels(0)
+ , mRendertraceLock("Rendertrace")
+{
+}
+
+uint64_t
+CheckerboardEvent::GetSeverity()
+{
+ return mTotalPixelMs;
+}
+
+std::string
+CheckerboardEvent::GetLog()
+{
+ MonitorAutoLock lock(mRendertraceLock);
+ return mRendertraceInfo.str();
+}
+
+void
+CheckerboardEvent::UpdateRendertraceProperty(RendertraceProperty aProperty,
+ const CSSRect& aRect)
+{
+ MonitorAutoLock lock(mRendertraceLock);
+ if (!mCheckerboardingActive) {
+ mBufferedProperties[aProperty].Update(aProperty, aRect, lock);
+ } else {
+ LogInfo(aProperty, TimeStamp::Now(), aRect, lock);
+ }
+}
+
+void
+CheckerboardEvent::LogInfo(RendertraceProperty aProperty,
+ const TimeStamp& aTimestamp,
+ const CSSRect& aRect,
+ const MonitorAutoLock& aProofOfLock)
+{
+ if (mRendertraceInfo.tellp() >= LOG_LENGTH_LIMIT) {
+ // The log is already long enough, don't put more things into it. We'll
+ // append a truncation message when this event ends.
+ return;
+ }
+ // The log is consumed by the page at http://people.mozilla.org/~kgupta/rendertrace.html
+ // and will move to about:checkerboard in bug 1238042. The format is not
+ // formally specced, but an informal description can be found at
+ // https://github.com/staktrace/rendertrace/blob/master/index.html#L30
+ mRendertraceInfo << "RENDERTRACE "
+ << (aTimestamp - mOriginTime).ToMilliseconds() << " rect "
+ << sColors[aProperty] << " "
+ << aRect.x << " "
+ << aRect.y << " "
+ << aRect.width << " "
+ << aRect.height << " "
+ << "// " << sDescriptions[aProperty] << std::endl;
+}
+
+bool
+CheckerboardEvent::RecordFrameInfo(const TimeStamp& aSampleTime,
+ uint32_t aCssPixelsCheckerboarded)
+{
+ bool eventEnding = false;
+ if (aCssPixelsCheckerboarded > 0) {
+ if (!mCheckerboardingActive) {
+ StartEvent();
+ }
+ MOZ_ASSERT(mCheckerboardingActive);
+ MOZ_ASSERT(aSampleTime >= mLastSampleTime);
+ mTotalPixelMs += (uint64_t)((aSampleTime - mLastSampleTime).ToMilliseconds() * aCssPixelsCheckerboarded);
+ if (aCssPixelsCheckerboarded > mPeakPixels) {
+ mPeakPixels = aCssPixelsCheckerboarded;
+ }
+ mFrameCount++;
+ } else {
+ if (mCheckerboardingActive) {
+ StopEvent();
+ eventEnding = true;
+ }
+ MOZ_ASSERT(!mCheckerboardingActive);
+ }
+ mLastSampleTime = aSampleTime;
+ return eventEnding;
+}
+
+void
+CheckerboardEvent::StartEvent()
+{
+ MOZ_ASSERT(!mCheckerboardingActive);
+ mCheckerboardingActive = true;
+ mStartTime = TimeStamp::Now();
+
+ MonitorAutoLock lock(mRendertraceLock);
+ std::vector<PropertyValue> history;
+ for (int i = 0; i < MAX_RendertraceProperty; i++) {
+ mBufferedProperties[i].Flush(history, lock);
+ }
+ std::sort(history.begin(), history.end());
+ for (const PropertyValue& p : history) {
+ LogInfo(p.mProperty, p.mTimeStamp, p.mRect, lock);
+ }
+ mRendertraceInfo << " -- checkerboarding starts below --" << std::endl;
+}
+
+void
+CheckerboardEvent::StopEvent()
+{
+ mCheckerboardingActive = false;
+ mEndTime = TimeStamp::Now();
+
+ MonitorAutoLock lock(mRendertraceLock);
+ if (mRendertraceInfo.tellp() >= LOG_LENGTH_LIMIT) {
+ mRendertraceInfo << "[logging aborted due to length limitations]\n";
+ }
+ mRendertraceInfo << "Checkerboarded for " << mFrameCount << " frames ("
+ << (mEndTime - mStartTime).ToMilliseconds() << " ms), "
+ << mPeakPixels << " peak, " << GetSeverity() << " severity." << std::endl;
+}
+
+bool
+CheckerboardEvent::PropertyValue::operator<(const PropertyValue& aOther) const
+{
+ if (mTimeStamp < aOther.mTimeStamp) {
+ return true;
+ } else if (mTimeStamp > aOther.mTimeStamp) {
+ return false;
+ }
+ return mProperty < aOther.mProperty;
+}
+
+CheckerboardEvent::PropertyBuffer::PropertyBuffer()
+ : mIndex(0)
+{
+}
+
+void
+CheckerboardEvent::PropertyBuffer::Update(RendertraceProperty aProperty,
+ const CSSRect& aRect,
+ const MonitorAutoLock& aProofOfLock)
+{
+ mValues[mIndex] = { aProperty, TimeStamp::Now(), aRect };
+ mIndex = (mIndex + 1) % BUFFER_SIZE;
+}
+
+void
+CheckerboardEvent::PropertyBuffer::Flush(std::vector<PropertyValue>& aOut,
+ const MonitorAutoLock& aProofOfLock)
+{
+ for (uint32_t i = 0; i < BUFFER_SIZE; i++) {
+ uint32_t ix = (mIndex + i) % BUFFER_SIZE;
+ if (!mValues[ix].mTimeStamp.IsNull()) {
+ aOut.push_back(mValues[ix]);
+ mValues[ix].mTimeStamp = TimeStamp();
+ }
+ }
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/CheckerboardEvent.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_CheckerboardEvent_h
+#define mozilla_layers_CheckerboardEvent_h
+
+#include "mozilla/Monitor.h"
+#include "mozilla/TimeStamp.h"
+#include <sstream>
+#include "Units.h"
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * This class records information relevant to one "checkerboard event", which is
+ * a contiguous set of frames where a given APZC was checkerboarding. The intent
+ * of this class is to record enough information that it can provide actionable
+ * steps to reduce the occurrence of checkerboarding. Furthermore, it records
+ * information about the severity of the checkerboarding so as to allow
+ * prioritizing the debugging of some checkerboarding events over others.
+ */
+class CheckerboardEvent {
+public:
+ enum RendertraceProperty {
+ Page,
+ PaintedCriticalDisplayPort,
+ PaintedDisplayPort,
+ RequestedDisplayPort,
+ UserVisible,
+
+ // sentinel final value
+ MAX_RendertraceProperty
+ };
+
+ static const char* sDescriptions[MAX_RendertraceProperty];
+ static const char* sColors[MAX_RendertraceProperty];
+
+public:
+ CheckerboardEvent();
+
+ /**
+ * Gets the "severity" of the checkerboard event. This doesn't have units,
+ * it's just useful for comparing two checkerboard events to see which one
+ * is worse, for some implementation-specific definition of "worse".
+ */
+ uint64_t GetSeverity();
+
+ /**
+ * Gets the raw log of the checkerboard event. This can be called any time,
+ * although it really only makes sense to pull once the event is done, after
+ * RecordFrameInfo returns true.
+ */
+ std::string GetLog();
+
+ /**
+ * Provide a new value for one of the rects that is tracked for
+ * checkerboard events.
+ */
+ void UpdateRendertraceProperty(RendertraceProperty aProperty,
+ const CSSRect& aRect);
+
+ /**
+ * Provide the number of CSS pixels that are checkerboarded in a composite
+ * at the given sample time. The sample times must be non-decreasing, and
+ * should generally be one vsync apart.
+ * @return true if the checkerboard event has completed. The caller should
+ * stop updating this object once this happens.
+ */
+ bool RecordFrameInfo(const TimeStamp& aSampleTime,
+ uint32_t aCssPixelsCheckerboarded);
+
+private:
+ /**
+ * Helper method to do stuff when checkeboarding starts.
+ */
+ void StartEvent();
+ /**
+ * Helper method to do stuff when checkerboarding stops.
+ */
+ void StopEvent();
+
+ /**
+ * Helper method to log a rendertrace property and its value to the
+ * rendertrace info buffer (mRendertraceInfo).
+ */
+ void LogInfo(RendertraceProperty aProperty,
+ const TimeStamp& aTimestamp,
+ const CSSRect& aRect,
+ const MonitorAutoLock& aProofOfLock);
+
+ /**
+ * Helper struct that holds a single rendertrace property value.
+ */
+ struct PropertyValue
+ {
+ RendertraceProperty mProperty;
+ TimeStamp mTimeStamp;
+ CSSRect mRect;
+
+ bool operator<(const PropertyValue& aOther) const;
+ };
+
+ /**
+ * A circular buffer that stores the most recent BUFFER_SIZE values of a
+ * given property.
+ */
+ class PropertyBuffer
+ {
+ public:
+ PropertyBuffer();
+ /**
+ * Add a new value to the buffer, overwriting the oldest one if needed.
+ */
+ void Update(RendertraceProperty aProperty, const CSSRect& aRect,
+ const MonitorAutoLock& aProofOfLock);
+ /**
+ * Dump the recorded values, oldest to newest, to the given vector, and
+ * remove them from this buffer.
+ */
+ void Flush(std::vector<PropertyValue>& aOut,
+ const MonitorAutoLock& aProofOfLock);
+
+ private:
+ static const uint32_t BUFFER_SIZE = 5;
+
+ /**
+ * The index of the oldest value in the buffer. This is the next index
+ * that will be written to.
+ */
+ uint32_t mIndex;
+ PropertyValue mValues[BUFFER_SIZE];
+ };
+
+private:
+ /**
+ * A base time so that the other timestamps can be turned into durations.
+ */
+ const TimeStamp mOriginTime;
+ /**
+ * Whether or not a checkerboard event is currently occurring.
+ */
+ bool mCheckerboardingActive;
+
+ /**
+ * The start time of the checkerboard event.
+ */
+ TimeStamp mStartTime;
+ /**
+ * The end time of the checkerboard event.
+ */
+ TimeStamp mEndTime;
+ /**
+ * The sample time of the last frame recorded.
+ */
+ TimeStamp mLastSampleTime;
+ /**
+ * The number of contiguous frames with checkerboard.
+ */
+ uint32_t mFrameCount;
+ /**
+ * The total number of pixel-milliseconds of checkerboarding visible to
+ * the user during the checkerboarding event.
+ */
+ uint64_t mTotalPixelMs;
+ /**
+ * The largest number of pixels of checkerboarding visible to the user
+ * during any one frame, during this checkerboarding event.
+ */
+ uint32_t mPeakPixels;
+
+ /**
+ * Monitor that needs to be acquired before touching mBufferedProperties
+ * or mRendertraceInfo.
+ */
+ mutable Monitor mRendertraceLock;
+ /**
+ * A circular buffer to store some properties. This is used before the
+ * checkerboarding actually starts, so that we have some data on what
+ * was happening before the checkerboarding started.
+ */
+ PropertyBuffer mBufferedProperties[MAX_RendertraceProperty];
+ /**
+ * The rendertrace info buffer that gives us info on what was happening
+ * during the checkerboard event.
+ */
+ std::ostringstream mRendertraceInfo;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_CheckerboardEvent_h
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -243,16 +243,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
'ipc/GonkNativeHandleUtils.cpp',
'ipc/ShadowLayerUtilsGralloc.cpp',
]
UNIFIED_SOURCES += [
'apz/src/APZCTreeManager.cpp',
'apz/src/AsyncPanZoomController.cpp',
'apz/src/Axis.cpp',
+ 'apz/src/CheckerboardEvent.cpp',
'apz/src/GestureEventListener.cpp',
'apz/src/HitTestingTreeNode.cpp',
'apz/src/InputBlockState.cpp',
'apz/src/InputQueue.cpp',
'apz/src/OverscrollHandoffState.cpp',
'apz/src/TouchCounter.cpp',
'apz/src/WheelScrollAnimation.cpp',
'apz/testutil/APZTestData.cpp',
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -171,16 +171,17 @@ private:
DECL_GFX_PREF(Live, "apz.overscroll.min_pan_distance_ratio", APZMinPanDistanceRatio, float, 1.0f);
DECL_GFX_PREF(Live, "apz.overscroll.spring_friction", APZOverscrollSpringFriction, float, 0.015f);
DECL_GFX_PREF(Live, "apz.overscroll.spring_stiffness", APZOverscrollSpringStiffness, float, 0.001f);
DECL_GFX_PREF(Live, "apz.overscroll.stop_distance_threshold", APZOverscrollStopDistanceThreshold, float, 5.0f);
DECL_GFX_PREF(Live, "apz.overscroll.stop_velocity_threshold", APZOverscrollStopVelocityThreshold, float, 0.01f);
DECL_GFX_PREF(Live, "apz.overscroll.stretch_factor", APZOverscrollStretchFactor, float, 0.5f);
DECL_GFX_PREF(Live, "apz.pan_repaint_interval", APZPanRepaintInterval, int32_t, 250);
DECL_GFX_PREF(Live, "apz.printtree", APZPrintTree, bool, false);
+ DECL_GFX_PREF(Live, "apz.record_checkerboarding", APZRecordCheckerboarding, bool, false);
DECL_GFX_PREF(Live, "apz.smooth_scroll_repaint_interval", APZSmoothScrollRepaintInterval, int32_t, 75);
DECL_GFX_PREF(Live, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.touch_move_tolerance", APZTouchMoveTolerance, float, 0.0);
DECL_GFX_PREF(Live, "apz.touch_start_tolerance", APZTouchStartTolerance, float, 1.0f/4.5f);
DECL_GFX_PREF(Live, "apz.velocity_bias", APZVelocityBias, float, 1.0f);
DECL_GFX_PREF(Live, "apz.velocity_relevance_time_ms", APZVelocityRelevanceTime, uint32_t, 150);
DECL_GFX_PREF(Live, "apz.x_skate_highmem_adjust", APZXSkateHighMemAdjust, float, 0.0f);
DECL_GFX_PREF(Live, "apz.x_skate_size_multiplier", APZXSkateSizeMultiplier, float, 1.5f);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -569,16 +569,21 @@ pref("apz.overscroll.spring_stiffness",
pref("apz.overscroll.stop_distance_threshold", "5.0");
pref("apz.overscroll.stop_velocity_threshold", "0.01");
pref("apz.overscroll.stretch_factor", "0.35");
pref("apz.pan_repaint_interval", 16);
// Whether to print the APZC tree for debugging
pref("apz.printtree", false);
+#ifdef NIGHTLY_BUILD
+pref("apz.record_checkerboarding", true);
+#else
+pref("apz.record_checkerboarding", false);
+#endif
pref("apz.smooth_scroll_repaint_interval", 16);
pref("apz.test.logging_enabled", false);
pref("apz.touch_start_tolerance", "0.1");
pref("apz.touch_move_tolerance", "0.03");
pref("apz.velocity_bias", "1.0");
pref("apz.velocity_relevance_time_ms", 150);
pref("apz.x_skate_highmem_adjust", "0.0");
pref("apz.y_skate_highmem_adjust", "0.0");