• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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