blob: 481d43ce421fe159bd5536ac4f8756fb32b988e2 [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>
Mathias Agopian3330b202009-10-05 17:07:12 -070036#include <ui/GraphicBufferMapper.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070037#include <ui/Rect.h>
38
Dan Stoza8deb4da2016-06-01 18:21:44 -070039#include <system/graphics.h>
Mathias Agopian8b765b72009-04-10 20:34:46 -070040
Mathias Agopian076b1cc2009-04-10 14:24:30 -070041namespace android {
42// ---------------------------------------------------------------------------
43
Mathias Agopian3330b202009-10-05 17:07:12 -070044ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
Mathias Agopian4243e662009-04-15 18:34:24 -070045
Mathias Agopian3330b202009-10-05 17:07:12 -070046GraphicBufferMapper::GraphicBufferMapper()
Dan Stoza8deb4da2016-06-01 18:21:44 -070047 : mLoader(std::make_unique<Gralloc1::Loader>()),
48 mDevice(mLoader->getDevice()) {}
49
50
Mathias Agopian076b1cc2009-04-10 14:24:30 -070051
Mathias Agopian3330b202009-10-05 17:07:12 -070052status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -070053{
Mathias Agopiancf563192012-02-29 20:43:29 -080054 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -080055
Dan Stoza8deb4da2016-06-01 18:21:44 -070056 gralloc1_error_t error = mDevice->retain(handle);
57 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
58 handle, error);
Mathias Agopian0a757812010-12-08 16:40:01 -080059
Dan Stoza8deb4da2016-06-01 18:21:44 -070060 return error;
61}
62
63status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
64{
65 ATRACE_CALL();
66
67 gralloc1_error_t error = mDevice->retain(buffer);
68 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
69 buffer->getNativeBuffer()->handle, error);
70
71 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070072}
73
Mathias Agopian3330b202009-10-05 17:07:12 -070074status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -070075{
Mathias Agopiancf563192012-02-29 20:43:29 -080076 ATRACE_CALL();
Mathias Agopian0a757812010-12-08 16:40:01 -080077
Dan Stoza8deb4da2016-06-01 18:21:44 -070078 gralloc1_error_t error = mDevice->release(handle);
79 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
80 handle, error);
Mathias Agopian0a757812010-12-08 16:40:01 -080081
Dan Stoza8deb4da2016-06-01 18:21:44 -070082 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070083}
84
Dan Stoza8deb4da2016-06-01 18:21:44 -070085static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) {
86 gralloc1_rect_t outRect{};
87 outRect.left = rect.left;
88 outRect.top = rect.top;
89 outRect.width = rect.width();
90 outRect.height = rect.height();
91 return outRect;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070092}
93
Dan Stoza8deb4da2016-06-01 18:21:44 -070094status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
95 const Rect& bounds, void** vaddr)
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -070096{
Dan Stoza8deb4da2016-06-01 18:21:44 -070097 return lockAsync(handle, usage, bounds, vaddr, -1);
98}
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -070099
Dan Stoza8deb4da2016-06-01 18:21:44 -0700100status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage,
101 const Rect& bounds, android_ycbcr *ycbcr)
102{
103 return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1);
Eino-Ville Talvalac43946b2013-05-04 18:07:43 -0700104}
105
Mathias Agopian3330b202009-10-05 17:07:12 -0700106status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700107{
Dan Stoza8deb4da2016-06-01 18:21:44 -0700108 int32_t fenceFd = -1;
109 status_t error = unlockAsync(handle, &fenceFd);
110 if (error == NO_ERROR) {
111 sync_wait(fenceFd, -1);
112 close(fenceFd);
113 }
114 return error;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700115}
116
Francis Hart8f396012014-04-01 15:30:53 +0300117status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
Dan Stozad3182402014-11-17 12:03:59 -0800118 uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300119{
120 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300121
Dan Stoza8deb4da2016-06-01 18:21:44 -0700122 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
123 sp<Fence> fence = new Fence(fenceFd);
124 gralloc1_error_t error = mDevice->lock(handle,
125 static_cast<gralloc1_producer_usage_t>(usage),
126 static_cast<gralloc1_consumer_usage_t>(usage),
127 &accessRegion, vaddr, fence);
128 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,
129 error);
130
131 return error;
132}
133
134static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) {
135 if (plane.bits_per_component != 8) {
136 ALOGV("Invalid number of bits per component: %d",
137 plane.bits_per_component);
138 return false;
139 }
140 if (plane.bits_used != 8) {
141 ALOGV("Invalid number of bits used: %d", plane.bits_used);
142 return false;
Francis Hart8f396012014-04-01 15:30:53 +0300143 }
144
Dan Stoza8deb4da2016-06-01 18:21:44 -0700145 bool hasValidIncrement = plane.h_increment == 1 ||
146 (plane.component != FLEX_COMPONENT_Y && plane.h_increment == 2);
147 hasValidIncrement = hasValidIncrement && plane.v_increment > 0;
148 if (!hasValidIncrement) {
149 ALOGV("Invalid increment: h %d v %d", plane.h_increment,
150 plane.v_increment);
151 return false;
152 }
153
154 return true;
Francis Hart8f396012014-04-01 15:30:53 +0300155}
156
157status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
Dan Stozad3182402014-11-17 12:03:59 -0800158 uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
Francis Hart8f396012014-04-01 15:30:53 +0300159{
160 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300161
Dan Stoza8deb4da2016-06-01 18:21:44 -0700162 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
163 sp<Fence> fence = new Fence(fenceFd);
164
165 if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
166 gralloc1_error_t error = mDevice->lockYCbCr(handle,
167 static_cast<gralloc1_producer_usage_t>(usage),
168 static_cast<gralloc1_consumer_usage_t>(usage),
169 &accessRegion, ycbcr, fence);
170 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lockYCbCr(%p, ...) failed: %d",
171 handle, error);
172 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300173 }
174
Dan Stoza8deb4da2016-06-01 18:21:44 -0700175 uint32_t numPlanes = 0;
176 gralloc1_error_t error = mDevice->getNumFlexPlanes(handle, &numPlanes);
177 if (error != GRALLOC1_ERROR_NONE) {
178 ALOGV("Failed to retrieve number of flex planes: %d", error);
179 return error;
180 }
181 if (numPlanes < 3) {
182 ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
183 return GRALLOC1_ERROR_UNSUPPORTED;
184 }
185
186 std::vector<android_flex_plane_t> planes(numPlanes);
187 android_flex_layout_t flexLayout{};
188 flexLayout.num_planes = numPlanes;
189 flexLayout.planes = planes.data();
190
191 error = mDevice->lockFlex(handle,
192 static_cast<gralloc1_producer_usage_t>(usage),
193 static_cast<gralloc1_consumer_usage_t>(usage),
194 &accessRegion, &flexLayout, fence);
195 if (error != GRALLOC1_ERROR_NONE) {
196 ALOGW("lockFlex(%p, ...) failed: %d", handle, error);
197 return error;
198 }
199 if (flexLayout.format != FLEX_FORMAT_YCbCr) {
200 ALOGV("Unable to convert flex-format buffer to YCbCr");
201 unlock(handle);
202 return GRALLOC1_ERROR_UNSUPPORTED;
203 }
204
205 // Find planes
206 auto yPlane = planes.cend();
207 auto cbPlane = planes.cend();
208 auto crPlane = planes.cend();
209 for (auto planeIter = planes.cbegin(); planeIter != planes.cend();
210 ++planeIter) {
211 if (planeIter->component == FLEX_COMPONENT_Y) {
212 yPlane = planeIter;
213 } else if (planeIter->component == FLEX_COMPONENT_Cb) {
214 cbPlane = planeIter;
215 } else if (planeIter->component == FLEX_COMPONENT_Cr) {
216 crPlane = planeIter;
217 }
218 }
219 if (yPlane == planes.cend()) {
220 ALOGV("Unable to find Y plane");
221 unlock(handle);
222 return GRALLOC1_ERROR_UNSUPPORTED;
223 }
224 if (cbPlane == planes.cend()) {
225 ALOGV("Unable to find Cb plane");
226 unlock(handle);
227 return GRALLOC1_ERROR_UNSUPPORTED;
228 }
229 if (crPlane == planes.cend()) {
230 ALOGV("Unable to find Cr plane");
231 unlock(handle);
232 return GRALLOC1_ERROR_UNSUPPORTED;
233 }
234
235 // Validate planes
236 if (!isValidYCbCrPlane(*yPlane)) {
237 ALOGV("Y plane is invalid");
238 unlock(handle);
239 return GRALLOC1_ERROR_UNSUPPORTED;
240 }
241 if (!isValidYCbCrPlane(*cbPlane)) {
242 ALOGV("Cb plane is invalid");
243 unlock(handle);
244 return GRALLOC1_ERROR_UNSUPPORTED;
245 }
246 if (!isValidYCbCrPlane(*crPlane)) {
247 ALOGV("Cr plane is invalid");
248 unlock(handle);
249 return GRALLOC1_ERROR_UNSUPPORTED;
250 }
251 if (cbPlane->v_increment != crPlane->v_increment) {
252 ALOGV("Cb and Cr planes have different step (%d vs. %d)",
253 cbPlane->v_increment, crPlane->v_increment);
254 unlock(handle);
255 return GRALLOC1_ERROR_UNSUPPORTED;
256 }
257 if (cbPlane->h_increment != crPlane->h_increment) {
258 ALOGV("Cb and Cr planes have different stride (%d vs. %d)",
259 cbPlane->h_increment, crPlane->h_increment);
260 unlock(handle);
261 return GRALLOC1_ERROR_UNSUPPORTED;
262 }
263
264 // Pack plane data into android_ycbcr struct
265 ycbcr->y = yPlane->top_left;
266 ycbcr->cb = cbPlane->top_left;
267 ycbcr->cr = crPlane->top_left;
268 ycbcr->ystride = static_cast<size_t>(yPlane->v_increment);
269 ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment);
270 ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment);
271
272 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300273}
274
275status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
276{
277 ATRACE_CALL();
Francis Hart8f396012014-04-01 15:30:53 +0300278
Dan Stoza8deb4da2016-06-01 18:21:44 -0700279 sp<Fence> fence = Fence::NO_FENCE;
280 gralloc1_error_t error = mDevice->unlock(handle, &fence);
281 if (error != GRALLOC1_ERROR_NONE) {
282 ALOGE("unlock(%p) failed: %d", handle, error);
283 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300284 }
285
Dan Stoza8deb4da2016-06-01 18:21:44 -0700286 *fenceFd = fence->dup();
287 return error;
Francis Hart8f396012014-04-01 15:30:53 +0300288}
289
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700290// ---------------------------------------------------------------------------
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700291}; // namespace android