1 /*
2 * Copyright (C) 2020 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
17 #include "guest/hals/hwcomposer/common/gralloc_utils.h"
18
19 #include <drm_fourcc.h>
20 #include <log/log.h>
21
22 // TODO(b/146515640): remove these after upgrading to Gralloc 4.
23 #include "cros_gralloc/cros_gralloc_handle.h"
24 #include "cros_gralloc/cros_gralloc_helpers.h"
25 #include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
26 #include "guest/hals/hwcomposer/common/drm_utils.h"
27
28 using android::hardware::graphics::common::V1_2::PixelFormat;
29 using android::hardware::graphics::common::V1_0::BufferUsage;
30 using android::hardware::hidl_handle;
31
32 // TODO(b/146515640): remove these after upgrading to Gralloc 4.
33 using android::hardware::graphics::mapper::V3_0::YCbCrLayout;
34 using cuttlefish_gralloc0_buffer_handle_t = private_handle_t;
35 using ErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
36 using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
37
38 namespace cuttlefish {
39
Gralloc()40 Gralloc::Gralloc() {
41 gralloc3_ = IMapperV3::getService();
42 if (gralloc3_ != nullptr) {
43 ALOGE("%s using Gralloc3.", __FUNCTION__);
44 return;
45 }
46 ALOGE("%s Gralloc3 not available.", __FUNCTION__);
47
48 hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
49 reinterpret_cast<const hw_module_t**>(&gralloc0_));
50 if (gralloc0_ != nullptr) {
51 ALOGE("%s using Gralloc0.", __FUNCTION__);
52 return;
53 }
54 ALOGE("%s Gralloc0 not available.", __FUNCTION__);
55
56 ALOGE("%s No Grallocs available!", __FUNCTION__);
57 }
58
GetWidth(buffer_handle_t buffer)59 std::optional<uint32_t> Gralloc::GetWidth(buffer_handle_t buffer) {
60 if (gralloc3_ != nullptr) {
61 cros_gralloc_handle_t gralloc3_buffer = cros_gralloc_convert_handle(buffer);
62 if (gralloc3_buffer == nullptr) {
63 return std::nullopt;
64 }
65 return gralloc3_buffer->width;
66 }
67 if (gralloc0_ != nullptr) {
68 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
69 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
70
71 return gralloc0_buffer->x_res;
72 }
73 return std::nullopt;
74 }
75
GetHeight(buffer_handle_t buffer)76 std::optional<uint32_t> Gralloc::GetHeight(buffer_handle_t buffer) {
77 if (gralloc3_ != nullptr) {
78 cros_gralloc_handle_t gralloc3_buffer = cros_gralloc_convert_handle(buffer);
79 if (gralloc3_buffer == nullptr) {
80 return std::nullopt;
81 }
82 return gralloc3_buffer->height;
83 }
84 if (gralloc0_ != nullptr) {
85 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
86 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
87
88 return gralloc0_buffer->y_res;
89 }
90 return std::nullopt;
91 }
92
GetDrmFormat(buffer_handle_t buffer)93 std::optional<uint32_t> Gralloc::GetDrmFormat(buffer_handle_t buffer) {
94 if (gralloc3_ != nullptr) {
95 cros_gralloc_handle_t gralloc3_buffer = cros_gralloc_convert_handle(buffer);
96 if (gralloc3_buffer == nullptr) {
97 return std::nullopt;
98 }
99 return gralloc3_buffer->format;
100 }
101 if (gralloc0_ != nullptr) {
102 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
103 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
104
105 return GetDrmFormatFromHalFormat(gralloc0_buffer->format);
106 }
107 return std::nullopt;
108 }
109
GetMonoPlanarStrideBytes(buffer_handle_t buffer)110 std::optional<uint32_t> Gralloc::GetMonoPlanarStrideBytes(
111 buffer_handle_t buffer) {
112 if (gralloc3_ != nullptr) {
113 cros_gralloc_handle_t gralloc3_buffer = cros_gralloc_convert_handle(buffer);
114 if (gralloc3_buffer == nullptr) {
115 return std::nullopt;
116 }
117 return gralloc3_buffer->strides[0];
118 }
119 if (gralloc0_ != nullptr) {
120 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
121 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
122
123 int bytes_per_pixel = formatToBytesPerPixel(gralloc0_buffer->format);
124 return gralloc0_buffer->stride_in_pixels * bytes_per_pixel;
125 }
126 return std::nullopt;
127 }
128
Import(buffer_handle_t buffer)129 std::optional<GrallocBuffer> Gralloc::Import(buffer_handle_t buffer) {
130 if (gralloc3_ != nullptr) {
131 buffer_handle_t imported_buffer;
132
133 ErrorV3 error;
134 auto ret = gralloc3_->importBuffer(buffer,
135 [&](const auto& err, const auto& buf) {
136 error = err;
137 if (err == ErrorV3::NONE) {
138 imported_buffer =
139 static_cast<buffer_handle_t>(buf);
140 }
141 });
142 if (!ret.isOk() || error != ErrorV3::NONE) {
143 ALOGE("%s failed to import buffer", __FUNCTION__);
144 return std::nullopt;
145 }
146 return GrallocBuffer(this, imported_buffer);
147 }
148 if (gralloc0_ != nullptr) {
149 return GrallocBuffer(this, buffer);
150 }
151 return std::nullopt;
152 }
153
Release(buffer_handle_t buffer)154 void Gralloc::Release(buffer_handle_t buffer) {
155 if (gralloc3_ != nullptr) {
156 auto native_buffer = const_cast<native_handle_t*>(buffer);
157 auto ret = gralloc3_->freeBuffer(native_buffer);
158
159 if (!ret.isOk()) {
160 ALOGE("%s failed to release buffer", __FUNCTION__);
161 }
162 return;
163 }
164 if (gralloc0_) {
165 // no-opt
166 }
167 }
168
Lock(buffer_handle_t buffer)169 std::optional<void*> Gralloc::Lock(buffer_handle_t buffer) {
170 if (gralloc3_ != nullptr) {
171 void* raw_buffer = const_cast<void*>(reinterpret_cast<const void*>(buffer));
172
173 const auto buffer_usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
174
175 auto width_opt = GetWidth(buffer);
176 if (!width_opt) {
177 return std::nullopt;
178 }
179
180 auto height_opt = GetHeight(buffer);
181 if (!height_opt) {
182 return std::nullopt;
183 }
184
185 IMapperV3::Rect buffer_region;
186 buffer_region.left = 0;
187 buffer_region.top = 0;
188 buffer_region.width = *width_opt;
189 buffer_region.height = *height_opt;
190
191 // Empty fence, lock immedietly.
192 hidl_handle fence;
193
194 ErrorV3 error = ErrorV3::NONE;
195 void* data = nullptr;
196
197 auto ret = gralloc3_->lock(raw_buffer, buffer_usage, buffer_region, fence,
198 [&](const auto& lock_error,
199 const auto& lock_data,
200 int32_t /*bytes_per_pixel*/,
201 int32_t /*bytes_per_stride*/) {
202 error = lock_error;
203 if (lock_error == ErrorV3::NONE) {
204 data = lock_data;
205 }
206 });
207
208 if (!ret.isOk()) {
209 error = ErrorV3::NO_RESOURCES;
210 }
211
212 if (error != ErrorV3::NONE) {
213 ALOGE("%s failed to lock buffer", __FUNCTION__);
214 return std::nullopt;
215 }
216
217 return data;
218 }
219 if (gralloc0_ != nullptr) {
220 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
221 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
222
223 void* data = nullptr;
224 int ret = gralloc0_->lock(gralloc0_,
225 gralloc0_buffer,
226 GRALLOC_USAGE_SW_READ_OFTEN,
227 0,
228 0,
229 gralloc0_buffer->x_res,
230 gralloc0_buffer->y_res,
231 &data);
232
233 if (ret) {
234 ALOGE("%s failed to lock buffer", __FUNCTION__);
235 return std::nullopt;
236 }
237 return data;
238 }
239 return std::nullopt;
240 }
241
LockYCbCr(buffer_handle_t buffer)242 std::optional<android_ycbcr> Gralloc::LockYCbCr(buffer_handle_t buffer) {
243 auto format_opt = GetDrmFormat(buffer);
244 if (!format_opt) {
245 ALOGE("%s failed to check format of buffer", __FUNCTION__);
246 return std::nullopt;
247 }
248
249 if (*format_opt != DRM_FORMAT_NV12 &&
250 *format_opt != DRM_FORMAT_NV21 &&
251 *format_opt != DRM_FORMAT_YVU420) {
252 ALOGE("%s called on non-ycbcr buffer", __FUNCTION__);
253 return std::nullopt;
254 }
255
256 if (gralloc3_ != nullptr) {
257 void* raw_buffer = const_cast<void*>(reinterpret_cast<const void*>(buffer));
258
259 const auto buffer_usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
260
261 auto width_opt = GetWidth(buffer);
262 if (!width_opt) {
263 return std::nullopt;
264 }
265
266 auto height_opt = GetHeight(buffer);
267 if (!height_opt) {
268 return std::nullopt;
269 }
270
271 IMapperV3::Rect buffer_region;
272 buffer_region.left = 0;
273 buffer_region.top = 0;
274 buffer_region.width = *width_opt;
275 buffer_region.height = *height_opt;
276
277 // Empty fence, lock immedietly.
278 hidl_handle fence;
279
280 ErrorV3 error = ErrorV3::NONE;
281 YCbCrLayout ycbcr = {};
282
283 auto ret = gralloc3_->lockYCbCr(
284 raw_buffer, buffer_usage, buffer_region, fence,
285 [&](const auto& lock_error,
286 const auto& lock_ycbcr) {
287 error = lock_error;
288 if (lock_error == ErrorV3::NONE) {
289 ycbcr = lock_ycbcr;
290 }
291 });
292
293 if (!ret.isOk()) {
294 error = ErrorV3::NO_RESOURCES;
295 }
296
297 if (error != ErrorV3::NONE) {
298 ALOGE("%s failed to lock buffer", __FUNCTION__);
299 return std::nullopt;
300 }
301
302 android_ycbcr buffer_ycbcr;
303 buffer_ycbcr.y = ycbcr.y;
304 buffer_ycbcr.cb = ycbcr.cb;
305 buffer_ycbcr.cr = ycbcr.cr;
306 buffer_ycbcr.ystride = ycbcr.yStride;
307 buffer_ycbcr.cstride = ycbcr.cStride;
308 buffer_ycbcr.chroma_step = ycbcr.chromaStep;
309
310 return buffer_ycbcr;
311 }
312 if (gralloc0_ != nullptr) {
313 auto lock_opt = Lock(buffer);
314 if (!lock_opt) {
315 ALOGE("%s failed to lock buffer", __FUNCTION__);
316 return std::nullopt;
317 }
318 void* data = *lock_opt;
319
320 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
321 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
322
323 android_ycbcr buffer_ycbcr;
324 formatToYcbcr(gralloc0_buffer->format,
325 gralloc0_buffer->x_res,
326 gralloc0_buffer->y_res,
327 data,
328 &buffer_ycbcr);
329 return buffer_ycbcr;
330 }
331 return std::nullopt;
332 }
333
Unlock(buffer_handle_t buffer)334 void Gralloc::Unlock(buffer_handle_t buffer) {
335 if (gralloc3_ != nullptr) {
336 auto native_handle = const_cast<native_handle_t*>(buffer);
337
338 ErrorV3 error = ErrorV3::NONE;
339 auto ret = gralloc3_->unlock(native_handle,
340 [&](const auto& unlock_error, const auto&) {
341 error = unlock_error;
342 });
343 if (!ret.isOk()) {
344 error = ErrorV3::NO_RESOURCES;
345 }
346 if (error != ErrorV3::NONE) {
347 ALOGE("%s failed to unlock buffer", __FUNCTION__);
348 }
349 return;
350 }
351 if (gralloc0_ != nullptr) {
352 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
353 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
354
355 gralloc0_->unlock(gralloc0_, gralloc0_buffer);
356 return;
357 }
358 }
359
360
GrallocBuffer(Gralloc * gralloc,buffer_handle_t buffer)361 GrallocBuffer::GrallocBuffer(Gralloc* gralloc, buffer_handle_t buffer) :
362 gralloc_(gralloc), buffer_(buffer) {}
363
~GrallocBuffer()364 GrallocBuffer::~GrallocBuffer() { Release(); }
365
GrallocBuffer(GrallocBuffer && rhs)366 GrallocBuffer::GrallocBuffer(GrallocBuffer&& rhs) {
367 *this = std::move(rhs);
368 }
369
operator =(GrallocBuffer && rhs)370 GrallocBuffer& GrallocBuffer::operator=(GrallocBuffer&& rhs) {
371 gralloc_ = rhs.gralloc_;
372 buffer_ = rhs.buffer_;
373 rhs.gralloc_ = nullptr;
374 rhs.buffer_ = nullptr;
375 return *this;
376 }
377
Release()378 void GrallocBuffer::Release() {
379 if (gralloc_ && buffer_) {
380 gralloc_->Release(buffer_);
381 gralloc_ = nullptr;
382 buffer_ = nullptr;
383 }
384 }
385
Lock()386 std::optional<void*> GrallocBuffer::Lock() {
387 if (gralloc_ && buffer_) {
388 return gralloc_->Lock(buffer_);
389 }
390 return std::nullopt;
391 }
392
LockYCbCr()393 std::optional<android_ycbcr> GrallocBuffer::LockYCbCr() {
394 if (gralloc_ && buffer_) {
395 return gralloc_->LockYCbCr(buffer_);
396 }
397 return std::nullopt;
398 }
399
Unlock()400 void GrallocBuffer::Unlock() {
401 if (gralloc_ && buffer_) {
402 gralloc_->Unlock(buffer_);
403 }
404 }
405
GetWidth()406 std::optional<uint32_t> GrallocBuffer::GetWidth() {
407 if (gralloc_ && buffer_) {
408 return gralloc_->GetWidth(buffer_);
409 }
410 return std::nullopt;
411 }
412
GetHeight()413 std::optional<uint32_t> GrallocBuffer::GetHeight() {
414 if (gralloc_ && buffer_) {
415 return gralloc_->GetHeight(buffer_);
416 }
417 return std::nullopt;
418 }
419
GetDrmFormat()420 std::optional<uint32_t> GrallocBuffer::GetDrmFormat() {
421 if (gralloc_ && buffer_) {
422 return gralloc_->GetDrmFormat(buffer_);
423 }
424 return std::nullopt;
425 }
426
GetMonoPlanarStrideBytes()427 std::optional<uint32_t> GrallocBuffer::GetMonoPlanarStrideBytes() {
428 if (gralloc_ && buffer_) {
429 return gralloc_->GetMonoPlanarStrideBytes(buffer_);
430 }
431 return std::nullopt;
432 }
433
434 } // namespace cvd