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