1 /**
2 * Copyright (C) 2024 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 #pragma once
18
19 #include <ui/Fence.h>
20
21 namespace android {
22
23 // TODO: measure if Fence::merge is cheaper
mergeFence(const char * debugName,sp<Fence> && incomingFence,sp<Fence> & prevFence)24 inline void mergeFence(const char* debugName, sp<Fence>&& incomingFence, sp<Fence>& prevFence) {
25 if (prevFence == nullptr && incomingFence->getStatus() != Fence::Status::Invalid) {
26 prevFence = std::move(incomingFence);
27 } else if (prevFence != nullptr) {
28 // If both fences are signaled or both are unsignaled, we need to merge
29 // them to get an accurate timestamp.
30 if (prevFence->getStatus() != Fence::Status::Invalid &&
31 prevFence->getStatus() == incomingFence->getStatus()) {
32 char fenceName[32] = {};
33 snprintf(fenceName, 32, "%.28s", debugName);
34 sp<Fence> mergedFence = Fence::merge(fenceName, prevFence, incomingFence);
35 if (mergedFence->isValid()) {
36 prevFence = std::move(mergedFence);
37 }
38 } else if (incomingFence->getStatus() == Fence::Status::Unsignaled) {
39 // If one fence has signaled and the other hasn't, the unsignaled
40 // fence will approximately correspond with the correct timestamp.
41 // There's a small race if both fences signal at about the same time
42 // and their statuses are retrieved with unfortunate timing. However,
43 // by this point, they will have both signaled and only the timestamp
44 // will be slightly off; any dependencies after this point will
45 // already have been met.
46 prevFence = std::move(incomingFence);
47 }
48 }
49 }
50
51 } // namespace android
52