blob: b8bc6c425ab17602c4ffa26d92bb97a32a16b900 [file] [log] [blame]
Dan Stoza1e2a2a02016-01-11 15:21:07 -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#undef LOG_TAG
18#define LOG_TAG "Gralloc1On0Adapter"
19//#define LOG_NDEBUG 0
20
Mathias Agopianfe2f54f2017-02-15 19:48:58 -080021#include <ui/Gralloc1On0Adapter.h>
22
23
Dan Stoza1e2a2a02016-01-11 15:21:07 -080024#include <hardware/gralloc.h>
25
Mathias Agopiana9347642017-02-13 16:42:28 -080026#include <ui/GraphicBuffer.h>
Mathias Agopianfe2f54f2017-02-15 19:48:58 -080027#include <ui/Gralloc1.h>
Dan Stoza1e2a2a02016-01-11 15:21:07 -080028
29#include <utils/Log.h>
30
31#include <inttypes.h>
32
33template <typename PFN, typename T>
34static gralloc1_function_pointer_t asFP(T function)
35{
36 static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
37 return reinterpret_cast<gralloc1_function_pointer_t>(function);
38}
39
40namespace android {
41
42Gralloc1On0Adapter::Gralloc1On0Adapter(const hw_module_t* module)
43 : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
44 mMinorVersion(mModule->common.module_api_version & 0xFF),
45 mDevice(nullptr)
46{
47 ALOGV("Constructing");
48 getCapabilities = getCapabilitiesHook;
49 getFunction = getFunctionHook;
50 int error = ::gralloc_open(&(mModule->common), &mDevice);
51 if (error) {
52 ALOGE("Failed to open gralloc0 module: %d", error);
53 }
54 ALOGV("Opened gralloc0 device %p", mDevice);
55}
56
57Gralloc1On0Adapter::~Gralloc1On0Adapter()
58{
59 ALOGV("Destructing");
60 if (mDevice) {
61 ALOGV("Closing gralloc0 device %p", mDevice);
62 ::gralloc_close(mDevice);
63 }
64}
65
66void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount,
67 int32_t* outCapabilities)
68{
69 if (outCapabilities == nullptr) {
70 *outCount = 1;
71 return;
72 }
73 if (*outCount >= 1) {
74 *outCapabilities = GRALLOC1_CAPABILITY_ON_ADAPTER;
75 *outCount = 1;
76 }
77}
78
79gralloc1_function_pointer_t Gralloc1On0Adapter::doGetFunction(
80 int32_t intDescriptor)
81{
82 constexpr auto lastDescriptor =
83 static_cast<int32_t>(GRALLOC1_LAST_ADAPTER_FUNCTION);
84 if (intDescriptor < 0 || intDescriptor > lastDescriptor) {
85 ALOGE("Invalid function descriptor");
86 return nullptr;
87 }
88
89 auto descriptor =
90 static_cast<gralloc1_function_descriptor_t>(intDescriptor);
91 switch (descriptor) {
92 case GRALLOC1_FUNCTION_DUMP:
93 return asFP<GRALLOC1_PFN_DUMP>(dumpHook);
94 case GRALLOC1_FUNCTION_CREATE_DESCRIPTOR:
95 return asFP<GRALLOC1_PFN_CREATE_DESCRIPTOR>(createDescriptorHook);
96 case GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR:
97 return asFP<GRALLOC1_PFN_DESTROY_DESCRIPTOR>(destroyDescriptorHook);
98 case GRALLOC1_FUNCTION_SET_CONSUMER_USAGE:
99 return asFP<GRALLOC1_PFN_SET_CONSUMER_USAGE>(setConsumerUsageHook);
100 case GRALLOC1_FUNCTION_SET_DIMENSIONS:
101 return asFP<GRALLOC1_PFN_SET_DIMENSIONS>(setDimensionsHook);
102 case GRALLOC1_FUNCTION_SET_FORMAT:
103 return asFP<GRALLOC1_PFN_SET_FORMAT>(setFormatHook);
Craig Donner6ebc46a2016-10-21 15:23:44 -0700104 case GRALLOC1_FUNCTION_SET_LAYER_COUNT:
105 return asFP<GRALLOC1_PFN_SET_LAYER_COUNT>(setLayerCountHook);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800106 case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE:
107 return asFP<GRALLOC1_PFN_SET_PRODUCER_USAGE>(setProducerUsageHook);
108 case GRALLOC1_FUNCTION_GET_BACKING_STORE:
109 return asFP<GRALLOC1_PFN_GET_BACKING_STORE>(
110 bufferHook<decltype(&Buffer::getBackingStore),
111 &Buffer::getBackingStore, gralloc1_backing_store_t*>);
112 case GRALLOC1_FUNCTION_GET_CONSUMER_USAGE:
113 return asFP<GRALLOC1_PFN_GET_CONSUMER_USAGE>(getConsumerUsageHook);
114 case GRALLOC1_FUNCTION_GET_DIMENSIONS:
115 return asFP<GRALLOC1_PFN_GET_DIMENSIONS>(
116 bufferHook<decltype(&Buffer::getDimensions),
117 &Buffer::getDimensions, uint32_t*, uint32_t*>);
118 case GRALLOC1_FUNCTION_GET_FORMAT:
119 return asFP<GRALLOC1_PFN_GET_FORMAT>(
120 bufferHook<decltype(&Buffer::getFormat),
121 &Buffer::getFormat, int32_t*>);
Craig Donner6ebc46a2016-10-21 15:23:44 -0700122 case GRALLOC1_FUNCTION_GET_LAYER_COUNT:
123 return asFP<GRALLOC1_PFN_GET_LAYER_COUNT>(
124 bufferHook<decltype(&Buffer::getLayerCount),
125 &Buffer::getLayerCount, uint32_t*>);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800126 case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE:
127 return asFP<GRALLOC1_PFN_GET_PRODUCER_USAGE>(getProducerUsageHook);
128 case GRALLOC1_FUNCTION_GET_STRIDE:
129 return asFP<GRALLOC1_PFN_GET_STRIDE>(
130 bufferHook<decltype(&Buffer::getStride),
131 &Buffer::getStride, uint32_t*>);
132 case GRALLOC1_FUNCTION_ALLOCATE:
133 // Not provided, since we'll use ALLOCATE_WITH_ID
134 return nullptr;
135 case GRALLOC1_FUNCTION_ALLOCATE_WITH_ID:
136 if (mDevice != nullptr) {
137 return asFP<GRALLOC1_PFN_ALLOCATE_WITH_ID>(allocateWithIdHook);
138 } else {
139 return nullptr;
140 }
141 case GRALLOC1_FUNCTION_RETAIN:
142 return asFP<GRALLOC1_PFN_RETAIN>(
143 managementHook<&Gralloc1On0Adapter::retain>);
144 case GRALLOC1_FUNCTION_RELEASE:
145 return asFP<GRALLOC1_PFN_RELEASE>(
146 managementHook<&Gralloc1On0Adapter::release>);
147 case GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER:
148 return asFP<GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER>(
149 retainGraphicBufferHook);
150 case GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES:
151 return asFP<GRALLOC1_PFN_GET_NUM_FLEX_PLANES>(
152 bufferHook<decltype(&Buffer::getNumFlexPlanes),
153 &Buffer::getNumFlexPlanes, uint32_t*>);
154 case GRALLOC1_FUNCTION_LOCK:
155 return asFP<GRALLOC1_PFN_LOCK>(
156 lockHook<void*, &Gralloc1On0Adapter::lock>);
157 case GRALLOC1_FUNCTION_LOCK_FLEX:
158 return asFP<GRALLOC1_PFN_LOCK_FLEX>(
159 lockHook<struct android_flex_layout,
160 &Gralloc1On0Adapter::lockFlex>);
161 case GRALLOC1_FUNCTION_LOCK_YCBCR:
162 return asFP<GRALLOC1_PFN_LOCK_YCBCR>(
163 lockHook<struct android_ycbcr,
164 &Gralloc1On0Adapter::lockYCbCr>);
165 case GRALLOC1_FUNCTION_UNLOCK:
166 return asFP<GRALLOC1_PFN_UNLOCK>(unlockHook);
167 case GRALLOC1_FUNCTION_INVALID:
168 ALOGE("Invalid function descriptor");
169 return nullptr;
170 }
171
172 ALOGE("Unknown function descriptor: %d", intDescriptor);
173 return nullptr;
174}
175
176void Gralloc1On0Adapter::dump(uint32_t* outSize, char* outBuffer)
177{
178 ALOGV("dump(%u (%p), %p", outSize ? *outSize : 0, outSize, outBuffer);
179
180 if (!mDevice->dump) {
181 // dump is optional on gralloc0 implementations
182 *outSize = 0;
183 return;
184 }
185
186 if (!outBuffer) {
187 constexpr int32_t BUFFER_LENGTH = 4096;
188 char buffer[BUFFER_LENGTH] = {};
189 mDevice->dump(mDevice, buffer, BUFFER_LENGTH);
190 buffer[BUFFER_LENGTH - 1] = 0; // Ensure the buffer is null-terminated
191 size_t actualLength = std::strlen(buffer);
192 mCachedDump.resize(actualLength);
193 std::copy_n(buffer, actualLength, mCachedDump.begin());
194 *outSize = static_cast<uint32_t>(actualLength);
195 } else {
196 *outSize = std::min(*outSize,
197 static_cast<uint32_t>(mCachedDump.size()));
198 outBuffer = std::copy_n(mCachedDump.cbegin(), *outSize, outBuffer);
199 }
200}
201
202gralloc1_error_t Gralloc1On0Adapter::createDescriptor(
203 gralloc1_buffer_descriptor_t* outDescriptor)
204{
205 auto descriptorId = sNextBufferDescriptorId++;
Dan Stoza923c0662016-06-21 16:22:06 -0700206 std::lock_guard<std::mutex> lock(mDescriptorMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800207 mDescriptors.emplace(descriptorId,
208 std::make_shared<Descriptor>(this, descriptorId));
209
210 ALOGV("Created descriptor %" PRIu64, descriptorId);
211
212 *outDescriptor = descriptorId;
213 return GRALLOC1_ERROR_NONE;
214}
215
216gralloc1_error_t Gralloc1On0Adapter::destroyDescriptor(
217 gralloc1_buffer_descriptor_t descriptor)
218{
219 ALOGV("Destroying descriptor %" PRIu64, descriptor);
220
Dan Stoza923c0662016-06-21 16:22:06 -0700221 std::lock_guard<std::mutex> lock(mDescriptorMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800222 if (mDescriptors.count(descriptor) == 0) {
223 return GRALLOC1_ERROR_BAD_DESCRIPTOR;
224 }
225
226 mDescriptors.erase(descriptor);
227 return GRALLOC1_ERROR_NONE;
228}
229
230Gralloc1On0Adapter::Buffer::Buffer(buffer_handle_t handle,
231 gralloc1_backing_store_t store, const Descriptor& descriptor,
232 uint32_t stride, bool wasAllocated)
233 : mHandle(handle),
234 mReferenceCount(1),
235 mStore(store),
236 mDescriptor(descriptor),
237 mStride(stride),
238 mWasAllocated(wasAllocated) {}
239
240gralloc1_error_t Gralloc1On0Adapter::allocate(
241 const std::shared_ptr<Descriptor>& descriptor,
242 gralloc1_backing_store_t store,
243 buffer_handle_t* outBufferHandle)
244{
245 ALOGV("allocate(%" PRIu64 ", %#" PRIx64 ")", descriptor->id, store);
246
247 // If this function is being called, it's because we handed out its function
248 // pointer, which only occurs when mDevice has been loaded successfully and
249 // we are permitted to allocate
250
251 int usage = static_cast<int>(descriptor->producerUsage) |
252 static_cast<int>(descriptor->consumerUsage);
253 buffer_handle_t handle = nullptr;
254 int stride = 0;
255 ALOGV("Calling alloc(%p, %u, %u, %i, %u)", mDevice, descriptor->width,
256 descriptor->height, descriptor->format, usage);
257 auto error = mDevice->alloc(mDevice,
258 static_cast<int>(descriptor->width),
259 static_cast<int>(descriptor->height), descriptor->format,
260 usage, &handle, &stride);
261 if (error != 0) {
262 ALOGE("gralloc0 allocation failed: %d (%s)", error,
263 strerror(-error));
264 return GRALLOC1_ERROR_NO_RESOURCES;
265 }
266
267 *outBufferHandle = handle;
268 auto buffer = std::make_shared<Buffer>(handle, store, *descriptor, stride,
269 true);
Dan Stoza923c0662016-06-21 16:22:06 -0700270
271 std::lock_guard<std::mutex> lock(mBufferMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800272 mBuffers.emplace(handle, std::move(buffer));
273
274 return GRALLOC1_ERROR_NONE;
275}
276
277gralloc1_error_t Gralloc1On0Adapter::allocateWithIdHook(
278 gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptorId,
279 gralloc1_backing_store_t store, buffer_handle_t* outBuffer)
280{
281 auto adapter = getAdapter(device);
282
283 auto descriptor = adapter->getDescriptor(descriptorId);
284 if (!descriptor) {
285 return GRALLOC1_ERROR_BAD_DESCRIPTOR;
286 }
287
288 buffer_handle_t bufferHandle = nullptr;
289 auto error = adapter->allocate(descriptor, store, &bufferHandle);
290 if (error != GRALLOC1_ERROR_NONE) {
291 return error;
292 }
293
294 *outBuffer = bufferHandle;
295 return error;
296}
297
298gralloc1_error_t Gralloc1On0Adapter::retain(
299 const std::shared_ptr<Buffer>& buffer)
300{
Ajit Kumar56ec3af2016-11-25 12:08:53 +0530301 std::lock_guard<std::mutex> lock(mBufferMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800302 buffer->retain();
303 return GRALLOC1_ERROR_NONE;
304}
305
306gralloc1_error_t Gralloc1On0Adapter::release(
307 const std::shared_ptr<Buffer>& buffer)
308{
Ajit Kumar56ec3af2016-11-25 12:08:53 +0530309 std::lock_guard<std::mutex> lock(mBufferMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800310 if (!buffer->release()) {
311 return GRALLOC1_ERROR_NONE;
312 }
313
314 buffer_handle_t handle = buffer->getHandle();
315 if (buffer->wasAllocated()) {
316 ALOGV("Calling free(%p)", handle);
317 int result = mDevice->free(mDevice, handle);
318 if (result != 0) {
319 ALOGE("gralloc0 free failed: %d", result);
320 }
321 } else {
322 ALOGV("Calling unregisterBuffer(%p)", handle);
323 int result = mModule->unregisterBuffer(mModule, handle);
324 if (result != 0) {
325 ALOGE("gralloc0 unregister failed: %d", result);
326 }
327 }
Dan Stoza923c0662016-06-21 16:22:06 -0700328
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800329 mBuffers.erase(handle);
330 return GRALLOC1_ERROR_NONE;
331}
332
333gralloc1_error_t Gralloc1On0Adapter::retain(
334 const android::GraphicBuffer* graphicBuffer)
335{
336 ALOGV("retainGraphicBuffer(%p, %#" PRIx64 ")",
337 graphicBuffer->getNativeBuffer()->handle, graphicBuffer->getId());
338
339 buffer_handle_t handle = graphicBuffer->getNativeBuffer()->handle;
Dan Stoza923c0662016-06-21 16:22:06 -0700340 std::lock_guard<std::mutex> lock(mBufferMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800341 if (mBuffers.count(handle) != 0) {
342 mBuffers[handle]->retain();
343 return GRALLOC1_ERROR_NONE;
344 }
345
346 ALOGV("Calling registerBuffer(%p)", handle);
347 int result = mModule->registerBuffer(mModule, handle);
348 if (result != 0) {
349 ALOGE("gralloc0 register failed: %d", result);
350 return GRALLOC1_ERROR_NO_RESOURCES;
351 }
352
353 Descriptor descriptor{this, sNextBufferDescriptorId++};
354 descriptor.setDimensions(graphicBuffer->getWidth(),
355 graphicBuffer->getHeight());
356 descriptor.setFormat(graphicBuffer->getPixelFormat());
357 descriptor.setProducerUsage(
358 static_cast<gralloc1_producer_usage_t>(graphicBuffer->getUsage()));
359 descriptor.setConsumerUsage(
360 static_cast<gralloc1_consumer_usage_t>(graphicBuffer->getUsage()));
361 auto buffer = std::make_shared<Buffer>(handle,
362 static_cast<gralloc1_backing_store_t>(graphicBuffer->getId()),
363 descriptor, graphicBuffer->getStride(), false);
364 mBuffers.emplace(handle, std::move(buffer));
365 return GRALLOC1_ERROR_NONE;
366}
367
368gralloc1_error_t Gralloc1On0Adapter::lock(
369 const std::shared_ptr<Buffer>& buffer,
370 gralloc1_producer_usage_t producerUsage,
371 gralloc1_consumer_usage_t consumerUsage,
372 const gralloc1_rect_t& accessRegion, void** outData,
373 const sp<Fence>& acquireFence)
374{
375 if (mMinorVersion >= 3) {
376 int result = mModule->lockAsync(mModule, buffer->getHandle(),
377 static_cast<int32_t>(producerUsage | consumerUsage),
378 accessRegion.left, accessRegion.top, accessRegion.width,
379 accessRegion.height, outData, acquireFence->dup());
380 if (result != 0) {
381 return GRALLOC1_ERROR_UNSUPPORTED;
382 }
383 } else {
384 acquireFence->waitForever("Gralloc1On0Adapter::lock");
385 int result = mModule->lock(mModule, buffer->getHandle(),
386 static_cast<int32_t>(producerUsage | consumerUsage),
387 accessRegion.left, accessRegion.top, accessRegion.width,
388 accessRegion.height, outData);
389 ALOGV("gralloc0 lock returned %d", result);
390 if (result != 0) {
391 return GRALLOC1_ERROR_UNSUPPORTED;
392 }
393 }
394 return GRALLOC1_ERROR_NONE;
395}
396
397gralloc1_error_t Gralloc1On0Adapter::lockFlex(
398 const std::shared_ptr<Buffer>& /*buffer*/,
399 gralloc1_producer_usage_t /*producerUsage*/,
400 gralloc1_consumer_usage_t /*consumerUsage*/,
401 const gralloc1_rect_t& /*accessRegion*/,
402 struct android_flex_layout* /*outData*/,
403 const sp<Fence>& /*acquireFence*/)
404{
405 // TODO
406 return GRALLOC1_ERROR_UNSUPPORTED;
407}
408
409gralloc1_error_t Gralloc1On0Adapter::lockYCbCr(
410 const std::shared_ptr<Buffer>& buffer,
411 gralloc1_producer_usage_t producerUsage,
412 gralloc1_consumer_usage_t consumerUsage,
413 const gralloc1_rect_t& accessRegion, struct android_ycbcr* outData,
414 const sp<Fence>& acquireFence)
415{
416 if (mMinorVersion >= 3 && mModule->lockAsync_ycbcr) {
417 int result = mModule->lockAsync_ycbcr(mModule, buffer->getHandle(),
418 static_cast<int>(producerUsage | consumerUsage),
419 accessRegion.left, accessRegion.top, accessRegion.width,
420 accessRegion.height, outData, acquireFence->dup());
421 if (result != 0) {
422 return GRALLOC1_ERROR_UNSUPPORTED;
423 }
424 } else if (mModule->lock_ycbcr) {
425 acquireFence->waitForever("Gralloc1On0Adapter::lockYCbCr");
426 int result = mModule->lock_ycbcr(mModule, buffer->getHandle(),
427 static_cast<int>(producerUsage | consumerUsage),
428 accessRegion.left, accessRegion.top, accessRegion.width,
429 accessRegion.height, outData);
430 ALOGV("gralloc0 lockYCbCr returned %d", result);
431 if (result != 0) {
432 return GRALLOC1_ERROR_UNSUPPORTED;
433 }
434 } else {
435 return GRALLOC1_ERROR_UNSUPPORTED;
436 }
437
438 return GRALLOC1_ERROR_NONE;
439}
440
441gralloc1_error_t Gralloc1On0Adapter::unlock(
442 const std::shared_ptr<Buffer>& buffer,
443 sp<Fence>* outReleaseFence)
444{
445 if (mMinorVersion >= 3) {
446 int fenceFd = -1;
447 int result = mModule->unlockAsync(mModule, buffer->getHandle(),
448 &fenceFd);
449 if (result != 0) {
450 close(fenceFd);
451 ALOGE("gralloc0 unlockAsync failed: %d", result);
452 } else {
453 *outReleaseFence = new Fence(fenceFd);
454 }
455 } else {
456 int result = mModule->unlock(mModule, buffer->getHandle());
457 if (result != 0) {
458 ALOGE("gralloc0 unlock failed: %d", result);
459 }
460 }
461 return GRALLOC1_ERROR_NONE;
462}
463
464std::shared_ptr<Gralloc1On0Adapter::Descriptor>
465Gralloc1On0Adapter::getDescriptor(gralloc1_buffer_descriptor_t descriptorId)
466{
Dan Stoza923c0662016-06-21 16:22:06 -0700467 std::lock_guard<std::mutex> lock(mDescriptorMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800468 if (mDescriptors.count(descriptorId) == 0) {
469 return nullptr;
470 }
471
472 return mDescriptors[descriptorId];
473}
474
475std::shared_ptr<Gralloc1On0Adapter::Buffer> Gralloc1On0Adapter::getBuffer(
476 buffer_handle_t bufferHandle)
477{
Dan Stoza923c0662016-06-21 16:22:06 -0700478 std::lock_guard<std::mutex> lock(mBufferMutex);
Dan Stoza1e2a2a02016-01-11 15:21:07 -0800479 if (mBuffers.count(bufferHandle) == 0) {
480 return nullptr;
481 }
482
483 return mBuffers[bufferHandle];
484}
485
486std::atomic<gralloc1_buffer_descriptor_t>
487 Gralloc1On0Adapter::sNextBufferDescriptorId(1);
488
489} // namespace android