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 "Gralloc1Mapper"
17
18 #include "Gralloc1Mapper.h"
19
20 #include <vector>
21
22 #include <log/log.h>
23
24 namespace android {
25 namespace hardware {
26 namespace graphics {
27 namespace mapper {
28 namespace V2_0 {
29 namespace implementation {
30
31 using android::hardware::graphics::common::V1_0::BufferUsage;
32
Gralloc1Mapper(const hw_module_t * module)33 Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module)
34 : mDevice(nullptr), mDispatch() {
35 int result = gralloc1_open(module, &mDevice);
36 if (result) {
37 LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
38 strerror(-result));
39 }
40
41 initCapabilities();
42 initDispatch();
43 }
44
~Gralloc1Mapper()45 Gralloc1Mapper::~Gralloc1Mapper() {
46 gralloc1_close(mDevice);
47 }
48
initCapabilities()49 void Gralloc1Mapper::initCapabilities() {
50 mCapabilities.highUsageBits = true;
51 mCapabilities.layeredBuffers = false;
52 mCapabilities.unregisterImplyDelete = false;
53
54 uint32_t count = 0;
55 mDevice->getCapabilities(mDevice, &count, nullptr);
56
57 std::vector<int32_t> capabilities(count);
58 mDevice->getCapabilities(mDevice, &count, capabilities.data());
59 capabilities.resize(count);
60
61 for (auto capability : capabilities) {
62 switch (capability) {
63 case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
64 mCapabilities.layeredBuffers = true;
65 break;
66 case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
67 mCapabilities.unregisterImplyDelete = true;
68 break;
69 }
70 }
71 }
72
73 template <typename T>
initDispatch(gralloc1_function_descriptor_t desc,T * outPfn)74 void Gralloc1Mapper::initDispatch(gralloc1_function_descriptor_t desc,
75 T* outPfn) {
76 auto pfn = mDevice->getFunction(mDevice, desc);
77 if (!pfn) {
78 LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
79 }
80
81 *outPfn = reinterpret_cast<T>(pfn);
82 }
83
initDispatch()84 void Gralloc1Mapper::initDispatch() {
85 initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
86 initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
87 initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
88 &mDispatch.getNumFlexPlanes);
89 initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
90 initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
91 initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
92 }
93
toError(int32_t error)94 Error Gralloc1Mapper::toError(int32_t error) {
95 switch (error) {
96 case GRALLOC1_ERROR_NONE:
97 return Error::NONE;
98 case GRALLOC1_ERROR_BAD_DESCRIPTOR:
99 return Error::BAD_DESCRIPTOR;
100 case GRALLOC1_ERROR_BAD_HANDLE:
101 return Error::BAD_BUFFER;
102 case GRALLOC1_ERROR_BAD_VALUE:
103 return Error::BAD_VALUE;
104 case GRALLOC1_ERROR_NOT_SHARED:
105 return Error::NONE; // this is fine
106 case GRALLOC1_ERROR_NO_RESOURCES:
107 return Error::NO_RESOURCES;
108 case GRALLOC1_ERROR_UNDEFINED:
109 case GRALLOC1_ERROR_UNSUPPORTED:
110 default:
111 return Error::UNSUPPORTED;
112 }
113 }
114
toYCbCrLayout(const android_flex_layout & flex,YCbCrLayout * outLayout)115 bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex,
116 YCbCrLayout* outLayout) {
117 // must be YCbCr
118 if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
119 return false;
120 }
121
122 for (int i = 0; i < 3; i++) {
123 const auto& plane = flex.planes[i];
124 // must have 8-bit depth
125 if (plane.bits_per_component != 8 || plane.bits_used != 8) {
126 return false;
127 }
128
129 if (plane.component == FLEX_COMPONENT_Y) {
130 // Y must not be interleaved
131 if (plane.h_increment != 1) {
132 return false;
133 }
134 } else {
135 // Cb and Cr can be interleaved
136 if (plane.h_increment != 1 && plane.h_increment != 2) {
137 return false;
138 }
139 }
140
141 if (!plane.v_increment) {
142 return false;
143 }
144 }
145
146 if (flex.planes[0].component != FLEX_COMPONENT_Y ||
147 flex.planes[1].component != FLEX_COMPONENT_Cb ||
148 flex.planes[2].component != FLEX_COMPONENT_Cr) {
149 return false;
150 }
151
152 const auto& y = flex.planes[0];
153 const auto& cb = flex.planes[1];
154 const auto& cr = flex.planes[2];
155
156 if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
157 return false;
158 }
159
160 outLayout->y = y.top_left;
161 outLayout->cb = cb.top_left;
162 outLayout->cr = cr.top_left;
163 outLayout->yStride = y.v_increment;
164 outLayout->cStride = cb.v_increment;
165 outLayout->chromaStep = cb.h_increment;
166
167 return true;
168 }
169
asGralloc1Rect(const IMapper::Rect & rect)170 gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) {
171 return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
172 }
173
registerBuffer(buffer_handle_t bufferHandle)174 Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) {
175 return toError(mDispatch.retain(mDevice, bufferHandle));
176 }
177
unregisterBuffer(buffer_handle_t bufferHandle)178 void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
179 mDispatch.release(mDevice, bufferHandle);
180 }
181
lockBuffer(buffer_handle_t bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int fenceFd,void ** outData)182 Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
183 uint64_t cpuUsage,
184 const IMapper::Rect& accessRegion, int fenceFd,
185 void** outData) {
186 // Dup fenceFd as it is going to be owned by gralloc. Note that it is
187 // gralloc's responsibility to close it, even on locking errors.
188 if (fenceFd >= 0) {
189 fenceFd = dup(fenceFd);
190 if (fenceFd < 0) {
191 return Error::NO_RESOURCES;
192 }
193 }
194
195 const uint64_t consumerUsage =
196 cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
197 const auto accessRect = asGralloc1Rect(accessRegion);
198 void* data = nullptr;
199 int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage,
200 consumerUsage, &accessRect, &data, fenceFd);
201
202 if (error == GRALLOC1_ERROR_NONE) {
203 *outData = data;
204 }
205
206 return toError(error);
207 }
208
lockBuffer(buffer_handle_t bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int fenceFd,YCbCrLayout * outLayout)209 Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
210 uint64_t cpuUsage,
211 const IMapper::Rect& accessRegion, int fenceFd,
212 YCbCrLayout* outLayout) {
213 // prepare flex layout
214 android_flex_layout flex = {};
215 int32_t error =
216 mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
217 if (error != GRALLOC1_ERROR_NONE) {
218 return toError(error);
219 }
220 std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
221 flex.planes = flexPlanes.data();
222
223 // Dup fenceFd as it is going to be owned by gralloc. Note that it is
224 // gralloc's responsibility to close it, even on locking errors.
225 if (fenceFd >= 0) {
226 fenceFd = dup(fenceFd);
227 if (fenceFd < 0) {
228 return Error::NO_RESOURCES;
229 }
230 }
231
232 const uint64_t consumerUsage =
233 cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
234 const auto accessRect = asGralloc1Rect(accessRegion);
235 error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage,
236 &accessRect, &flex, fenceFd);
237 if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
238 ALOGD("unable to convert android_flex_layout to YCbCrLayout");
239
240 // undo the lock
241 fenceFd = -1;
242 mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
243 if (fenceFd >= 0) {
244 close(fenceFd);
245 }
246
247 error = GRALLOC1_ERROR_BAD_HANDLE;
248 }
249
250 return toError(error);
251 }
252
unlockBuffer(buffer_handle_t bufferHandle,int * outFenceFd)253 Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle,
254 int* outFenceFd) {
255 int fenceFd = -1;
256 int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
257
258 if (error == GRALLOC1_ERROR_NONE) {
259 *outFenceFd = fenceFd;
260 } else if (fenceFd >= 0) {
261 // we always own the fenceFd even when unlock failed
262 close(fenceFd);
263 }
264
265 return toError(error);
266 }
267
268 } // namespace implementation
269 } // namespace V2_0
270 } // namespace mapper
271 } // namespace graphics
272 } // namespace hardware
273 } // namespace android
274