blob: e1498030043eb9d9b0ce74939d4cd6c2e8c4f1d9 [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 Hall75ca86f2017-06-07 14:44:46 -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
35Mapper::Mapper()
36{
37 mMapper = IMapper::getService();
Chia-I Wucb8405e2017-04-17 15:20:19 -070038 if (mMapper == nullptr || mMapper->isRemote()) {
Chia-I Wu5bac7f32017-04-06 12:34:32 -070039 LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
40 }
41}
42
43Error Mapper::createDescriptor(
44 const IMapper::BufferDescriptorInfo& descriptorInfo,
45 BufferDescriptor* outDescriptor) const
46{
47 Error error;
48 auto ret = mMapper->createDescriptor(descriptorInfo,
49 [&](const auto& tmpError, const auto& tmpDescriptor)
50 {
51 error = tmpError;
52 if (error != Error::NONE) {
53 return;
54 }
55
56 *outDescriptor = tmpDescriptor;
57 });
58
59 return (ret.isOk()) ? error : kTransactionError;
60}
61
62Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
63 buffer_handle_t* outBufferHandle) const
64{
65 Error error;
66 auto ret = mMapper->importBuffer(rawHandle,
67 [&](const auto& tmpError, const auto& tmpBuffer)
68 {
69 error = tmpError;
70 if (error != Error::NONE) {
71 return;
72 }
73
74 *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
75 });
76
77 return (ret.isOk()) ? error : kTransactionError;
78}
79
80void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
81{
82 auto buffer = const_cast<native_handle_t*>(bufferHandle);
83 auto ret = mMapper->freeBuffer(buffer);
84
85 auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
86 ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
87 buffer, error);
88}
89
90Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
91 const IMapper::Rect& accessRegion,
92 int acquireFence, void** outData) const
93{
94 auto buffer = const_cast<native_handle_t*>(bufferHandle);
95
96 // put acquireFence in a hidl_handle
97 hardware::hidl_handle acquireFenceHandle;
98 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
99 if (acquireFence >= 0) {
100 auto h = native_handle_init(acquireFenceStorage, 1, 0);
101 h->data[0] = acquireFence;
102 acquireFenceHandle = h;
103 }
104
105 Error error;
106 auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
107 [&](const auto& tmpError, const auto& tmpData)
108 {
109 error = tmpError;
110 if (error != Error::NONE) {
111 return;
112 }
113
114 *outData = tmpData;
115 });
116
117 // we own acquireFence even on errors
118 if (acquireFence >= 0) {
119 close(acquireFence);
120 }
121
122 return (ret.isOk()) ? error : kTransactionError;
123}
124
125Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
126 const IMapper::Rect& accessRegion,
127 int acquireFence, YCbCrLayout* outLayout) const
128{
129 auto buffer = const_cast<native_handle_t*>(bufferHandle);
130
131 // put acquireFence in a hidl_handle
132 hardware::hidl_handle acquireFenceHandle;
133 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
134 if (acquireFence >= 0) {
135 auto h = native_handle_init(acquireFenceStorage, 1, 0);
136 h->data[0] = acquireFence;
137 acquireFenceHandle = h;
138 }
139
140 Error error;
141 auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
142 acquireFenceHandle,
143 [&](const auto& tmpError, const auto& tmpLayout)
144 {
145 error = tmpError;
146 if (error != Error::NONE) {
147 return;
148 }
149
150 *outLayout = tmpLayout;
151 });
152
153 // we own acquireFence even on errors
154 if (acquireFence >= 0) {
155 close(acquireFence);
156 }
157
158 return (ret.isOk()) ? error : kTransactionError;
159}
160
161int Mapper::unlock(buffer_handle_t bufferHandle) const
162{
163 auto buffer = const_cast<native_handle_t*>(bufferHandle);
164
165 int releaseFence = -1;
166 Error error;
167 auto ret = mMapper->unlock(buffer,
168 [&](const auto& tmpError, const auto& tmpReleaseFence)
169 {
170 error = tmpError;
171 if (error != Error::NONE) {
172 return;
173 }
174
175 auto fenceHandle = tmpReleaseFence.getNativeHandle();
176 if (fenceHandle && fenceHandle->numFds == 1) {
177 int fd = dup(fenceHandle->data[0]);
178 if (fd >= 0) {
179 releaseFence = fd;
180 } else {
181 ALOGD("failed to dup unlock release fence");
182 sync_wait(fenceHandle->data[0], -1);
183 }
184 }
185 });
186
187 if (!ret.isOk()) {
188 error = kTransactionError;
189 }
190
191 if (error != Error::NONE) {
192 ALOGE("unlock(%p) failed with %d", buffer, error);
193 }
194
195 return releaseFence;
196}
197
198Allocator::Allocator(const Mapper& mapper)
199 : mMapper(mapper)
200{
Chia-I Wucb8405e2017-04-17 15:20:19 -0700201 mAllocator = IAllocator::getService();
202 if (mAllocator == nullptr) {
203 LOG_ALWAYS_FATAL("gralloc-alloc is missing");
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700204 }
205}
206
207std::string Allocator::dumpDebugInfo() const
208{
209 std::string debugInfo;
210
211 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
212 debugInfo = tmpDebugInfo.c_str();
213 });
214
215 return debugInfo;
216}
217
218Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
219 uint32_t* outStride, buffer_handle_t* outBufferHandles) const
220{
221 Error error;
222 auto ret = mAllocator->allocate(descriptor, count,
223 [&](const auto& tmpError, const auto& tmpStride,
224 const auto& tmpBuffers) {
225 error = tmpError;
226 if (tmpError != Error::NONE) {
227 return;
228 }
229
230 // import buffers
231 for (uint32_t i = 0; i < count; i++) {
232 error = mMapper.importBuffer(tmpBuffers[i],
233 &outBufferHandles[i]);
234 if (error != Error::NONE) {
235 for (uint32_t j = 0; j < i; j++) {
236 mMapper.freeBuffer(outBufferHandles[j]);
237 outBufferHandles[j] = nullptr;
238 }
239 return;
240 }
241 }
242
243 *outStride = tmpStride;
244 });
245
Chia-I Wud8091b92017-05-16 14:30:34 -0700246 // make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
247 hardware::IPCThreadState::self()->flushCommands();
248
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700249 return (ret.isOk()) ? error : kTransactionError;
250}
251
252} // namespace Gralloc2
253
Jesse Hall75ca86f2017-06-07 14:44:46 -0700254namespace {
255// Load the IMapper implementation library when this shared library is loaded, rather than when
256// we (lazily) create the Gralloc2::Mapper instance. Since these libraries will all be needed by
257// nearly all apps, this allows us to load them in Zygote rather than on each app launch.
258class PreloadMapperImpl {
259public:
260 PreloadMapperImpl() {
261 android::hardware::preloadPassthroughService<hardware::graphics::mapper::V2_0::IMapper>();
262 }
263};
264static PreloadMapperImpl preloadMapperImpl;
265} // namespace
266
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700267} // namespace android