• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 The Android Open Source Project
3  * * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #ifndef LOG_TAG
19 #warning "Gralloc1Hal.h included without LOG_TAG"
20 #endif
21 
22 #include <inttypes.h>
23 
24 #include <vector>
25 
26 #include <hardware/gralloc1.h>
27 #include <log/log.h>
28 #include <mapper-hal/2.0/MapperHal.h>
29 #include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
30 
31 namespace android {
32 namespace hardware {
33 namespace graphics {
34 namespace mapper {
35 namespace V2_0 {
36 namespace passthrough {
37 
38 namespace detail {
39 
40 using common::V1_0::BufferUsage;
41 
42 // Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
43 template <typename Hal>
44 class Gralloc1HalImpl : public Hal {
45    public:
~Gralloc1HalImpl()46     ~Gralloc1HalImpl() {
47         if (mDevice) {
48             gralloc1_close(mDevice);
49         }
50     }
51 
initWithModule(const hw_module_t * module)52     bool initWithModule(const hw_module_t* module) {
53         int result = gralloc1_open(module, &mDevice);
54         if (result) {
55             ALOGE("failed to open gralloc1 device: %s", strerror(-result));
56             mDevice = nullptr;
57             return false;
58         }
59 
60         initCapabilities();
61 
62         if (!initDispatch()) {
63             gralloc1_close(mDevice);
64             mDevice = nullptr;
65             return false;
66         }
67 
68         return true;
69     }
70 
createDescriptor(const IMapper::BufferDescriptorInfo & descriptorInfo,BufferDescriptor * outDescriptor)71     Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
72                            BufferDescriptor* outDescriptor) override {
73         if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
74             return Error::BAD_VALUE;
75         }
76 
77         if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount != 1) {
78             return Error::UNSUPPORTED;
79         }
80 
81         if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
82             return Error::BAD_VALUE;
83         }
84 
85         const uint64_t validUsageBits = getValidBufferUsageMask();
86         if (descriptorInfo.usage & ~validUsageBits) {
87             ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
88                   descriptorInfo.usage & ~validUsageBits);
89         }
90 
91         *outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
92 
93         return Error::NONE;
94     }
95 
importBuffer(const native_handle_t * rawHandle,native_handle_t ** outBufferHandle)96     Error importBuffer(const native_handle_t* rawHandle,
97                        native_handle_t** outBufferHandle) override {
98         native_handle_t* bufferHandle = native_handle_clone(rawHandle);
99         if (!bufferHandle) {
100             return Error::NO_RESOURCES;
101         }
102 
103         int32_t error = mDispatch.retain(mDevice, bufferHandle);
104         if (error != GRALLOC1_ERROR_NONE) {
105             native_handle_close(bufferHandle);
106             native_handle_delete(bufferHandle);
107             return toError(error);
108         }
109 
110         *outBufferHandle = bufferHandle;
111 
112         return Error::NONE;
113     }
114 
freeBuffer(native_handle_t * bufferHandle)115     Error freeBuffer(native_handle_t* bufferHandle) override {
116         int32_t error = mDispatch.release(mDevice, bufferHandle);
117         if (error == GRALLOC1_ERROR_NONE && !mCapabilities.releaseImplyDelete) {
118             native_handle_close(bufferHandle);
119             native_handle_delete(bufferHandle);
120         }
121         return toError(error);
122     }
123 
lock(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,base::unique_fd fenceFd,void ** outData)124     Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
125                const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
126                void** outData) override {
127         const uint64_t consumerUsage =
128             cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
129         const auto accessRect = asGralloc1Rect(accessRegion);
130         void* data = nullptr;
131         int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
132                                        &data, fenceFd.release());
133         if (error == GRALLOC1_ERROR_NONE) {
134             *outData = data;
135         }
136 
137         return toError(error);
138     }
139 
lockYCbCr(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,base::unique_fd fenceFd,YCbCrLayout * outLayout)140     Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
141                     const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
142                     YCbCrLayout* outLayout) override {
143         // prepare flex layout
144         android_flex_layout flex = {};
145         int32_t error = mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
146         if (error != GRALLOC1_ERROR_NONE) {
147             return toError(error);
148         }
149         std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
150         flex.planes = flexPlanes.data();
151 
152         const uint64_t consumerUsage =
153             cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
154         const auto accessRect = asGralloc1Rect(accessRegion);
155         error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
156                                    &flex, fenceFd.release());
157         if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
158             ALOGD("unable to convert android_flex_layout to YCbCrLayout");
159             // undo the lock
160             unlock(bufferHandle, &fenceFd);
161             error = GRALLOC1_ERROR_BAD_HANDLE;
162         }
163 
164         return toError(error);
165     }
166 
unlock(const native_handle_t * bufferHandle,base::unique_fd * outFenceFd)167     Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
168         int fenceFd = -1;
169         int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
170 
171         // we always own the fenceFd even when unlock failed
172         outFenceFd->reset(fenceFd);
173         return toError(error);
174     }
175 
176    protected:
initCapabilities()177     virtual void initCapabilities() {
178         uint32_t count = 0;
179         mDevice->getCapabilities(mDevice, &count, nullptr);
180 
181         std::vector<int32_t> capabilities(count);
182         mDevice->getCapabilities(mDevice, &count, capabilities.data());
183         capabilities.resize(count);
184 
185         for (auto capability : capabilities) {
186             switch (capability) {
187                 case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
188                     mCapabilities.layeredBuffers = true;
189                     break;
190                 case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
191                     mCapabilities.releaseImplyDelete = true;
192                     break;
193             }
194         }
195     }
196 
197     template <typename T>
initDispatch(gralloc1_function_descriptor_t desc,T * outPfn)198     bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
199         auto pfn = mDevice->getFunction(mDevice, desc);
200         if (pfn) {
201             *outPfn = reinterpret_cast<T>(pfn);
202             return true;
203         } else {
204             ALOGE("failed to get gralloc1 function %d", desc);
205             return false;
206         }
207     }
208 
initDispatch()209     virtual bool initDispatch() {
210         if (!initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain) ||
211             !initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release) ||
212             !initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, &mDispatch.getNumFlexPlanes) ||
213             !initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock) ||
214             !initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex) ||
215             !initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock)) {
216             return false;
217         }
218 
219         return true;
220     }
221 
getValidBufferUsageMask()222     virtual uint64_t getValidBufferUsageMask() const {
223         return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
224                BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
225                BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
226                BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
227                BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
228                BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
229                BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
230                BufferUsage::VENDOR_MASK_HI;
231     }
232 
toError(int32_t error)233     static Error toError(int32_t error) {
234         switch (error) {
235             case GRALLOC1_ERROR_NONE:
236                 return Error::NONE;
237             case GRALLOC1_ERROR_BAD_DESCRIPTOR:
238                 return Error::BAD_DESCRIPTOR;
239             case GRALLOC1_ERROR_BAD_HANDLE:
240                 return Error::BAD_BUFFER;
241             case GRALLOC1_ERROR_BAD_VALUE:
242                 return Error::BAD_VALUE;
243             case GRALLOC1_ERROR_NOT_SHARED:
244                 return Error::NONE;  // this is fine
245             case GRALLOC1_ERROR_NO_RESOURCES:
246                 return Error::NO_RESOURCES;
247             case GRALLOC1_ERROR_UNDEFINED:
248             case GRALLOC1_ERROR_UNSUPPORTED:
249             default:
250                 return Error::UNSUPPORTED;
251         }
252     }
253 
toYCbCrLayout(const android_flex_layout & flex,YCbCrLayout * outLayout)254     static bool toYCbCrLayout(const android_flex_layout& flex, YCbCrLayout* outLayout) {
255         // must be YCbCr
256         if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
257             return false;
258         }
259 
260         for (int i = 0; i < 3; i++) {
261             const auto& plane = flex.planes[i];
262             // must have 8-bit depth
263             if (plane.bits_per_component != 8 || plane.bits_used != 8) {
264                 return false;
265             }
266 
267             if (plane.component == FLEX_COMPONENT_Y) {
268                 // Y must not be interleaved
269                 if (plane.h_increment != 1) {
270                     return false;
271                 }
272             } else {
273                 // Cb and Cr can be interleaved
274                 if (plane.h_increment != 1 && plane.h_increment != 2) {
275                     return false;
276                 }
277             }
278 
279             if (!plane.v_increment) {
280                 return false;
281             }
282         }
283 
284         if (flex.planes[0].component != FLEX_COMPONENT_Y ||
285             flex.planes[1].component != FLEX_COMPONENT_Cb ||
286             flex.planes[2].component != FLEX_COMPONENT_Cr) {
287             return false;
288         }
289 
290         const auto& y = flex.planes[0];
291         const auto& cb = flex.planes[1];
292         const auto& cr = flex.planes[2];
293 
294         if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
295             return false;
296         }
297 
298         outLayout->y = y.top_left;
299         outLayout->cb = cb.top_left;
300         outLayout->cr = cr.top_left;
301         outLayout->yStride = y.v_increment;
302         outLayout->cStride = cb.v_increment;
303         outLayout->chromaStep = cb.h_increment;
304 
305         return true;
306     }
307 
asGralloc1Rect(const IMapper::Rect & rect)308     static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect) {
309         return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
310     }
311 
312     gralloc1_device_t* mDevice = nullptr;
313 
314     struct {
315         bool layeredBuffers;
316         bool releaseImplyDelete;
317     } mCapabilities = {};
318 
319     struct {
320         GRALLOC1_PFN_RETAIN retain;
321         GRALLOC1_PFN_RELEASE release;
322         GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
323         GRALLOC1_PFN_LOCK lock;
324         GRALLOC1_PFN_LOCK_FLEX lockFlex;
325         GRALLOC1_PFN_UNLOCK unlock;
326     } mDispatch = {};
327 };
328 
329 }  // namespace detail
330 
331 using Gralloc1Hal = detail::Gralloc1HalImpl<hal::MapperHal>;
332 
333 }  // namespace passthrough
334 }  // namespace V2_0
335 }  // namespace mapper
336 }  // namespace graphics
337 }  // namespace hardware
338 }  // namespace android
339