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/BufferUsage.h>
20 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
21 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
22 #include <drm_fourcc.h>
23 #include <gralloctypes/Gralloc4.h>
24 #include <log/log.h>
25 #include <ui/GraphicBufferMapper.h>
26 
27 #include <algorithm>
28 
29 #include "Drm.h"
30 
31 using aidl::android::hardware::graphics::common::BufferUsage;
32 using aidl::android::hardware::graphics::common::PlaneLayout;
33 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
34 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
35 using android::GraphicBufferMapper;
36 using android::OK;
37 using android::Rect;
38 using android::status_t;
39 
40 namespace aidl::android::hardware::graphics::composer3::impl {
41 
GetWidth(buffer_handle_t buffer)42 std::optional<uint32_t> Gralloc::GetWidth(buffer_handle_t buffer) {
43     uint64_t width = 0;
44     status_t status = GraphicBufferMapper::get().getWidth(buffer, &width);
45     if (status != OK) {
46         return std::nullopt;
47     }
48 
49     if (width > std::numeric_limits<uint32_t>::max()) {
50         ALOGE("%s Width too large to cast to uint32_t: %ld", __FUNCTION__, width);
51         return std::nullopt;
52     }
53     return static_cast<uint32_t>(width);
54 }
55 
GetHeight(buffer_handle_t buffer)56 std::optional<uint32_t> Gralloc::GetHeight(buffer_handle_t buffer) {
57     uint64_t height = 0;
58     status_t status = GraphicBufferMapper::get().getHeight(buffer, &height);
59     if (status != OK) {
60         return std::nullopt;
61     }
62 
63     if (height > std::numeric_limits<uint32_t>::max()) {
64         ALOGE("%s Height too large to cast to uint32_t: %ld", __FUNCTION__, height);
65         return std::nullopt;
66     }
67     return static_cast<uint32_t>(height);
68 }
69 
GetDrmFormat(buffer_handle_t buffer)70 std::optional<uint32_t> Gralloc::GetDrmFormat(buffer_handle_t buffer) {
71     uint32_t format = 0;
72     status_t status = GraphicBufferMapper::get().getPixelFormatFourCC(buffer, &format);
73     if (status != OK) {
74         return std::nullopt;
75     }
76 
77     return format;
78 }
79 
GetPlaneLayouts(buffer_handle_t buffer)80 std::optional<std::vector<PlaneLayout>> Gralloc::GetPlaneLayouts(buffer_handle_t buffer) {
81     std::vector<PlaneLayout> layouts;
82     status_t status = GraphicBufferMapper::get().getPlaneLayouts(buffer, &layouts);
83     if (status != OK) {
84         return std::nullopt;
85     }
86 
87     return layouts;
88 }
89 
GetMonoPlanarStrideBytes(buffer_handle_t buffer)90 std::optional<uint32_t> Gralloc::GetMonoPlanarStrideBytes(buffer_handle_t buffer) {
91     auto plane_layouts_opt = GetPlaneLayouts(buffer);
92     if (!plane_layouts_opt) {
93         return std::nullopt;
94     }
95 
96     std::vector<PlaneLayout>& plane_layouts = *plane_layouts_opt;
97     if (plane_layouts.size() != 1) {
98         return std::nullopt;
99     }
100 
101     if (plane_layouts[0].strideInBytes > std::numeric_limits<uint32_t>::max()) {
102         ALOGE("%s strideInBytes too large to cast to uint32_t: %ld", __FUNCTION__,
103               plane_layouts[0].strideInBytes);
104         return std::nullopt;
105     }
106     return static_cast<uint32_t>(plane_layouts[0].strideInBytes);
107 }
108 
Import(buffer_handle_t buffer)109 std::optional<GrallocBuffer> Gralloc::Import(buffer_handle_t buffer) {
110     buffer_handle_t imported_buffer;
111 
112     status_t status = GraphicBufferMapper::get().importBufferNoValidate(buffer, &imported_buffer);
113 
114     if (status != OK) {
115         ALOGE("%s failed to import buffer: %d", __FUNCTION__, status);
116         return std::nullopt;
117     }
118     return GrallocBuffer(this, imported_buffer);
119 }
120 
Release(buffer_handle_t buffer)121 void Gralloc::Release(buffer_handle_t buffer) {
122     status_t status = GraphicBufferMapper::get().freeBuffer(buffer);
123 
124     if (status != OK) {
125         ALOGE("%s failed to release buffer: %d", __FUNCTION__, status);
126     }
127 }
128 
Lock(buffer_handle_t buffer)129 std::optional<void*> Gralloc::Lock(buffer_handle_t buffer) {
130     const auto buffer_usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN) |
131                               static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN);
132 
133     auto width_opt = GetWidth(buffer);
134     if (!width_opt) {
135         return std::nullopt;
136     }
137 
138     auto height_opt = GetHeight(buffer);
139     if (!height_opt) {
140         return std::nullopt;
141     }
142 
143     Rect buffer_region;
144     buffer_region.left = 0;
145     buffer_region.top = 0;
146     // width = right - left
147     buffer_region.right = static_cast<int32_t>(*width_opt);
148     // height = bottom - top
149     buffer_region.bottom = static_cast<int32_t>(*height_opt);
150 
151     void* data = nullptr;
152 
153     status_t status = GraphicBufferMapper::get().lock(buffer, buffer_usage, buffer_region, &data);
154 
155     if (status != OK) {
156         ALOGE("%s failed to lock buffer: %d", __FUNCTION__, status);
157         return std::nullopt;
158     }
159 
160     return data;
161 }
162 
LockYCbCr(buffer_handle_t buffer)163 std::optional<android_ycbcr> Gralloc::LockYCbCr(buffer_handle_t buffer) {
164     auto format_opt = GetDrmFormat(buffer);
165     if (!format_opt) {
166         ALOGE("%s failed to check format of buffer", __FUNCTION__);
167         return std::nullopt;
168     }
169 
170     if (*format_opt != DRM_FORMAT_NV12 && *format_opt != DRM_FORMAT_NV21 &&
171         *format_opt != DRM_FORMAT_YVU420) {
172         ALOGE("%s called on non-ycbcr buffer", __FUNCTION__);
173         return std::nullopt;
174     }
175 
176     auto lock_opt = Lock(buffer);
177     if (!lock_opt) {
178         ALOGE("%s failed to lock buffer", __FUNCTION__);
179         return std::nullopt;
180     }
181 
182     auto plane_layouts_opt = GetPlaneLayouts(buffer);
183     if (!plane_layouts_opt) {
184         ALOGE("%s failed to get plane layouts", __FUNCTION__);
185         return std::nullopt;
186     }
187 
188     android_ycbcr buffer_ycbcr;
189     buffer_ycbcr.y = nullptr;
190     buffer_ycbcr.cb = nullptr;
191     buffer_ycbcr.cr = nullptr;
192     buffer_ycbcr.ystride = 0;
193     buffer_ycbcr.cstride = 0;
194     buffer_ycbcr.chroma_step = 0;
195 
196     for (const auto& plane_layout : *plane_layouts_opt) {
197         for (const auto& plane_layout_component : plane_layout.components) {
198             const auto& type = plane_layout_component.type;
199 
200             if (!::android::gralloc4::isStandardPlaneLayoutComponentType(type)) {
201                 continue;
202             }
203 
204             auto* component_data = reinterpret_cast<uint8_t*>(*lock_opt) +
205                                    plane_layout.offsetInBytes +
206                                    plane_layout_component.offsetInBits / 8;
207 
208             switch (static_cast<PlaneLayoutComponentType>(type.value)) {
209                 case PlaneLayoutComponentType::Y:
210                     buffer_ycbcr.y = component_data;
211                     buffer_ycbcr.ystride = static_cast<size_t>(plane_layout.strideInBytes);
212                     break;
213                 case PlaneLayoutComponentType::CB:
214                     buffer_ycbcr.cb = component_data;
215                     buffer_ycbcr.cstride = static_cast<size_t>(plane_layout.strideInBytes);
216                     buffer_ycbcr.chroma_step =
217                         static_cast<size_t>(plane_layout.sampleIncrementInBits / 8);
218                     break;
219                 case PlaneLayoutComponentType::CR:
220                     buffer_ycbcr.cr = component_data;
221                     buffer_ycbcr.cstride = static_cast<size_t>(plane_layout.strideInBytes);
222                     buffer_ycbcr.chroma_step =
223                         static_cast<size_t>(plane_layout.sampleIncrementInBits / 8);
224                     break;
225                 default:
226                     break;
227             }
228         }
229     }
230 
231     return buffer_ycbcr;
232 }
233 
Unlock(buffer_handle_t buffer)234 void Gralloc::Unlock(buffer_handle_t buffer) {
235     status_t status = GraphicBufferMapper::get().unlock(buffer);
236 
237     if (status != OK) {
238         ALOGE("%s failed to unlock buffer %d", __FUNCTION__, status);
239     }
240 }
241 
GrallocBuffer(Gralloc * gralloc,buffer_handle_t buffer)242 GrallocBuffer::GrallocBuffer(Gralloc* gralloc, buffer_handle_t buffer)
243     : gralloc_(gralloc), buffer_(buffer) {}
244 
~GrallocBuffer()245 GrallocBuffer::~GrallocBuffer() { Release(); }
246 
GrallocBuffer(GrallocBuffer && rhs)247 GrallocBuffer::GrallocBuffer(GrallocBuffer&& rhs) { *this = std::move(rhs); }
248 
operator =(GrallocBuffer && rhs)249 GrallocBuffer& GrallocBuffer::operator=(GrallocBuffer&& rhs) {
250     gralloc_ = rhs.gralloc_;
251     buffer_ = rhs.buffer_;
252     rhs.gralloc_ = nullptr;
253     rhs.buffer_ = nullptr;
254     return *this;
255 }
256 
Release()257 void GrallocBuffer::Release() {
258     if (gralloc_ && buffer_) {
259         gralloc_->Release(buffer_);
260         gralloc_ = nullptr;
261         buffer_ = nullptr;
262     }
263 }
264 
Lock()265 std::optional<GrallocBufferView> GrallocBuffer::Lock() {
266     if (gralloc_ && buffer_) {
267         auto format_opt = GetDrmFormat();
268         if (!format_opt) {
269             ALOGE("%s failed to check format of buffer", __FUNCTION__);
270             return std::nullopt;
271         }
272         if (*format_opt != DRM_FORMAT_NV12 && *format_opt != DRM_FORMAT_NV21 &&
273             *format_opt != DRM_FORMAT_YVU420) {
274             auto locked_opt = gralloc_->Lock(buffer_);
275             if (!locked_opt) {
276                 return std::nullopt;
277             }
278             return GrallocBufferView(this, *locked_opt);
279         } else {
280             auto locked_ycbcr_opt = gralloc_->LockYCbCr(buffer_);
281             if (!locked_ycbcr_opt) {
282                 ALOGE("%s failed to lock ycbcr buffer", __FUNCTION__);
283                 return std::nullopt;
284             }
285             return GrallocBufferView(this, *locked_ycbcr_opt);
286         }
287     }
288     return std::nullopt;
289 }
290 
Unlock()291 void GrallocBuffer::Unlock() {
292     if (gralloc_ && buffer_) {
293         gralloc_->Unlock(buffer_);
294     }
295 }
296 
GetWidth()297 std::optional<uint32_t> GrallocBuffer::GetWidth() {
298     if (gralloc_ && buffer_) {
299         return gralloc_->GetWidth(buffer_);
300     }
301     return std::nullopt;
302 }
303 
GetHeight()304 std::optional<uint32_t> GrallocBuffer::GetHeight() {
305     if (gralloc_ && buffer_) {
306         return gralloc_->GetHeight(buffer_);
307     }
308     return std::nullopt;
309 }
310 
GetDrmFormat()311 std::optional<uint32_t> GrallocBuffer::GetDrmFormat() {
312     if (gralloc_ && buffer_) {
313         return gralloc_->GetDrmFormat(buffer_);
314     }
315     return std::nullopt;
316 }
317 
GetPlaneLayouts()318 std::optional<std::vector<PlaneLayout>> GrallocBuffer::GetPlaneLayouts() {
319     if (gralloc_ && buffer_) {
320         return gralloc_->GetPlaneLayouts(buffer_);
321     }
322     return std::nullopt;
323 }
324 
GetMonoPlanarStrideBytes()325 std::optional<uint32_t> GrallocBuffer::GetMonoPlanarStrideBytes() {
326     if (gralloc_ && buffer_) {
327         return gralloc_->GetMonoPlanarStrideBytes(buffer_);
328     }
329     return std::nullopt;
330 }
331 
GrallocBufferView(GrallocBuffer * buffer,void * raw)332 GrallocBufferView::GrallocBufferView(GrallocBuffer* buffer, void* raw)
333     : gralloc_buffer_(buffer), locked_(raw) {}
334 
GrallocBufferView(GrallocBuffer * buffer,android_ycbcr raw)335 GrallocBufferView::GrallocBufferView(GrallocBuffer* buffer, android_ycbcr raw)
336     : gralloc_buffer_(buffer), locked_ycbcr_(raw) {}
337 
~GrallocBufferView()338 GrallocBufferView::~GrallocBufferView() {
339     if (gralloc_buffer_) {
340         gralloc_buffer_->Unlock();
341     }
342 }
343 
GrallocBufferView(GrallocBufferView && rhs)344 GrallocBufferView::GrallocBufferView(GrallocBufferView&& rhs) { *this = std::move(rhs); }
345 
operator =(GrallocBufferView && rhs)346 GrallocBufferView& GrallocBufferView::operator=(GrallocBufferView&& rhs) {
347     std::swap(gralloc_buffer_, rhs.gralloc_buffer_);
348     std::swap(locked_, rhs.locked_);
349     std::swap(locked_ycbcr_, rhs.locked_ycbcr_);
350     return *this;
351 }
352 
Get() const353 const std::optional<void*> GrallocBufferView::Get() const { return locked_; }
354 
GetYCbCr() const355 const std::optional<android_ycbcr>& GrallocBufferView::GetYCbCr() const { return locked_ycbcr_; }
356 
357 }  // namespace aidl::android::hardware::graphics::composer3::impl
358