1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_layers_CheckerboardEvent_h
8 #define mozilla_layers_CheckerboardEvent_h
9 
10 #include "mozilla/DefineEnum.h"
11 #include "mozilla/Monitor.h"
12 #include "mozilla/TimeStamp.h"
13 #include <sstream>
14 #include "Units.h"
15 #include <vector>
16 
17 namespace mozilla {
18 namespace layers {
19 
20 /**
21  * This class records information relevant to one "checkerboard event", which is
22  * a contiguous set of frames where a given APZC was checkerboarding. The intent
23  * of this class is to record enough information that it can provide actionable
24  * steps to reduce the occurrence of checkerboarding. Furthermore, it records
25  * information about the severity of the checkerboarding so as to allow
26  * prioritizing the debugging of some checkerboarding events over others.
27  */
28 class CheckerboardEvent final {
29  public:
30   // clang-format off
31   MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(
32     RendertraceProperty, (
33       Page,
34       PaintedCriticalDisplayPort,
35       PaintedDisplayPort,
36       RequestedDisplayPort,
37       UserVisible
38   ));
39   // clang-format on
40 
41   static const char* sDescriptions[sRendertracePropertyCount];
42   static const char* sColors[sRendertracePropertyCount];
43 
44  public:
45   explicit CheckerboardEvent(bool aRecordTrace);
46 
47   /**
48    * Gets the "severity" of the checkerboard event. This doesn't have units,
49    * it's just useful for comparing two checkerboard events to see which one
50    * is worse, for some implementation-specific definition of "worse".
51    */
52   uint32_t GetSeverity();
53 
54   /**
55    * Gets the number of CSS pixels that were checkerboarded at the peak of the
56    * checkerboard event.
57    */
58   uint32_t GetPeak();
59 
60   /**
61    * Gets the length of the checkerboard event.
62    */
63   TimeDuration GetDuration();
64 
65   /**
66    * Gets the raw log of the checkerboard event. This can be called any time,
67    * although it really only makes sense to pull once the event is done, after
68    * RecordFrameInfo returns true.
69    */
70   std::string GetLog();
71 
72   /**
73    * Returns true iff this event is recording a detailed trace of the event.
74    * This is the argument passed in to the constructor.
75    */
76   bool IsRecordingTrace();
77 
78   /**
79    * Provide a new value for one of the rects that is tracked for
80    * checkerboard events.
81    */
82   void UpdateRendertraceProperty(RendertraceProperty aProperty,
83                                  const CSSRect& aRect,
84                                  const std::string& aExtraInfo = std::string());
85 
86   /**
87    * Provide the number of CSS pixels that are checkerboarded in a composite
88    * at the current time.
89    * @return true if the checkerboard event has completed. The caller should
90    * stop updating this object once this happens.
91    */
92   bool RecordFrameInfo(uint32_t aCssPixelsCheckerboarded);
93 
94  private:
95   /**
96    * Helper method to do stuff when checkeboarding starts.
97    */
98   void StartEvent();
99   /**
100    * Helper method to do stuff when checkerboarding stops.
101    */
102   void StopEvent();
103 
104   /**
105    * Helper method to log a rendertrace property and its value to the
106    * rendertrace info buffer (mRendertraceInfo).
107    */
108   void LogInfo(RendertraceProperty aProperty, const TimeStamp& aTimestamp,
109                const CSSRect& aRect, const std::string& aExtraInfo,
110                const MonitorAutoLock& aProofOfLock);
111 
112   /**
113    * Helper struct that holds a single rendertrace property value.
114    */
115   struct PropertyValue {
116     RendertraceProperty mProperty;
117     TimeStamp mTimeStamp;
118     CSSRect mRect;
119     std::string mExtraInfo;
120 
121     bool operator<(const PropertyValue& aOther) const;
122   };
123 
124   /**
125    * A circular buffer that stores the most recent BUFFER_SIZE values of a
126    * given property.
127    */
128   class PropertyBuffer {
129    public:
130     PropertyBuffer();
131     /**
132      * Add a new value to the buffer, overwriting the oldest one if needed.
133      */
134     void Update(RendertraceProperty aProperty, const CSSRect& aRect,
135                 const std::string& aExtraInfo,
136                 const MonitorAutoLock& aProofOfLock);
137     /**
138      * Dump the recorded values, oldest to newest, to the given vector, and
139      * remove them from this buffer.
140      */
141     void Flush(std::vector<PropertyValue>& aOut,
142                const MonitorAutoLock& aProofOfLock);
143 
144    private:
145     static const uint32_t BUFFER_SIZE = 5;
146 
147     /**
148      * The index of the oldest value in the buffer. This is the next index
149      * that will be written to.
150      */
151     uint32_t mIndex;
152     PropertyValue mValues[BUFFER_SIZE];
153   };
154 
155  private:
156   /**
157    * If true, we should log the various properties during the checkerboard
158    * event. If false, we only need to record things we need for telemetry
159    * measures.
160    */
161   const bool mRecordTrace;
162   /**
163    * A base time so that the other timestamps can be turned into durations.
164    */
165   const TimeStamp mOriginTime;
166   /**
167    * Whether or not a checkerboard event is currently occurring.
168    */
169   bool mCheckerboardingActive;
170 
171   /**
172    * The start time of the checkerboard event.
173    */
174   TimeStamp mStartTime;
175   /**
176    * The end time of the checkerboard event.
177    */
178   TimeStamp mEndTime;
179   /**
180    * The sample time of the last frame recorded.
181    */
182   TimeStamp mLastSampleTime;
183   /**
184    * The number of contiguous frames with checkerboard.
185    */
186   uint32_t mFrameCount;
187   /**
188    * The total number of pixel-milliseconds of checkerboarding visible to
189    * the user during the checkerboarding event.
190    */
191   uint64_t mTotalPixelMs;
192   /**
193    * The largest number of pixels of checkerboarding visible to the user
194    * during any one frame, during this checkerboarding event.
195    */
196   uint32_t mPeakPixels;
197 
198   /**
199    * Monitor that needs to be acquired before touching mBufferedProperties
200    * or mRendertraceInfo.
201    */
202   mutable Monitor mRendertraceLock;
203   /**
204    * A circular buffer to store some properties. This is used before the
205    * checkerboarding actually starts, so that we have some data on what
206    * was happening before the checkerboarding started.
207    */
208   PropertyBuffer mBufferedProperties[sRendertracePropertyCount];
209   /**
210    * The rendertrace info buffer that gives us info on what was happening
211    * during the checkerboard event.
212    */
213   std::ostringstream mRendertraceInfo;
214 };
215 
216 }  // namespace layers
217 }  // namespace mozilla
218 
219 #endif  // mozilla_layers_CheckerboardEvent_h
220