• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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