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