blob: 87519bf3b87e6ab03bbd2c2b7f6f71097c7414af [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
Mathias Agopianfe2f54f2017-02-15 19:48:58 -080021#include <ui/GraphicBufferMapper.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070022
Chia-I Wu5bac7f32017-04-06 12:34:32 -070023#include <grallocusage/GrallocUsageConversion.h>
24
Dan Stozad3182402014-11-17 12:03:59 -080025// We would eliminate the non-conforming zero-length array, but we can't since
26// this is effectively included from the Linux kernel
27#pragma clang diagnostic push
28#pragma clang diagnostic ignored "-Wzero-length-array"
Francis Hart8f396012014-04-01 15:30:53 +030029#include <sync/sync.h>
Dan Stozad3182402014-11-17 12:03:59 -080030#pragma clang diagnostic pop
Francis Hart8f396012014-04-01 15:30:53 +030031
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
Chia-I Wu5bac7f32017-04-06 12:34:32 -070035#include <ui/Gralloc2.h>
Mathias Agopiana9347642017-02-13 16:42:28 -080036#include <ui/GraphicBuffer.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070037
Dan Stoza8deb4da2016-06-01 18:21:44 -070038#include <system/graphics.h>
Mathias Agopian8b765b72009-04-10 20:34:46 -070039
Mathias Agopian076b1cc2009-04-10 14:24:30 -070040namespace android {
41// ---------------------------------------------------------------------------
42
Mathias Agopian3330b202009-10-05 17:07:12 -070043ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
Mathias Agopian4243e662009-04-15 18:34:24 -070044
Mathias Agopian3330b202009-10-05 17:07:12 -070045GraphicBufferMapper::GraphicBufferMapper()
Chia-I Wu9ba189d2016-09-22 17:13:08 +080046 : mMapper(std::make_unique<const Gralloc2::Mapper>())
47{
48 if (!mMapper->valid()) {
49 mLoader = std::make_unique<Gralloc1::Loader>();
50 mDevice = mLoader->getDevice();
51 }
52}
Dan Stoza8deb4da2016-06-01 18:21:44 -070053
Chia-I Wu5bac7f32017-04-06 12:34:32 -070054status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
55 buffer_handle_t* outHandle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -070056{
Mathias Agopiancf563192012-02-29 20:43:29 -080057 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -080058
Chia-I Wu5bac7f32017-04-06 12:34:32 -070059 Gralloc2::Error error;
60 if (mMapper->valid()) {
61 error = mMapper->importBuffer(hardware::hidl_handle(rawHandle),
62 outHandle);
63 } else {
64 error = Gralloc2::Error::UNSUPPORTED;
65 }
66
67 ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
68 rawHandle, error);
69
70 return static_cast<status_t>(error);
71}
72
73status_t GraphicBufferMapper::importBuffer(const GraphicBuffer* buffer)
74{
75 ATRACE_CALL();
76
77 ANativeWindowBuffer* nativeBuffer = buffer->getNativeBuffer();
78 buffer_handle_t rawHandle = nativeBuffer->handle;
79
Chia-I Wu9ba189d2016-09-22 17:13:08 +080080 gralloc1_error_t error;
81 if (mMapper->valid()) {
Chia-I Wu5bac7f32017-04-06 12:34:32 -070082 buffer_handle_t importedHandle;
83 error = static_cast<gralloc1_error_t>(mMapper->importBuffer(
84 hardware::hidl_handle(rawHandle), &importedHandle));
85 if (error == GRALLOC1_ERROR_NONE) {
86 nativeBuffer->handle = importedHandle;
87 }
Chia-I Wu9ba189d2016-09-22 17:13:08 +080088 } else {
Chia-I Wu5bac7f32017-04-06 12:34:32 -070089 native_handle_t* clonedHandle = native_handle_clone(rawHandle);
90 if (clonedHandle) {
91 nativeBuffer->handle = clonedHandle;
92 error = mDevice->retain(buffer);
93 if (error != GRALLOC1_ERROR_NONE) {
94 nativeBuffer->handle = rawHandle;
95 native_handle_close(clonedHandle);
96 native_handle_delete(clonedHandle);
97 }
98 } else {
99 error = GRALLOC1_ERROR_NO_RESOURCES;
Chia-I Wu7bd8adb2017-02-10 14:53:12 -0800100 }
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800101 }
102
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700103 // the raw handle is owned by GraphicBuffer and is now replaced
104 if (error == GRALLOC1_ERROR_NONE) {
105 native_handle_close(rawHandle);
106 native_handle_delete(const_cast<native_handle_t*>(rawHandle));
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800107 }
108
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700109 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "importBuffer(%p) failed: %d",
110 rawHandle, error);
Dan Stoza8deb4da2016-06-01 18:21:44 -0700111
112 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700113}
114
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700115status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700116{
Mathias Agopiancf563192012-02-29 20:43:29 -0800117 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -0800118
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800119 gralloc1_error_t error;
120 if (mMapper->valid()) {
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700121 mMapper->freeBuffer(handle);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800122 error = GRALLOC1_ERROR_NONE;
123 } else {
124 error = mDevice->release(handle);
Chia-I Wua3c428a2017-04-11 10:03:38 -0700125 if (!mDevice->hasCapability(GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE)) {
126 native_handle_close(handle);
127 native_handle_delete(const_cast<native_handle_t*>(handle));
128 }
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800129 }
130
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700131 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "freeBuffer(%p): failed %d",
Dan Stoza8deb4da2016-06-01 18:21:44 -0700132 handle, error);
Mathias Agopian0a757812010-12-08 16:40:01 -0800133
Dan Stoza8deb4da2016-06-01 18:21:44 -0700134 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700135}
136
Dan Stoza8deb4da2016-06-01 18:21:44 -0700137static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) {
138 gralloc1_rect_t outRect{};
139 outRect.left = rect.left;
140 outRect.top = rect.top;
141 outRect.width = rect.width();
142 outRect.height = rect.height();
143 return outRect;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700144}
145
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700146static inline Gralloc2::IMapper::Rect asGralloc2Rect(const Rect& rect) {
147 Gralloc2::IMapper::Rect outRect{};
148 outRect.left = rect.left;
149 outRect.top = rect.top;
150 outRect.width = rect.width();
151 outRect.height = rect.height();
152 return outRect;
Craig Donner58a1ef22017-02-02 12:40:05 -0800153}
154
Dan Stoza8deb4da2016-06-01 18:21:44 -0700155status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
156 const Rect& bounds, void** vaddr)
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700157{
Dan Stoza8deb4da2016-06-01 18:21:44 -0700158 return lockAsync(handle, usage, bounds, vaddr, -1);
159}
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700160
Dan Stoza8deb4da2016-06-01 18:21:44 -0700161status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage,
162 const Rect& bounds, android_ycbcr *ycbcr)
163{
164 return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1);
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700165}
166
Mathias Agopian3330b202009-10-05 17:07:12 -0700167status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700168{
Dan Stoza8deb4da2016-06-01 18:21:44 -0700169 int32_t fenceFd = -1;
170 status_t error = unlockAsync(handle, &fenceFd);
171 if (error == NO_ERROR) {
172 sync_wait(fenceFd, -1);
173 close(fenceFd);
174 }
175 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700176}
177
Francis Hart8f396012014-04-01 15:30:53 +0300178status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
Dan Stozad3182402014-11-17 12:03:59 -0800179 uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300180{
Craig Donnere96a3252017-02-02 12:13:34 -0800181 return lockAsync(handle, usage, usage, bounds, vaddr, fenceFd);
182}
183
184status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
185 uint64_t producerUsage, uint64_t consumerUsage, const Rect& bounds,
186 void** vaddr, int fenceFd)
187{
Francis Hart8f396012014-04-01 15:30:53 +0300188 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300189
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800190 gralloc1_error_t error;
191 if (mMapper->valid()) {
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700192 const uint64_t usage =
193 static_cast<uint64_t>(android_convertGralloc1To0Usage(
194 producerUsage, consumerUsage));
195 error = static_cast<gralloc1_error_t>(mMapper->lock(handle,
196 usage, asGralloc2Rect(bounds), fenceFd, vaddr));
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800197 } else {
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700198 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800199 sp<Fence> fence = new Fence(fenceFd);
200 error = mDevice->lock(handle,
Craig Donnere96a3252017-02-02 12:13:34 -0800201 static_cast<gralloc1_producer_usage_t>(producerUsage),
202 static_cast<gralloc1_consumer_usage_t>(consumerUsage),
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800203 &accessRegion, vaddr, fence);
204 }
205
Dan Stoza8deb4da2016-06-01 18:21:44 -0700206 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,
207 error);
208
209 return error;
210}
211
212static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) {
213 if (plane.bits_per_component != 8) {
214 ALOGV("Invalid number of bits per component: %d",
215 plane.bits_per_component);
216 return false;
217 }
218 if (plane.bits_used != 8) {
219 ALOGV("Invalid number of bits used: %d", plane.bits_used);
220 return false;
Francis Hart8f396012014-04-01 15:30:53 +0300221 }
222
Dan Stoza8deb4da2016-06-01 18:21:44 -0700223 bool hasValidIncrement = plane.h_increment == 1 ||
224 (plane.component != FLEX_COMPONENT_Y && plane.h_increment == 2);
225 hasValidIncrement = hasValidIncrement && plane.v_increment > 0;
226 if (!hasValidIncrement) {
227 ALOGV("Invalid increment: h %d v %d", plane.h_increment,
228 plane.v_increment);
229 return false;
230 }
231
232 return true;
Francis Hart8f396012014-04-01 15:30:53 +0300233}
234
235status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
Dan Stozad3182402014-11-17 12:03:59 -0800236 uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300237{
238 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300239
Dan Stoza8deb4da2016-06-01 18:21:44 -0700240 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
Dan Stoza8deb4da2016-06-01 18:21:44 -0700241
Chia-I Wu31669472016-12-07 14:55:24 +0800242 std::vector<android_flex_plane_t> planes;
243 android_flex_layout_t flexLayout{};
244 gralloc1_error_t error;
245
246 if (mMapper->valid()) {
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700247 Gralloc2::YCbCrLayout layout;
248 error = static_cast<gralloc1_error_t>(mMapper->lock(handle, usage,
249 asGralloc2Rect(bounds), fenceFd, &layout));
Chia-I Wu31669472016-12-07 14:55:24 +0800250 if (error == GRALLOC1_ERROR_NONE) {
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700251 ycbcr->y = layout.y;
252 ycbcr->cb = layout.cb;
253 ycbcr->cr = layout.cr;
254 ycbcr->ystride = static_cast<size_t>(layout.yStride);
255 ycbcr->cstride = static_cast<size_t>(layout.cStride);
256 ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
Chia-I Wu31669472016-12-07 14:55:24 +0800257 }
Chia-I Wu5bac7f32017-04-06 12:34:32 -0700258
259 return error;
Chia-I Wu31669472016-12-07 14:55:24 +0800260 } else {
261 sp<Fence> fence = new Fence(fenceFd);
262
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800263 if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
Chia-I Wu31669472016-12-07 14:55:24 +0800264 error = mDevice->lockYCbCr(handle,
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800265 static_cast<gralloc1_producer_usage_t>(usage),
266 static_cast<gralloc1_consumer_usage_t>(usage),
267 &accessRegion, ycbcr, fence);
268 ALOGW_IF(error != GRALLOC1_ERROR_NONE,
269 "lockYCbCr(%p, ...) failed: %d", handle, error);
270 return error;
271 }
Francis Hart8f396012014-04-01 15:30:53 +0300272
Chia-I Wu31669472016-12-07 14:55:24 +0800273 uint32_t numPlanes = 0;
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800274 error = mDevice->getNumFlexPlanes(handle, &numPlanes);
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800275
Chia-I Wu31669472016-12-07 14:55:24 +0800276 if (error != GRALLOC1_ERROR_NONE) {
277 ALOGV("Failed to retrieve number of flex planes: %d", error);
278 return error;
279 }
280 if (numPlanes < 3) {
281 ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
282 return GRALLOC1_ERROR_UNSUPPORTED;
283 }
Dan Stoza8deb4da2016-06-01 18:21:44 -0700284
Chia-I Wu31669472016-12-07 14:55:24 +0800285 planes.resize(numPlanes);
286 flexLayout.num_planes = numPlanes;
287 flexLayout.planes = planes.data();
Dan Stoza8deb4da2016-06-01 18:21:44 -0700288
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800289 error = mDevice->lockFlex(handle,
290 static_cast<gralloc1_producer_usage_t>(usage),
291 static_cast<gralloc1_consumer_usage_t>(usage),
292 &accessRegion, &flexLayout, fence);
293 }
294
Dan Stoza8deb4da2016-06-01 18:21:44 -0700295 if (error != GRALLOC1_ERROR_NONE) {
296 ALOGW("lockFlex(%p, ...) failed: %d", handle, error);
297 return error;
298 }
299 if (flexLayout.format != FLEX_FORMAT_YCbCr) {
300 ALOGV("Unable to convert flex-format buffer to YCbCr");
301 unlock(handle);
302 return GRALLOC1_ERROR_UNSUPPORTED;
303 }
304
305 // Find planes
306 auto yPlane = planes.cend();
307 auto cbPlane = planes.cend();
308 auto crPlane = planes.cend();
309 for (auto planeIter = planes.cbegin(); planeIter != planes.cend();
310 ++planeIter) {
311 if (planeIter->component == FLEX_COMPONENT_Y) {
312 yPlane = planeIter;
313 } else if (planeIter->component == FLEX_COMPONENT_Cb) {
314 cbPlane = planeIter;
315 } else if (planeIter->component == FLEX_COMPONENT_Cr) {
316 crPlane = planeIter;
317 }
318 }
319 if (yPlane == planes.cend()) {
320 ALOGV("Unable to find Y plane");
321 unlock(handle);
322 return GRALLOC1_ERROR_UNSUPPORTED;
323 }
324 if (cbPlane == planes.cend()) {
325 ALOGV("Unable to find Cb plane");
326 unlock(handle);
327 return GRALLOC1_ERROR_UNSUPPORTED;
328 }
329 if (crPlane == planes.cend()) {
330 ALOGV("Unable to find Cr plane");
331 unlock(handle);
332 return GRALLOC1_ERROR_UNSUPPORTED;
333 }
334
335 // Validate planes
336 if (!isValidYCbCrPlane(*yPlane)) {
337 ALOGV("Y plane is invalid");
338 unlock(handle);
339 return GRALLOC1_ERROR_UNSUPPORTED;
340 }
341 if (!isValidYCbCrPlane(*cbPlane)) {
342 ALOGV("Cb plane is invalid");
343 unlock(handle);
344 return GRALLOC1_ERROR_UNSUPPORTED;
345 }
346 if (!isValidYCbCrPlane(*crPlane)) {
347 ALOGV("Cr plane is invalid");
348 unlock(handle);
349 return GRALLOC1_ERROR_UNSUPPORTED;
350 }
351 if (cbPlane->v_increment != crPlane->v_increment) {
352 ALOGV("Cb and Cr planes have different step (%d vs. %d)",
353 cbPlane->v_increment, crPlane->v_increment);
354 unlock(handle);
355 return GRALLOC1_ERROR_UNSUPPORTED;
356 }
357 if (cbPlane->h_increment != crPlane->h_increment) {
358 ALOGV("Cb and Cr planes have different stride (%d vs. %d)",
359 cbPlane->h_increment, crPlane->h_increment);
360 unlock(handle);
361 return GRALLOC1_ERROR_UNSUPPORTED;
362 }
363
364 // Pack plane data into android_ycbcr struct
365 ycbcr->y = yPlane->top_left;
366 ycbcr->cb = cbPlane->top_left;
367 ycbcr->cr = crPlane->top_left;
368 ycbcr->ystride = static_cast<size_t>(yPlane->v_increment);
369 ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment);
370 ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment);
371
372 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300373}
374
375status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
376{
377 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300378
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800379 gralloc1_error_t error;
380 if (mMapper->valid()) {
381 *fenceFd = mMapper->unlock(handle);
382 error = GRALLOC1_ERROR_NONE;
383 } else {
384 sp<Fence> fence = Fence::NO_FENCE;
385 error = mDevice->unlock(handle, &fence);
386 if (error != GRALLOC1_ERROR_NONE) {
387 ALOGE("unlock(%p) failed: %d", handle, error);
388 return error;
389 }
Francis Hart8f396012014-04-01 15:30:53 +0300390
Chia-I Wu9ba189d2016-09-22 17:13:08 +0800391 *fenceFd = fence->dup();
392 }
Dan Stoza8deb4da2016-06-01 18:21:44 -0700393 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300394}
395
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700396// ---------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700397}; // namespace android