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