1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2021 GlobalLogic Ukraine
5 * Copyright (C) 2021 Roman Stratiienko (r.stratiienko@gmail.com)
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26#include "platform_android.h"
27
28#include <system/window.h>
29#include <aidl/android/hardware/graphics/common/ChromaSiting.h>
30#include <aidl/android/hardware/graphics/common/Dataspace.h>
31#include <aidl/android/hardware/graphics/common/ExtendableType.h>
32#include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
33#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
34#include <gralloctypes/Gralloc4.h>
35
36using aidl::android::hardware::graphics::common::ChromaSiting;
37using aidl::android::hardware::graphics::common::Dataspace;
38using aidl::android::hardware::graphics::common::ExtendableType;
39using aidl::android::hardware::graphics::common::PlaneLayout;
40using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
41using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
42using android::hardware::graphics::common::V1_2::BufferUsage;
43using android::hardware::graphics::mapper::V4_0::Error;
44using android::hardware::graphics::mapper::V4_0::IMapper;
45using android::hardware::hidl_handle;
46using android::hardware::hidl_vec;
47using MetadataType =
48   android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
49
50Error
51GetMetadata(android::sp<IMapper> mapper, const native_handle_t *buffer,
52            MetadataType type, hidl_vec<uint8_t>* metadata)
53{
54   Error error = Error::NONE;
55
56   auto native_handle = const_cast<native_handle_t*>(buffer);
57
58   auto ret = mapper->get(native_handle, type,
59                          [&](const auto& get_error, const auto& get_metadata) {
60                              error = get_error;
61                              *metadata = get_metadata;
62                          });
63
64   if (!ret.isOk())
65      error = Error::NO_RESOURCES;
66
67   return error;
68}
69
70std::optional<std::vector<PlaneLayout>> GetPlaneLayouts(
71   android::sp<IMapper> mapper, const native_handle_t *buffer)
72{
73   hidl_vec<uint8_t> encoded_layouts;
74
75   Error error = GetMetadata(mapper, buffer,
76                            android::gralloc4::MetadataType_PlaneLayouts,
77                            &encoded_layouts);
78
79   if (error != Error::NONE)
80      return std::nullopt;
81
82   std::vector<PlaneLayout> plane_layouts;
83
84   auto status = android::gralloc4::decodePlaneLayouts(encoded_layouts, &plane_layouts);
85
86   if (status != android::OK)
87      return std::nullopt;
88
89   return plane_layouts;
90}
91
92extern "C"
93{
94
95int
96mapper_metadata_get_buffer_info(struct ANativeWindowBuffer *buf,
97                                struct buffer_info *out_buf_info)
98{
99   static android::sp<IMapper> mapper = IMapper::getService();
100   struct buffer_info buf_info = *out_buf_info;
101   if (mapper == nullptr)
102      return -EINVAL;
103
104   if (!buf->handle)
105      return -EINVAL;
106
107   buf_info.width = buf->width;
108   buf_info.height = buf->height;
109
110   hidl_vec<uint8_t> encoded_format;
111   auto err = GetMetadata(mapper, buf->handle, android::gralloc4::MetadataType_PixelFormatFourCC, &encoded_format);
112   if (err != Error::NONE)
113      return -EINVAL;
114
115   auto status = android::gralloc4::decodePixelFormatFourCC(encoded_format, &buf_info.drm_fourcc);
116   if (status != android::OK)
117      return -EINVAL;
118
119   hidl_vec<uint8_t> encoded_modifier;
120   err = GetMetadata(mapper, buf->handle, android::gralloc4::MetadataType_PixelFormatModifier, &encoded_modifier);
121   if (err != Error::NONE)
122      return -EINVAL;
123
124   status = android::gralloc4::decodePixelFormatModifier(encoded_modifier, &buf_info.modifier);
125   if (status != android::OK)
126      return -EINVAL;
127
128   auto layouts_opt = GetPlaneLayouts(mapper, buf->handle);
129
130   if (!layouts_opt)
131      return -EINVAL;
132
133   std::vector<PlaneLayout>& layouts = *layouts_opt;
134
135   buf_info.num_planes = layouts.size();
136
137   bool per_plane_unique_fd = buf->handle->numFds == buf_info.num_planes;
138
139   for (uint32_t i = 0; i < layouts.size(); i++) {
140      buf_info.fds[i] = per_plane_unique_fd ? buf->handle->data[i] : buf->handle->data[0];
141      buf_info.pitches[i] = layouts[i].strideInBytes;
142      buf_info.offsets[i] = layouts[i].offsetInBytes;
143   }
144
145   /* optional attributes */
146   hidl_vec<uint8_t> encoded_chroma_siting;
147   err = GetMetadata(mapper, buf->handle, android::gralloc4::MetadataType_ChromaSiting, &encoded_chroma_siting);
148   if (err == Error::NONE) {
149      ExtendableType chroma_siting_ext;
150      status = android::gralloc4::decodeChromaSiting(encoded_chroma_siting, &chroma_siting_ext);
151      if (status != android::OK)
152         return -EINVAL;
153
154      ChromaSiting chroma_siting = android::gralloc4::getStandardChromaSitingValue(chroma_siting_ext);
155      switch (chroma_siting) {
156         case ChromaSiting::SITED_INTERSTITIAL:
157            buf_info.horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
158            buf_info.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
159            break;
160         case ChromaSiting::COSITED_HORIZONTAL:
161            buf_info.horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
162            buf_info.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
163            break;
164         default:
165            break;
166      }
167   }
168
169   hidl_vec<uint8_t> encoded_dataspace;
170   err = GetMetadata(mapper, buf->handle, android::gralloc4:: MetadataType_Dataspace, &encoded_dataspace);
171   if (err == Error::NONE) {
172      Dataspace dataspace;
173      status = android::gralloc4::decodeDataspace(encoded_dataspace, &dataspace);
174      if (status != android::OK)
175         return -EINVAL;
176
177      Dataspace standard = (Dataspace)((int)dataspace & (uint32_t)Dataspace::STANDARD_MASK);
178      switch (standard) {
179         case Dataspace::STANDARD_BT709:
180            buf_info.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709;
181            break;
182         case Dataspace::STANDARD_BT601_625:
183         case Dataspace::STANDARD_BT601_625_UNADJUSTED:
184         case Dataspace::STANDARD_BT601_525:
185         case Dataspace::STANDARD_BT601_525_UNADJUSTED:
186            buf_info.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601;
187            break;
188         case Dataspace::STANDARD_BT2020:
189         case Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE:
190            buf_info.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020;
191            break;
192         default:
193            break;
194      }
195
196      Dataspace range = (Dataspace)((int)dataspace & (uint32_t)Dataspace::RANGE_MASK);
197      switch (range) {
198         case Dataspace::RANGE_FULL:
199            buf_info.sample_range = __DRI_YUV_FULL_RANGE;
200            break;
201         case Dataspace::RANGE_LIMITED:
202            buf_info.sample_range = __DRI_YUV_NARROW_RANGE;
203            break;
204         default:
205            break;
206      }
207   }
208
209   *out_buf_info = buf_info;
210
211   return 0;
212}
213
214} // extern "C"
215