• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
createAndroidNativeImageSource(GLenum format,deUint32 numLayers,bool isYUV)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 
createAndroidNativeImageSource(GLenum format,deUint32 numLayers,bool isYUV)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 
androidGetSdkVersion(void)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 
ahbFunctionsLoaded(AhbFunctions * pAhbFunctions,deInt32 sdkVersion)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 
loadAhbDynamicApis(deInt32 sdkVersion)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 
getPixelFormat(GLenum format)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 
AndroidNativeClientBuffer(const Library & egl,GLenum format,deUint32 numLayers,bool isYUV)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 
~AndroidNativeClientBuffer(void)235 AndroidNativeClientBuffer::~AndroidNativeClientBuffer (void)
236 {
237 	ahbFunctions.release(m_hardwareBuffer);
238 }
239 
get(void) const240 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 
lock(void ** data)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 
unlock(void)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 
describe(void)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:
AndroidNativeImageSource(GLenum format,deUint32 numLayers,bool isYUV)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;
getRequiredExtension(void) const275 	string					getRequiredExtension		(void) const { return "EGL_ANDROID_get_native_client_buffer"; }
276 	EGLImageKHR				createImage					(const Library& egl, EGLDisplay dpy, EGLContext ctx, EGLClientBuffer clientBuffer) const;
getEffectiveFormat(void) const277 	GLenum					getEffectiveFormat			(void) const { return m_format; }
isYUVFormatImage(void) const278 	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 
~AndroidNativeImageSource(void)285 AndroidNativeImageSource::~AndroidNativeImageSource (void)
286 {
287 }
288 
createBuffer(const Library & egl,const glw::Functions &,Texture2D * ref) const289 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 
createImage(const Library & egl,EGLDisplay dpy,EGLContext,EGLClientBuffer clientBuffer) const326 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 
createAndroidNativeImageSource(GLenum format,deUint32 numLayers,bool isYUV)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
356