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 ©); // Not Implemented
244 AndroidHardwareBufferExternalApi26 &operator=(AndroidHardwareBufferExternalApi26 const ©); // 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 ©); // Not Implemented
434 AndroidHardwareBufferExternalApi28 &operator=(AndroidHardwareBufferExternalApi28 const ©); // 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 ©); // Not Implemented
533 AndroidHardwareBufferExternalApi33 &operator=(AndroidHardwareBufferExternalApi33 const ©); // 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 ©); // Not Implemented
614 AndroidHardwareBufferExternalApi34 &operator=(AndroidHardwareBufferExternalApi34 const ©); // 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