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