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