Merge vk-gl-cts/vulkan-cts-1.3.4 into vk-gl-cts/vulkan-cts-1.3.5
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglAndroidUtil.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Android-specific operations.
22  *//*--------------------------------------------------------------------*/
23
24 #include "teglAndroidUtil.hpp"
25
26 #include "deStringUtil.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "glwEnums.hpp"
30 #include "eglwLibrary.hpp"
31 #include "eglwEnums.hpp"
32
33 namespace deqp
34 {
35 namespace egl
36 {
37 namespace Image
38 {
39
40 using std::string;
41 using de::MovePtr;
42 using tcu::PixelBufferAccess;
43 using tcu::TextureFormat;
44 using tcu::Texture2D;
45 using eglu::AttribMap;
46 using namespace glw;
47 using namespace eglw;
48
49 #if (DE_OS != DE_OS_ANDROID)
50
51 MovePtr<ImageSource> createAndroidNativeImageSource     (GLenum format, deUint32 numLayers, bool isYUV)
52 {
53         DE_UNREF(numLayers);
54         return createUnsupportedImageSource("Not Android platform", format, isYUV);
55 }
56
57 #else // DE_OS == DE_OS_ANDROID
58
59 #if defined(__ANDROID_API_O__) && (DE_ANDROID_API >= __ANDROID_API_O__)
60 #       define BUILT_WITH_ANDROID_HARDWARE_BUFFER 1
61 #endif
62
63 #if defined(__ANDROID_API_P__) && (DE_ANDROID_API >= __ANDROID_API_P__)
64 #       define BUILT_WITH_ANDROID_P_HARDWARE_BUFFER 1
65 #endif
66
67 #if !defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
68
69 MovePtr<ImageSource> createAndroidNativeImageSource     (GLenum format, deUint32 numLayers, bool isYUV)
70 {
71         DE_UNREF(numLayers);
72         return createUnsupportedImageSource("AHB API not supported", format, isYUV);
73 }
74
75 #else // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
76
77 namespace
78 {
79
80 #include <sys/system_properties.h>
81 #include <android/hardware_buffer.h>
82 #include "deDynamicLibrary.hpp"
83
84 const deUint32 AHB_FORMAT_Y8Cb8Cr8_420 = 0x23;
85
86 deInt32 androidGetSdkVersion (void)
87 {
88         static deInt32 sdkVersion = -1;
89         if (sdkVersion < 0)
90         {
91                 char value[128] = {0};
92                 __system_property_get("ro.build.version.sdk", value);
93                 sdkVersion = static_cast<deInt32>(strtol(value, DE_NULL, 10));
94                 printf("SDK Version is %d\n", sdkVersion);
95         }
96         return sdkVersion;
97 }
98
99 typedef int             (*pfnAHardwareBuffer_allocate)(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer);
100 typedef void    (*pfnAHardwareBuffer_describe)(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc);
101 typedef void    (*pfnAHardwareBuffer_acquire)(AHardwareBuffer* buffer);
102 typedef void    (*pfnAHardwareBuffer_release)(AHardwareBuffer* buffer);
103 typedef int             (*pfnAHardwareBuffer_isSupported)(const AHardwareBuffer_Desc* desc);
104
105 struct AhbFunctions
106 {
107         pfnAHardwareBuffer_allocate             allocate;
108         pfnAHardwareBuffer_describe             describe;
109         pfnAHardwareBuffer_acquire              acquire;
110         pfnAHardwareBuffer_release              release;
111         pfnAHardwareBuffer_isSupported  isSupported;
112 };
113
114 AhbFunctions ahbFunctions;
115
116 bool ahbFunctionsLoaded (AhbFunctions* pAhbFunctions, deInt32 sdkVersion)
117 {
118         static bool ahbApiLoaded = false;
119         if (ahbApiLoaded ||
120                         ((pAhbFunctions->allocate != DE_NULL) &&
121                          (pAhbFunctions->describe != DE_NULL) &&
122                          (pAhbFunctions->acquire  != DE_NULL) &&
123                          (pAhbFunctions->release  != DE_NULL) &&
124                          (pAhbFunctions->isSupported != DE_NULL || sdkVersion < 29)))
125         {
126                 ahbApiLoaded = true;
127                 return true;
128         }
129         return false;
130 }
131
132 bool loadAhbDynamicApis (deInt32 sdkVersion)
133 {
134         if (!ahbFunctionsLoaded(&ahbFunctions, sdkVersion))
135         {
136                 static de::DynamicLibrary libnativewindow("libnativewindow.so");
137                 ahbFunctions.allocate = reinterpret_cast<pfnAHardwareBuffer_allocate>(libnativewindow.getFunction("AHardwareBuffer_allocate"));
138                 ahbFunctions.describe = reinterpret_cast<pfnAHardwareBuffer_describe>(libnativewindow.getFunction("AHardwareBuffer_describe"));
139                 ahbFunctions.acquire  = reinterpret_cast<pfnAHardwareBuffer_acquire>(libnativewindow.getFunction("AHardwareBuffer_acquire"));
140                 ahbFunctions.release  = reinterpret_cast<pfnAHardwareBuffer_release>(libnativewindow.getFunction("AHardwareBuffer_release"));
141                 if (sdkVersion >= 29)
142                         ahbFunctions.isSupported = reinterpret_cast<pfnAHardwareBuffer_isSupported>(libnativewindow.getFunction("AHardwareBuffer_isSupported"));
143                 else
144                         ahbFunctions.isSupported = DE_NULL;
145
146                 return ahbFunctionsLoaded(&ahbFunctions, sdkVersion);
147         }
148
149         return true;
150 }
151
152 deUint32 getPixelFormat (GLenum format)
153 {
154         switch (format)
155         {
156                 case GL_RGB565:                         return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
157                 case GL_RGB8:                           return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM;
158                 case GL_RGBA8:                          return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
159                 case GL_DEPTH_COMPONENT16:      return AHARDWAREBUFFER_FORMAT_D16_UNORM;
160                 case GL_DEPTH_COMPONENT24:      return AHARDWAREBUFFER_FORMAT_D24_UNORM;
161                 case GL_DEPTH24_STENCIL8:       return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT;
162                 case GL_DEPTH_COMPONENT32F:     return AHARDWAREBUFFER_FORMAT_D32_FLOAT;
163                 case GL_DEPTH32F_STENCIL8:      return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT;
164                 case GL_RGB10_A2:                       return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
165                 case GL_RGBA16F:                        return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
166                 case GL_STENCIL_INDEX8:         return AHARDWAREBUFFER_FORMAT_S8_UINT;
167
168                 default:                                        TCU_THROW(NotSupportedError, "Texture format unsupported by Android");
169         }
170 }
171
172 class AndroidNativeClientBuffer : public ClientBuffer
173 {
174 public:
175                                                 AndroidNativeClientBuffer       (const Library& egl, GLenum format, deUint32 numLayers, bool isYUV);
176                                                 ~AndroidNativeClientBuffer      (void);
177         EGLClientBuffer         get                                                     (void) const;
178         void                            lock                                            (void** data);
179         void                            unlock                                          (void);
180         AHardwareBuffer_Desc    describe                                        (void);
181
182 private:
183         const Library&                  m_egl;
184         AHardwareBuffer*                m_hardwareBuffer;
185 };
186
187 AndroidNativeClientBuffer::AndroidNativeClientBuffer (const Library& egl, GLenum format, deUint32 numLayers, bool isYUV)
188         : m_egl(egl)
189 {
190         deInt32 sdkVersion = androidGetSdkVersion();
191
192 #if defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
193         // When testing AHB on Android-P and newer the CTS must be compiled against API28 or newer.
194         DE_TEST_ASSERT(sdkVersion >= 28); /*__ANDROID_API_P__ */
195 #else
196         // When testing AHB on Android-O and newer the CTS must be compiled against API26 or newer.
197         DE_TEST_ASSERT(sdkVersion >= 26); /* __ANDROID_API_O__ */
198 #endif // !defined(BUILT_WITH_ANDROID_P_HARDWARE_BUFFER)
199
200         if (!loadAhbDynamicApis(sdkVersion))
201         {
202                 // Couldn't load Android AHB system APIs.
203                 DE_TEST_ASSERT(false);
204         }
205
206         AHardwareBuffer_Desc hbufferdesc = {
207                 64u,
208                 64u,
209                 numLayers,
210                 isYUV ? AHB_FORMAT_Y8Cb8Cr8_420 : getPixelFormat(format),
211                 AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN    |
212                 AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY  |
213                 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
214                 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT,
215                 0u,             // Stride in pixels, ignored for AHardwareBuffer_allocate()
216                 0u,             // Initialize to zero, reserved for future use
217                 0u              // Initialize to zero, reserved for future use
218         };
219
220         // If we have AHardwareBuffer_isSupported use that before trying the allocation.
221         if (ahbFunctions.isSupported != DE_NULL)
222         {
223                 if (!ahbFunctions.isSupported(&hbufferdesc))
224                         TCU_THROW(NotSupportedError, "Texture format unsupported");
225         }
226
227         if (ahbFunctions.allocate(&hbufferdesc, &m_hardwareBuffer) != 0)
228         {
229                 // Throw unsupported instead of failing the test as the texture format or the number
230                 // of layers might be unsupported.
231                 TCU_THROW(NotSupportedError, "AHB allocation failed");
232         }
233 }
234
235 AndroidNativeClientBuffer::~AndroidNativeClientBuffer (void)
236 {
237         ahbFunctions.release(m_hardwareBuffer);
238 }
239
240 EGLClientBuffer AndroidNativeClientBuffer::get (void) const
241 {
242         typedef EGLW_APICALL EGLClientBuffer (EGLW_APIENTRY* eglGetNativeClientBufferANDROIDFunc) (const struct AHardwareBuffer *buffer);
243         return ((eglGetNativeClientBufferANDROIDFunc)m_egl.getProcAddress("eglGetNativeClientBufferANDROID"))(m_hardwareBuffer);
244 }
245
246 void AndroidNativeClientBuffer::lock (void** data)
247 {
248         const int status = AHardwareBuffer_lock(m_hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1, DE_NULL, data);
249
250         if (status != 0)
251                 TCU_FAIL(("AHardwareBuffer_lock failed with error: " + de::toString(status)).c_str());
252 }
253
254 void AndroidNativeClientBuffer::unlock (void)
255 {
256         const int status = AHardwareBuffer_unlock(m_hardwareBuffer, DE_NULL);
257
258         if (status != 0)
259                 TCU_FAIL(("AHardwareBuffer_unlock failed with error: " + de::toString(status)).c_str());
260 }
261
262 AHardwareBuffer_Desc AndroidNativeClientBuffer::describe (void)
263 {
264         AHardwareBuffer_Desc ret;
265         ahbFunctions.describe(m_hardwareBuffer, &ret);
266         return ret;
267 }
268
269 class AndroidNativeImageSource : public ImageSource
270 {
271 public:
272                                                         AndroidNativeImageSource        (GLenum format, deUint32 numLayers, bool isYUV) : m_format(format), m_numLayers(numLayers), m_isY8Cb8Cr8_420(isYUV) {}
273                                                         ~AndroidNativeImageSource       (void);
274         MovePtr<ClientBuffer>   createBuffer                            (const Library& egl, const glw::Functions&, Texture2D*) const;
275         string                                  getRequiredExtension            (void) const { return "EGL_ANDROID_get_native_client_buffer"; }
276         EGLImageKHR                             createImage                                     (const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
277         GLenum                                  getEffectiveFormat                      (void) const { return m_format; }
278         bool                                    isYUVFormatImage                        (void) const { return m_isY8Cb8Cr8_420; }
279 protected:
280         GLenum                                  m_format;
281         deUint32                                m_numLayers;
282         bool                                    m_isY8Cb8Cr8_420;
283 };
284
285 AndroidNativeImageSource::~AndroidNativeImageSource (void)
286 {
287 }
288
289 MovePtr<ClientBuffer> AndroidNativeImageSource::createBuffer (const Library& egl, const glw::Functions&, Texture2D* ref) const
290 {
291         MovePtr<AndroidNativeClientBuffer> buffer (new AndroidNativeClientBuffer(egl, m_format, m_numLayers, m_isY8Cb8Cr8_420));
292
293         if (ref != DE_NULL)
294         {
295                 const TextureFormat     texFormat       = glu::mapGLInternalFormat(m_format);
296                 void*                           bufferData      = DE_NULL;
297
298                 *ref = Texture2D(texFormat, 64, 64);
299                 ref->m_yuvTextureUsed = m_isY8Cb8Cr8_420;
300                 ref->allocLevel(0);
301                 tcu::fillWithComponentGradients(ref->getLevel(0),
302                                                                                 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
303                                                                                 tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
304
305                 // AHB doesn't allow locking a layered image. In that case the data
306                 // will be initialized later using OpenGL API.
307                 // YUV format texture will be initialized by glClear.
308
309                 if (m_numLayers == 1u && !m_isY8Cb8Cr8_420)
310                 {
311                         buffer->lock(&bufferData);
312                         {
313                                 AHardwareBuffer_Desc    desc                    = buffer->describe();
314                                 const int                               rowPitch                = texFormat.getPixelSize() * desc.stride;
315                                 const int                               slicePitch              = rowPitch * desc.height;
316                                 PixelBufferAccess               nativeBuffer    (texFormat, desc.width, desc.height, 1, rowPitch, slicePitch, bufferData);
317
318                                 tcu::copy(nativeBuffer, ref->getLevel(0));
319                         }
320                         buffer->unlock();
321                 }
322         }
323         return MovePtr<ClientBuffer>(buffer);
324 }
325
326 EGLImageKHR AndroidNativeImageSource::createImage (const Library& egl, EGLDisplay dpy, EGLContext, EGLClientBuffer clientBuffer) const
327 {
328         static const EGLint     attribs[]       = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
329         const EGLImageKHR       image           = egl.createImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attribs);
330
331         EGLU_CHECK_MSG(egl, "eglCreateImageKHR()");
332         return image;
333 }
334
335 } // anonymous
336
337 MovePtr<ImageSource> createAndroidNativeImageSource     (GLenum format, deUint32 numLayers, bool isYUV)
338 {
339         try
340         {
341                 return MovePtr<ImageSource>(new AndroidNativeImageSource(format, numLayers, isYUV));
342         }
343         catch (const std::runtime_error& exc)
344         {
345                 return createUnsupportedImageSource(string("Android native buffers unsupported: ") + exc.what(), format, isYUV);
346         }
347 }
348
349 #endif // defined(BUILT_WITH_ANDROID_HARDWARE_BUFFER)
350
351 #endif // DE_OS == DE_OS_ANDROID
352
353 } // Image
354 } // egl
355 } // deqp