blob: e3d2703bccdafa42774260c3f4467ced7aff0738 [file] [log] [blame]
Chia-I Wu109571a2016-09-05 11:46:36 +08001/*
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 "GrallocPassthrough"
18
Chia-I Wua7f234c2016-11-22 11:37:04 +080019#include <mutex>
Chia-I Wu109571a2016-09-05 11:46:36 +080020#include <type_traits>
21#include <unordered_set>
22#include <vector>
23
24#include <string.h>
25
26#include <hardware/gralloc1.h>
27#include <log/log.h>
28
29#include "Gralloc.h"
30
31namespace android {
32namespace hardware {
33namespace graphics {
34namespace allocator {
35namespace V2_0 {
36namespace implementation {
37
38class GrallocHal : public IAllocator {
39public:
40 GrallocHal(const hw_module_t* module);
41 virtual ~GrallocHal();
42
43 // IAllocator interface
44 Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
45 Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
Chia-I Wua7f234c2016-11-22 11:37:04 +080046 Return<void> createClient(createClient_cb hidl_cb) override;
Chia-I Wu109571a2016-09-05 11:46:36 +080047
Chia-I Wua7f234c2016-11-22 11:37:04 +080048 Error createDescriptor(
49 const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
50 BufferDescriptor& outDescriptor);
51 Error destroyDescriptor(BufferDescriptor descriptor);
Chia-I Wu109571a2016-09-05 11:46:36 +080052
Chia-I Wua7f234c2016-11-22 11:37:04 +080053 Error testAllocate(const hidl_vec<BufferDescriptor>& descriptors);
54 Error allocate(const hidl_vec<BufferDescriptor>& descriptors,
55 hidl_vec<Buffer>& outBuffers);
56 Error free(Buffer buffer);
57
58 Error exportHandle(Buffer buffer, const native_handle_t*& outHandle);
Chia-I Wu109571a2016-09-05 11:46:36 +080059
60private:
61 void initCapabilities();
62
63 template<typename T>
64 void initDispatch(T& func, gralloc1_function_descriptor_t desc);
65 void initDispatch();
66
67 bool hasCapability(Capability capability) const;
68
69 gralloc1_device_t* mDevice;
70
71 std::unordered_set<Capability> mCapabilities;
72
73 struct {
74 GRALLOC1_PFN_DUMP dump;
75 GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
76 GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
77 GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
78 GRALLOC1_PFN_SET_FORMAT setFormat;
Craig Donner0b00adf2016-10-20 17:12:58 -070079 GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
Chia-I Wu109571a2016-09-05 11:46:36 +080080 GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
81 GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
82 GRALLOC1_PFN_ALLOCATE allocate;
83 GRALLOC1_PFN_RELEASE release;
Chia-I Wu109571a2016-09-05 11:46:36 +080084 } mDispatch;
85};
86
Chia-I Wua7f234c2016-11-22 11:37:04 +080087class GrallocClient : public IAllocatorClient {
88public:
89 GrallocClient(GrallocHal& hal);
90 virtual ~GrallocClient();
91
92 // IAllocatorClient interface
93 Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
94 createDescriptor_cb hidl_cb) override;
95 Return<Error> destroyDescriptor(BufferDescriptor descriptor) override;
96
97 Return<Error> testAllocate(
98 const hidl_vec<BufferDescriptor>& descriptors) override;
99 Return<void> allocate(const hidl_vec<BufferDescriptor>& descriptors,
100 allocate_cb hidl_cb) override;
101 Return<Error> free(Buffer buffer) override;
102
103 Return<void> exportHandle(BufferDescriptor descriptor,
104 Buffer buffer, exportHandle_cb hidl_cb) override;
105
106private:
107 GrallocHal& mHal;
108
109 std::mutex mMutex;
110 std::unordered_set<BufferDescriptor> mDescriptors;
111 std::unordered_set<Buffer> mBuffers;
112};
113
Chia-I Wu109571a2016-09-05 11:46:36 +0800114GrallocHal::GrallocHal(const hw_module_t* module)
115 : mDevice(nullptr), mDispatch()
116{
117 int status = gralloc1_open(module, &mDevice);
118 if (status) {
119 LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
120 strerror(-status));
121 }
122
123 initCapabilities();
124 initDispatch();
125}
126
127GrallocHal::~GrallocHal()
128{
129 gralloc1_close(mDevice);
130}
131
132void GrallocHal::initCapabilities()
133{
134 uint32_t count;
135 mDevice->getCapabilities(mDevice, &count, nullptr);
136
137 std::vector<Capability> caps(count);
138 mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
139 std::underlying_type<Capability>::type*>(caps.data()));
140 caps.resize(count);
141
142 mCapabilities.insert(caps.cbegin(), caps.cend());
143}
144
145template<typename T>
146void GrallocHal::initDispatch(T& func, gralloc1_function_descriptor_t desc)
147{
148 auto pfn = mDevice->getFunction(mDevice, desc);
149 if (!pfn) {
150 LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
151 }
152
153 func = reinterpret_cast<T>(pfn);
154}
155
156void GrallocHal::initDispatch()
157{
158 initDispatch(mDispatch.dump, GRALLOC1_FUNCTION_DUMP);
159 initDispatch(mDispatch.createDescriptor,
160 GRALLOC1_FUNCTION_CREATE_DESCRIPTOR);
161 initDispatch(mDispatch.destroyDescriptor,
162 GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR);
163 initDispatch(mDispatch.setDimensions, GRALLOC1_FUNCTION_SET_DIMENSIONS);
164 initDispatch(mDispatch.setFormat, GRALLOC1_FUNCTION_SET_FORMAT);
Craig Donner0b00adf2016-10-20 17:12:58 -0700165 if (hasCapability(Capability::LAYERED_BUFFERS)) {
166 initDispatch(
167 mDispatch.setLayerCount, GRALLOC1_FUNCTION_SET_LAYER_COUNT);
168 }
Chia-I Wu109571a2016-09-05 11:46:36 +0800169 initDispatch(mDispatch.setConsumerUsage,
170 GRALLOC1_FUNCTION_SET_CONSUMER_USAGE);
171 initDispatch(mDispatch.setProducerUsage,
172 GRALLOC1_FUNCTION_SET_PRODUCER_USAGE);
173 initDispatch(mDispatch.allocate, GRALLOC1_FUNCTION_ALLOCATE);
174 initDispatch(mDispatch.release, GRALLOC1_FUNCTION_RELEASE);
175}
176
177bool GrallocHal::hasCapability(Capability capability) const
178{
179 return (mCapabilities.count(capability) > 0);
180}
181
182Return<void> GrallocHal::getCapabilities(getCapabilities_cb hidl_cb)
183{
184 std::vector<Capability> caps(
185 mCapabilities.cbegin(), mCapabilities.cend());
186
187 hidl_vec<Capability> reply;
188 reply.setToExternal(caps.data(), caps.size());
189 hidl_cb(reply);
190
191 return Void();
192}
193
194Return<void> GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
195{
196 uint32_t len = 0;
197 mDispatch.dump(mDevice, &len, nullptr);
198
199 std::vector<char> buf(len + 1);
200 mDispatch.dump(mDevice, &len, buf.data());
201 buf.resize(len + 1);
202 buf[len] = '\0';
203
204 hidl_string reply;
205 reply.setToExternal(buf.data(), len);
206 hidl_cb(reply);
207
208 return Void();
209}
210
Chia-I Wua7f234c2016-11-22 11:37:04 +0800211Return<void> GrallocHal::createClient(createClient_cb hidl_cb)
Chia-I Wu109571a2016-09-05 11:46:36 +0800212{
Chia-I Wua7f234c2016-11-22 11:37:04 +0800213 sp<IAllocatorClient> client = new GrallocClient(*this);
214 hidl_cb(Error::NONE, client);
215
216 return Void();
217}
218
219Error GrallocHal::createDescriptor(
220 const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
221 BufferDescriptor& outDescriptor)
222{
223 gralloc1_buffer_descriptor_t descriptor;
Chia-I Wu109571a2016-09-05 11:46:36 +0800224 int32_t err = mDispatch.createDescriptor(mDevice, &descriptor);
Chia-I Wua7f234c2016-11-22 11:37:04 +0800225 if (err != GRALLOC1_ERROR_NONE) {
226 return static_cast<Error>(err);
Chia-I Wu109571a2016-09-05 11:46:36 +0800227 }
Chia-I Wua7f234c2016-11-22 11:37:04 +0800228
229 err = mDispatch.setDimensions(mDevice, descriptor,
230 descriptorInfo.width, descriptorInfo.height);
Chia-I Wu109571a2016-09-05 11:46:36 +0800231 if (err == GRALLOC1_ERROR_NONE) {
232 err = mDispatch.setFormat(mDevice, descriptor,
233 static_cast<int32_t>(descriptorInfo.format));
234 }
Chia-I Wua7f234c2016-11-22 11:37:04 +0800235 if (err == GRALLOC1_ERROR_NONE) {
236 if (hasCapability(Capability::LAYERED_BUFFERS)) {
237 err = mDispatch.setLayerCount(mDevice, descriptor,
238 descriptorInfo.layerCount);
239 } else if (descriptorInfo.layerCount != 1) {
240 err = GRALLOC1_ERROR_BAD_VALUE;
241 }
Craig Donner0b00adf2016-10-20 17:12:58 -0700242 }
Chia-I Wu109571a2016-09-05 11:46:36 +0800243 if (err == GRALLOC1_ERROR_NONE) {
244 uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
245 if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
246 producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
247 }
248 if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
249 producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
250 }
251 err = mDispatch.setProducerUsage(mDevice, descriptor,
252 descriptorInfo.producerUsageMask);
253 }
254 if (err == GRALLOC1_ERROR_NONE) {
255 uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask;
256 if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
257 consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
258 }
259 err = mDispatch.setConsumerUsage(mDevice, descriptor,
260 consumerUsageMask);
261 }
262
Chia-I Wua7f234c2016-11-22 11:37:04 +0800263 if (err == GRALLOC1_ERROR_NONE) {
264 outDescriptor = descriptor;
265 } else {
266 mDispatch.destroyDescriptor(mDevice, descriptor);
267 }
Chia-I Wu109571a2016-09-05 11:46:36 +0800268
Chia-I Wua7f234c2016-11-22 11:37:04 +0800269 return static_cast<Error>(err);
Chia-I Wu109571a2016-09-05 11:46:36 +0800270}
271
Chia-I Wua7f234c2016-11-22 11:37:04 +0800272Error GrallocHal::destroyDescriptor(BufferDescriptor descriptor)
Chia-I Wu109571a2016-09-05 11:46:36 +0800273{
274 int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor);
275 return static_cast<Error>(err);
276}
277
Chia-I Wua7f234c2016-11-22 11:37:04 +0800278Error GrallocHal::testAllocate(const hidl_vec<BufferDescriptor>& descriptors)
Chia-I Wu109571a2016-09-05 11:46:36 +0800279{
280 if (!hasCapability(Capability::TEST_ALLOCATE)) {
281 return Error::UNDEFINED;
282 }
283
284 int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
Chia-I Wua7f234c2016-11-22 11:37:04 +0800285 descriptors.data(), nullptr);
Chia-I Wu109571a2016-09-05 11:46:36 +0800286 return static_cast<Error>(err);
287}
288
Chia-I Wua7f234c2016-11-22 11:37:04 +0800289Error GrallocHal::allocate(const hidl_vec<BufferDescriptor>& descriptors,
290 hidl_vec<Buffer>& outBuffers)
291{
Chia-I Wu109571a2016-09-05 11:46:36 +0800292 std::vector<buffer_handle_t> buffers(descriptors.size());
293 int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
Chia-I Wua7f234c2016-11-22 11:37:04 +0800294 descriptors.data(), buffers.data());
295 if (err == GRALLOC1_ERROR_NONE || err == GRALLOC1_ERROR_NOT_SHARED) {
296 outBuffers.resize(buffers.size());
297 for (size_t i = 0; i < outBuffers.size(); i++) {
298 outBuffers[i] = static_cast<Buffer>(
299 reinterpret_cast<uintptr_t>(buffers[i]));
300 }
Chia-I Wu109571a2016-09-05 11:46:36 +0800301 }
302
Chia-I Wua7f234c2016-11-22 11:37:04 +0800303 return static_cast<Error>(err);
Chia-I Wu109571a2016-09-05 11:46:36 +0800304}
305
Chia-I Wua7f234c2016-11-22 11:37:04 +0800306Error GrallocHal::free(Buffer buffer)
Chia-I Wu109571a2016-09-05 11:46:36 +0800307{
Chia-I Wua7f234c2016-11-22 11:37:04 +0800308 buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(
309 static_cast<uintptr_t>(buffer));
310
Chia-I Wu109571a2016-09-05 11:46:36 +0800311 int32_t err = mDispatch.release(mDevice, handle);
312 return static_cast<Error>(err);
313}
314
Chia-I Wua7f234c2016-11-22 11:37:04 +0800315Error GrallocHal::exportHandle(Buffer buffer,
316 const native_handle_t*& outHandle)
317{
318 // we rely on the caller to validate buffer here
319 outHandle = reinterpret_cast<buffer_handle_t>(
320 static_cast<uintptr_t>(buffer));
321 return Error::NONE;
322}
323
324GrallocClient::GrallocClient(GrallocHal& hal)
325 : mHal(hal)
326{
327}
328
329GrallocClient::~GrallocClient()
330{
331 if (!mBuffers.empty()) {
332 ALOGW("client destroyed with valid buffers");
333 for (auto buf : mBuffers) {
334 mHal.free(buf);
335 }
336 }
337
338 if (!mDescriptors.empty()) {
339 ALOGW("client destroyed with valid buffer descriptors");
340 for (auto desc : mDescriptors) {
341 mHal.destroyDescriptor(desc);
342 }
343 }
344}
345
346Return<void> GrallocClient::createDescriptor(
347 const BufferDescriptorInfo& descriptorInfo,
348 createDescriptor_cb hidl_cb)
349{
350 BufferDescriptor descriptor;
351 Error err = mHal.createDescriptor(descriptorInfo, descriptor);
352
353 if (err == Error::NONE) {
354 std::lock_guard<std::mutex> lock(mMutex);
355
356 auto result = mDescriptors.insert(descriptor);
357 if (!result.second) {
358 ALOGW("duplicated buffer descriptor id returned");
359 mHal.destroyDescriptor(descriptor);
360 err = Error::NO_RESOURCES;
361 }
362 }
363
364 hidl_cb(err, descriptor);
365 return Void();
366}
367
368Return<Error> GrallocClient::destroyDescriptor(BufferDescriptor descriptor)
369{
370 {
371 std::lock_guard<std::mutex> lock(mMutex);
372 if (!mDescriptors.erase(descriptor)) {
373 return Error::BAD_DESCRIPTOR;
374 }
375 }
376
377 return mHal.destroyDescriptor(descriptor);
378}
379
380Return<Error> GrallocClient::testAllocate(
381 const hidl_vec<BufferDescriptor>& descriptors)
382{
383 return mHal.testAllocate(descriptors);
384}
385
386Return<void> GrallocClient::allocate(
387 const hidl_vec<BufferDescriptor>& descriptors,
388 allocate_cb hidl_cb) {
389 hidl_vec<Buffer> buffers;
390 Error err = mHal.allocate(descriptors, buffers);
391
392 if (err == Error::NONE || err == Error::NOT_SHARED) {
393 std::lock_guard<std::mutex> lock(mMutex);
394
395 for (size_t i = 0; i < buffers.size(); i++) {
396 auto result = mBuffers.insert(buffers[i]);
397 if (!result.second) {
398 ALOGW("duplicated buffer id returned");
399
400 for (size_t j = 0; j < buffers.size(); j++) {
401 if (j < i) {
402 mBuffers.erase(buffers[i]);
403 }
404 mHal.free(buffers[i]);
405 }
406
407 buffers = hidl_vec<Buffer>();
408 err = Error::NO_RESOURCES;
409 break;
410 }
411 }
412 }
413
414 hidl_cb(err, buffers);
415 return Void();
416}
417
418Return<Error> GrallocClient::free(Buffer buffer)
419{
420 {
421 std::lock_guard<std::mutex> lock(mMutex);
422 if (!mBuffers.erase(buffer)) {
423 return Error::BAD_BUFFER;
424 }
425 }
426
427 return mHal.free(buffer);
428}
429
430Return<void> GrallocClient::exportHandle(BufferDescriptor /*descriptor*/,
Chia-I Wu109571a2016-09-05 11:46:36 +0800431 Buffer buffer, exportHandle_cb hidl_cb)
432{
Chia-I Wua7f234c2016-11-22 11:37:04 +0800433 const native_handle_t* handle = nullptr;
Chia-I Wu109571a2016-09-05 11:46:36 +0800434
Chia-I Wua7f234c2016-11-22 11:37:04 +0800435 {
436 std::lock_guard<std::mutex> lock(mMutex);
437 if (mBuffers.count(buffer) == 0) {
438 hidl_cb(Error::BAD_BUFFER, handle);
439 return Void();
440 }
441 }
Chia-I Wu109571a2016-09-05 11:46:36 +0800442
Chia-I Wua7f234c2016-11-22 11:37:04 +0800443 Error err = mHal.exportHandle(buffer, handle);
444
445 hidl_cb(err, handle);
Chia-I Wu109571a2016-09-05 11:46:36 +0800446 return Void();
447}
448
449IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
450 const hw_module_t* module;
451 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
452 if (err) {
453 ALOGE("failed to get gralloc module");
454 return nullptr;
455 }
456
457 uint8_t major = (module->module_api_version >> 8) & 0xff;
458 if (major != 1) {
459 ALOGE("unknown gralloc module major version %d", major);
460 return nullptr;
461 }
462
463 return new GrallocHal(module);
464}
465
466} // namespace implementation
467} // namespace V2_0
468} // namespace allocator
469} // namespace graphics
470} // namespace hardware
471} // namespace android