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 <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
20 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
21 #include <drm_fourcc.h>
22 #include <gralloctypes/Gralloc4.h>
23 #include <hidl/ServiceManagement.h>
24 #include <log/log.h>
25
26 // TODO(b/146515640): remove this.
27 #include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
28 #include "guest/hals/hwcomposer/common/drm_utils.h"
29
30 using aidl::android::hardware::graphics::common::PlaneLayout;
31 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
32 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
33 using android::hardware::graphics::common::V1_2::BufferUsage;
34 using android::hardware::graphics::mapper::V4_0::Error;
35 using android::hardware::graphics::mapper::V4_0::IMapper;
36 using android::hardware::hidl_handle;
37 using android::hardware::hidl_vec;
38 using MetadataType =
39 android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
40
41 // TODO(b/146515640): remove this.
42 using cuttlefish_gralloc0_buffer_handle_t = private_handle_t;
43
44 namespace cvd {
45
Gralloc()46 Gralloc::Gralloc() {
47 android::hardware::preloadPassthroughService<IMapper>();
48
49 gralloc4_ = IMapper::getService();
50 if (gralloc4_ != nullptr) {
51 ALOGE("%s using Gralloc4.", __FUNCTION__);
52 return;
53 }
54 ALOGE("%s Gralloc4 not available.", __FUNCTION__);
55
56
57 hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
58 reinterpret_cast<const hw_module_t**>(&gralloc0_));
59 if (gralloc0_ != nullptr) {
60 ALOGE("%s using Gralloc0.", __FUNCTION__);
61 return;
62 }
63 ALOGE("%s Gralloc0 not available.", __FUNCTION__);
64
65 ALOGE("%s No Grallocs available!", __FUNCTION__);
66 }
67
GetMetadata(buffer_handle_t buffer,MetadataType type,hidl_vec<uint8_t> * metadata)68 Error Gralloc::GetMetadata(buffer_handle_t buffer, MetadataType type,
69 hidl_vec<uint8_t>* metadata) {
70 if (gralloc4_ == nullptr) {
71 ALOGE("%s Gralloc4 not available.", __FUNCTION__);
72 return Error::NO_RESOURCES;
73 }
74
75 if (metadata == nullptr) {
76 return Error::BAD_VALUE;
77 }
78
79 Error error = Error::NONE;
80
81 auto native_handle = const_cast<native_handle_t*>(buffer);
82
83 auto ret = gralloc4_->get(native_handle, type,
84 [&](const auto& get_error, const auto& get_metadata) {
85 error = get_error;
86 *metadata = get_metadata;
87 });
88
89 if (!ret.isOk()) {
90 error = Error::NO_RESOURCES;
91 }
92
93 if (error != Error::NONE) {
94 ALOGE("%s failed to get metadata %s", __FUNCTION__, type.name.c_str());
95 }
96 return error;
97 }
98
GetWidth(buffer_handle_t buffer)99 std::optional<uint32_t> Gralloc::GetWidth(buffer_handle_t buffer) {
100 if (gralloc4_ != nullptr) {
101 hidl_vec<uint8_t> encoded_width;
102
103 Error error = GetMetadata(buffer, android::gralloc4::MetadataType_Width,
104 &encoded_width);
105 if (error != Error::NONE) {
106 return std::nullopt;
107 }
108
109 uint64_t width = 0;
110 android::gralloc4::decodeWidth(encoded_width, &width);
111 return static_cast<uint32_t>(width);
112 }
113 if (gralloc0_ != nullptr) {
114 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
115 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
116
117 return gralloc0_buffer->x_res;
118 }
119 return std::nullopt;
120 }
121
GetHeight(buffer_handle_t buffer)122 std::optional<uint32_t> Gralloc::GetHeight(buffer_handle_t buffer) {
123 if (gralloc4_ != nullptr) {
124 hidl_vec<uint8_t> encoded_height;
125
126 Error error = GetMetadata(buffer, android::gralloc4::MetadataType_Height,
127 &encoded_height);
128 if (error != Error::NONE) {
129 return std::nullopt;
130 }
131
132 uint64_t height = 0;
133 android::gralloc4::decodeHeight(encoded_height, &height);
134 return static_cast<uint32_t>(height);
135 }
136 if (gralloc0_ != nullptr) {
137 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
138 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
139
140 return gralloc0_buffer->y_res;
141 }
142 return std::nullopt;
143 }
144
GetDrmFormat(buffer_handle_t buffer)145 std::optional<uint32_t> Gralloc::GetDrmFormat(buffer_handle_t buffer) {
146 if (gralloc4_ != nullptr) {
147 hidl_vec<uint8_t> encoded_format;
148
149 Error error = GetMetadata(buffer,
150 android::gralloc4::MetadataType_PixelFormatFourCC,
151 &encoded_format);
152 if (error != Error::NONE) {
153 return std::nullopt;
154 }
155
156 uint32_t format = 0;
157 android::gralloc4::decodePixelFormatFourCC(encoded_format, &format);
158 return static_cast<uint32_t>(format);
159 }
160 if (gralloc0_ != nullptr) {
161 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
162 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
163
164 return GetDrmFormatFromHalFormat(gralloc0_buffer->format);
165 }
166 return std::nullopt;
167 }
168
GetPlaneLayouts(buffer_handle_t buffer)169 std::optional<std::vector<PlaneLayout>> Gralloc::GetPlaneLayouts(
170 buffer_handle_t buffer) {
171 if (gralloc4_ != nullptr) {
172 hidl_vec<uint8_t> encoded_layouts;
173
174 Error error = GetMetadata(buffer,
175 android::gralloc4::MetadataType_PlaneLayouts,
176 &encoded_layouts);
177 if (error != Error::NONE) {
178 return std::nullopt;
179 }
180
181 std::vector<PlaneLayout> plane_layouts;
182 android::gralloc4::decodePlaneLayouts(encoded_layouts, &plane_layouts);
183 return plane_layouts;
184 }
185 return std::nullopt;
186 }
187
GetMonoPlanarStrideBytes(buffer_handle_t buffer)188 std::optional<uint32_t> Gralloc::GetMonoPlanarStrideBytes(
189 buffer_handle_t buffer) {
190 if (gralloc4_ != nullptr) {
191 auto plane_layouts_opt = GetPlaneLayouts(buffer);
192 if (!plane_layouts_opt) {
193 return std::nullopt;
194 }
195
196 std::vector<PlaneLayout>& plane_layouts = *plane_layouts_opt;
197 if (plane_layouts.size() != 1) {
198 return std::nullopt;
199 }
200
201 return static_cast<uint32_t>(plane_layouts[0].strideInBytes);
202 }
203 if (gralloc0_ != nullptr) {
204 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
205 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
206
207 int bytes_per_pixel = formatToBytesPerPixel(gralloc0_buffer->format);
208 return gralloc0_buffer->stride_in_pixels * bytes_per_pixel;
209 }
210 return std::nullopt;
211 }
212
Import(buffer_handle_t buffer)213 std::optional<GrallocBuffer> Gralloc::Import(buffer_handle_t buffer) {
214 if (gralloc4_ != nullptr) {
215 buffer_handle_t imported_buffer;
216
217 Error error;
218 auto ret = gralloc4_->importBuffer(buffer,
219 [&](const auto& err, const auto& buf) {
220 error = err;
221 if (err == Error::NONE) {
222 imported_buffer =
223 static_cast<buffer_handle_t>(buf);
224 }
225 });
226
227 if (!ret.isOk() || error != Error::NONE) {
228 ALOGE("%s failed to import buffer", __FUNCTION__);
229 return std::nullopt;
230 }
231 return GrallocBuffer(this, imported_buffer);
232 }
233 if (gralloc0_ != nullptr) {
234 return GrallocBuffer(this, buffer);
235 }
236 return std::nullopt;
237 }
238
Release(buffer_handle_t buffer)239 void Gralloc::Release(buffer_handle_t buffer) {
240 if (gralloc4_ != nullptr) {
241 auto native_buffer = const_cast<native_handle_t*>(buffer);
242 auto ret = gralloc4_->freeBuffer(native_buffer);
243
244 if (!ret.isOk()) {
245 ALOGE("%s failed to release buffer", __FUNCTION__);
246 }
247 return;
248 }
249 if (gralloc0_) {
250 // no-opt
251 }
252 }
253
Lock(buffer_handle_t buffer)254 std::optional<void*> Gralloc::Lock(buffer_handle_t buffer) {
255 if (gralloc4_ != nullptr) {
256 auto native_buffer = const_cast<native_handle_t*>(buffer);
257
258 const auto buffer_usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
259
260 auto width_opt = GetWidth(buffer);
261 if (!width_opt) {
262 return std::nullopt;
263 }
264
265 auto height_opt = GetHeight(buffer);
266 if (!height_opt) {
267 return std::nullopt;
268 }
269
270 IMapper::Rect buffer_region;
271 buffer_region.left = 0;
272 buffer_region.top = 0;
273 buffer_region.width = *width_opt;
274 buffer_region.height = *height_opt;
275
276 // Empty fence, lock immedietly.
277 hidl_handle fence;
278
279 Error error = Error::NONE;
280 void* data = nullptr;
281
282 auto ret = gralloc4_->lock(native_buffer, buffer_usage, buffer_region,
283 fence,
284 [&](const auto& lock_error,
285 const auto& lock_data) {
286 error = lock_error;
287 if (lock_error == Error::NONE) {
288 data = lock_data;
289 }
290 });
291
292 if (!ret.isOk()) {
293 error = Error::NO_RESOURCES;
294 }
295
296 if (error != Error::NONE) {
297 ALOGE("%s failed to lock buffer", __FUNCTION__);
298 return std::nullopt;
299 }
300
301 return data;
302 }
303 if (gralloc0_ != nullptr) {
304 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
305 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
306
307 void* data = nullptr;
308 int ret = gralloc0_->lock(gralloc0_,
309 gralloc0_buffer,
310 GRALLOC_USAGE_SW_READ_OFTEN,
311 0,
312 0,
313 gralloc0_buffer->x_res,
314 gralloc0_buffer->y_res,
315 &data);
316
317 if (ret) {
318 ALOGE("%s failed to lock buffer", __FUNCTION__);
319 return std::nullopt;
320 }
321 return data;
322 }
323 return std::nullopt;
324 }
325
LockYCbCr(buffer_handle_t buffer)326 std::optional<android_ycbcr> Gralloc::LockYCbCr(buffer_handle_t buffer) {
327 auto format_opt = GetDrmFormat(buffer);
328 if (!format_opt) {
329 ALOGE("%s failed to check format of buffer", __FUNCTION__);
330 return std::nullopt;
331 }
332
333 if (*format_opt != DRM_FORMAT_NV12 &&
334 *format_opt != DRM_FORMAT_NV21 &&
335 *format_opt != DRM_FORMAT_YVU420) {
336 ALOGE("%s called on non-ycbcr buffer", __FUNCTION__);
337 return std::nullopt;
338 }
339
340 if (gralloc4_ != nullptr) {
341 auto lock_opt = Lock(buffer);
342 if (!lock_opt) {
343 ALOGE("%s failed to lock buffer", __FUNCTION__);
344 return std::nullopt;
345 }
346
347 auto plane_layouts_opt = GetPlaneLayouts(buffer);
348 if (!plane_layouts_opt) {
349 ALOGE("%s failed to get plane layouts", __FUNCTION__);
350 return std::nullopt;
351 }
352
353 android_ycbcr buffer_ycbcr;
354 buffer_ycbcr.y = nullptr;
355 buffer_ycbcr.cb = nullptr;
356 buffer_ycbcr.cr = nullptr;
357 buffer_ycbcr.ystride = 0;
358 buffer_ycbcr.cstride = 0;
359 buffer_ycbcr.chroma_step = 0;
360
361 for (const auto& plane_layout : *plane_layouts_opt) {
362 for (const auto& plane_layout_component : plane_layout.components) {
363 const auto& type = plane_layout_component.type;
364
365 if (!android::gralloc4::isStandardPlaneLayoutComponentType(type)) {
366 continue;
367 }
368
369 auto* component_data =
370 reinterpret_cast<uint8_t*>(*lock_opt) +
371 plane_layout.offsetInBytes +
372 plane_layout_component.offsetInBits / 8;
373
374 switch (static_cast<PlaneLayoutComponentType>(type.value)) {
375 case PlaneLayoutComponentType::Y:
376 buffer_ycbcr.y = component_data;
377 buffer_ycbcr.ystride = plane_layout.strideInBytes;
378 break;
379 case PlaneLayoutComponentType::CB:
380 buffer_ycbcr.cb = component_data;
381 buffer_ycbcr.cstride = plane_layout.strideInBytes;
382 buffer_ycbcr.chroma_step = plane_layout.sampleIncrementInBits / 8;
383 break;
384 case PlaneLayoutComponentType::CR:
385 buffer_ycbcr.cr = component_data;
386 buffer_ycbcr.cstride = plane_layout.strideInBytes;
387 buffer_ycbcr.chroma_step = plane_layout.sampleIncrementInBits / 8;
388 break;
389 default:
390 break;
391 }
392 }
393 }
394
395 return buffer_ycbcr;
396 }
397 if (gralloc0_ != nullptr) {
398 auto lock_opt = Lock(buffer);
399 if (!lock_opt) {
400 ALOGE("%s failed to lock buffer", __FUNCTION__);
401 return std::nullopt;
402 }
403 void* data = *lock_opt;
404
405 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
406 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
407
408 android_ycbcr buffer_ycbcr;
409 formatToYcbcr(gralloc0_buffer->format,
410 gralloc0_buffer->x_res,
411 gralloc0_buffer->y_res,
412 data,
413 &buffer_ycbcr);
414 return buffer_ycbcr;
415 }
416 return std::nullopt;
417 }
418
Unlock(buffer_handle_t buffer)419 void Gralloc::Unlock(buffer_handle_t buffer) {
420 if (gralloc4_ != nullptr) {
421 auto native_handle = const_cast<native_handle_t*>(buffer);
422
423 Error error = Error::NONE;
424 auto ret = gralloc4_->unlock(native_handle,
425 [&](const auto& unlock_error, const auto&) {
426 error = unlock_error;
427 });
428
429 if (!ret.isOk()) {
430 error = Error::NO_RESOURCES;
431 }
432
433 if (error != Error::NONE) {
434 ALOGE("%s failed to unlock buffer", __FUNCTION__);
435 }
436 return;
437 }
438 if (gralloc0_ != nullptr) {
439 const cuttlefish_gralloc0_buffer_handle_t* gralloc0_buffer =
440 reinterpret_cast<const cuttlefish_gralloc0_buffer_handle_t*>(buffer);
441
442 gralloc0_->unlock(gralloc0_, gralloc0_buffer);
443 return;
444 }
445 }
446
447
GrallocBuffer(Gralloc * gralloc,buffer_handle_t buffer)448 GrallocBuffer::GrallocBuffer(Gralloc* gralloc, buffer_handle_t buffer) :
449 gralloc_(gralloc), buffer_(buffer) {}
450
~GrallocBuffer()451 GrallocBuffer::~GrallocBuffer() { Release(); }
452
GrallocBuffer(GrallocBuffer && rhs)453 GrallocBuffer::GrallocBuffer(GrallocBuffer&& rhs) {
454 *this = std::move(rhs);
455 }
456
operator =(GrallocBuffer && rhs)457 GrallocBuffer& GrallocBuffer::operator=(GrallocBuffer&& rhs) {
458 gralloc_ = rhs.gralloc_;
459 buffer_ = rhs.buffer_;
460 rhs.gralloc_ = nullptr;
461 rhs.buffer_ = nullptr;
462 return *this;
463 }
464
Release()465 void GrallocBuffer::Release() {
466 if (gralloc_ && buffer_) {
467 gralloc_->Release(buffer_);
468 gralloc_ = nullptr;
469 buffer_ = nullptr;
470 }
471 }
472
Lock()473 std::optional<void*> GrallocBuffer::Lock() {
474 if (gralloc_ && buffer_) {
475 return gralloc_->Lock(buffer_);
476 }
477 return std::nullopt;
478 }
479
LockYCbCr()480 std::optional<android_ycbcr> GrallocBuffer::LockYCbCr() {
481 if (gralloc_ && buffer_) {
482 return gralloc_->LockYCbCr(buffer_);
483 }
484 return std::nullopt;
485 }
486
Unlock()487 void GrallocBuffer::Unlock() {
488 if (gralloc_ && buffer_) {
489 gralloc_->Unlock(buffer_);
490 }
491 }
492
GetWidth()493 std::optional<uint32_t> GrallocBuffer::GetWidth() {
494 if (gralloc_ && buffer_) {
495 return gralloc_->GetWidth(buffer_);
496 }
497 return std::nullopt;
498 }
499
GetHeight()500 std::optional<uint32_t> GrallocBuffer::GetHeight() {
501 if (gralloc_ && buffer_) {
502 return gralloc_->GetHeight(buffer_);
503 }
504 return std::nullopt;
505 }
506
GetDrmFormat()507 std::optional<uint32_t> GrallocBuffer::GetDrmFormat() {
508 if (gralloc_ && buffer_) {
509 return gralloc_->GetDrmFormat(buffer_);
510 }
511 return std::nullopt;
512 }
513
514 std::optional<std::vector<PlaneLayout>>
GetPlaneLayouts()515 GrallocBuffer::GetPlaneLayouts() {
516 if (gralloc_ && buffer_) {
517 return gralloc_->GetPlaneLayouts(buffer_);
518 }
519 return std::nullopt;
520 }
521
GetMonoPlanarStrideBytes()522 std::optional<uint32_t> GrallocBuffer::GetMonoPlanarStrideBytes() {
523 if (gralloc_ && buffer_) {
524 return gralloc_->GetMonoPlanarStrideBytes(buffer_);
525 }
526 return std::nullopt;
527 }
528
529 } // namespace cvd