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 33namespace deqp 34{ 35namespace egl 36{ 37namespace Image 38{ 39 40using std::string; 41using de::MovePtr; 42using tcu::PixelBufferAccess; 43using tcu::TextureFormat; 44using tcu::Texture2D; 45using eglu::AttribMap; 46using namespace glw; 47using namespace eglw; 48 49#if (DE_OS != DE_OS_ANDROID) 50 51MovePtr<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 69MovePtr<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 77namespace 78{ 79 80#include <sys/system_properties.h> 81#include <android/hardware_buffer.h> 82#include "deDynamicLibrary.hpp" 83 84const deUint32 AHB_FORMAT_Y8Cb8Cr8_420 = 0x23; 85 86deInt32 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 99typedef int (*pfnAHardwareBuffer_allocate)(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer); 100typedef void (*pfnAHardwareBuffer_describe)(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc); 101typedef void (*pfnAHardwareBuffer_acquire)(AHardwareBuffer* buffer); 102typedef void (*pfnAHardwareBuffer_release)(AHardwareBuffer* buffer); 103typedef int (*pfnAHardwareBuffer_isSupported)(const AHardwareBuffer_Desc* desc); 104 105struct AhbFunctions 106{ 107 pfnAHardwareBuffer_allocate allocate; 108 pfnAHardwareBuffer_describe describe; 109 pfnAHardwareBuffer_acquire acquire; 110 pfnAHardwareBuffer_release release; 111 pfnAHardwareBuffer_isSupported isSupported; 112}; 113 114AhbFunctions ahbFunctions; 115 116bool 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 132bool 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 152deUint32 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 172class AndroidNativeClientBuffer : public ClientBuffer 173{ 174public: 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 182private: 183 const Library& m_egl; 184 AHardwareBuffer* m_hardwareBuffer; 185}; 186 187AndroidNativeClientBuffer::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 235AndroidNativeClientBuffer::~AndroidNativeClientBuffer (void) 236{ 237 ahbFunctions.release(m_hardwareBuffer); 238} 239 240EGLClientBuffer 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 246void 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 254void 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 262AHardwareBuffer_Desc AndroidNativeClientBuffer::describe (void) 263{ 264 AHardwareBuffer_Desc ret; 265 ahbFunctions.describe(m_hardwareBuffer, &ret); 266 return ret; 267} 268 269class AndroidNativeImageSource : public ImageSource 270{ 271public: 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; } 279protected: 280 GLenum m_format; 281 deUint32 m_numLayers; 282 bool m_isY8Cb8Cr8_420; 283}; 284 285AndroidNativeImageSource::~AndroidNativeImageSource (void) 286{ 287} 288 289MovePtr<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 326EGLImageKHR 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 337MovePtr<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 356