1 #ifndef _VKTEXTERNALMEMORYANDROIDHARDWAREBUFFERUTIL_HPP
2 #define _VKTEXTERNALMEMORYANDROIDHARDWAREBUFFERUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2023 The Khronos Group Inc.
8  * Copyright (c) 2023 Google Inc.
9  * Copyright (c) 2023 LunarG Inc.
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  *//*!
24  * \file
25  * \brief Vulkan external memory utilities for Android Hardware Buffer
26  *//*--------------------------------------------------------------------*/
27 
28 #include "tcuDefs.hpp"
29 
30 #include "vkPlatform.hpp"
31 #include "vkRefUtil.hpp"
32 
33 #include "tcuTexture.hpp"
34 #include "tcuCompressedTexture.hpp"
35 
36 #include <vector>
37 
38 #ifndef CTS_USES_VULKANSC
39 
40 namespace vkt
41 {
42 
43 namespace ExternalMemoryUtil
44 {
45 
46 class AndroidHardwareBufferExternalApi
47 {
48 public:
49     /**
50      * getInstance obtains the object, that provides an interface to AHB system APIs .
51      * If the AHB system API is not supported or if it is not built as supported with the CTS,
52      * then this function would return a null object.
53      */
54     static AndroidHardwareBufferExternalApi *getInstance();
55 
56     /* Is AndroidHardwareBuffer supported? */
57     static bool supportsAhb();
58 
59     /* Are Cube maps supported on current api level? */
60     static bool supportsCubeMap();
61 
62     /**
63      * Allocates a buffer that backs an AHardwareBuffer using the passed parameter as follows:
64      * width;      - width in pixels
65      * height;     - height in pixels
66      * layers;     - number of images
67      * format;     - One of AHARDWAREBUFFER_FORMAT_*
68      * usage;      - Combination of AHARDWAREBUFFER_USAGE_*
69      *
70      * Returns a valid AndroidHardwareBufferPtr object on success, or an null AndroidHardwareBufferPtr if
71      * the allocation fails for any reason.
72      */
73     virtual vk::pt::AndroidHardwareBufferPtr allocate(uint32_t width, uint32_t height, uint32_t layers, uint32_t format,
74                                                       uint64_t usage) = 0;
75 
76     /**
77      * Acquire a reference on the given AHardwareBuffer object.  This prevents the
78      * object from being deleted until the last reference is removed.
79      */
80     virtual void acquire(vk::pt::AndroidHardwareBufferPtr buffer) = 0;
81 
82     /**
83      * Remove a reference that was previously acquired with
84      * AHardwareBuffer_acquire().
85      */
86     virtual void release(vk::pt::AndroidHardwareBufferPtr buffer) = 0;
87 
88     /**
89      * Return a description of the AHardwareBuffer in the passed in the following fields, if not NULL:
90      * width;      - width in pixels
91      * height;     - height in pixels
92      * layers;     - number of images
93      * format;     - One of AHARDWAREBUFFER_FORMAT_*
94      * usage;      - Combination of AHARDWAREBUFFER_USAGE_*
95      *
96      */
97     virtual void describe(const vk::pt::AndroidHardwareBufferPtr buffer, uint32_t *width, uint32_t *height,
98                           uint32_t *layers, uint32_t *format, uint64_t *usage, uint32_t *stride) = 0;
99 
100     /**
101      * Return a pointer to buffer data for CPU read. nullptr is returned on failure.
102      * Buffer must have been created with usage flags.
103      */
104     virtual void *lock(vk::pt::AndroidHardwareBufferPtr buffer, uint64_t usage) = 0;
105 
106     /**
107      * Returns TRUE if locking the buffer for buffer data for CPU read was successful, FALSE otherwise.
108      * Buffer must have been created with usage flags.
109      * Out parameters will be be filled with required data to access each plane according to planeCountOut.
110      * Plane 0 will have all data in planeDataOut[0], planeStrideOut[0], planeRowStrideOut[0]
111      * Plane 1 will have all data in planeDataOut[1], planeStrideOut[1], planeRowStrideOut[1]
112      * ...
113      * planeCount            - number of planes present in buffer
114      * planeDataOut            - array of pointers to plane data
115      * planePixelStrideOut    - plane stride for each pixel in a row
116      * planeRowStrideOut    - plane stride for each row
117      */
118     virtual bool lockPlanes(vk::pt::AndroidHardwareBufferPtr buffer, uint64_t usage, uint32_t &planeCountOut,
119                             void *planeDataOut[4], uint32_t planePixelStrideOut[4], uint32_t planeRowStrideOut[4]) = 0;
120 
121     /**
122      * Returns TRUE if buffer was unlocked successfully from previous lock operations.
123      * FALSE is returned otherwise.
124      */
125     virtual bool unlock(vk::pt::AndroidHardwareBufferPtr buffer) = 0;
126 
127     virtual uint64_t vkUsageToAhbUsage(vk::VkImageUsageFlagBits vkFlag)   = 0;
128     virtual uint64_t vkCreateToAhbUsage(vk::VkImageCreateFlagBits vkFlag) = 0;
129     virtual uint32_t vkFormatToAhbFormat(vk::VkFormat vkFormat)           = 0;
130     virtual uint64_t mustSupportAhbUsageFlags()                           = 0;
131     virtual bool ahbFormatIsBlob(uint32_t format)                         = 0;
132     virtual bool ahbFormatIsYuv(uint32_t format)                          = 0;
133 
134     /* Retrieves all present formats in AHB */
135     virtual std::vector<uint32_t> getAllSupportedFormats() = 0;
136 
137     /* AHB format as a string */
138     virtual const char *getFormatAsString(uint32_t format) = 0;
139 
140     virtual ~AndroidHardwareBufferExternalApi();
141 
142 protected:
143     // Protected Constructor
144     AndroidHardwareBufferExternalApi();
145 
146 private:
147     // Stop the compiler generating methods of copy the object
148     AndroidHardwareBufferExternalApi(AndroidHardwareBufferExternalApi const &copy);            // Not Implemented
149     AndroidHardwareBufferExternalApi &operator=(AndroidHardwareBufferExternalApi const &copy); // Not Implemented
150 
151     static bool loadAhbDynamicApis(int32_t sdkVersion);
152 };
153 
154 // Buffer class that allows CPU read/writes to Android Hardware Buffers
155 class AndroidHardwareBufferInstance
156 {
157     // Class/struct/enum/... definitions
158 public:
159     // Can check if format is supported using isFormatSupported
160     enum Format : uint32_t
161     {
162         // Formats exposed by Native Hardware Buffer API
163         R8G8B8A8_UNORM = 0,
164         R8G8B8X8_UNORM,
165         R8G8B8_UNORM,
166         R5G6B5_UNORM,
167         R16G16B16A16_FLOAT,
168         R10G10B10A2_UNORM,
169         BLOB,
170         D16_UNORM,
171         D24_UNORM,
172         D24_UNORM_S8_UINT,
173         D32_FLOAT,
174         D32_FLOAT_S8_UINT, // No CPU side validation available through AHB
175         S8_UINT,
176         Y8Cb8Cr8_420,
177         YCbCr_P010,
178         R8_UNORM,
179         R16_UINT,
180         R16G16_UINT,
181         R10G10B10A10_UNORM,
182 
183         // Formats not exposed by Native Hardware Buffer API
184         // Present in Android Hardware Buffer
185         // Values obtained AOSP header (nativewindow/include/vndk/hardware_buffer.h)
186         B8G8R8A8_UNORM,
187         YV12,
188         Y8,
189         Y16,
190         RAW10,
191         RAW12,
192         RAW16,
193         RAW_OPAQUE,             // No validation possible
194         IMPLEMENTATION_DEFINED, // No validation possible
195         NV16,                   // AHARDWAREBUFFER_FORMAT_YCbCr_422_SP
196         NV21,                   // AHARDWAREBUFFER_FORMAT_YCrCb_420_SP
197         YUY2,                   // AHARDWAREBUFFER_FORMAT_YCbCr_422_I
198 
199         COUNT,
200         UNASSIGNED
201     };
202 
203     // Can be expanded as needed
204     enum Usage : uint32_t
205     {
206         UNUSED          = 0,
207         GPU_FRAMEBUFFER = 1,
208         GPU_SAMPLED     = 2,
209         CPU_READ        = 4,
210         CPU_WRITE       = 8,
211     };
212 
213     enum ChromaLocation : uint32_t
214     {
215         COSITED_EVEN = 0, // VK_CHROMA_LOCATION_COSITED_EVEN
216         MIDPOINT,         // VK_CHROMA_LOCATION_MIDPOINT
217     };
218 
219 protected:
220     struct AccessDataCPU
221     {
222         uint32_t m_planeCount = 0u;
223         union
224         {
225             uint8_t *m_planeData[4] = {nullptr, nullptr, nullptr, nullptr};
226             void *m_planeDataVoid[4];
227         };
228         uint32_t m_planePixelStride[4] = {0u, 0u, 0u, 0u};
229         uint32_t m_planeRowStride[4]   = {0u, 0u, 0u, 0u};
230     };
231 
232     using AhbApi = AndroidHardwareBufferExternalApi;
233     using Handle = vk::pt::AndroidHardwareBufferPtr;
234 
235     // Static functions
236 public:
237     static int32_t getSdkVersion();
238     static bool isFormatSupported(Format format);
239     static bool isFormatYuv(Format format);
240     static bool isFormatRaw(Format format);
241     static bool isFormatColor(Format format);
242     static bool isFormatDepth(Format format);
243     static bool isFormatStencil(Format format);
244     static bool hasFormatAlpha(Format format);
245     static const char *getFormatName(Format format);
246     static uint32_t formatToInternalFormat(Format format);
247     static tcu::TextureFormat formatToTextureFormat(Format format);
248     static ChromaLocation vkChromaLocationToChromaLocation(vk::VkChromaLocation location);
249     static void reduceYuvTexture(tcu::TextureLevel &texture, Format format, ChromaLocation xChroma,
250                                  ChromaLocation yChroma);
251 
252 protected:
253     static void reduceYuv420Texture(tcu::TextureLevel &texture, ChromaLocation xChroma, ChromaLocation yChroma);
254     static void reduceYuv422Texture(tcu::TextureLevel &texture, ChromaLocation xChroma);
255     static uint64_t usageToInternalUsage(Usage usage);
256     // Pixel stride in bytes
257     static uint32_t pixelStride(Format format);
258 
259     // Member functions
260 public:
261     ~AndroidHardwareBufferInstance(void);
262 
263     bool allocate(Format format, uint32_t width, uint32_t height, uint32_t layers, Usage usage);
264     void release(void);
265 
266     bool lock(Usage usage);
267     bool unlock(void);
268 
269     void copyCpuBufferToAndroidBuffer(const tcu::TextureLevel &cpuBuffer);
270     void copyCpuBufferToAndroidBufferCompressed(const tcu::CompressedTexture &cpuBuffer);
271     void copyAndroidBufferToCpuBuffer(tcu::TextureLevel &cpuBuffer) const;
272     void copyAndroidBufferToCpuBufferCompressed(tcu::CompressedTexture &cpuBuffer) const;
273 
getAhbTextureFormat(void) const274     tcu::TextureFormat getAhbTextureFormat(void) const
275     {
276         return formatToTextureFormat(m_format);
277     };
getHandle(void) const278     Handle getHandle(void) const
279     {
280         return m_handle;
281     }
282 
283     bool isYuv(void) const;
284     bool isRaw(void) const;
285     bool hasDepth(void) const;
286     bool hasStencil(void) const;
287 
288     // Data
289 protected:
290     AccessDataCPU m_accessData;
291     AhbApi *m_ahbApi          = AhbApi::getInstance();
292     Handle m_handle           = Handle(nullptr);
293     Usage m_usage             = UNUSED;
294     uint64_t m_internalUsage  = 0u;
295     Format m_format           = UNASSIGNED;
296     uint32_t m_internalFormat = 0u;
297     uint32_t m_width          = 0u;
298     uint32_t m_height         = 0u;
299     uint32_t m_layers         = 0u;
300 };
301 
302 } // namespace ExternalMemoryUtil
303 
304 } // namespace vkt
305 
306 #endif // CTS_USES_VULKANSC
307 
308 #endif // _VKTEXTERNALMEMORYANDROIDHARDWAREBUFFERUTIL_HPP
309