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 #define LOG_TAG "Gralloc1Allocator"
18 
19 #include "Gralloc1Allocator.h"
20 #include "GrallocBufferDescriptor.h"
21 
22 #include <vector>
23 
24 #include <string.h>
25 
26 #include <log/log.h>
27 
28 namespace android {
29 namespace hardware {
30 namespace graphics {
31 namespace allocator {
32 namespace V2_0 {
33 namespace implementation {
34 
35 using android::hardware::graphics::common::V1_0::BufferUsage;
36 using android::hardware::graphics::mapper::V2_0::implementation::
37     grallocDecodeBufferDescriptor;
38 
Gralloc1Allocator(const hw_module_t * module)39 Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module)
40     : mDevice(nullptr), mCapabilities(), mDispatch() {
41     int result = gralloc1_open(module, &mDevice);
42     if (result) {
43         LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
44                          strerror(-result));
45     }
46 
47     initCapabilities();
48     initDispatch();
49 }
50 
~Gralloc1Allocator()51 Gralloc1Allocator::~Gralloc1Allocator() {
52     gralloc1_close(mDevice);
53 }
54 
initCapabilities()55 void Gralloc1Allocator::initCapabilities() {
56     uint32_t count = 0;
57     mDevice->getCapabilities(mDevice, &count, nullptr);
58 
59     std::vector<int32_t> capabilities(count);
60     mDevice->getCapabilities(mDevice, &count, capabilities.data());
61     capabilities.resize(count);
62 
63     for (auto capability : capabilities) {
64         if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
65             mCapabilities.layeredBuffers = true;
66             break;
67         }
68     }
69 }
70 
71 template <typename T>
initDispatch(gralloc1_function_descriptor_t desc,T * outPfn)72 void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc,
73                                      T* outPfn) {
74     auto pfn = mDevice->getFunction(mDevice, desc);
75     if (!pfn) {
76         LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
77     }
78 
79     *outPfn = reinterpret_cast<T>(pfn);
80 }
81 
initDispatch()82 void Gralloc1Allocator::initDispatch() {
83     initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
84     initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
85                  &mDispatch.createDescriptor);
86     initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
87                  &mDispatch.destroyDescriptor);
88     initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
89     initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
90     if (mCapabilities.layeredBuffers) {
91         initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
92                      &mDispatch.setLayerCount);
93     }
94     initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
95                  &mDispatch.setConsumerUsage);
96     initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
97                  &mDispatch.setProducerUsage);
98     initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
99     initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
100     initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
101 }
102 
dumpDebugInfo(dumpDebugInfo_cb hidl_cb)103 Return<void> Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
104     uint32_t len = 0;
105     mDispatch.dump(mDevice, &len, nullptr);
106 
107     std::vector<char> buf(len + 1);
108     mDispatch.dump(mDevice, &len, buf.data());
109     buf.resize(len + 1);
110     buf[len] = '\0';
111 
112     hidl_string reply;
113     reply.setToExternal(buf.data(), len);
114     hidl_cb(reply);
115 
116     return Void();
117 }
118 
allocate(const BufferDescriptor & descriptor,uint32_t count,allocate_cb hidl_cb)119 Return<void> Gralloc1Allocator::allocate(const BufferDescriptor& descriptor,
120                                          uint32_t count, allocate_cb hidl_cb) {
121     IMapper::BufferDescriptorInfo descriptorInfo;
122     if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
123         hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
124         return Void();
125     }
126 
127     gralloc1_buffer_descriptor_t desc;
128     Error error = createDescriptor(descriptorInfo, &desc);
129     if (error != Error::NONE) {
130         hidl_cb(error, 0, hidl_vec<hidl_handle>());
131         return Void();
132     }
133 
134     uint32_t stride = 0;
135     std::vector<hidl_handle> buffers;
136     buffers.reserve(count);
137 
138     // allocate the buffers
139     for (uint32_t i = 0; i < count; i++) {
140         buffer_handle_t tmpBuffer;
141         uint32_t tmpStride;
142         error = allocateOne(desc, &tmpBuffer, &tmpStride);
143         if (error != Error::NONE) {
144             break;
145         }
146 
147         if (stride == 0) {
148             stride = tmpStride;
149         } else if (stride != tmpStride) {
150             // non-uniform strides
151             mDispatch.release(mDevice, tmpBuffer);
152             stride = 0;
153             error = Error::UNSUPPORTED;
154             break;
155         }
156 
157         buffers.emplace_back(hidl_handle(tmpBuffer));
158     }
159 
160     mDispatch.destroyDescriptor(mDevice, desc);
161 
162     // return the buffers
163     hidl_vec<hidl_handle> hidl_buffers;
164     if (error == Error::NONE) {
165         hidl_buffers.setToExternal(buffers.data(), buffers.size());
166     }
167     hidl_cb(error, stride, hidl_buffers);
168 
169     // free the buffers
170     for (const auto& buffer : buffers) {
171         mDispatch.release(mDevice, buffer.getNativeHandle());
172     }
173 
174     return Void();
175 }
176 
toError(int32_t error)177 Error Gralloc1Allocator::toError(int32_t error) {
178     switch (error) {
179         case GRALLOC1_ERROR_NONE:
180             return Error::NONE;
181         case GRALLOC1_ERROR_BAD_DESCRIPTOR:
182             return Error::BAD_DESCRIPTOR;
183         case GRALLOC1_ERROR_BAD_HANDLE:
184             return Error::BAD_BUFFER;
185         case GRALLOC1_ERROR_BAD_VALUE:
186             return Error::BAD_VALUE;
187         case GRALLOC1_ERROR_NOT_SHARED:
188             return Error::NONE;  // this is fine
189         case GRALLOC1_ERROR_NO_RESOURCES:
190             return Error::NO_RESOURCES;
191         case GRALLOC1_ERROR_UNDEFINED:
192         case GRALLOC1_ERROR_UNSUPPORTED:
193         default:
194             return Error::UNSUPPORTED;
195     }
196 }
197 
toProducerUsage(uint64_t usage)198 uint64_t Gralloc1Allocator::toProducerUsage(uint64_t usage) {
199     // this is potentially broken as we have no idea which private flags
200     // should be filtered out
201     uint64_t producerUsage =
202         usage &
203         ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
204                                BufferUsage::CPU_WRITE_MASK);
205 
206     switch (usage & BufferUsage::CPU_WRITE_MASK) {
207         case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
208             producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
209             break;
210         case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
211             producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
212             break;
213         default:
214             break;
215     }
216 
217     switch (usage & BufferUsage::CPU_READ_MASK) {
218         case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
219             producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
220             break;
221         case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
222             producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
223             break;
224         default:
225             break;
226     }
227 
228     return producerUsage;
229 }
230 
toConsumerUsage(uint64_t usage)231 uint64_t Gralloc1Allocator::toConsumerUsage(uint64_t usage) {
232     // this is potentially broken as we have no idea which private flags
233     // should be filtered out
234     uint64_t consumerUsage =
235         usage &
236         ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
237                                BufferUsage::CPU_WRITE_MASK);
238 
239     switch (usage & BufferUsage::CPU_READ_MASK) {
240         case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
241             consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
242             break;
243         case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
244             consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
245             break;
246         default:
247             break;
248     }
249 
250     return consumerUsage;
251 }
252 
createDescriptor(const IMapper::BufferDescriptorInfo & info,gralloc1_buffer_descriptor_t * outDescriptor)253 Error Gralloc1Allocator::createDescriptor(
254     const IMapper::BufferDescriptorInfo& info,
255     gralloc1_buffer_descriptor_t* outDescriptor) {
256     gralloc1_buffer_descriptor_t descriptor;
257 
258     int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
259 
260     if (error == GRALLOC1_ERROR_NONE) {
261         error = mDispatch.setDimensions(mDevice, descriptor, info.width,
262                                         info.height);
263     }
264     if (error == GRALLOC1_ERROR_NONE) {
265         error = mDispatch.setFormat(mDevice, descriptor,
266                                     static_cast<int32_t>(info.format));
267     }
268     if (error == GRALLOC1_ERROR_NONE) {
269         if (mCapabilities.layeredBuffers) {
270             error =
271                 mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
272         } else if (info.layerCount > 1) {
273             error = GRALLOC1_ERROR_UNSUPPORTED;
274         }
275     }
276     if (error == GRALLOC1_ERROR_NONE) {
277         error = mDispatch.setProducerUsage(mDevice, descriptor,
278                                            toProducerUsage(info.usage));
279     }
280     if (error == GRALLOC1_ERROR_NONE) {
281         error = mDispatch.setConsumerUsage(mDevice, descriptor,
282                                            toConsumerUsage(info.usage));
283     }
284 
285     if (error == GRALLOC1_ERROR_NONE) {
286         *outDescriptor = descriptor;
287     } else {
288         mDispatch.destroyDescriptor(mDevice, descriptor);
289     }
290 
291     return toError(error);
292 }
293 
allocateOne(gralloc1_buffer_descriptor_t descriptor,buffer_handle_t * outBuffer,uint32_t * outStride)294 Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor,
295                                      buffer_handle_t* outBuffer,
296                                      uint32_t* outStride) {
297     buffer_handle_t buffer = nullptr;
298     int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
299     if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
300         return toError(error);
301     }
302 
303     uint32_t stride = 0;
304     error = mDispatch.getStride(mDevice, buffer, &stride);
305     if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
306         mDispatch.release(mDevice, buffer);
307         return toError(error);
308     }
309 
310     *outBuffer = buffer;
311     *outStride = stride;
312 
313     return Error::NONE;
314 }
315 
316 }  // namespace implementation
317 }  // namespace V2_0
318 }  // namespace allocator
319 }  // namespace graphics
320 }  // namespace hardware
321 }  // namespace android
322