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#define LOG_TAG "Gralloc0Mapper"
17
18#include "Gralloc0Mapper.h"
19
20#include <log/log.h>
21
22namespace android {
23namespace hardware {
24namespace graphics {
25namespace mapper {
26namespace V2_0 {
27namespace implementation {
28
29Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
30    : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
31      mMinor(module->module_api_version & 0xff) {
32    mCapabilities.highUsageBits = false;
33    mCapabilities.layeredBuffers = false;
34    mCapabilities.unregisterImplyDelete = false;
35}
36
37Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) {
38    int result = mModule->registerBuffer(mModule, bufferHandle);
39    return result ? Error::BAD_BUFFER : Error::NONE;
40}
41
42void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
43    mModule->unregisterBuffer(mModule, bufferHandle);
44}
45
46Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
47                                 uint64_t cpuUsage,
48                                 const IMapper::Rect& accessRegion, int fenceFd,
49                                 void** outData) {
50    int result;
51    void* data = nullptr;
52    if (mMinor >= 3 && mModule->lockAsync) {
53        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
54        // gralloc's responsibility to close it, even on locking errors.
55        if (fenceFd >= 0) {
56            fenceFd = dup(fenceFd);
57            if (fenceFd < 0) {
58                return Error::NO_RESOURCES;
59            }
60        }
61
62        result = mModule->lockAsync(mModule, bufferHandle, cpuUsage,
63                                    accessRegion.left, accessRegion.top,
64                                    accessRegion.width, accessRegion.height,
65                                    &data, fenceFd);
66    } else {
67        waitFenceFd(fenceFd, "Gralloc0Mapper::lock");
68
69        result = mModule->lock(mModule, bufferHandle, cpuUsage,
70                               accessRegion.left, accessRegion.top,
71                               accessRegion.width, accessRegion.height, &data);
72    }
73
74    if (result) {
75        return Error::BAD_VALUE;
76    } else {
77        *outData = data;
78        return Error::NONE;
79    }
80}
81
82Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
83                                 uint64_t cpuUsage,
84                                 const IMapper::Rect& accessRegion, int fenceFd,
85                                 YCbCrLayout* outLayout) {
86    int result;
87    android_ycbcr ycbcr = {};
88    if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
89        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
90        // gralloc's responsibility to close it, even on locking errors.
91        if (fenceFd >= 0) {
92            fenceFd = dup(fenceFd);
93            if (fenceFd < 0) {
94                return Error::NO_RESOURCES;
95            }
96        }
97
98        result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage,
99                                          accessRegion.left, accessRegion.top,
100                                          accessRegion.width,
101                                          accessRegion.height, &ycbcr, fenceFd);
102    } else {
103        waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr");
104
105        if (mModule->lock_ycbcr) {
106            result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage,
107                                         accessRegion.left, accessRegion.top,
108                                         accessRegion.width,
109                                         accessRegion.height, &ycbcr);
110        } else {
111            result = -EINVAL;
112        }
113    }
114
115    if (result) {
116        return Error::BAD_VALUE;
117    } else {
118        outLayout->y = ycbcr.y;
119        outLayout->cb = ycbcr.cb;
120        outLayout->cr = ycbcr.cr;
121        outLayout->yStride = ycbcr.ystride;
122        outLayout->cStride = ycbcr.cstride;
123        outLayout->chromaStep = ycbcr.chroma_step;
124        return Error::NONE;
125    }
126}
127
128Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle,
129                                   int* outFenceFd) {
130    int result;
131    int fenceFd = -1;
132    if (mMinor >= 3 && mModule->unlockAsync) {
133        result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
134    } else {
135        result = mModule->unlock(mModule, bufferHandle);
136    }
137
138    if (result) {
139        // we always own the fenceFd even when unlock failed
140        if (fenceFd >= 0) {
141            close(fenceFd);
142        }
143
144        return Error::BAD_VALUE;
145    } else {
146        *outFenceFd = fenceFd;
147        return Error::NONE;
148    }
149}
150
151}  // namespace implementation
152}  // namespace V2_0
153}  // namespace mapper
154}  // namespace graphics
155}  // namespace hardware
156}  // namespace android
157