blob: 0eb08e59a9806168d29b6ab17e9fde921f78e950 [file] [log] [blame]
Chia-I Wu5bac7f32017-04-06 12:34:32 -07001/*
2 * Copyright 2016 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#define LOG_TAG "Gralloc2"
18
Jesse Hall5dac7812017-07-06 14:02:29 -070019#include <hidl/ServiceManagement.h>
Chia-I Wud8091b92017-05-16 14:30:34 -070020#include <hwbinder/IPCThreadState.h>
Chia-I Wu5bac7f32017-04-06 12:34:32 -070021#include <ui/Gralloc2.h>
22
23#include <log/log.h>
24#pragma clang diagnostic push
25#pragma clang diagnostic ignored "-Wzero-length-array"
26#include <sync/sync.h>
27#pragma clang diagnostic pop
28
29namespace android {
30
31namespace Gralloc2 {
32
33static constexpr Error kTransactionError = Error::NO_RESOURCES;
34
Jesse Hall5dac7812017-07-06 14:02:29 -070035void Mapper::preload() {
36 android::hardware::preloadPassthroughService<hardware::graphics::mapper::V2_0::IMapper>();
37}
38
Chia-I Wu5bac7f32017-04-06 12:34:32 -070039Mapper::Mapper()
40{
41 mMapper = IMapper::getService();
Chia-I Wucb8405e2017-04-17 15:20:19 -070042 if (mMapper == nullptr || mMapper->isRemote()) {
Chia-I Wu5bac7f32017-04-06 12:34:32 -070043 LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
44 }
45}
46
47Error Mapper::createDescriptor(
48 const IMapper::BufferDescriptorInfo& descriptorInfo,
49 BufferDescriptor* outDescriptor) const
50{
51 Error error;
52 auto ret = mMapper->createDescriptor(descriptorInfo,
53 [&](const auto& tmpError, const auto& tmpDescriptor)
54 {
55 error = tmpError;
56 if (error != Error::NONE) {
57 return;
58 }
59
60 *outDescriptor = tmpDescriptor;
61 });
62
63 return (ret.isOk()) ? error : kTransactionError;
64}
65
66Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
67 buffer_handle_t* outBufferHandle) const
68{
69 Error error;
70 auto ret = mMapper->importBuffer(rawHandle,
71 [&](const auto& tmpError, const auto& tmpBuffer)
72 {
73 error = tmpError;
74 if (error != Error::NONE) {
75 return;
76 }
77
78 *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
79 });
80
81 return (ret.isOk()) ? error : kTransactionError;
82}
83
84void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
85{
86 auto buffer = const_cast<native_handle_t*>(bufferHandle);
87 auto ret = mMapper->freeBuffer(buffer);
88
89 auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
90 ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
91 buffer, error);
92}
93
94Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
95 const IMapper::Rect& accessRegion,
96 int acquireFence, void** outData) const
97{
98 auto buffer = const_cast<native_handle_t*>(bufferHandle);
99
100 // put acquireFence in a hidl_handle
101 hardware::hidl_handle acquireFenceHandle;
102 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
103 if (acquireFence >= 0) {
104 auto h = native_handle_init(acquireFenceStorage, 1, 0);
105 h->data[0] = acquireFence;
106 acquireFenceHandle = h;
107 }
108
109 Error error;
110 auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
111 [&](const auto& tmpError, const auto& tmpData)
112 {
113 error = tmpError;
114 if (error != Error::NONE) {
115 return;
116 }
117
118 *outData = tmpData;
119 });
120
121 // we own acquireFence even on errors
122 if (acquireFence >= 0) {
123 close(acquireFence);
124 }
125
126 return (ret.isOk()) ? error : kTransactionError;
127}
128
129Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
130 const IMapper::Rect& accessRegion,
131 int acquireFence, YCbCrLayout* outLayout) const
132{
133 auto buffer = const_cast<native_handle_t*>(bufferHandle);
134
135 // put acquireFence in a hidl_handle
136 hardware::hidl_handle acquireFenceHandle;
137 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
138 if (acquireFence >= 0) {
139 auto h = native_handle_init(acquireFenceStorage, 1, 0);
140 h->data[0] = acquireFence;
141 acquireFenceHandle = h;
142 }
143
144 Error error;
145 auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
146 acquireFenceHandle,
147 [&](const auto& tmpError, const auto& tmpLayout)
148 {
149 error = tmpError;
150 if (error != Error::NONE) {
151 return;
152 }
153
154 *outLayout = tmpLayout;
155 });
156
157 // we own acquireFence even on errors
158 if (acquireFence >= 0) {
159 close(acquireFence);
160 }
161
162 return (ret.isOk()) ? error : kTransactionError;
163}
164
165int Mapper::unlock(buffer_handle_t bufferHandle) const
166{
167 auto buffer = const_cast<native_handle_t*>(bufferHandle);
168
169 int releaseFence = -1;
170 Error error;
171 auto ret = mMapper->unlock(buffer,
172 [&](const auto& tmpError, const auto& tmpReleaseFence)
173 {
174 error = tmpError;
175 if (error != Error::NONE) {
176 return;
177 }
178
179 auto fenceHandle = tmpReleaseFence.getNativeHandle();
180 if (fenceHandle && fenceHandle->numFds == 1) {
181 int fd = dup(fenceHandle->data[0]);
182 if (fd >= 0) {
183 releaseFence = fd;
184 } else {
185 ALOGD("failed to dup unlock release fence");
186 sync_wait(fenceHandle->data[0], -1);
187 }
188 }
189 });
190
191 if (!ret.isOk()) {
192 error = kTransactionError;
193 }
194
195 if (error != Error::NONE) {
196 ALOGE("unlock(%p) failed with %d", buffer, error);
197 }
198
199 return releaseFence;
200}
201
202Allocator::Allocator(const Mapper& mapper)
203 : mMapper(mapper)
204{
Chia-I Wucb8405e2017-04-17 15:20:19 -0700205 mAllocator = IAllocator::getService();
206 if (mAllocator == nullptr) {
207 LOG_ALWAYS_FATAL("gralloc-alloc is missing");
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700208 }
209}
210
211std::string Allocator::dumpDebugInfo() const
212{
213 std::string debugInfo;
214
215 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
216 debugInfo = tmpDebugInfo.c_str();
217 });
218
219 return debugInfo;
220}
221
222Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
223 uint32_t* outStride, buffer_handle_t* outBufferHandles) const
224{
225 Error error;
226 auto ret = mAllocator->allocate(descriptor, count,
227 [&](const auto& tmpError, const auto& tmpStride,
228 const auto& tmpBuffers) {
229 error = tmpError;
230 if (tmpError != Error::NONE) {
231 return;
232 }
233
234 // import buffers
235 for (uint32_t i = 0; i < count; i++) {
236 error = mMapper.importBuffer(tmpBuffers[i],
237 &outBufferHandles[i]);
238 if (error != Error::NONE) {
239 for (uint32_t j = 0; j < i; j++) {
240 mMapper.freeBuffer(outBufferHandles[j]);
241 outBufferHandles[j] = nullptr;
242 }
243 return;
244 }
245 }
246
247 *outStride = tmpStride;
248 });
249
Chia-I Wud8091b92017-05-16 14:30:34 -0700250 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
251 hardware::IPCThreadState::self()->flushCommands();
252
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700253 return (ret.isOk()) ? error : kTransactionError;
254}
255
256} // namespace Gralloc2
257
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700258} // namespace android