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 #include "../OpenglSystemCommon/HostConnection.h"
18 
19 #include "vk_format_info.h"
20 #include "vk_util.h"
21 
22 namespace goldfish_vk {
23 
24 // From Intel ANV implementation.
25 /* Construct ahw usage mask from image usage bits, see
26  * 'AHardwareBuffer Usage Equivalence' in Vulkan spec.
27  */
28 uint64_t
getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,const VkImageUsageFlags vk_usage)29 getAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags vk_create,
30                                  const VkImageUsageFlags vk_usage)
31 {
32    uint64_t ahw_usage = 0;
33 
34    if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
35       ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
36 
37    if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
38       ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
39 
40    if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
41       ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
42 
43    if (vk_create & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
44       ahw_usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
45 
46    if (vk_create & VK_IMAGE_CREATE_PROTECTED_BIT)
47       ahw_usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
48 
49    /* No usage bits set - set at least one GPU usage. */
50    if (ahw_usage == 0)
51       ahw_usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
52 
53    return ahw_usage;
54 }
55 
getAndroidHardwareBufferPropertiesANDROID(Gralloc * grallocHelper,const HostVisibleMemoryVirtualizationInfo * hostMemVirtInfo,VkDevice,const AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)56 VkResult getAndroidHardwareBufferPropertiesANDROID(
57     Gralloc* grallocHelper,
58     const HostVisibleMemoryVirtualizationInfo* hostMemVirtInfo,
59     VkDevice,
60     const AHardwareBuffer* buffer,
61     VkAndroidHardwareBufferPropertiesANDROID* pProperties) {
62 
63     VkAndroidHardwareBufferFormatPropertiesANDROID* ahbFormatProps =
64         vk_find_struct<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties);
65 
66     if (ahbFormatProps) {
67         AHardwareBuffer_Desc desc;
68         AHardwareBuffer_describe(buffer, &desc);
69 
70        const uint64_t gpu_usage =
71           AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
72           AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
73           AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
74 
75         if (!(desc.usage & (gpu_usage))) {
76             return VK_ERROR_INVALID_EXTERNAL_HANDLE;
77         }
78 
79         ahbFormatProps->format = vk_format_from_android(desc.format);
80         ahbFormatProps->externalFormat = desc.format;
81 
82         // The formatFeatures member must include
83         // VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT and at least one of
84         // VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT or
85         // VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT, and should include
86         // VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT and
87         // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
88 
89         ahbFormatProps->formatFeatures =
90             VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
91             VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
92 
93         // "Implementations may not always be able to determine the color model,
94         // numerical range, or chroma offsets of the image contents, so the values in
95         // VkAndroidHardwareBufferFormatPropertiesANDROID are only suggestions.
96         // Applications should treat these values as sensible defaults to use in the
97         // absence of more reliable information obtained through some other means."
98 
99         ahbFormatProps->samplerYcbcrConversionComponents.r = VK_COMPONENT_SWIZZLE_IDENTITY;
100         ahbFormatProps->samplerYcbcrConversionComponents.g = VK_COMPONENT_SWIZZLE_IDENTITY;
101         ahbFormatProps->samplerYcbcrConversionComponents.b = VK_COMPONENT_SWIZZLE_IDENTITY;
102         ahbFormatProps->samplerYcbcrConversionComponents.a = VK_COMPONENT_SWIZZLE_IDENTITY;
103 
104         ahbFormatProps->suggestedYcbcrModel =
105             android_format_is_yuv(desc.format) ?
106                 VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 :
107                 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
108         ahbFormatProps->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
109 
110         ahbFormatProps->suggestedXChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
111         ahbFormatProps->suggestedYChromaOffset = VK_CHROMA_LOCATION_MIDPOINT;
112     }
113 
114     const native_handle_t *handle =
115        AHardwareBuffer_getNativeHandle(buffer);
116     uint32_t colorBufferHandle =
117         grallocHelper->getHostHandle(handle);
118     if (!colorBufferHandle) {
119         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
120     }
121 
122     // Disallow host visible and noflags heaps for now
123     // (hard to make actual dedicated allocs)
124     uint32_t memoryTypeBits = 0;
125     for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
126         if (isNoFlagsMemoryTypeIndexForGuest(hostMemVirtInfo, i)) continue;
127         if (isHostVisibleMemoryTypeIndexForGuest(hostMemVirtInfo, i)) continue;
128         memoryTypeBits |= (1 << i);
129     }
130 
131     pProperties->memoryTypeBits = memoryTypeBits;
132     pProperties->allocationSize =
133         grallocHelper->getAllocatedSize(handle);
134 
135     return VK_SUCCESS;
136 }
137 
138 // Based on Intel ANV implementation.
getMemoryAndroidHardwareBufferANDROID(struct AHardwareBuffer ** pBuffer)139 VkResult getMemoryAndroidHardwareBufferANDROID(struct AHardwareBuffer **pBuffer) {
140 
141    /* Some quotes from Vulkan spec:
142     *
143     * "If the device memory was created by importing an Android hardware
144     * buffer, vkGetMemoryAndroidHardwareBufferANDROID must return that same
145     * Android hardware buffer object."
146     *
147     * "VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID must
148     * have been included in VkExportMemoryAllocateInfo::handleTypes when
149     * memory was created."
150     */
151 
152     if (!pBuffer) return VK_ERROR_OUT_OF_HOST_MEMORY;
153     if (!(*pBuffer)) return VK_ERROR_OUT_OF_HOST_MEMORY;
154 
155     AHardwareBuffer_acquire(*pBuffer);
156     return VK_SUCCESS;
157 }
158 
importAndroidHardwareBuffer(Gralloc * grallocHelper,const VkImportAndroidHardwareBufferInfoANDROID * info,struct AHardwareBuffer ** importOut)159 VkResult importAndroidHardwareBuffer(
160     Gralloc* grallocHelper,
161     const VkImportAndroidHardwareBufferInfoANDROID* info,
162     struct AHardwareBuffer **importOut) {
163 
164     if (!info || !info->buffer) {
165         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
166     }
167 
168     uint32_t colorBufferHandle =
169         grallocHelper->getHostHandle(
170             AHardwareBuffer_getNativeHandle(info->buffer));
171     if (!colorBufferHandle) {
172         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
173     }
174 
175     auto ahb = info->buffer;
176 
177     AHardwareBuffer_acquire(ahb);
178 
179     if (importOut) *importOut = ahb;
180 
181     return VK_SUCCESS;
182 }
183 
createAndroidHardwareBuffer(bool hasDedicatedImage,bool hasDedicatedBuffer,const VkExtent3D & imageExtent,uint32_t imageLayers,VkFormat imageFormat,VkImageUsageFlags imageUsage,VkImageCreateFlags imageCreateFlags,VkDeviceSize bufferSize,VkDeviceSize allocationInfoAllocSize,struct AHardwareBuffer ** out)184 VkResult createAndroidHardwareBuffer(
185     bool hasDedicatedImage,
186     bool hasDedicatedBuffer,
187     const VkExtent3D& imageExtent,
188     uint32_t imageLayers,
189     VkFormat imageFormat,
190     VkImageUsageFlags imageUsage,
191     VkImageCreateFlags imageCreateFlags,
192     VkDeviceSize bufferSize,
193     VkDeviceSize allocationInfoAllocSize,
194     struct AHardwareBuffer **out) {
195 
196     uint32_t w = 0;
197     uint32_t h = 1;
198     uint32_t layers = 1;
199     uint32_t format = 0;
200     uint64_t usage = 0;
201 
202     /* If caller passed dedicated information. */
203     if (hasDedicatedImage) {
204        w = imageExtent.width;
205        h = imageExtent.height;
206        layers = imageLayers;
207        format = android_format_from_vk(imageFormat);
208        usage = getAndroidHardwareBufferUsageFromVkUsage(imageCreateFlags, imageUsage);
209     } else if (hasDedicatedBuffer) {
210        w = bufferSize;
211        format = AHARDWAREBUFFER_FORMAT_BLOB;
212        usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
213                AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
214                AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
215     } else {
216        w = allocationInfoAllocSize;
217        format = AHARDWAREBUFFER_FORMAT_BLOB;
218        usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
219                AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
220                AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
221     }
222 
223     struct AHardwareBuffer *ahw = NULL;
224     struct AHardwareBuffer_Desc desc = {
225         .width = w,
226         .height = h,
227         .layers = layers,
228         .format = format,
229         .usage = usage,
230     };
231 
232     if (AHardwareBuffer_allocate(&desc, &ahw) != 0) {
233         return VK_ERROR_OUT_OF_HOST_MEMORY;
234     }
235 
236     *out = ahw;
237 
238     return VK_SUCCESS;
239 }
240 
241 } // namespace goldfish_vk
242