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