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
31namespace android {
32namespace hardware {
33namespace graphics {
34namespace mapper {
35namespace V2_0 {
36namespace passthrough {
37
38namespace detail {
39
40using common::V1_0::BufferUsage;
41
42// Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
43template <typename Hal>
44class Gralloc1HalImpl : public Hal {
45   public:
46    ~Gralloc1HalImpl() {
47        if (mDevice) {
48            gralloc1_close(mDevice);
49        }
50    }
51
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
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
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
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
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
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
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:
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>
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
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
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
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
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
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
331using 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