blob: fb55bf1a25865b26ca41f354b7d76242787ef28f [file] [log] [blame]
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001/*
2 * Copyright (C) 2007 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
Mathias Agopian3330b202009-10-05 17:07:12 -070017#define LOG_TAG "GraphicBufferMapper"
Mathias Agopiancf563192012-02-29 20:43:29 -080018#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Dan Stoza8deb4da2016-06-01 18:21:44 -070019//#define LOG_NDEBUG 0
Mathias Agopian076b1cc2009-04-10 14:24:30 -070020
21#include <stdint.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070022#include <errno.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070023
Dan Stozad3182402014-11-17 12:03:59 -080024// We would eliminate the non-conforming zero-length array, but we can't since
25// this is effectively included from the Linux kernel
26#pragma clang diagnostic push
27#pragma clang diagnostic ignored "-Wzero-length-array"
Francis Hart8f396012014-04-01 15:30:53 +030028#include <sync/sync.h>
Dan Stozad3182402014-11-17 12:03:59 -080029#pragma clang diagnostic pop
Francis Hart8f396012014-04-01 15:30:53 +030030
Mathias Agopian076b1cc2009-04-10 14:24:30 -070031#include <utils/Errors.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070032#include <utils/Log.h>
Mathias Agopiancf563192012-02-29 20:43:29 -080033#include <utils/Trace.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070034
Dan Stoza8deb4da2016-06-01 18:21:44 -070035#include <ui/Gralloc1On0Adapter.h>
Chia-I Wu9ba189d2016-09-22 17:13:08 +080036#include <ui/GrallocMapper.h>
Mathias Agopian3330b202009-10-05 17:07:12 -070037#include <ui/GraphicBufferMapper.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070038#include <ui/Rect.h>
39
Dan Stoza8deb4da2016-06-01 18:21:44 -070040#include <system/graphics.h>
Mathias Agopian8b765b72009-04-10 20:34:46 -070041
Mathias Agopian076b1cc2009-04-10 14:24:30 -070042namespace android {
43// ---------------------------------------------------------------------------
44
Mathias Agopian3330b202009-10-05 17:07:12 -070045ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
Mathias Agopian4243e662009-04-15 18:34:24 -070046
Mathias Agopian3330b202009-10-05 17:07:12 -070047GraphicBufferMapper::GraphicBufferMapper()
Chia-I Wu9ba189d2016-09-22 17:13:08 +080048 : mMapper(std::make_unique<const Gralloc2::Mapper>())
49{
50 if (!mMapper->valid()) {
51 mLoader = std::make_unique<Gralloc1::Loader>();
52 mDevice = mLoader->getDevice();
53 }
54}
Dan Stoza8deb4da2016-06-01 18:21:44 -070055
56
Mathias Agopian076b1cc2009-04-10 14:24:30 -070057
Mathias Agopian3330b202009-10-05 17:07:12 -070058status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -070059{
Mathias Agopiancf563192012-02-29 20:43:29 -080060 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -080061
Chia-I Wu9ba189d2016-09-22 17:13:08 +080062 gralloc1_error_t error;
63 if (mMapper->valid()) {
64 error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
65 } else {
66 error = mDevice->retain(handle);
67 }
68
Dan Stoza8deb4da2016-06-01 18:21:44 -070069 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
70 handle, error);
Mathias Agopian0a757812010-12-08 16:40:01 -080071
Dan Stoza8deb4da2016-06-01 18:21:44 -070072 return error;
73}
74
75status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
76{
77 ATRACE_CALL();
78
Chia-I Wu9ba189d2016-09-22 17:13:08 +080079 gralloc1_error_t error;
80 if (mMapper->valid()) {
81 error = static_cast<gralloc1_error_t>(
82 mMapper->retain(buffer->getNativeBuffer()->handle));
83 } else {
84 error = mDevice->retain(buffer);
85 }
86
Dan Stoza8deb4da2016-06-01 18:21:44 -070087 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
88 buffer->getNativeBuffer()->handle, error);
89
90 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070091}
92
Mathias Agopian3330b202009-10-05 17:07:12 -070093status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -070094{
Mathias Agopiancf563192012-02-29 20:43:29 -080095 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -080096
Chia-I Wu9ba189d2016-09-22 17:13:08 +080097 gralloc1_error_t error;
98 if (mMapper->valid()) {
99 mMapper->release(handle);
100 error = GRALLOC1_ERROR_NONE;
101 } else {
102 error = mDevice->release(handle);
103 }
104
Dan Stoza8deb4da2016-06-01 18:21:44 -0700105 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
106 handle, error);
Mathias Agopian0a757812010-12-08 16:40:01 -0800107
Dan Stoza8deb4da2016-06-01 18:21:44 -0700108 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700109}
110
Dan Stoza8deb4da2016-06-01 18:21:44 -0700111static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) {
112 gralloc1_rect_t outRect{};
113 outRect.left = rect.left;
114 outRect.top = rect.top;
115 outRect.width = rect.width();
116 outRect.height = rect.height();
117 return outRect;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700118}
119
Dan Stoza8deb4da2016-06-01 18:21:44 -0700120status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
121 const Rect& bounds, void** vaddr)
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700122{
Dan Stoza8deb4da2016-06-01 18:21:44 -0700123 return lockAsync(handle, usage, bounds, vaddr, -1);
124}
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700125
Dan Stoza8deb4da2016-06-01 18:21:44 -0700126status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage,
127 const Rect& bounds, android_ycbcr *ycbcr)
128{
129 return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1);
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700130}
131
Mathias Agopian3330b202009-10-05 17:07:12 -0700132status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700133{
Dan Stoza8deb4da2016-06-01 18:21:44 -0700134 int32_t fenceFd = -1;
135 status_t error = unlockAsync(handle, &fenceFd);
136 if (error == NO_ERROR) {
137 sync_wait(fenceFd, -1);
138 close(fenceFd);
139 }
140 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700141}
142
Francis Hart8f396012014-04-01 15:30:53 +0300143status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
Dan Stozad3182402014-11-17 12:03:59 -0800144 uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300145{
146 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300147
Dan Stoza8deb4da2016-06-01 18:21:44 -0700148 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800149 gralloc1_error_t error;
150 if (mMapper->valid()) {
151 const Gralloc2::Device::Rect& accessRect =
152 *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
153 error = static_cast<gralloc1_error_t>(mMapper->lock(
154 handle, usage, usage, accessRect, fenceFd, *vaddr));
155 } else {
156 sp<Fence> fence = new Fence(fenceFd);
157 error = mDevice->lock(handle,
158 static_cast<gralloc1_producer_usage_t>(usage),
159 static_cast<gralloc1_consumer_usage_t>(usage),
160 &accessRegion, vaddr, fence);
161 }
162
Dan Stoza8deb4da2016-06-01 18:21:44 -0700163 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,
164 error);
165
166 return error;
167}
168
169static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) {
170 if (plane.bits_per_component != 8) {
171 ALOGV("Invalid number of bits per component: %d",
172 plane.bits_per_component);
173 return false;
174 }
175 if (plane.bits_used != 8) {
176 ALOGV("Invalid number of bits used: %d", plane.bits_used);
177 return false;
Francis Hart8f396012014-04-01 15:30:53 +0300178 }
179
Dan Stoza8deb4da2016-06-01 18:21:44 -0700180 bool hasValidIncrement = plane.h_increment == 1 ||
181 (plane.component != FLEX_COMPONENT_Y && plane.h_increment == 2);
182 hasValidIncrement = hasValidIncrement && plane.v_increment > 0;
183 if (!hasValidIncrement) {
184 ALOGV("Invalid increment: h %d v %d", plane.h_increment,
185 plane.v_increment);
186 return false;
187 }
188
189 return true;
Francis Hart8f396012014-04-01 15:30:53 +0300190}
191
192status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
Dan Stozad3182402014-11-17 12:03:59 -0800193 uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300194{
195 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300196
Dan Stoza8deb4da2016-06-01 18:21:44 -0700197 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
Dan Stoza8deb4da2016-06-01 18:21:44 -0700198
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800199 if (!mMapper->valid()) {
200 if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
201 sp<Fence> fence = new Fence(fenceFd);
202 gralloc1_error_t error = mDevice->lockYCbCr(handle,
203 static_cast<gralloc1_producer_usage_t>(usage),
204 static_cast<gralloc1_consumer_usage_t>(usage),
205 &accessRegion, ycbcr, fence);
206 ALOGW_IF(error != GRALLOC1_ERROR_NONE,
207 "lockYCbCr(%p, ...) failed: %d", handle, error);
208 return error;
209 }
Francis Hart8f396012014-04-01 15:30:53 +0300210 }
211
Dan Stoza8deb4da2016-06-01 18:21:44 -0700212 uint32_t numPlanes = 0;
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800213 gralloc1_error_t error;
214 if (mMapper->valid()) {
215 error = static_cast<gralloc1_error_t>(
216 mMapper->getNumFlexPlanes(handle, numPlanes));
217 } else {
218 error = mDevice->getNumFlexPlanes(handle, &numPlanes);
219 }
220
Dan Stoza8deb4da2016-06-01 18:21:44 -0700221 if (error != GRALLOC1_ERROR_NONE) {
222 ALOGV("Failed to retrieve number of flex planes: %d", error);
223 return error;
224 }
225 if (numPlanes < 3) {
226 ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
227 return GRALLOC1_ERROR_UNSUPPORTED;
228 }
229
230 std::vector<android_flex_plane_t> planes(numPlanes);
231 android_flex_layout_t flexLayout{};
232 flexLayout.num_planes = numPlanes;
233 flexLayout.planes = planes.data();
234
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800235 if (mMapper->valid()) {
236 const Gralloc2::Device::Rect& accessRect =
237 *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
238 Gralloc2::FlexLayout& layout =
239 *reinterpret_cast<Gralloc2::FlexLayout*>(&flexLayout);
240 error = static_cast<gralloc1_error_t>(mMapper->lock(
241 handle, usage, usage, accessRect, fenceFd, layout));
242 } else {
243 sp<Fence> fence = new Fence(fenceFd);
244 error = mDevice->lockFlex(handle,
245 static_cast<gralloc1_producer_usage_t>(usage),
246 static_cast<gralloc1_consumer_usage_t>(usage),
247 &accessRegion, &flexLayout, fence);
248 }
249
Dan Stoza8deb4da2016-06-01 18:21:44 -0700250 if (error != GRALLOC1_ERROR_NONE) {
251 ALOGW("lockFlex(%p, ...) failed: %d", handle, error);
252 return error;
253 }
254 if (flexLayout.format != FLEX_FORMAT_YCbCr) {
255 ALOGV("Unable to convert flex-format buffer to YCbCr");
256 unlock(handle);
257 return GRALLOC1_ERROR_UNSUPPORTED;
258 }
259
260 // Find planes
261 auto yPlane = planes.cend();
262 auto cbPlane = planes.cend();
263 auto crPlane = planes.cend();
264 for (auto planeIter = planes.cbegin(); planeIter != planes.cend();
265 ++planeIter) {
266 if (planeIter->component == FLEX_COMPONENT_Y) {
267 yPlane = planeIter;
268 } else if (planeIter->component == FLEX_COMPONENT_Cb) {
269 cbPlane = planeIter;
270 } else if (planeIter->component == FLEX_COMPONENT_Cr) {
271 crPlane = planeIter;
272 }
273 }
274 if (yPlane == planes.cend()) {
275 ALOGV("Unable to find Y plane");
276 unlock(handle);
277 return GRALLOC1_ERROR_UNSUPPORTED;
278 }
279 if (cbPlane == planes.cend()) {
280 ALOGV("Unable to find Cb plane");
281 unlock(handle);
282 return GRALLOC1_ERROR_UNSUPPORTED;
283 }
284 if (crPlane == planes.cend()) {
285 ALOGV("Unable to find Cr plane");
286 unlock(handle);
287 return GRALLOC1_ERROR_UNSUPPORTED;
288 }
289
290 // Validate planes
291 if (!isValidYCbCrPlane(*yPlane)) {
292 ALOGV("Y plane is invalid");
293 unlock(handle);
294 return GRALLOC1_ERROR_UNSUPPORTED;
295 }
296 if (!isValidYCbCrPlane(*cbPlane)) {
297 ALOGV("Cb plane is invalid");
298 unlock(handle);
299 return GRALLOC1_ERROR_UNSUPPORTED;
300 }
301 if (!isValidYCbCrPlane(*crPlane)) {
302 ALOGV("Cr plane is invalid");
303 unlock(handle);
304 return GRALLOC1_ERROR_UNSUPPORTED;
305 }
306 if (cbPlane->v_increment != crPlane->v_increment) {
307 ALOGV("Cb and Cr planes have different step (%d vs. %d)",
308 cbPlane->v_increment, crPlane->v_increment);
309 unlock(handle);
310 return GRALLOC1_ERROR_UNSUPPORTED;
311 }
312 if (cbPlane->h_increment != crPlane->h_increment) {
313 ALOGV("Cb and Cr planes have different stride (%d vs. %d)",
314 cbPlane->h_increment, crPlane->h_increment);
315 unlock(handle);
316 return GRALLOC1_ERROR_UNSUPPORTED;
317 }
318
319 // Pack plane data into android_ycbcr struct
320 ycbcr->y = yPlane->top_left;
321 ycbcr->cb = cbPlane->top_left;
322 ycbcr->cr = crPlane->top_left;
323 ycbcr->ystride = static_cast<size_t>(yPlane->v_increment);
324 ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment);
325 ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment);
326
327 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300328}
329
330status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
331{
332 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300333
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800334 gralloc1_error_t error;
335 if (mMapper->valid()) {
336 *fenceFd = mMapper->unlock(handle);
337 error = GRALLOC1_ERROR_NONE;
338 } else {
339 sp<Fence> fence = Fence::NO_FENCE;
340 error = mDevice->unlock(handle, &fence);
341 if (error != GRALLOC1_ERROR_NONE) {
342 ALOGE("unlock(%p) failed: %d", handle, error);
343 return error;
344 }
Francis Hart8f396012014-04-01 15:30:53 +0300345
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800346 *fenceFd = fence->dup();
347 }
Dan Stoza8deb4da2016-06-01 18:21:44 -0700348 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300349}
350
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700351// ---------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700352}; // namespace android