1 /// Copyright (C) 2019 The Android Open Source Project
2 // Copyright (C) 2019 Google Inc.
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 #include "AndroidHardwareBuffer.h"
16
17 #if defined(__ANDROID__) || defined(__linux__)
18 #include <drm_fourcc.h>
19 #define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7')
20 #endif
21
22 #include <assert.h>
23
24 #include "../OpenglSystemCommon/HostConnection.h"
25 #include "vk_format_info.h"
26 #include "vk_util.h"
27
28 namespace gfxstream {
29 namespace vk {
30
31 // From Intel ANV implementation.
32 /* Construct ahw usage mask from image usage bits, see
33 * 'AHardwareBuffer Usage Equivalence' in Vulkan spec.
34 */
getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,const VkImageUsageFlags vk_usage)35 uint64_t getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,
36 const VkImageUsageFlags vk_usage) {
37 uint64_t ahw_usage = 0;
38
39 if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT) ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
40
41 if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
42 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
43
44 if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
45 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
46
47 if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
48 ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
49
50 if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT)
51 ahw_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
52
53 /* No usage bits set - set at least one GPU usage. */
54 if (ahw_usage == 0) ahw_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
55
56 return ahw_usage;
57 }
58
getAndroidHardwareBufferPropertiesANDROID(gfxstream::Gralloc * grallocHelper,const AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)59 VkResult getAndroidHardwareBufferPropertiesANDROID(
60 gfxstream::Gralloc* grallocHelper, const AHardwareBuffer* buffer,
61 VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
62 VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps =
63 vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties);
64
65 const auto format = grallocHelper->getFormat(buffer);
66 if (ahbFormatProps) {
67 switch (format) {
68 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
69 ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
70 break;
71 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
72 ahbFormatProps->format = VK_FORMAT_R8G8B8A8_UNORM;
73 break;
74 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
75 ahbFormatProps->format = VK_FORMAT_R8G8B8_UNORM;
76 break;
77 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
78 ahbFormatProps->format = VK_FORMAT_R5G6B5_UNORM_PACK16;
79 break;
80 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
81 ahbFormatProps->format = VK_FORMAT_R16G16B16A16_SFLOAT;
82 break;
83 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
84 ahbFormatProps->format = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
85 break;
86 case AHARDWAREBUFFER_FORMAT_D16_UNORM:
87 ahbFormatProps->format = VK_FORMAT_D16_UNORM;
88 break;
89 case AHARDWAREBUFFER_FORMAT_D24_UNORM:
90 ahbFormatProps->format = VK_FORMAT_X8_D24_UNORM_PACK32;
91 break;
92 case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
93 ahbFormatProps->format = VK_FORMAT_D24_UNORM_S8_UINT;
94 break;
95 case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
96 ahbFormatProps->format = VK_FORMAT_D32_SFLOAT;
97 break;
98 case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
99 ahbFormatProps->format = VK_FORMAT_D32_SFLOAT_S8_UINT;
100 break;
101 case AHARDWAREBUFFER_FORMAT_S8_UINT:
102 ahbFormatProps->format = VK_FORMAT_S8_UINT;
103 break;
104 default:
105 ahbFormatProps->format = VK_FORMAT_UNDEFINED;
106 }
107 ahbFormatProps->externalFormat = format;
108
109 // The formatFeatures member must include
110 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
111 // VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
112 // VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, and should include
113 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT and
114 // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
115
116 // org.skia.skqp.SkQPRunner#UnitTest_VulkanHardwareBuffer* requires the following:
117 // VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
118 // VK_FORMAT_FEATURE_TRANSFER_DST_BIT
119 // VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
120 ahbFormatProps->formatFeatures =
121 VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT |
122 VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
123 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
124
125 // "Implementations may not always be able to determine the color model,
126 // numerical range, or chroma offsets of the image contents, so the values in
127 // VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
128 // Applications should treat these values as sensible defaults to use in the
129 // absence of more reliable information obtained through some other means."
130
131 ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
132 ahbFormatProps->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
133 ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
134 ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
135
136 #if defined(__ANDROID__) || defined(__linux__)
137 if (android_format_is_yuv(format)) {
138 uint32_t drmFormat = grallocHelper->getFormatDrmFourcc(buffer);
139 if (drmFormat) {
140 // The host renderer is not aware of the plane ordering for YUV formats used
141 // in the guest and simply knows that the format "layout" is one of:
142 //
143 // * VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
144 // * VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
145 // * VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
146 //
147 // With this, the guest needs to adjust the component swizzle based on plane
148 // ordering to ensure that the channels are interpreted correctly.
149 //
150 // From the Vulkan spec's "Sampler Y'CBCR Conversion" section:
151 //
152 // * Y comes from the G-channel (after swizzle)
153 // * U (CB) comes from the B-channel (after swizzle)
154 // * V (CR) comes from the R-channel (after swizzle)
155 //
156 // See
157 // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#textures-sampler-YCbCr-conversion
158 //
159 // To match the above, the guest needs to swizzle such that:
160 //
161 // * Y ends up in the G-channel
162 // * U (CB) ends up in the B-channel
163 // * V (CB) ends up in the R-channel
164 switch (drmFormat) {
165 case DRM_FORMAT_NV12:
166 // NV12 is a Y-plane followed by a interleaved UV-plane and is
167 // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
168 case DRM_FORMAT_P010:
169 // P010 is a Y-plane followed by a interleaved UV-plane and is
170 // VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 on the host.
171 break;
172
173 case DRM_FORMAT_NV21:
174 // NV21 is a Y-plane followed by a interleaved VU-plane and is
175 // VK_FORMAT_G8_B8R8_2PLANE_420_UNORM on the host.
176 case DRM_FORMAT_YVU420:
177 // YV12 is a Y-plane, then a V-plane, and then a U-plane and is
178 // VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM on the host.
179 case DRM_FORMAT_YVU420_ANDROID:
180 // DRM_FORMAT_YVU420_ANDROID is the same as DRM_FORMAT_YVU420 with
181 // Android's extra alignement requirements.
182 ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_B;
183 ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_R;
184 break;
185
186 default:
187 ALOGE("%s: Unhandled YUV drm format:%" PRIu32, __FUNCTION__, drmFormat);
188 break;
189 }
190 }
191 }
192 #endif
193 ahbFormatProps->suggestedYcbcrModel = android_format_is_yuv(format)
194 ? VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601
195 : VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
196 ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
197
198 ahbFormatProps->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
199 ahbFormatProps->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
200 }
201
202 uint32_t colorBufferHandle = grallocHelper->getHostHandle(buffer);
203 if (!colorBufferHandle) {
204 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
205 }
206
207 pProperties->allocationSize = grallocHelper->getAllocatedSize(buffer);
208
209 return VK_SUCCESS;
210 }
211
212 // Based on Intel ANV implementation.
getMemoryAndroidHardwareBufferANDROID(gfxstream::Gralloc * gralloc,struct AHardwareBuffer ** pBuffer)213 VkResult getMemoryAndroidHardwareBufferANDROID(gfxstream::Gralloc* gralloc,
214 struct AHardwareBuffer** pBuffer) {
215 /* Some quotes from Vulkan spec:
216 *
217 * "If the device memory was created by importing an Android hardware
218 * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
219 * Android hardware buffer object."
220 *
221 * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
222 * have been included in VkExportMemoryAllocateInfo::handleTypes when
223 * memory was created."
224 */
225
226 if (!pBuffer) return VK_ERROR_OUT_OF_HOST_MEMORY;
227 if (!(*pBuffer)) return VK_ERROR_OUT_OF_HOST_MEMORY;
228
229 gralloc->acquire(*pBuffer);
230 return VK_SUCCESS;
231 }
232
importAndroidHardwareBuffer(gfxstream::Gralloc * grallocHelper,const VkImportAndroidHardwareBufferInfoANDROID * info,struct AHardwareBuffer ** importOut)233 VkResult importAndroidHardwareBuffer(gfxstream::Gralloc* grallocHelper,
234 const VkImportAndroidHardwareBufferInfoANDROID* info,
235 struct AHardwareBuffer** importOut) {
236 if (!info || !info->buffer) {
237 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
238 }
239
240 auto ahb = info->buffer;
241
242 uint32_t colorBufferHandle = grallocHelper->getHostHandle(ahb);
243 if (!colorBufferHandle) {
244 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
245 }
246
247 grallocHelper->acquire(ahb);
248
249 if (importOut) *importOut = ahb;
250
251 return VK_SUCCESS;
252 }
253
createAndroidHardwareBuffer(gfxstream::Gralloc * gralloc,bool hasDedicatedImage,bool hasDedicatedBuffer,const VkExtent3D & imageExtent,uint32_t imageLayers,VkFormat imageFormat,VkImageUsageFlags imageUsage,VkImageCreateFlags imageCreateFlags,VkDeviceSize bufferSize,VkDeviceSize allocationInfoAllocSize,struct AHardwareBuffer ** out)254 VkResult createAndroidHardwareBuffer(gfxstream::Gralloc* gralloc, bool hasDedicatedImage,
255 bool hasDedicatedBuffer, const VkExtent3D& imageExtent,
256 uint32_t imageLayers, VkFormat imageFormat,
257 VkImageUsageFlags imageUsage,
258 VkImageCreateFlags imageCreateFlags, VkDeviceSize bufferSize,
259 VkDeviceSize allocationInfoAllocSize,
260 struct AHardwareBuffer** out) {
261 uint32_t w = 0;
262 uint32_t h = 1;
263 uint32_t layers = 1;
264 uint32_t format = 0;
265 uint64_t usage = 0;
266
267 /* If caller passed dedicated information. */
268 if (hasDedicatedImage) {
269 w = imageExtent.width;
270 h = imageExtent.height;
271 layers = imageLayers;
272 format = android_format_from_vk(imageFormat);
273 usage = getAndroidHardwareBufferUsageFromVkUsage(imageCreateFlags, imageUsage);
274 } else if (hasDedicatedBuffer) {
275 w = bufferSize;
276 format = AHARDWAREBUFFER_FORMAT_BLOB;
277 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
278 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
279 } else {
280 w = allocationInfoAllocSize;
281 format = AHARDWAREBUFFER_FORMAT_BLOB;
282 usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
283 AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
284 }
285
286 struct AHardwareBuffer* ahb = NULL;
287
288 if (gralloc->allocate(w, h, format, usage, &ahb) != 0) {
289 return VK_ERROR_OUT_OF_HOST_MEMORY;
290 }
291
292 *out = ahb;
293
294 return VK_SUCCESS;
295 }
296
297 } // namespace vk
298 } // namespace gfxstream
299