1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 The Khronos Group Inc.
6  * Copyright (c) 2023 Google Inc.
7  * Copyright (c) 2023 LunarG Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Vulkan external memory utilities for Android Hardware Buffer
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktExternalMemoryAndroidHardwareBufferUtil.hpp"
27 
28 #ifndef CTS_USES_VULKANSC
29 
30 #if (DE_OS == DE_OS_ANDROID)
31 #include <sys/system_properties.h>
32 
33 #if defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
34 #include <android/hardware_buffer.h>
35 #include "deDynamicLibrary.hpp"
36 #define BUILT_WITH_ANDROID_HARDWARE_BUFFER 1
37 #endif // defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
38 
39 #if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
40 #define BUILT_WITH_ANDROID_P_HARDWARE_BUFFER 1
41 #endif // defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
42 
43 #if defined(__ANDROID_API_T__) && (DE_ANDROID_API >= __ANDROID_API_T__)
44 #define BUILT_WITH_ANDROID_T_HARDWARE_BUFFER 1
45 #endif // defined(__ANDROID_API_T__) && (DE_ANDROID_API >= __ANDROID_API_T__)
46 
47 #if defined(__ANDROID_API_U__) && (DE_ANDROID_API >= __ANDROID_API_U__)
48 #define BUILT_WITH_ANDROID_U_HARDWARE_BUFFER 1
49 #endif // defined(__ANDROID_API_U__) && (DE_ANDROID_API >= __ANDROID_API_U__)
50 
51 #endif // (DE_OS == DE_OS_ANDROID)
52 
53 namespace vkt
54 {
55 
56 namespace ExternalMemoryUtil
57 {
58 
59 #if (DE_OS == DE_OS_ANDROID)
60 
androidGetSdkVersion()61 static int32_t androidGetSdkVersion()
62 {
63     static int32_t sdkVersion = -1;
64     if (sdkVersion < 0)
65     {
66         char value[128] = {0};
67         __system_property_get("ro.build.version.sdk", value);
68         sdkVersion = static_cast<int32_t>(strtol(value, DE_NULL, 10));
69         printf("SDK Version is %d\n", sdkVersion);
70     }
71     return sdkVersion;
72 }
73 
checkAnbApiBuild()74 static int32_t checkAnbApiBuild()
75 {
76     int32_t sdkVersion = androidGetSdkVersion();
77 #if !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
78     // When testing AHB on Android-O and newer the CTS must be compiled against API26 or newer.
79     DE_TEST_ASSERT(!(sdkVersion >= 26)); /* __ANDROID_API_O__ */
80 #endif                                   // !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
81 #if !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
82     // When testing AHB on Android-P and newer the CTS must be compiled against API28 or newer.
83     DE_TEST_ASSERT(!(sdkVersion >= 28)); /*__ANDROID_API_P__ */
84 #endif                                   // !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
85 #if !defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
86     // When testing AHB on Android-T and newer the CTS must be compiled against API33 or newer.
87     DE_TEST_ASSERT(!(sdkVersion >= 33)); /*__ANDROID_API_T__ */
88 #endif                                   // !defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
89 #if !defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
90     // When testing AHB on Android-U and newer the CTS must be compiled against API34 or newer.
91     DE_TEST_ASSERT(!(sdkVersion >= 34)); /*__ANDROID_API_U__ */
92 #endif                                   // !defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
93     return sdkVersion;
94 }
95 
supportsAhb()96 bool AndroidHardwareBufferExternalApi::supportsAhb()
97 {
98     return (checkAnbApiBuild() >= __ANDROID_API_O__);
99 }
100 
supportsCubeMap()101 bool AndroidHardwareBufferExternalApi::supportsCubeMap()
102 {
103     return (checkAnbApiBuild() >= 28);
104 }
105 
AndroidHardwareBufferExternalApi()106 AndroidHardwareBufferExternalApi::AndroidHardwareBufferExternalApi()
107 {
108     int32_t sdkVersion = checkAnbApiBuild();
109     if (sdkVersion >= __ANDROID_API_O__)
110     {
111 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
112         if (!loadAhbDynamicApis(sdkVersion))
113         {
114             // Couldn't load  Android AHB system APIs.
115             DE_TEST_ASSERT(false);
116         }
117 #else
118         // Invalid Android AHB APIs configuration. Please check the instructions on how to build NDK for Android.
119         DE_TEST_ASSERT(false);
120 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
121     }
122 }
123 
~AndroidHardwareBufferExternalApi()124 AndroidHardwareBufferExternalApi::~AndroidHardwareBufferExternalApi()
125 {
126 }
127 
128 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
129 typedef int (*pfn_system_property_get)(const char *, char *);
130 typedef int (*pfnAHardwareBuffer_allocate)(const AHardwareBuffer_Desc *desc, AHardwareBuffer **outBuffer);
131 typedef void (*pfnAHardwareBuffer_describe)(const AHardwareBuffer *buffer, AHardwareBuffer_Desc *outDesc);
132 typedef void (*pfnAHardwareBuffer_acquire)(AHardwareBuffer *buffer);
133 typedef void (*pfnAHardwareBuffer_release)(AHardwareBuffer *buffer);
134 typedef int (*pfnAHardwareBuffer_lock)(AHardwareBuffer *buffer, uint64_t usage, int32_t fence, const ARect *rect,
135                                        void **outVirtualAddress);
136 typedef int (*pfnAHardwareBuffer_unlock)(AHardwareBuffer *buffer, int32_t *fence);
137 
138 #if defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
139 typedef int (*pfnAHardwareBuffer_lockPlanes)(AHardwareBuffer *buffer, uint64_t usage, int32_t fence, const ARect *rect,
140                                              AHardwareBuffer_Planes *outPlanes);
141 #endif // defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
142 
143 struct AhbFunctions
144 {
145     pfnAHardwareBuffer_allocate allocate;
146     pfnAHardwareBuffer_describe describe;
147     pfnAHardwareBuffer_acquire acquire;
148     pfnAHardwareBuffer_release release;
149     pfnAHardwareBuffer_lock lock;
150     pfnAHardwareBuffer_unlock unlock;
151 #if defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
152     pfnAHardwareBuffer_lockPlanes lockPlanes; // Introduced in SDK 29
153 #endif                                        // defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
154 };
155 
156 static AhbFunctions ahbFunctions;
157 
ahbFunctionsLoaded(AhbFunctions * pAhbFunctions)158 static bool ahbFunctionsLoaded(AhbFunctions *pAhbFunctions)
159 {
160     static bool ahbApiLoaded = false;
161     if (ahbApiLoaded || ((pAhbFunctions->allocate != DE_NULL) && (pAhbFunctions->describe != DE_NULL) &&
162                          (pAhbFunctions->acquire != DE_NULL) && (pAhbFunctions->release != DE_NULL) &&
163                          (pAhbFunctions->lock != DE_NULL) && (pAhbFunctions->unlock != DE_NULL)
164 #if defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
165                          && (pAhbFunctions->lockPlanes != DE_NULL)
166 #endif // defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
167                              ))
168     {
169         ahbApiLoaded = true;
170         return true;
171     }
172     return false;
173 }
174 
loadAhbDynamicApis(int32_t sdkVersion)175 bool AndroidHardwareBufferExternalApi::loadAhbDynamicApis(int32_t sdkVersion)
176 {
177     if (sdkVersion >= __ANDROID_API_O__)
178     {
179         if (!ahbFunctionsLoaded(&ahbFunctions))
180         {
181             static de::DynamicLibrary libnativewindow("libnativewindow.so");
182             ahbFunctions.allocate =
183                 reinterpret_cast<pfnAHardwareBuffer_allocate>(libnativewindow.getFunction("AHardwareBuffer_allocate"));
184             ahbFunctions.describe =
185                 reinterpret_cast<pfnAHardwareBuffer_describe>(libnativewindow.getFunction("AHardwareBuffer_describe"));
186             ahbFunctions.acquire =
187                 reinterpret_cast<pfnAHardwareBuffer_acquire>(libnativewindow.getFunction("AHardwareBuffer_acquire"));
188             ahbFunctions.release =
189                 reinterpret_cast<pfnAHardwareBuffer_release>(libnativewindow.getFunction("AHardwareBuffer_release"));
190             ahbFunctions.lock =
191                 reinterpret_cast<pfnAHardwareBuffer_lock>(libnativewindow.getFunction("AHardwareBuffer_lock"));
192             ahbFunctions.unlock =
193                 reinterpret_cast<pfnAHardwareBuffer_unlock>(libnativewindow.getFunction("AHardwareBuffer_unlock"));
194 #if defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
195             ahbFunctions.lockPlanes = reinterpret_cast<pfnAHardwareBuffer_lockPlanes>(
196                 libnativewindow.getFunction("AHardwareBuffer_lockPlanes"));
197 #endif // defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
198 
199             return ahbFunctionsLoaded(&ahbFunctions);
200         }
201         else
202         {
203             return true;
204         }
205     }
206 
207     return false;
208 }
209 
210 class AndroidHardwareBufferExternalApi26 : public AndroidHardwareBufferExternalApi
211 {
212 public:
213     vk::pt::AndroidHardwareBufferPtr allocate(uint32_t width, uint32_t height, uint32_t layers, uint32_t format,
214                                               uint64_t usage) override;
215     void acquire(vk::pt::AndroidHardwareBufferPtr buffer) override;
216     void release(vk::pt::AndroidHardwareBufferPtr buffer) override;
217     void describe(const vk::pt::AndroidHardwareBufferPtr buffer, uint32_t *width, uint32_t *height, uint32_t *layers,
218                   uint32_t *format, uint64_t *usage, uint32_t *stride) override;
219     void *lock(vk::pt::AndroidHardwareBufferPtr buffer, uint64_t usage) override;
220     bool lockPlanes(vk::pt::AndroidHardwareBufferPtr buffer, uint64_t usage, uint32_t &planeCount, void *planeData[4],
221                     uint32_t planeStride[4], uint32_t planeRowStride[4]) override;
222     bool unlock(vk::pt::AndroidHardwareBufferPtr buffer) override;
223     uint64_t vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlag) override;
224     uint64_t vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag) override;
225     uint32_t vkFormatToAhbFormat(vk::VkFormat vkFormat) override;
226     uint64_t mustSupportAhbUsageFlags() override;
ahbFormatIsBlob(uint32_t ahbFormat)227     bool ahbFormatIsBlob(uint32_t ahbFormat) override
228     {
229         return (ahbFormat == AHARDWAREBUFFER_FORMAT_BLOB);
230     };
ahbFormatIsYuv(uint32_t)231     bool ahbFormatIsYuv(uint32_t) override
232     {
233         return false;
234     };
235     std::vector<uint32_t> getAllSupportedFormats() override;
236     const char *getFormatAsString(uint32_t format) override;
237 
AndroidHardwareBufferExternalApi26()238     AndroidHardwareBufferExternalApi26() : AndroidHardwareBufferExternalApi(){};
~AndroidHardwareBufferExternalApi26()239     virtual ~AndroidHardwareBufferExternalApi26(){};
240 
241 private:
242     // Stop the compiler generating methods of copy the object
243     AndroidHardwareBufferExternalApi26(AndroidHardwareBufferExternalApi26 const &copy);            // Not Implemented
244     AndroidHardwareBufferExternalApi26 &operator=(AndroidHardwareBufferExternalApi26 const &copy); // Not Implemented
245 };
246 
allocate(uint32_t width,uint32_t height,uint32_t layers,uint32_t format,uint64_t usage)247 vk::pt::AndroidHardwareBufferPtr AndroidHardwareBufferExternalApi26::allocate(uint32_t width, uint32_t height,
248                                                                               uint32_t layers, uint32_t format,
249                                                                               uint64_t usage)
250 {
251     AHardwareBuffer_Desc hbufferdesc = {
252         width,  height,
253         layers, // number of images
254         format, usage,
255         0u, // Stride in pixels, ignored for AHardwareBuffer_allocate()
256         0u, // Initialize to zero, reserved for future use
257         0u  // Initialize to zero, reserved for future use
258     };
259 
260     AHardwareBuffer *hbuffer = DE_NULL;
261     ahbFunctions.allocate(&hbufferdesc, &hbuffer);
262 
263     return vk::pt::AndroidHardwareBufferPtr(hbuffer);
264 }
265 
acquire(vk::pt::AndroidHardwareBufferPtr buffer)266 void AndroidHardwareBufferExternalApi26::acquire(vk::pt::AndroidHardwareBufferPtr buffer)
267 {
268     ahbFunctions.acquire(static_cast<AHardwareBuffer *>(buffer.internal));
269 }
270 
release(vk::pt::AndroidHardwareBufferPtr buffer)271 void AndroidHardwareBufferExternalApi26::release(vk::pt::AndroidHardwareBufferPtr buffer)
272 {
273     ahbFunctions.release(static_cast<AHardwareBuffer *>(buffer.internal));
274 }
275 
describe(const vk::pt::AndroidHardwareBufferPtr buffer,uint32_t * width,uint32_t * height,uint32_t * layers,uint32_t * format,uint64_t * usage,uint32_t * stride)276 void AndroidHardwareBufferExternalApi26::describe(const vk::pt::AndroidHardwareBufferPtr buffer, uint32_t *width,
277                                                   uint32_t *height, uint32_t *layers, uint32_t *format, uint64_t *usage,
278                                                   uint32_t *stride)
279 {
280     AHardwareBuffer_Desc desc;
281     ahbFunctions.describe(static_cast<const AHardwareBuffer *>(buffer.internal), &desc);
282     if (width)
283         *width = desc.width;
284     if (height)
285         *height = desc.height;
286     if (layers)
287         *layers = desc.layers;
288     if (format)
289         *format = desc.format;
290     if (usage)
291         *usage = desc.usage;
292     if (stride)
293         *stride = desc.stride;
294 }
295 
lock(vk::pt::AndroidHardwareBufferPtr buffer,uint64_t usage)296 void *AndroidHardwareBufferExternalApi26::lock(vk::pt::AndroidHardwareBufferPtr buffer, uint64_t usage)
297 {
298     void *data        = nullptr;
299     int32_t fence     = -1;      // No fence
300     const ARect *rect = nullptr; // NULL rect means all buffer access
301     int result        = ahbFunctions.lock(static_cast<AHardwareBuffer *>(buffer.internal), usage, fence, rect, &data);
302     return result == 0 ? data : nullptr;
303 }
304 
lockPlanes(vk::pt::AndroidHardwareBufferPtr,uint64_t,uint32_t &,void * [4],uint32_t[4],uint32_t[4])305 bool AndroidHardwareBufferExternalApi26::lockPlanes(vk::pt::AndroidHardwareBufferPtr, uint64_t, uint32_t &, void *[4],
306                                                     uint32_t[4], uint32_t[4])
307 {
308     // SDK 26 does not support locking planes
309     return false;
310 }
311 
unlock(vk::pt::AndroidHardwareBufferPtr buffer)312 bool AndroidHardwareBufferExternalApi26::unlock(vk::pt::AndroidHardwareBufferPtr buffer)
313 {
314     int32_t *fence = nullptr; // No fence
315 
316     // 0 is the success code for the unlock function
317     return (ahbFunctions.unlock(static_cast<AHardwareBuffer *>(buffer.internal), fence) == 0u);
318 }
319 
vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlags)320 uint64_t AndroidHardwareBufferExternalApi26::vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlags)
321 {
322     switch (vkFlags)
323     {
324     case vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
325     case vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT:
326         // No AHB equivalent.
327         return 0u;
328     case vk::VK_IMAGE_USAGE_SAMPLED_BIT:
329         return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
330     case vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT:
331         return AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
332     case vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
333     case vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT:
334         // Alias of AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER which is defined in later Android API versions.
335         return AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
336     default:
337         return 0u;
338     }
339 }
340 
vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)341 uint64_t AndroidHardwareBufferExternalApi26::vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)
342 {
343     switch (vkFlags)
344     {
345     case vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT:
346     case vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT:
347         // No AHB equivalent.
348         return 0u;
349     case vk::VK_IMAGE_CREATE_PROTECTED_BIT:
350         return AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
351     default:
352         return 0u;
353     }
354 }
355 
vkFormatToAhbFormat(vk::VkFormat vkFormat)356 uint32_t AndroidHardwareBufferExternalApi26::vkFormatToAhbFormat(vk::VkFormat vkFormat)
357 {
358     switch (vkFormat)
359     {
360     case vk::VK_FORMAT_R8G8B8A8_UNORM:
361         return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
362     case vk::VK_FORMAT_R8G8B8_UNORM:
363         return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
364     case vk::VK_FORMAT_R5G6B5_UNORM_PACK16:
365         return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
366     case vk::VK_FORMAT_R16G16B16A16_SFLOAT:
367         return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
368     case vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32:
369         return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
370     default:
371         return 0u;
372     }
373 }
374 
mustSupportAhbUsageFlags()375 uint64_t AndroidHardwareBufferExternalApi26::mustSupportAhbUsageFlags()
376 {
377     return (AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT);
378 }
379 
getAllSupportedFormats()380 std::vector<uint32_t> AndroidHardwareBufferExternalApi26::getAllSupportedFormats()
381 {
382     std::vector<uint32_t> formats = {
383         AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
384         AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
385         AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM,
386         AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM,
387         AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT,
388         AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM,
389         AHARDWAREBUFFER_FORMAT_BLOB,
390     };
391 
392     return formats;
393 }
394 
getFormatAsString(uint32_t format)395 const char *AndroidHardwareBufferExternalApi26::getFormatAsString(uint32_t format)
396 {
397     switch (format)
398     {
399     case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
400         return "AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM";
401     case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
402         return "AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM";
403     case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
404         return "AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM";
405     case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
406         return "AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM";
407     case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
408         return "AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT";
409     case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
410         return "AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM";
411     case AHARDWAREBUFFER_FORMAT_BLOB:
412         return "AHARDWAREBUFFER_FORMAT_BLOB";
413     default:
414         return "Unknown";
415     }
416 }
417 
418 #if defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
419 class AndroidHardwareBufferExternalApi28 : public AndroidHardwareBufferExternalApi26
420 {
421 public:
422     uint64_t vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag) override;
423     uint32_t vkFormatToAhbFormat(vk::VkFormat vkFormat) override;
424     uint64_t mustSupportAhbUsageFlags() override;
425     std::vector<uint32_t> getAllSupportedFormats() override;
426     const char *getFormatAsString(uint32_t format) override;
427 
AndroidHardwareBufferExternalApi28()428     AndroidHardwareBufferExternalApi28() : AndroidHardwareBufferExternalApi26(){};
~AndroidHardwareBufferExternalApi28()429     virtual ~AndroidHardwareBufferExternalApi28(){};
430 
431 private:
432     // Stop the compiler generating methods of copy the object
433     AndroidHardwareBufferExternalApi28(AndroidHardwareBufferExternalApi28 const &copy);            // Not Implemented
434     AndroidHardwareBufferExternalApi28 &operator=(AndroidHardwareBufferExternalApi28 const &copy); // Not Implemented
435 };
436 
vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)437 uint64_t AndroidHardwareBufferExternalApi28::vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlags)
438 {
439     switch (vkFlags)
440     {
441     case vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT:
442         return AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
443     default:
444         return AndroidHardwareBufferExternalApi26::vkCreateToAhbUsage(vkFlags);
445     }
446 }
447 
vkFormatToAhbFormat(vk::VkFormat vkFormat)448 uint32_t AndroidHardwareBufferExternalApi28::vkFormatToAhbFormat(vk::VkFormat vkFormat)
449 {
450     switch (vkFormat)
451     {
452     case vk::VK_FORMAT_D16_UNORM:
453         return AHARDWAREBUFFER_FORMAT_D16_UNORM;
454     case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
455         return AHARDWAREBUFFER_FORMAT_D24_UNORM;
456     case vk::VK_FORMAT_D24_UNORM_S8_UINT:
457         return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT;
458     case vk::VK_FORMAT_D32_SFLOAT:
459         return AHARDWAREBUFFER_FORMAT_D32_FLOAT;
460     case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
461         return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT;
462     case vk::VK_FORMAT_S8_UINT:
463         return AHARDWAREBUFFER_FORMAT_S8_UINT;
464     default:
465         return AndroidHardwareBufferExternalApi26::vkFormatToAhbFormat(vkFormat);
466     }
467 }
468 
mustSupportAhbUsageFlags()469 uint64_t AndroidHardwareBufferExternalApi28::mustSupportAhbUsageFlags()
470 {
471     return AndroidHardwareBufferExternalApi26::mustSupportAhbUsageFlags() | AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP |
472            AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE;
473 }
474 
getAllSupportedFormats()475 std::vector<uint32_t> AndroidHardwareBufferExternalApi28::getAllSupportedFormats()
476 {
477     std::vector<uint32_t> formats = AndroidHardwareBufferExternalApi26::getAllSupportedFormats();
478 
479     formats.emplace_back(AHARDWAREBUFFER_FORMAT_D16_UNORM);
480     formats.emplace_back(AHARDWAREBUFFER_FORMAT_D24_UNORM);
481     formats.emplace_back(AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT);
482     formats.emplace_back(AHARDWAREBUFFER_FORMAT_D32_FLOAT);
483     formats.emplace_back(AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT);
484     formats.emplace_back(AHARDWAREBUFFER_FORMAT_S8_UINT);
485 
486     return formats;
487 }
488 
getFormatAsString(uint32_t format)489 const char *AndroidHardwareBufferExternalApi28::getFormatAsString(uint32_t format)
490 {
491     switch (format)
492     {
493     case AHARDWAREBUFFER_FORMAT_D16_UNORM:
494         return "AHARDWAREBUFFER_FORMAT_D16_UNORM";
495     case AHARDWAREBUFFER_FORMAT_D24_UNORM:
496         return "AHARDWAREBUFFER_FORMAT_D24_UNORM";
497     case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
498         return "AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT";
499     case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
500         return "AHARDWAREBUFFER_FORMAT_D32_FLOAT";
501     case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
502         return "AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT";
503     case AHARDWAREBUFFER_FORMAT_S8_UINT:
504         return "AHARDWAREBUFFER_FORMAT_S8_UINT";
505     default:
506         return AndroidHardwareBufferExternalApi26::getFormatAsString(format);
507     }
508 }
509 
510 #endif // defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
511 
512 #if defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
513 class AndroidHardwareBufferExternalApi33 : public AndroidHardwareBufferExternalApi28
514 {
515 public:
516     bool lockPlanes(vk::pt::AndroidHardwareBufferPtr buffer, uint64_t usage, uint32_t &planeCount, void *planeData[4],
517                     uint32_t planeStride[4], uint32_t planeRowStride[4]) override;
518 
519     uint32_t vkFormatToAhbFormat(vk::VkFormat vkFormat) override;
520     std::vector<uint32_t> getAllSupportedFormats() override;
521     const char *getFormatAsString(uint32_t format) override;
ahbFormatIsYuv(uint32_t format)522     bool ahbFormatIsYuv(uint32_t format) override
523     {
524         return (format == AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420) || (format == AHARDWAREBUFFER_FORMAT_YCbCr_P010);
525     }
526 
AndroidHardwareBufferExternalApi33()527     AndroidHardwareBufferExternalApi33() : AndroidHardwareBufferExternalApi28(){};
~AndroidHardwareBufferExternalApi33()528     virtual ~AndroidHardwareBufferExternalApi33(){};
529 
530 private:
531     // Stop the compiler generating methods of copy the object
532     AndroidHardwareBufferExternalApi33(AndroidHardwareBufferExternalApi33 const &copy);            // Not Implemented
533     AndroidHardwareBufferExternalApi33 &operator=(AndroidHardwareBufferExternalApi33 const &copy); // Not Implemented
534 };
535 
lockPlanes(vk::pt::AndroidHardwareBufferPtr buffer,uint64_t usage,uint32_t & planeCountOut,void * planeDataOut[4],uint32_t planePixelStrideOut[4],uint32_t planeRowStrideOut[4])536 bool AndroidHardwareBufferExternalApi33::lockPlanes(vk::pt::AndroidHardwareBufferPtr buffer, uint64_t usage,
537                                                     uint32_t &planeCountOut, void *planeDataOut[4],
538                                                     uint32_t planePixelStrideOut[4], uint32_t planeRowStrideOut[4])
539 {
540     AHardwareBuffer_Planes planes;
541     int32_t fence     = -1;      // No fence
542     const ARect *rect = nullptr; // NULL rect means all buffer access
543     const int lockResult =
544         ahbFunctions.lockPlanes(static_cast<AHardwareBuffer *>(buffer.internal), usage, fence, rect, &planes);
545     const bool succeeded = (lockResult == 0);
546 
547     if (succeeded)
548     {
549         planeCountOut = planes.planeCount;
550         for (uint32_t i = 0; i < planeCountOut; ++i)
551         {
552             planeDataOut[i]        = planes.planes[i].data;
553             planePixelStrideOut[i] = planes.planes[i].pixelStride;
554             planeRowStrideOut[i]   = planes.planes[i].rowStride;
555         }
556     }
557 
558     return succeeded;
559 }
560 
vkFormatToAhbFormat(vk::VkFormat vkFormat)561 uint32_t AndroidHardwareBufferExternalApi33::vkFormatToAhbFormat(vk::VkFormat vkFormat)
562 {
563     switch (vkFormat)
564     {
565     case vk::VK_FORMAT_R8_UNORM:
566         return AHARDWAREBUFFER_FORMAT_R8_UNORM;
567     default:
568         return AndroidHardwareBufferExternalApi28::vkFormatToAhbFormat(vkFormat);
569     }
570 }
571 
getAllSupportedFormats()572 std::vector<uint32_t> AndroidHardwareBufferExternalApi33::getAllSupportedFormats()
573 {
574     std::vector<uint32_t> formats = AndroidHardwareBufferExternalApi28::getAllSupportedFormats();
575 
576     formats.emplace_back(AHARDWAREBUFFER_FORMAT_R8_UNORM);
577     formats.emplace_back(AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420); // Unsure if this was added in SDK 30
578     formats.emplace_back(AHARDWAREBUFFER_FORMAT_YCbCr_P010);
579 
580     return formats;
581 }
582 
getFormatAsString(uint32_t format)583 const char *AndroidHardwareBufferExternalApi33::getFormatAsString(uint32_t format)
584 {
585     switch (format)
586     {
587     case AHARDWAREBUFFER_FORMAT_R8_UNORM:
588         return "AHARDWAREBUFFER_FORMAT_R8_UNORM";
589     case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
590         return "AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420";
591     case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
592         return "AHARDWAREBUFFER_FORMAT_YCbCr_P010";
593     default:
594         return AndroidHardwareBufferExternalApi28::getFormatAsString(format);
595     }
596 }
597 
598 #endif // defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
599 
600 #if defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
601 class AndroidHardwareBufferExternalApi34 : public AndroidHardwareBufferExternalApi33
602 {
603 public:
604     uint32_t vkFormatToAhbFormat(vk::VkFormat vkFormat) override;
605     std::vector<uint32_t> getAllSupportedFormats() override;
606     const char *getFormatAsString(uint32_t format) override;
607 
AndroidHardwareBufferExternalApi34()608     AndroidHardwareBufferExternalApi34() : AndroidHardwareBufferExternalApi33(){};
~AndroidHardwareBufferExternalApi34()609     virtual ~AndroidHardwareBufferExternalApi34(){};
610 
611 private:
612     // Stop the compiler generating methods of copy the object
613     AndroidHardwareBufferExternalApi34(AndroidHardwareBufferExternalApi34 const &copy);            // Not Implemented
614     AndroidHardwareBufferExternalApi34 &operator=(AndroidHardwareBufferExternalApi34 const &copy); // Not Implemented
615 };
616 
vkFormatToAhbFormat(vk::VkFormat vkFormat)617 uint32_t AndroidHardwareBufferExternalApi34::vkFormatToAhbFormat(vk::VkFormat vkFormat)
618 {
619     switch (vkFormat)
620     {
621     case vk::VK_FORMAT_R16_UINT:
622         return AHARDWAREBUFFER_FORMAT_R16_UINT;
623     case vk::VK_FORMAT_R16G16_UINT:
624         return AHARDWAREBUFFER_FORMAT_R16G16_UINT;
625     case vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
626         return AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
627     default:
628         return AndroidHardwareBufferExternalApi33::vkFormatToAhbFormat(vkFormat);
629     }
630 }
631 
getAllSupportedFormats()632 std::vector<uint32_t> AndroidHardwareBufferExternalApi34::getAllSupportedFormats()
633 {
634     std::vector<uint32_t> formats = AndroidHardwareBufferExternalApi33::getAllSupportedFormats();
635 
636     formats.emplace_back(AHARDWAREBUFFER_FORMAT_R16_UINT);
637     formats.emplace_back(AHARDWAREBUFFER_FORMAT_R16G16_UINT);
638     formats.emplace_back(AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM);
639 
640     return formats;
641 }
642 
getFormatAsString(uint32_t format)643 const char *AndroidHardwareBufferExternalApi34::getFormatAsString(uint32_t format)
644 {
645     switch (format)
646     {
647     case AHARDWAREBUFFER_FORMAT_R16_UINT:
648         return "AHARDWAREBUFFER_FORMAT_R16_UINT";
649     case AHARDWAREBUFFER_FORMAT_R16G16_UINT:
650         return "AHARDWAREBUFFER_FORMAT_R16G16_UINT";
651     case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
652         return "AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM";
653     default:
654         return AndroidHardwareBufferExternalApi33::getFormatAsString(format);
655     }
656 }
657 
658 #endif // defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
659 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
660 #endif // (DE_OS == DE_OS_ANDROID)
661 
getInstance()662 AndroidHardwareBufferExternalApi *AndroidHardwareBufferExternalApi::getInstance()
663 {
664 #if (DE_OS == DE_OS_ANDROID)
665     int32_t sdkVersion = checkAnbApiBuild();
666 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
667 #if defined(__ANDROID_API_U__) && (DE_ANDROID_API >= __ANDROID_API_U__)
668     if (sdkVersion >= __ANDROID_API_U__)
669     {
670         static AndroidHardwareBufferExternalApi34 api34Instance;
671         return &api34Instance;
672     }
673 #endif // defined(__ANDROID_API_U__) && (DE_ANDROID_API >= __ANDROID_API_U__)
674 
675 #if defined(__ANDROID_API_T__) && (DE_ANDROID_API >= __ANDROID_API_T__)
676     if (sdkVersion >= __ANDROID_API_T__)
677     {
678         static AndroidHardwareBufferExternalApi33 api33Instance;
679         return &api33Instance;
680     }
681 #endif // defined(__ANDROID_API_T__) && (DE_ANDROID_API >= __ANDROID_API_T__)
682 
683 #if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
684     if (sdkVersion >= __ANDROID_API_P__)
685     {
686         static AndroidHardwareBufferExternalApi28 api28Instance;
687         return &api28Instance;
688     }
689 #endif // defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
690 
691 #if defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
692     if (sdkVersion >= __ANDROID_API_O__)
693     {
694         static AndroidHardwareBufferExternalApi26 api26Instance;
695         return &api26Instance;
696     }
697 #endif // defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
698 
699 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
700     DE_UNREF(sdkVersion);
701 #endif // DE_OS == DE_OS_ANDROID
702     return DE_NULL;
703 }
704 
getSdkVersion()705 int32_t AndroidHardwareBufferInstance::getSdkVersion()
706 {
707 #if (DE_OS == DE_OS_ANDROID)
708     return androidGetSdkVersion();
709 #endif // (DE_OS == DE_OS_ANDROID)
710     return 0u;
711 }
712 
isFormatSupported(Format format)713 bool AndroidHardwareBufferInstance::isFormatSupported(Format format)
714 {
715     switch (format)
716     {
717 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
718     case Format::R8G8B8A8_UNORM:
719     case Format::R8G8B8X8_UNORM:
720     case Format::R8G8B8_UNORM:
721     case Format::R5G6B5_UNORM:
722     case Format::R16G16B16A16_FLOAT:
723     case Format::R10G10B10A2_UNORM:
724     case Format::BLOB:
725 
726 #if defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
727     case Format::D16_UNORM:
728     case Format::D24_UNORM:
729     case Format::D24_UNORM_S8_UINT:
730     case Format::D32_FLOAT:
731     case Format::D32_FLOAT_S8_UINT:
732     case Format::S8_UINT:
733 #endif // defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
734 
735 #if defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
736     case Format::Y8Cb8Cr8_420:
737     case Format::YCbCr_P010:
738     case Format::R8_UNORM:
739 #endif // defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
740 
741 #if defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
742     case Format::R16_UINT:
743     case Format::R16G16_UINT:
744     case Format::R10G10B10A10_UNORM:
745 #endif // defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
746 
747     case Format::B8G8R8A8_UNORM:
748     case Format::YV12:
749     case Format::Y8:
750     case Format::Y16:
751     case Format::RAW16:
752     case Format::RAW10:
753     case Format::RAW12:
754     case Format::RAW_OPAQUE:
755     case Format::IMPLEMENTATION_DEFINED:
756     case Format::NV16:
757     case Format::NV21:
758     case Format::YUY2:
759         return true;
760 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
761 
762     default:
763         return false;
764     }
765 }
766 
isFormatYuv(Format format)767 bool AndroidHardwareBufferInstance::isFormatYuv(Format format)
768 {
769     switch (format)
770     {
771     case Format::Y8Cb8Cr8_420:
772     case Format::YCbCr_P010:
773     case Format::YV12:
774     case Format::Y8:
775     case Format::Y16:
776     case Format::NV16:
777     case Format::NV21:
778     case Format::YUY2:
779         return true;
780     default:
781         return false;
782     }
783 }
784 
isFormatRaw(Format format)785 bool AndroidHardwareBufferInstance::isFormatRaw(Format format)
786 {
787     switch (format)
788     {
789     case Format::RAW10:
790     case Format::RAW12:
791     case Format::RAW16:
792     case Format::RAW_OPAQUE:
793         return true;
794     default:
795         return false;
796     }
797 }
798 
isFormatColor(Format format)799 bool AndroidHardwareBufferInstance::isFormatColor(Format format)
800 {
801     switch (format)
802     {
803     case Format::R8G8B8A8_UNORM:
804     case Format::R8G8B8X8_UNORM:
805     case Format::R8G8B8_UNORM:
806     case Format::R5G6B5_UNORM:
807     case Format::R16G16B16A16_FLOAT:
808     case Format::R10G10B10A2_UNORM:
809     case Format::Y8Cb8Cr8_420:
810     case Format::YCbCr_P010:
811     case Format::R8_UNORM:
812     case Format::R16_UINT:
813     case Format::R16G16_UINT:
814     case Format::R10G10B10A10_UNORM:
815     case Format::B8G8R8A8_UNORM:
816     case Format::YV12:
817     case Format::Y8:
818     case Format::Y16:
819     case Format::IMPLEMENTATION_DEFINED:
820     case Format::NV16:
821     case Format::NV21:
822     case Format::YUY2:
823         return true;
824     default:
825         return false;
826     }
827 }
828 
isFormatDepth(Format format)829 bool AndroidHardwareBufferInstance::isFormatDepth(Format format)
830 {
831     switch (format)
832     {
833     case Format::D16_UNORM:
834     case Format::D24_UNORM:
835     case Format::D24_UNORM_S8_UINT:
836     case Format::D32_FLOAT:
837     case Format::D32_FLOAT_S8_UINT:
838         return true;
839     default:
840         return false;
841     }
842 }
843 
isFormatStencil(Format format)844 bool AndroidHardwareBufferInstance::isFormatStencil(Format format)
845 {
846     switch (format)
847     {
848     case Format::D24_UNORM_S8_UINT:
849     case Format::D32_FLOAT_S8_UINT:
850     case Format::S8_UINT:
851         return true;
852     default:
853         return false;
854     }
855 }
856 
hasFormatAlpha(Format format)857 bool AndroidHardwareBufferInstance::hasFormatAlpha(Format format)
858 {
859     switch (format)
860     {
861     case Format::R8G8B8A8_UNORM:
862     case Format::R16G16B16A16_FLOAT:
863     case Format::R10G10B10A2_UNORM:
864     case Format::R10G10B10A10_UNORM:
865     case Format::B8G8R8A8_UNORM:
866         return true;
867     default:
868         return false;
869     }
870 }
871 
getFormatName(Format format)872 const char *AndroidHardwareBufferInstance::getFormatName(Format format)
873 {
874     switch (format)
875     {
876     case Format::R8G8B8A8_UNORM:
877         return "AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM";
878     case Format::R8G8B8X8_UNORM:
879         return "AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM";
880     case Format::R8G8B8_UNORM:
881         return "AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM";
882     case Format::R5G6B5_UNORM:
883         return "AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM";
884     case Format::R16G16B16A16_FLOAT:
885         return "AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT";
886     case Format::R10G10B10A2_UNORM:
887         return "AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM";
888     case Format::BLOB:
889         return "AHARDWAREBUFFER_FORMAT_BLOB";
890     case Format::D16_UNORM:
891         return "AHARDWAREBUFFER_FORMAT_D16_UNORM";
892     case Format::D24_UNORM:
893         return "AHARDWAREBUFFER_FORMAT_D24_UNORM";
894     case Format::D24_UNORM_S8_UINT:
895         return "AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT";
896     case Format::D32_FLOAT:
897         return "AHARDWAREBUFFER_FORMAT_D32_FLOAT";
898     case Format::D32_FLOAT_S8_UINT:
899         return "AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT";
900     case Format::S8_UINT:
901         return "AHARDWAREBUFFER_FORMAT_S8_UINT";
902     case Format::Y8Cb8Cr8_420:
903         return "AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420";
904     case Format::YCbCr_P010:
905         return "AHARDWAREBUFFER_FORMAT_YCbCr_P010";
906     case Format::R8_UNORM:
907         return "AHARDWAREBUFFER_FORMAT_R8_UNORM";
908     case Format::R16_UINT:
909         return "AHARDWAREBUFFER_FORMAT_R16_UINT";
910     case Format::R16G16_UINT:
911         return "AHARDWAREBUFFER_FORMAT_R16G16_UINT";
912     case Format::R10G10B10A10_UNORM:
913         return "AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM";
914     case Format::B8G8R8A8_UNORM:
915         return "AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM";
916     case Format::YV12:
917         return "AHARDWAREBUFFER_FORMAT_YV12";
918     case Format::Y8:
919         return "AHARDWAREBUFFER_FORMAT_Y8";
920     case Format::Y16:
921         return "AHARDWAREBUFFER_FORMAT_Y16";
922     case Format::RAW16:
923         return "AHARDWAREBUFFER_FORMAT_RAW16";
924     case Format::RAW10:
925         return "AHARDWAREBUFFER_FORMAT_RAW10";
926     case Format::RAW12:
927         return "AHARDWAREBUFFER_FORMAT_RAW12";
928     case Format::RAW_OPAQUE:
929         return "AHARDWAREBUFFER_FORMAT_RAW_OPAQUE";
930     case Format::IMPLEMENTATION_DEFINED:
931         return "AHARDWAREBUFFER_FORMAT_IMPLEMENTATION_DEFINED";
932     case Format::NV16:
933         return "AHARDWAREBUFFER_FORMAT_YCbCr_422_SP";
934     case Format::NV21:
935         return "AHARDWAREBUFFER_FORMAT_YCrCb_420_SP";
936     case Format::YUY2:
937         return "AHARDWAREBUFFER_FORMAT_YCbCr_422_I";
938 
939     default:
940         return "Unknown";
941     }
942 }
943 
formatToInternalFormat(Format format)944 uint32_t AndroidHardwareBufferInstance::formatToInternalFormat(Format format)
945 {
946     switch (format)
947     {
948 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
949     case Format::R8G8B8A8_UNORM:
950         return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
951     case Format::R8G8B8X8_UNORM:
952         return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
953     case Format::R8G8B8_UNORM:
954         return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
955     case Format::R5G6B5_UNORM:
956         return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
957     case Format::R16G16B16A16_FLOAT:
958         return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
959     case Format::R10G10B10A2_UNORM:
960         return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
961     case Format::BLOB:
962         return AHARDWAREBUFFER_FORMAT_BLOB;
963 
964 #if defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
965     case Format::D16_UNORM:
966         return AHARDWAREBUFFER_FORMAT_D16_UNORM;
967     case Format::D24_UNORM:
968         return AHARDWAREBUFFER_FORMAT_D24_UNORM;
969     case Format::D24_UNORM_S8_UINT:
970         return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT;
971     case Format::D32_FLOAT:
972         return AHARDWAREBUFFER_FORMAT_D32_FLOAT;
973     case Format::D32_FLOAT_S8_UINT:
974         return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT;
975     case Format::S8_UINT:
976         return AHARDWAREBUFFER_FORMAT_S8_UINT;
977 #endif // defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
978 
979 #if defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
980     case Format::Y8Cb8Cr8_420:
981         return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
982     case Format::YCbCr_P010:
983         return AHARDWAREBUFFER_FORMAT_YCbCr_P010;
984     case Format::R8_UNORM:
985         return AHARDWAREBUFFER_FORMAT_R8_UNORM;
986 #endif // defined(BUILT_WITH_ANDROID_T_HARDWARE_BUFFER)
987 
988 #if defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
989     case Format::R16_UINT:
990         return AHARDWAREBUFFER_FORMAT_R16_UINT;
991     case Format::R16G16_UINT:
992         return AHARDWAREBUFFER_FORMAT_R16G16_UINT;
993     case Format::R10G10B10A10_UNORM:
994         return AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
995 #endif // defined(BUILT_WITH_ANDROID_U_HARDWARE_BUFFER)
996 
997     // Values obtained AOSP header (nativewindow/include/vndk/hardware_buffer.h)
998     case B8G8R8A8_UNORM:
999         return 5;
1000     case YV12:
1001         return 0x32315659;
1002     case Y8:
1003         return 0x20203859;
1004     case Y16:
1005         return 0x20363159;
1006     case RAW16:
1007         return 0x20;
1008     case RAW10:
1009         return 0x25;
1010     case RAW12:
1011         return 0x26;
1012     case RAW_OPAQUE:
1013         return 0x24;
1014     case IMPLEMENTATION_DEFINED:
1015         return 0x22;
1016     case NV16:
1017         return 0x10;
1018     case NV21:
1019         return 0x11;
1020     case YUY2:
1021         return 0x14;
1022 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1023 
1024     default:
1025         return 0u;
1026     }
1027 }
1028 
formatToTextureFormat(Format format)1029 tcu::TextureFormat AndroidHardwareBufferInstance::formatToTextureFormat(Format format)
1030 {
1031     switch (format)
1032     {
1033     case Format::R8G8B8A8_UNORM:
1034         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGBA, tcu::TextureFormat::ChannelType::UNORM_INT8);
1035     case Format::R8G8B8X8_UNORM:
1036         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGBA, tcu::TextureFormat::ChannelType::UNORM_INT8);
1037     case Format::R8G8B8_UNORM:
1038         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGB, tcu::TextureFormat::ChannelType::UNORM_INT8);
1039     case Format::R5G6B5_UNORM:
1040         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGB,
1041                                   tcu::TextureFormat::ChannelType::UNORM_SHORT_565);
1042     case Format::R16G16B16A16_FLOAT:
1043         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGBA, tcu::TextureFormat::ChannelType::HALF_FLOAT);
1044     case Format::R10G10B10A2_UNORM:
1045         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGBA,
1046                                   tcu::TextureFormat::ChannelType::UNORM_INT_1010102_REV);
1047     case Format::D16_UNORM:
1048         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::D, tcu::TextureFormat::ChannelType::UNORM_INT16);
1049     case Format::D24_UNORM:
1050         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::D, tcu::TextureFormat::ChannelType::UNORM_INT24);
1051     case Format::D24_UNORM_S8_UINT:
1052         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::DS,
1053                                   tcu::TextureFormat::ChannelType::UNSIGNED_INT_24_8_REV);
1054     case Format::D32_FLOAT:
1055         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::D, tcu::TextureFormat::ChannelType::FLOAT);
1056     case Format::S8_UINT:
1057         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::S, tcu::TextureFormat::ChannelType::UNSIGNED_INT8);
1058     case Format::Y8Cb8Cr8_420:
1059     case Format::YV12:
1060     case Format::NV16:
1061     case Format::NV21:
1062     case Format::YUY2:
1063         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGB, tcu::TextureFormat::ChannelType::UNORM_INT8);
1064     case Format::YCbCr_P010:
1065         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGB,
1066                                   tcu::TextureFormat::ChannelType::UNORM_INT_101010);
1067     case Format::R8_UNORM:
1068     case Format::Y8:
1069         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::R, tcu::TextureFormat::ChannelType::UNORM_INT8);
1070     case Format::Y16:
1071         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::R, tcu::TextureFormat::ChannelType::UNORM_INT16);
1072     case Format::RAW16:
1073     case Format::R16_UINT:
1074         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::R, tcu::TextureFormat::ChannelType::UNSIGNED_INT16);
1075     case Format::R16G16_UINT:
1076         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RG,
1077                                   tcu::TextureFormat::ChannelType::UNSIGNED_INT16);
1078     case Format::R10G10B10A10_UNORM:
1079         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::RGBA,
1080                                   tcu::TextureFormat::ChannelType::UNORM_SHORT_10);
1081 
1082     case Format::B8G8R8A8_UNORM:
1083         return tcu::TextureFormat(tcu::TextureFormat::ChannelOrder::BGRA, tcu::TextureFormat::ChannelType::UNORM_INT8);
1084     case Format::RAW10:
1085         return tcu::getUncompressedFormat(tcu::COMPRESSEDTEXFORMAT_AHB_RAW10);
1086     case Format::RAW12:
1087         return tcu::getUncompressedFormat(tcu::COMPRESSEDTEXFORMAT_AHB_RAW12);
1088 
1089     // Format::IMPLEMENTATION_DEFINED
1090     // Format::RAW_OPAQUE
1091     // Format::D32_FLOAT_S8_UINT
1092     // Format::BLOB
1093     default:
1094         return tcu::TextureFormat(); // Unassigned
1095     }
1096 }
1097 
vkChromaLocationToChromaLocation(vk::VkChromaLocation location)1098 AndroidHardwareBufferInstance::ChromaLocation AndroidHardwareBufferInstance::vkChromaLocationToChromaLocation(
1099     vk::VkChromaLocation location)
1100 {
1101     switch (location)
1102     {
1103     case vk::VK_CHROMA_LOCATION_COSITED_EVEN:
1104         return ChromaLocation::COSITED_EVEN;
1105     case vk::VK_CHROMA_LOCATION_MIDPOINT:
1106         return ChromaLocation::MIDPOINT;
1107     default:
1108         DE_ASSERT(false); // Should never reach this
1109         return ChromaLocation::COSITED_EVEN;
1110         break;
1111     }
1112 }
1113 
reduceYuvTexture(tcu::TextureLevel & texture,Format format,ChromaLocation xChroma,ChromaLocation yChroma)1114 void AndroidHardwareBufferInstance::reduceYuvTexture(tcu::TextureLevel &texture, Format format, ChromaLocation xChroma,
1115                                                      ChromaLocation yChroma)
1116 {
1117     switch (format)
1118     {
1119     // YUV 4:2:0
1120     case Y8Cb8Cr8_420:
1121     case YCbCr_P010:
1122     case YV12:
1123     case NV21:
1124         reduceYuv420Texture(texture, xChroma, yChroma);
1125         break;
1126 
1127     // YUV 4:2:2
1128     case NV16:
1129     case YUY2:
1130         reduceYuv422Texture(texture, xChroma);
1131         break;
1132 
1133     default:
1134         break;
1135     }
1136 }
1137 
reduceYuv420Texture(tcu::TextureLevel & texture,ChromaLocation xChroma,ChromaLocation yChroma)1138 void AndroidHardwareBufferInstance::reduceYuv420Texture(tcu::TextureLevel &texture, ChromaLocation xChroma,
1139                                                         ChromaLocation yChroma)
1140 {
1141     tcu::PixelBufferAccess access = texture.getAccess();
1142 
1143     for (int32_t y = 0; y < texture.getHeight(); y += 2)
1144     {
1145         for (int32_t x = 0; x < texture.getWidth(); x += 2)
1146         {
1147             tcu::Vec4 colors[4] = {access.getPixel(x, y), access.getPixel(x, y + 1), access.getPixel(x + 1, y),
1148                                    access.getPixel(x + 1, y + 1)};
1149             tcu::Vec2 chroma    = colors[0].xz();
1150             float texelCount    = 1.0f;
1151 
1152             if (yChroma == ChromaLocation::MIDPOINT)
1153             {
1154                 chroma += colors[1].xz();
1155                 texelCount += 1.0f;
1156 
1157                 if (xChroma == ChromaLocation::MIDPOINT)
1158                 {
1159                     chroma += colors[3].xz();
1160                     texelCount += 1.0f;
1161                 }
1162             }
1163 
1164             if (xChroma == ChromaLocation::MIDPOINT)
1165             {
1166                 chroma += colors[2].xz();
1167                 texelCount += 1.0f;
1168             }
1169 
1170             chroma = chroma / texelCount;
1171 
1172             colors[0].xz() = chroma;
1173             access.setPixel(colors[0], x, y);
1174             colors[1].xz() = chroma;
1175             access.setPixel(colors[1], x, y + 1);
1176             colors[2].xz() = chroma;
1177             access.setPixel(colors[2], x + 1, y);
1178             colors[3].xz() = chroma;
1179             access.setPixel(colors[3], x + 1, y + 1);
1180         }
1181     }
1182 }
1183 
reduceYuv422Texture(tcu::TextureLevel & texture,ChromaLocation xChroma)1184 void AndroidHardwareBufferInstance::reduceYuv422Texture(tcu::TextureLevel &texture, ChromaLocation xChroma)
1185 {
1186     tcu::PixelBufferAccess access = texture.getAccess();
1187 
1188     for (int32_t y = 0; y < texture.getHeight(); ++y)
1189     {
1190         for (int32_t x = 0; x < texture.getWidth(); x += 2)
1191         {
1192             tcu::Vec4 colors[2] = {access.getPixel(x, y), access.getPixel(x + 1, y)};
1193             tcu::Vec2 chroma    = colors[0].xz();
1194 
1195             if (xChroma == ChromaLocation::MIDPOINT)
1196             {
1197                 chroma += colors[1].xz();
1198                 chroma = chroma / 2.0f;
1199             }
1200 
1201             colors[0].xz() = chroma;
1202             access.setPixel(colors[0], x, y);
1203             colors[1].xz() = chroma;
1204             access.setPixel(colors[1], x + 1, y);
1205         }
1206     }
1207 }
1208 
usageToInternalUsage(Usage usage)1209 uint64_t AndroidHardwareBufferInstance::usageToInternalUsage(Usage usage)
1210 {
1211     uint64_t internalUsage = 0u;
1212 
1213 #if defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1214 
1215     // AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT used instead of AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER
1216     // due to the latter requiring higher SDK versions than the former
1217     if (usage & Usage::GPU_FRAMEBUFFER)
1218         internalUsage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
1219 
1220     if (usage & Usage::GPU_SAMPLED)
1221         internalUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
1222 
1223     if (usage & Usage::CPU_READ)
1224         internalUsage |= AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
1225 
1226     if (usage & Usage::CPU_WRITE)
1227         internalUsage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1228 #else
1229     DE_UNREF(usage);
1230 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
1231 
1232     return internalUsage;
1233 }
1234 
pixelStride(Format format)1235 uint32_t AndroidHardwareBufferInstance::pixelStride(Format format)
1236 {
1237     return tcu::getPixelSize(formatToTextureFormat(format));
1238 }
1239 
~AndroidHardwareBufferInstance(void)1240 AndroidHardwareBufferInstance::~AndroidHardwareBufferInstance(void)
1241 {
1242     release();
1243 }
1244 
allocate(Format format,uint32_t width,uint32_t height,uint32_t layers,Usage usage)1245 bool AndroidHardwareBufferInstance::allocate(Format format, uint32_t width, uint32_t height, uint32_t layers,
1246                                              Usage usage)
1247 {
1248     // Should never be called when there's no actual api to call with
1249     DE_ASSERT(m_ahbApi);
1250 
1251     // Don't allocate another buffer before releasing previous
1252     DE_ASSERT(m_handle.internal == nullptr);
1253 
1254     m_format         = format;
1255     m_internalFormat = formatToInternalFormat(m_format);
1256     m_usage          = usage;
1257     m_internalUsage  = usageToInternalUsage(m_usage);
1258     m_width          = width;
1259     m_height         = height;
1260     m_layers         = layers;
1261 
1262     m_handle = m_ahbApi->allocate(width, height, layers, m_internalFormat, m_internalUsage);
1263 
1264     return m_handle.internal != nullptr;
1265 }
1266 
release(void)1267 void AndroidHardwareBufferInstance::release(void)
1268 {
1269     if (m_handle.internal != nullptr)
1270     {
1271         // Should never be called when there's no actual api to call with
1272         DE_ASSERT(m_ahbApi);
1273 
1274         m_ahbApi->release(m_handle);
1275         m_handle.internal = nullptr;
1276     }
1277 }
1278 
lock(Usage usage)1279 bool AndroidHardwareBufferInstance::lock(Usage usage)
1280 {
1281     // Should never be called when there's no actual api to call with
1282     DE_ASSERT(m_ahbApi);
1283 
1284     // Only allowed to lock once
1285     DE_ASSERT(m_accessData.m_planeCount == 0);
1286 
1287     // Cannot lock what we don't have
1288     if (m_handle.internal == nullptr)
1289         return false;
1290 
1291     // Validate buffer was allocated with wanted usage
1292     if ((usage & m_usage) != usage)
1293         return false;
1294 
1295     bool lockSuccessful    = false;
1296     uint64_t internalUsage = usageToInternalUsage(usage);
1297 
1298     if (isYuv())
1299         lockSuccessful =
1300             m_ahbApi->lockPlanes(m_handle, internalUsage, m_accessData.m_planeCount, m_accessData.m_planeDataVoid,
1301                                  m_accessData.m_planePixelStride, m_accessData.m_planeRowStride);
1302     else
1303     {
1304         m_accessData.m_planeDataVoid[0] = m_ahbApi->lock(m_handle, internalUsage);
1305 
1306         // null data means locking failed
1307         if (m_accessData.m_planeDataVoid[0])
1308         {
1309             lockSuccessful = true;
1310 
1311             m_accessData.m_planePixelStride[0] = pixelStride(m_format);
1312             // Need to retrieve row stride from description (will only return how many pixels). Need to multiply by pixel size
1313             m_ahbApi->describe(m_handle, nullptr, nullptr, nullptr, nullptr, nullptr,
1314                                &m_accessData.m_planeRowStride[0]);
1315             m_accessData.m_planeRowStride[0] *= m_accessData.m_planePixelStride[0];
1316             m_accessData.m_planeCount = 1u; // Non planar formats will be treated as a single plane
1317         }
1318     }
1319 
1320     return lockSuccessful;
1321 }
1322 
unlock(void)1323 bool AndroidHardwareBufferInstance::unlock(void)
1324 {
1325     // Should never be called when there's no actual api to call with
1326     DE_ASSERT(m_ahbApi);
1327 
1328     // Force locking again if we want to read/write again
1329     m_accessData.m_planeCount = 0u;
1330 
1331     return m_ahbApi->unlock(m_handle);
1332 }
1333 
copyCpuBufferToAndroidBuffer(const tcu::TextureLevel & cpuBuffer)1334 void AndroidHardwareBufferInstance::copyCpuBufferToAndroidBuffer(const tcu::TextureLevel &cpuBuffer)
1335 {
1336     // Running into this assertion means no locking was performed
1337     DE_ASSERT(m_accessData.m_planeCount != 0);
1338 
1339     tcu::ConstPixelBufferAccess access = cpuBuffer.getAccess();
1340 
1341     for (uint32_t y = 0u; y < m_height; ++y)
1342     {
1343         for (uint32_t x = 0u; x < m_width; ++x)
1344         {
1345             const uint8_t *cpuBufferPixel = static_cast<const uint8_t *>(access.getPixelPtr(x, y));
1346             uint32_t offset = (y * m_accessData.m_planeRowStride[0]) + (x * m_accessData.m_planePixelStride[0]);
1347             uint8_t *androidBufferPixel = m_accessData.m_planeData[0] + offset;
1348 
1349             switch (m_format)
1350             {
1351             // YUV 4:2:0 formats
1352             case Y8Cb8Cr8_420:
1353             case YV12:
1354             case NV21:
1355                 DE_ASSERT(m_accessData.m_planeCount == 3u);
1356 
1357                 // Component size is UNSIGNED_INT8. We can copy values directly
1358                 // YUV need to map RGB the following way according to Vulkan spec:
1359                 // G is Y
1360                 // B is Cb
1361                 // R is Cr
1362 
1363                 // Plane 0 contains Y information
1364                 *(androidBufferPixel) = *(cpuBufferPixel + 1);
1365 
1366                 // Plane 1 contains Cb information
1367                 // 4:2:0 has half size for Cb
1368                 offset = ((y / 2) * m_accessData.m_planeRowStride[1]) + ((x / 2) * m_accessData.m_planePixelStride[1]);
1369                 androidBufferPixel    = m_accessData.m_planeData[1] + offset;
1370                 *(androidBufferPixel) = *(cpuBufferPixel + 2);
1371 
1372                 // Plane 2 contains Cr information
1373                 // 4:2:0 has half size for Cr
1374                 offset = ((y / 2) * m_accessData.m_planeRowStride[2]) + ((x / 2) * m_accessData.m_planePixelStride[2]);
1375                 androidBufferPixel    = m_accessData.m_planeData[2] + offset;
1376                 *(androidBufferPixel) = *(cpuBufferPixel);
1377 
1378                 break;
1379 
1380             // YUV 4:2:2 formats
1381             case NV16:
1382             case YUY2:
1383                 DE_ASSERT(m_accessData.m_planeCount == 3u);
1384 
1385                 // Component size is UNSIGNED_INT8. We can copy values directly
1386                 // YUV need to map RGB the following way according to Vulkan spec:
1387                 // G is Y
1388                 // B is Cb
1389                 // R is Cr
1390 
1391                 // Plane 0 contains Y information
1392                 *(androidBufferPixel) = *(cpuBufferPixel + 1);
1393 
1394                 // Plane 1 contains Cb information
1395                 // 4:2:2 has half width for Cb
1396                 offset = (y * m_accessData.m_planeRowStride[1]) + ((x / 2) * m_accessData.m_planePixelStride[1]);
1397                 androidBufferPixel    = m_accessData.m_planeData[1] + offset;
1398                 *(androidBufferPixel) = *(cpuBufferPixel + 2);
1399 
1400                 // Plane 2 contains Cr information
1401                 // 4:2:2 has half width for Cr
1402                 offset = (y * m_accessData.m_planeRowStride[2]) + ((x / 2) * m_accessData.m_planePixelStride[2]);
1403                 androidBufferPixel    = m_accessData.m_planeData[2] + offset;
1404                 *(androidBufferPixel) = *(cpuBufferPixel);
1405 
1406                 break;
1407 
1408             // YUV 4:2:0 format
1409             case YCbCr_P010:
1410             {
1411                 DE_ASSERT(m_accessData.m_planeCount == 3u);
1412 
1413                 // YCbCr_P010 does not have same comoponent size as m_cpuBuffer type (UNORM_INT_101010)
1414                 // We need to transform from UNORM_INT_101010 to YCbCr_P010 where data is stored in the higher bits of 16 bit values
1415 
1416                 uint32_t redOffset   = 22u;
1417                 uint32_t greenOffset = 12u;
1418                 uint32_t blueOffset  = 2u;
1419                 uint32_t bitOffset   = 6u;
1420                 uint32_t bitCount    = 10u;
1421                 uint32_t mask        = (1u << bitCount) - 1u;
1422                 uint32_t cpuValue    = *(reinterpret_cast<const uint32_t *>(cpuBufferPixel));
1423                 uint16_t red         = static_cast<uint16_t>(((cpuValue >> redOffset) & mask) << bitOffset);
1424                 uint16_t green       = static_cast<uint16_t>(((cpuValue >> greenOffset) & mask) << bitOffset);
1425                 uint16_t blue        = static_cast<uint16_t>(((cpuValue >> blueOffset) & mask) << bitOffset);
1426 
1427                 // m_cpuBuffer for YCbCr_P010 has order RGB, so we need to swizzle values
1428                 // Following Vulkan spec for ordering where:
1429                 // G is Y
1430                 // B is Cb
1431                 // R is Cr
1432 
1433                 // Plane 0 contains Y information
1434                 *(reinterpret_cast<uint16_t *>(androidBufferPixel)) = green;
1435 
1436                 // Plane 1 contains Cb information
1437                 // YCbCr_P010 is half size for Cb
1438                 offset = ((y / 2) * m_accessData.m_planeRowStride[1]) + ((x / 2) * m_accessData.m_planePixelStride[1]);
1439                 androidBufferPixel                                  = m_accessData.m_planeData[1] + offset;
1440                 *(reinterpret_cast<uint16_t *>(androidBufferPixel)) = blue;
1441 
1442                 // Plane 2 contains Cr information
1443                 // YCbCr_P010 is half size for Cr
1444                 offset = ((y / 2) * m_accessData.m_planeRowStride[2]) + ((x / 2) * m_accessData.m_planePixelStride[2]);
1445                 androidBufferPixel                                  = m_accessData.m_planeData[2] + offset;
1446                 *(reinterpret_cast<uint16_t *>(androidBufferPixel)) = red;
1447 
1448                 break;
1449             }
1450 
1451             case RAW10:
1452             case RAW12:
1453                 DE_ASSERT(false); // Use compressed variation
1454                 break;
1455 
1456             default:
1457                 memcpy(androidBufferPixel, cpuBufferPixel, m_accessData.m_planePixelStride[0]);
1458             }
1459         }
1460     }
1461 }
1462 
copyCpuBufferToAndroidBufferCompressed(const tcu::CompressedTexture & cpuBuffer)1463 void AndroidHardwareBufferInstance::copyCpuBufferToAndroidBufferCompressed(const tcu::CompressedTexture &cpuBuffer)
1464 {
1465     // Running into this assertion means no locking was performed
1466     DE_ASSERT(m_accessData.m_planeCount != 0);
1467 
1468     const uint8_t *cpuBufferPixel = static_cast<const uint8_t *>(cpuBuffer.getData());
1469 
1470     for (uint32_t y = 0u; y < m_height; ++y)
1471     {
1472         for (uint32_t x = 0u; x < m_width; ++x)
1473         {
1474             uint32_t offset = (y * m_accessData.m_planeRowStride[0]) + (x * m_accessData.m_planePixelStride[0]);
1475             uint8_t *androidBufferPixel = m_accessData.m_planeData[0] + offset;
1476 
1477             switch (m_format)
1478             {
1479             case RAW10:
1480             {
1481                 DE_ASSERT(m_accessData.m_planeCount == 1u);
1482 
1483                 // Packed format with 4 pixels in 5 bytes
1484                 // Layout: https://developer.android.com/reference/android/graphics/ImageFormat#RAW10
1485                 memcpy(androidBufferPixel, cpuBufferPixel, 5u); // Copy 4 pixels packed in 5 bytes
1486 
1487                 // Advance 3 pixels so in total we advance 4
1488                 x += 3u;
1489                 cpuBufferPixel += 5u;
1490 
1491                 break;
1492             }
1493 
1494             case RAW12:
1495             {
1496                 DE_ASSERT(m_accessData.m_planeCount == 1u);
1497 
1498                 // Packed format with 2 pixels in 3 bytes
1499                 // Layout: https://developer.android.com/reference/android/graphics/ImageFormat#RAW12
1500                 memcpy(androidBufferPixel, cpuBufferPixel, 3u); // Copy 2 pixels packed in 3 bytes
1501 
1502                 // Advance 1 pixels so in total we advance 2
1503                 x += 1u;
1504                 cpuBufferPixel += 3u;
1505 
1506                 break;
1507             }
1508 
1509             default:
1510                 DE_ASSERT(false); // Use non-compressed variant
1511                 break;
1512             }
1513         }
1514     }
1515 }
1516 
copyAndroidBufferToCpuBuffer(tcu::TextureLevel & cpuBuffer) const1517 void AndroidHardwareBufferInstance::copyAndroidBufferToCpuBuffer(tcu::TextureLevel &cpuBuffer) const
1518 {
1519     // Running into this assertion means no locking was performed
1520     DE_ASSERT(m_accessData.m_planeCount != 0);
1521 
1522     tcu::PixelBufferAccess access = cpuBuffer.getAccess();
1523 
1524     for (uint32_t y = 0u; y < m_height; ++y)
1525     {
1526         for (uint32_t x = 0u; x < m_width; ++x)
1527         {
1528             uint32_t offset         = (y * m_accessData.m_planeRowStride[0]) + (x * m_accessData.m_planePixelStride[0]);
1529             uint8_t *cpuBufferPixel = static_cast<uint8_t *>(access.getPixelPtr(x, y));
1530             const uint8_t *androidBufferPixel = m_accessData.m_planeData[0] + offset;
1531 
1532             switch (m_format)
1533             {
1534             // YUV 4:2:0 formats
1535             case Y8Cb8Cr8_420:
1536             case YV12:
1537             case NV21:
1538                 DE_ASSERT(m_accessData.m_planeCount == 3u);
1539 
1540                 // Component size is UNSIGNED_INT8. We can copy values directly
1541                 // YUV need to map RGB the following way according to Vulkan spec:
1542                 // Y is G
1543                 // Cb is B
1544                 // Cr is R
1545 
1546                 // Plane 0 contains Y information
1547                 *(cpuBufferPixel + 1) = *(androidBufferPixel);
1548 
1549                 // Plane 1 contains Cb information
1550                 // 4:2:0 has half size for Cb
1551                 offset = ((y / 2) * m_accessData.m_planeRowStride[1]) + ((x / 2) * m_accessData.m_planePixelStride[1]);
1552                 androidBufferPixel    = m_accessData.m_planeData[1] + offset;
1553                 *(cpuBufferPixel + 2) = *(androidBufferPixel);
1554 
1555                 // Plane 2 contains Cr information
1556                 // 4:2:0 has half size for Cr
1557                 offset = ((y / 2) * m_accessData.m_planeRowStride[2]) + ((x / 2) * m_accessData.m_planePixelStride[2]);
1558                 androidBufferPixel = m_accessData.m_planeData[2] + offset;
1559                 *(cpuBufferPixel)  = *(androidBufferPixel);
1560 
1561                 break;
1562 
1563             // YUV 4:2:2 formats
1564             case NV16:
1565             case YUY2:
1566                 DE_ASSERT(m_accessData.m_planeCount == 3u);
1567 
1568                 // Component size is UNSIGNED_INT8. We can copy values directly
1569                 // YUV need to map RGB the following way according to Vulkan spec:
1570                 // Y is G
1571                 // Cb is B
1572                 // Cr is R
1573 
1574                 // Plane 0 contains Y information
1575                 *(cpuBufferPixel + 1) = *(androidBufferPixel);
1576 
1577                 // Plane 1 contains Cb information
1578                 // 4:2:2 has half width for Cb
1579                 offset = (y * m_accessData.m_planeRowStride[1]) + ((x / 2) * m_accessData.m_planePixelStride[1]);
1580                 androidBufferPixel    = m_accessData.m_planeData[1] + offset;
1581                 *(cpuBufferPixel + 2) = *(androidBufferPixel);
1582 
1583                 // Plane 2 contains Cr information
1584                 // 4:2:2 has half width for Cr
1585                 offset = (y * m_accessData.m_planeRowStride[2]) + ((x / 2) * m_accessData.m_planePixelStride[2]);
1586                 androidBufferPixel = m_accessData.m_planeData[2] + offset;
1587                 *(cpuBufferPixel)  = *(androidBufferPixel);
1588 
1589                 break;
1590 
1591             // YUV 4:2:0 format
1592             case YCbCr_P010:
1593             {
1594                 DE_ASSERT(m_accessData.m_planeCount == 3u);
1595 
1596                 // m_cpuBuffer for YCbCr_P010 has order RGB, so we need to swizzle values
1597                 // Following Vulkan spec for ordering where:
1598                 // Y is G
1599                 // Cb is B
1600                 // Cr is R
1601 
1602                 // Plane 0 contains Y information
1603                 uint16_t green = *(reinterpret_cast<const uint16_t *>(androidBufferPixel));
1604 
1605                 // Plane 1 contains Cb information
1606                 // YCbCr_P010 is half size for Cb
1607                 offset = ((y / 2) * m_accessData.m_planeRowStride[1]) + ((x / 2) * m_accessData.m_planePixelStride[1]);
1608                 androidBufferPixel = m_accessData.m_planeData[1] + offset;
1609                 uint16_t blue      = *(reinterpret_cast<const uint16_t *>(androidBufferPixel));
1610 
1611                 // Plane 2 contains Cr information
1612                 // YCbCr_P010 is half size for Cr
1613                 offset = ((y / 2) * m_accessData.m_planeRowStride[2]) + ((x / 2) * m_accessData.m_planePixelStride[2]);
1614                 androidBufferPixel = m_accessData.m_planeData[2] + offset;
1615                 uint16_t red       = *(reinterpret_cast<const uint16_t *>(androidBufferPixel));
1616 
1617                 // YCbCr_P010 does not have same comoponent size as m_cpuBuffer type (UNORM_INT_101010)
1618                 // We need to transform from YCbCr_P010 where data is stored in the higher bits of 16 bit values to UNORM_INT_101010
1619 
1620                 uint32_t redOffset   = 22u;
1621                 uint32_t greenOffset = 12u;
1622                 uint32_t blueOffset  = 2u;
1623                 uint32_t bitOffset   = 6u;
1624                 uint32_t finalValue  = 0u;
1625 
1626                 finalValue |= static_cast<uint32_t>(blue >> bitOffset) << blueOffset;
1627                 finalValue |= static_cast<uint32_t>(green >> bitOffset) << greenOffset;
1628                 finalValue |= static_cast<uint32_t>(red >> bitOffset) << redOffset;
1629 
1630                 *(reinterpret_cast<uint32_t *>(cpuBufferPixel)) = finalValue;
1631 
1632                 break;
1633             }
1634 
1635             case RAW10:
1636             case RAW12:
1637                 DE_ASSERT(false); // Use compressed variation
1638                 break;
1639 
1640             default:
1641                 memcpy(cpuBufferPixel, androidBufferPixel, m_accessData.m_planePixelStride[0]);
1642             }
1643         }
1644     }
1645 }
1646 
copyAndroidBufferToCpuBufferCompressed(tcu::CompressedTexture & cpuBuffer) const1647 void AndroidHardwareBufferInstance::copyAndroidBufferToCpuBufferCompressed(tcu::CompressedTexture &cpuBuffer) const
1648 {
1649     // Running into this assertion means no locking was performed
1650     DE_ASSERT(m_accessData.m_planeCount != 0);
1651 
1652     uint8_t *cpuBufferPixel = static_cast<uint8_t *>(cpuBuffer.getData());
1653 
1654     for (uint32_t y = 0u; y < m_height; ++y)
1655     {
1656         for (uint32_t x = 0u; x < m_width; ++x)
1657         {
1658             uint32_t offset = (y * m_accessData.m_planeRowStride[0]) + (x * m_accessData.m_planePixelStride[0]);
1659             const uint8_t *androidBufferPixel = m_accessData.m_planeData[0] + offset;
1660 
1661             switch (m_format)
1662             {
1663             case RAW10:
1664             {
1665                 DE_ASSERT(m_accessData.m_planeCount == 1u);
1666 
1667                 // Packed format with 4 pixels in 5 bytes
1668                 // Layout: https://developer.android.com/reference/android/graphics/ImageFormat#RAW10
1669                 memcpy(cpuBufferPixel, androidBufferPixel, 5u); // Copy 4 pixels packed in 5 bytes
1670 
1671                 // Advance 3 pixels so in total we advance 4
1672                 x += 3u;
1673                 cpuBufferPixel += 5u;
1674 
1675                 break;
1676             }
1677 
1678             case RAW12:
1679             {
1680                 DE_ASSERT(m_accessData.m_planeCount == 1u);
1681 
1682                 // Packed format with 2 pixels in 3 bytes
1683                 // Layout: https://developer.android.com/reference/android/graphics/ImageFormat#RAW12
1684                 memcpy(cpuBufferPixel, androidBufferPixel, 3u); // Copy 2 pixels packed in 3 bytes
1685 
1686                 // Advance 1 pixels so in total we advance 2
1687                 x += 1u;
1688                 cpuBufferPixel += 3u;
1689 
1690                 break;
1691             }
1692 
1693             default:
1694                 DE_ASSERT(false); // Use non-compressed variant
1695                 break;
1696             }
1697         }
1698     }
1699 }
1700 
isYuv(void) const1701 bool AndroidHardwareBufferInstance::isYuv(void) const
1702 {
1703     return isFormatYuv(m_format);
1704 }
1705 
isRaw(void) const1706 bool AndroidHardwareBufferInstance::isRaw(void) const
1707 {
1708     return isFormatRaw(m_format);
1709 }
1710 
hasDepth(void) const1711 bool AndroidHardwareBufferInstance::hasDepth(void) const
1712 {
1713     switch (m_format)
1714     {
1715     case D16_UNORM:
1716     case D24_UNORM:
1717     case D24_UNORM_S8_UINT:
1718     case D32_FLOAT:
1719     case D32_FLOAT_S8_UINT:
1720         return true;
1721     default:
1722         return false;
1723     }
1724 }
1725 
hasStencil(void) const1726 bool AndroidHardwareBufferInstance::hasStencil(void) const
1727 {
1728     switch (m_format)
1729     {
1730     case D24_UNORM_S8_UINT:
1731     case D32_FLOAT_S8_UINT:
1732     case S8_UINT:
1733         return true;
1734     default:
1735         return false;
1736     }
1737 }
1738 
1739 } // namespace ExternalMemoryUtil
1740 
1741 } // namespace vkt
1742 
1743 #endif // CTS_USES_VULKANSC
1744