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 #pragma once 18 19 #ifndef LOG_TAG 20 #warning "Gralloc0Hal.h included without LOG_TAG" 21 #endif 22 23 #include <cstring> // for strerror 24 25 #include <allocator-hal/2.0/AllocatorHal.h> 26 #include <hardware/gralloc.h> 27 #include <log/log.h> 28 #include <mapper-passthrough/2.0/GrallocBufferDescriptor.h> 29 30 namespace android { 31 namespace hardware { 32 namespace graphics { 33 namespace allocator { 34 namespace V2_0 { 35 namespace passthrough { 36 37 namespace detail { 38 39 using mapper::V2_0::BufferDescriptor; 40 using mapper::V2_0::Error; 41 using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor; 42 43 // Gralloc0HalImpl implements V2_*::hal::AllocatorHal on top of gralloc0 44 template <typename Hal> 45 class Gralloc0HalImpl : public Hal { 46 public: ~Gralloc0HalImpl()47 ~Gralloc0HalImpl() { 48 if (mDevice) { 49 gralloc_close(mDevice); 50 } 51 } 52 initWithModule(const hw_module_t * module)53 bool initWithModule(const hw_module_t* module) { 54 int result = gralloc_open(module, &mDevice); 55 if (result) { 56 ALOGE("failed to open gralloc0 device: %s", strerror(-result)); 57 mDevice = nullptr; 58 return false; 59 } 60 61 return true; 62 } 63 dumpDebugInfo()64 std::string dumpDebugInfo() override { 65 char buf[4096] = {}; 66 if (mDevice->dump) { 67 mDevice->dump(mDevice, buf, sizeof(buf)); 68 buf[sizeof(buf) - 1] = '\0'; 69 } 70 71 return buf; 72 } 73 allocateBuffers(const BufferDescriptor & descriptor,uint32_t count,uint32_t * outStride,std::vector<const native_handle_t * > * outBuffers)74 Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride, 75 std::vector<const native_handle_t*>* outBuffers) override { 76 mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo; 77 if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) { 78 return Error::BAD_DESCRIPTOR; 79 } 80 81 Error error = Error::NONE; 82 uint32_t stride = 0; 83 std::vector<const native_handle_t*> buffers; 84 buffers.reserve(count); 85 86 // allocate the buffers 87 for (uint32_t i = 0; i < count; i++) { 88 const native_handle_t* tmpBuffer; 89 uint32_t tmpStride; 90 error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride); 91 if (error != Error::NONE) { 92 break; 93 } 94 95 buffers.push_back(tmpBuffer); 96 97 if (stride == 0) { 98 stride = tmpStride; 99 } else if (stride != tmpStride) { 100 // non-uniform strides 101 error = Error::UNSUPPORTED; 102 break; 103 } 104 } 105 106 if (error != Error::NONE) { 107 freeBuffers(buffers); 108 return error; 109 } 110 111 *outStride = stride; 112 *outBuffers = std::move(buffers); 113 114 return Error::NONE; 115 } 116 freeBuffers(const std::vector<const native_handle_t * > & buffers)117 void freeBuffers(const std::vector<const native_handle_t*>& buffers) override { 118 for (auto buffer : buffers) { 119 int result = mDevice->free(mDevice, buffer); 120 if (result != 0) { 121 ALOGE("failed to free buffer %p: %d", buffer, result); 122 } 123 } 124 } 125 126 protected: allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo & info,const native_handle_t ** outBuffer,uint32_t * outStride)127 Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info, 128 const native_handle_t** outBuffer, uint32_t* outStride) { 129 if (info.layerCount > 1 || (info.usage >> 32) != 0) { 130 return Error::BAD_VALUE; 131 } 132 133 const native_handle_t* buffer = nullptr; 134 int stride = 0; 135 int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format), 136 info.usage, &buffer, &stride); 137 switch (result) { 138 case 0: 139 *outBuffer = buffer; 140 *outStride = stride; 141 return Error::NONE; 142 case -EINVAL: 143 return Error::BAD_VALUE; 144 default: 145 return Error::NO_RESOURCES; 146 } 147 } 148 149 alloc_device_t* mDevice = nullptr; 150 }; 151 152 } // namespace detail 153 154 using Gralloc0Hal = detail::Gralloc0HalImpl<hal::AllocatorHal>; 155 156 } // namespace passthrough 157 } // namespace V2_0 158 } // namespace allocator 159 } // namespace graphics 160 } // namespace hardware 161 } // namespace android 162