blob: 7cbb8d8b7c0050a0a38f8997e5d2d0a22b1c70ab [file] [log] [blame]
Mikael Pessa90092f42019-08-26 17:22:04 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#undef LOG_TAG
18#define LOG_TAG "FrameTracer"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include "FrameTracer.h"
22
23#include <android-base/stringprintf.h>
24
25#include <algorithm>
26
27PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
28
29namespace android {
30
31void FrameTracer::initialize() {
32 perfetto::TracingInitArgs args;
33 args.backends = perfetto::kSystemBackend;
34 perfetto::Tracing::Initialize(args);
35 registerDataSource();
36}
37
38void FrameTracer::registerDataSource() {
39 perfetto::DataSourceDescriptor dsd;
40 dsd.set_name(kFrameTracerDataSource);
41 FrameTracerDataSource::Register(dsd);
42}
43
44void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) {
45 FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) {
46 if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
47 std::lock_guard<std::mutex> lock(mTraceMutex);
48 mTraceTracker[layerID].layerName = layerName;
49 }
50 });
51}
52
53void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
54 nsecs_t timestamp, FrameEvent::BufferEventType type,
55 nsecs_t duration) {
56 FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
57 duration](FrameTracerDataSource::TraceContext ctx) {
58 std::lock_guard<std::mutex> lock(mTraceMutex);
59 if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
60 return;
61 }
62
63 // Handle any pending fences for this buffer.
64 tracePendingFencesLocked(ctx, layerID, bufferID);
65
66 // Complete current trace.
67 traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
68 });
69}
70
71void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
72 const std::shared_ptr<FenceTime>& fence,
73 FrameEvent::BufferEventType type, nsecs_t startTime) {
74 FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
75 startTime](FrameTracerDataSource::TraceContext ctx) {
76 const nsecs_t signalTime = fence->getSignalTime();
77 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
78 std::lock_guard<std::mutex> lock(mTraceMutex);
79 if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
80 return;
81 }
82
83 // Handle any pending fences for this buffer.
84 tracePendingFencesLocked(ctx, layerID, bufferID);
85
86 if (signalTime != Fence::SIGNAL_TIME_PENDING) {
87 traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
88 } else {
89 mTraceTracker[layerID].pendingFences[bufferID].push_back(
90 {.frameNumber = frameNumber,
91 .type = type,
92 .fence = fence,
93 .startTime = startTime});
94 }
95 }
96 });
97}
98
99void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
100 int32_t layerID, uint64_t bufferID) {
101 if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
102 auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
103 for (size_t i = 0; i < pendingFences.size(); ++i) {
104 auto& pendingFence = pendingFences[i];
105
106 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
107 if (pendingFence.fence && pendingFence.fence->isValid()) {
108 signalTime = pendingFence.fence->getSignalTime();
109 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
110 continue;
111 }
112 }
113
114 if (signalTime != Fence::SIGNAL_TIME_INVALID &&
115 systemTime() - signalTime < kFenceSignallingDeadline) {
116 traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
117 pendingFence.startTime, signalTime);
118 }
119
120 pendingFences.erase(pendingFences.begin() + i);
121 --i;
122 }
123 }
124}
125
126void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
127 uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
128 FrameEvent::BufferEventType type, nsecs_t duration) {
129 auto packet = ctx.NewTracePacket();
130 packet->set_timestamp(timestamp);
131 auto* event = packet->set_graphics_frame_event()->set_buffer_event();
132 event->set_buffer_id(static_cast<uint32_t>(bufferID));
133 event->set_frame_number(frameNumber);
134 event->set_type(type);
135
136 if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
137 !mTraceTracker[layerID].layerName.empty()) {
138 const std::string& layerName = mTraceTracker[layerID].layerName;
139 event->set_layer_name(layerName.c_str(), layerName.size());
140 }
141
142 if (duration > 0) {
143 event->set_duration_ns(duration);
144 }
145}
146
147void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
148 uint64_t bufferID, uint64_t frameNumber,
149 FrameEvent::BufferEventType type, nsecs_t startTime,
150 nsecs_t endTime) {
151 nsecs_t timestamp = endTime;
152 nsecs_t duration = 0;
153 if (startTime > 0 && startTime < endTime) {
154 timestamp = startTime;
155 duration = endTime - startTime;
156 }
157 traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
158}
159
160void FrameTracer::onDestroy(int32_t layerID) {
161 std::lock_guard<std::mutex> traceLock(mTraceMutex);
162 mTraceTracker.erase(layerID);
163}
164
165std::string FrameTracer::miniDump() {
166 std::string result = "FrameTracer miniDump:\n";
167 std::lock_guard<std::mutex> lock(mTraceMutex);
168 android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
169 mTraceTracker.size());
170 return result;
171}
172
173} // namespace android