blob: b269be000f9350c9360771ff8ec1ddea618df394
1 | /* |
2 | // Copyright (c) 2016 Amlogic |
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 | |
18 | |
19 | #include <sync/sync.h> |
20 | #include <sw_sync.h> |
21 | |
22 | #include <HwcFenceControl.h> |
23 | #include <unistd.h> |
24 | #include <utils/Log.h> |
25 | #include <HwcTrace.h> |
26 | |
27 | namespace android { |
28 | namespace amlogic { |
29 | |
30 | const sp<HwcFenceControl> HwcFenceControl::NO_FENCE = sp<HwcFenceControl>(new HwcFenceControl); |
31 | |
32 | HwcFenceControl::HwcFenceControl() : |
33 | mFenceFd(-1) { |
34 | } |
35 | |
36 | HwcFenceControl::HwcFenceControl(int32_t fenceFd) : |
37 | mFenceFd(fenceFd) { |
38 | } |
39 | |
40 | HwcFenceControl::~HwcFenceControl() { |
41 | if (mFenceFd != -1) { |
42 | close(mFenceFd); |
43 | } |
44 | } |
45 | |
46 | int32_t HwcFenceControl::createFenceTimeline() { |
47 | int32_t syncTimelineFd; |
48 | |
49 | syncTimelineFd = sw_sync_timeline_create(); |
50 | if (syncTimelineFd < 0) { |
51 | ETRACE("Create sw_sync_timeline failed!"); |
52 | return -1; |
53 | } |
54 | |
55 | return syncTimelineFd; |
56 | } |
57 | |
58 | int32_t HwcFenceControl::createFence(int32_t syncTimelineFd, |
59 | char* str, uint32_t val) { |
60 | |
61 | int32_t fenceFd = sw_sync_fence_create(syncTimelineFd, str, val); |
62 | if (fenceFd < 0) { |
63 | ETRACE("Create fence %d failed, error(%s)", val, strerror(errno)); |
64 | return -1; |
65 | } |
66 | |
67 | return fenceFd; |
68 | } |
69 | |
70 | status_t HwcFenceControl::syncTimelineInc(int32_t syncTimelineFd) { |
71 | status_t err; |
72 | |
73 | err = sw_sync_timeline_inc(syncTimelineFd, 1); |
74 | if (err < 0) { |
75 | ETRACE("can't increment timeline(%d)", syncTimelineFd); |
76 | return -1; |
77 | } |
78 | return err; |
79 | } |
80 | |
81 | status_t HwcFenceControl::traceFenceInfo(int32_t fence) { |
82 | status_t err; |
83 | struct sync_fence_info_data *info; |
84 | |
85 | err = sync_wait(fence, 10000); |
86 | |
87 | if (err < 0) { |
88 | ITRACE("wait %d failed: %s\n", fence, strerror(errno)); |
89 | } else { |
90 | ITRACE("wait %d done\n", fence); |
91 | } |
92 | info = sync_fence_info(fence); |
93 | if (info) { |
94 | struct sync_pt_info *pt_info = NULL; |
95 | ITRACE(" fence %s %d\n", info->name, info->status); |
96 | |
97 | while ((pt_info = sync_pt_info(info, pt_info))) { |
98 | int ts_sec = pt_info->timestamp_ns / 1000000000LL; |
99 | int ts_usec = (pt_info->timestamp_ns % 1000000000LL) / 1000LL; |
100 | ITRACE(" pt %s %s %d %d.%06d", pt_info->obj_name, |
101 | pt_info->driver_name, pt_info->status, |
102 | ts_sec, ts_usec); |
103 | if (!strcmp(pt_info->driver_name, "sw_sync")) |
104 | ITRACE(" val=%d\n", *(uint32_t *)pt_info->driver_data); |
105 | else |
106 | ITRACE("\n"); |
107 | } |
108 | sync_fence_info_free(info); |
109 | } |
110 | |
111 | // closeFd( fence); |
112 | return err; |
113 | } |
114 | |
115 | status_t HwcFenceControl::wait(int32_t fence, int32_t timeout) { |
116 | if (fence == -1) { |
117 | return NO_ERROR; |
118 | } |
119 | int32_t err = sync_wait(fence, timeout); |
120 | return err < 0 ? -errno : status_t(NO_ERROR); |
121 | } |
122 | |
123 | status_t HwcFenceControl::waitForever(const char* logname) { |
124 | if (mFenceFd == -1) { |
125 | return NO_ERROR; |
126 | } |
127 | int32_t warningTimeout = 3000; |
128 | int32_t err = sync_wait(mFenceFd, warningTimeout); |
129 | if (err < 0 && errno == ETIME) { |
130 | ETRACE("%s: fence %d didn't signal in %u ms", logname, mFenceFd, |
131 | warningTimeout); |
132 | err = sync_wait(mFenceFd, TIMEOUT_NEVER); |
133 | } |
134 | return err < 0 ? -errno : status_t(NO_ERROR); |
135 | } |
136 | |
137 | int32_t HwcFenceControl::merge(const String8& name, const int32_t& f1, |
138 | const int32_t& f2) { |
139 | int32_t result; |
140 | // Merge the two fences. In the case where one of the fences is not a |
141 | // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so |
142 | // that a new fence with the given name is created. |
143 | if (f1 != -1 && f2 != -1) { |
144 | result = sync_merge(name.string(), f1, f2); |
145 | } else if (f1 != -1) { |
146 | result = sync_merge(name.string(), f1, f1); |
147 | } else if (f2 != -1) { |
148 | result = sync_merge(name.string(), f2, f2); |
149 | } else { |
150 | return -1; |
151 | } |
152 | if (result == -1) { |
153 | status_t err = -errno; |
154 | ETRACE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)", |
155 | name.string(), f1, f2, |
156 | strerror(-err), err); |
157 | return -1; |
158 | } |
159 | return result; |
160 | } |
161 | |
162 | int32_t HwcFenceControl::dupFence(int32_t fence) { |
163 | if (-1 == fence) { |
164 | DTRACE("acquire fence already been signaled."); |
165 | return -1; |
166 | } |
167 | |
168 | int32_t dupFence = ::dup(fence); |
169 | if (dupFence < 0) { |
170 | ETRACE("acquire fence dup failed! please check it immeditely!"); |
171 | } |
172 | |
173 | return dupFence; |
174 | } |
175 | |
176 | } // namespace amlogic |
177 | } // namespace android |
178 |