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