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