1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "FrameUniformityData.h"
7
8 #include <map>
9
10 #include "Units.h"
11 #include "gfxPoint.h"
12 #include "mozilla/TimeStamp.h"
13 #include "mozilla/dom/APZTestDataBinding.h"
14 #include "mozilla/dom/ToJSValue.h"
15 #include "nsTArray.h"
16
17 namespace mozilla {
18 namespace layers {
19
20 using namespace gfx;
21
22 Point
GetAverage()23 LayerTransforms::GetAverage()
24 {
25 MOZ_ASSERT(!mTransforms.IsEmpty());
26
27 Point current = mTransforms[0];
28 Point average;
29 size_t length = mTransforms.Length();
30
31 for (size_t i = 1; i < length; i++) {
32 Point nextTransform = mTransforms[i];
33 Point movement = nextTransform - current;
34 average += Point(std::fabs(movement.x), std::fabs(movement.y));
35 current = nextTransform;
36 }
37
38 average = average / (float) length;
39 return average;
40 }
41
42 Point
GetStdDev()43 LayerTransforms::GetStdDev()
44 {
45 Point average = GetAverage();
46 Point stdDev;
47 Point current = mTransforms[0];
48
49 for (size_t i = 1; i < mTransforms.Length(); i++) {
50 Point next = mTransforms[i];
51 Point move = next - current;
52 move.x = fabs(move.x);
53 move.y = fabs(move.y);
54
55 Point diff = move - average;
56 diff.x = diff.x * diff.x;
57 diff.y = diff.y * diff.y;
58 stdDev += diff;
59
60 current = next;
61 }
62
63 stdDev = stdDev / mTransforms.Length();
64 stdDev.x = sqrt(stdDev.x);
65 stdDev.y = sqrt(stdDev.y);
66 return stdDev;
67 }
68
~LayerTransformRecorder()69 LayerTransformRecorder::~LayerTransformRecorder()
70 {
71 Reset();
72 }
73
74 void
RecordTransform(Layer * aLayer,const Point & aTransform)75 LayerTransformRecorder::RecordTransform(Layer* aLayer, const Point& aTransform)
76 {
77 LayerTransforms* layerTransforms = GetLayerTransforms((uintptr_t) aLayer);
78 layerTransforms->mTransforms.AppendElement(aTransform);
79 }
80
81 void
EndTest(FrameUniformityData * aOutData)82 LayerTransformRecorder::EndTest(FrameUniformityData* aOutData)
83 {
84 for (auto iter = mFrameTransforms.begin(); iter != mFrameTransforms.end(); ++iter) {
85 uintptr_t layer = iter->first;
86 float uniformity = CalculateFrameUniformity(layer);
87
88 std::pair<uintptr_t,float> result(layer, uniformity);
89 aOutData->mUniformities.insert(result);
90 }
91
92 Reset();
93 }
94
95 LayerTransforms*
GetLayerTransforms(uintptr_t aLayer)96 LayerTransformRecorder::GetLayerTransforms(uintptr_t aLayer)
97 {
98 if (!mFrameTransforms.count(aLayer)) {
99 LayerTransforms* newTransform = new LayerTransforms();
100 std::pair<uintptr_t, LayerTransforms*> newLayer(aLayer, newTransform);
101 mFrameTransforms.insert(newLayer);
102 }
103
104 return mFrameTransforms.find(aLayer)->second;
105 }
106
107 void
Reset()108 LayerTransformRecorder::Reset()
109 {
110 for (auto iter = mFrameTransforms.begin(); iter != mFrameTransforms.end(); ++iter) {
111 LayerTransforms* layerTransforms = iter->second;
112 delete layerTransforms;
113 }
114
115 mFrameTransforms.clear();
116 }
117
118 float
CalculateFrameUniformity(uintptr_t aLayer)119 LayerTransformRecorder::CalculateFrameUniformity(uintptr_t aLayer)
120 {
121 LayerTransforms* layerTransform = GetLayerTransforms(aLayer);
122 float yUniformity = -1;
123 if (!layerTransform->mTransforms.IsEmpty()) {
124 Point stdDev = layerTransform->GetStdDev();
125 yUniformity = stdDev.y;
126 }
127 return yUniformity;
128 }
129
130 bool
ToJS(JS::MutableHandleValue aOutValue,JSContext * aContext)131 FrameUniformityData::ToJS(JS::MutableHandleValue aOutValue, JSContext* aContext)
132 {
133 dom::FrameUniformityResults results;
134 dom::Sequence<dom::FrameUniformity>& layers = results.mLayerUniformities.Construct();
135
136 for (auto iter = mUniformities.begin(); iter != mUniformities.end(); ++iter) {
137 uintptr_t layerAddr = iter->first;
138 float uniformity = iter->second;
139
140 // FIXME: Make this infallible after bug 968520 is done.
141 MOZ_ALWAYS_TRUE(layers.AppendElement(fallible));
142 dom::FrameUniformity& entry = layers.LastElement();
143
144 entry.mLayerAddress.Construct() = layerAddr;
145 entry.mFrameUniformity.Construct() = uniformity;
146 }
147
148 return dom::ToJSValue(aContext, results, aOutValue);
149 }
150
151 } // namespace layers
152 } // namespace mozilla
153