• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
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 Access to Android internals that are not a part of the NDK.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "tcuAndroidInternals.hpp"
25 #include "deMemory.h"
26 #include "deStringUtil.hpp"
27 
28 namespace tcu
29 {
30 namespace Android
31 {
32 namespace internal
33 {
34 
35 using std::string;
36 using de::DynamicLibrary;
37 
38 template<typename Func>
setFuncPtr(Func * & funcPtr,DynamicLibrary & lib,const string & symname)39 void setFuncPtr (Func*& funcPtr, DynamicLibrary& lib, const string& symname)
40 {
41 	funcPtr = reinterpret_cast<Func*>(lib.getFunction(symname.c_str()));
42 	if (!funcPtr)
43 		TCU_THROW(NotSupportedError, ("Unable to look up symbol from shared object: " + symname).c_str());
44 }
45 
LibUI(void)46 LibUI::LibUI (void)
47 	: m_library	("libui.so")
48 {
49 	GraphicBufferFunctions& gb = m_functions.graphicBuffer;
50 
51 	setFuncPtr(gb.constructor,		m_library,	"_ZN7android13GraphicBufferC1Ejjij");
52 	setFuncPtr(gb.destructor,		m_library,	"_ZN7android13GraphicBufferD1Ev");
53 	setFuncPtr(gb.getNativeBuffer,	m_library,	"_ZNK7android13GraphicBuffer15getNativeBufferEv");
54 	setFuncPtr(gb.lock,				m_library,	"_ZN7android13GraphicBuffer4lockEjPPv");
55 	setFuncPtr(gb.unlock,			m_library,	"_ZN7android13GraphicBuffer6unlockEv");
56 	setFuncPtr(gb.initCheck,		m_library,	"_ZNK7android13GraphicBuffer9initCheckEv");
57 }
58 
59 #define GRAPHICBUFFER_SIZE 1024 // Hopefully enough
60 
61 typedef void (*GenericFptr)();
62 
63 //! call constructor with 4 arguments
64 template <typename RT, typename T1, typename T2, typename T3, typename T4>
callConstructor4(GenericFptr fptr,void * memory,size_t memorySize,T1 param1,T2 param2,T3 param3,T4 param4)65 RT* callConstructor4 (GenericFptr fptr, void* memory, size_t memorySize, T1 param1, T2 param2, T3 param3, T4 param4)
66 {
67 	DE_UNREF(memorySize);
68 
69 #if (DE_CPU == DE_CPU_ARM)
70 	// C1 constructors return pointer
71 	typedef RT* (*ABIFptr)(void*, T1, T2, T3, T4);
72 	(void)((ABIFptr)fptr)(memory, param1, param2, param3, param4);
73 	return reinterpret_cast<RT*>(memory);
74 #elif (DE_CPU == DE_CPU_ARM_64)
75 	// C1 constructors return void
76 	typedef void (*ABIFptr)(void*, T1, T2, T3, T4);
77 	((ABIFptr)fptr)(memory, param1, param2, param3, param4);
78 	return reinterpret_cast<RT*>(memory);
79 #elif (DE_CPU == DE_CPU_X86)
80 	// ctor returns void
81 	typedef void (*ABIFptr)(void*, T1, T2, T3, T4);
82 	((ABIFptr)fptr)(memory, param1, param2, param3, param4);
83 	return reinterpret_cast<RT*>(memory);
84 #elif (DE_CPU == DE_CPU_X86_64)
85 	// ctor returns void
86 	typedef void (*ABIFptr)(void*, T1, T2, T3, T4);
87 	((ABIFptr)fptr)(memory, param1, param2, param3, param4);
88 	return reinterpret_cast<RT*>(memory);
89 #else
90 	DE_UNREF(fptr);
91 	DE_UNREF(memory);
92 	DE_UNREF(param1);
93 	DE_UNREF(param2);
94 	DE_UNREF(param3);
95 	DE_UNREF(param4);
96 	TCU_THROW(NotSupportedError, "ABI not supported");
97 	return DE_NULL;
98 #endif
99 }
100 
101 template <typename T>
callDestructor(GenericFptr fptr,T * obj)102 void callDestructor (GenericFptr fptr, T* obj)
103 {
104 #if (DE_CPU == DE_CPU_ARM)
105 	// D1 destructor returns ptr
106 	typedef void* (*ABIFptr)(T* obj);
107 	(void)((ABIFptr)fptr)(obj);
108 #elif (DE_CPU == DE_CPU_ARM_64)
109 	// D1 destructor returns void
110 	typedef void (*ABIFptr)(T* obj);
111 	((ABIFptr)fptr)(obj);
112 #elif (DE_CPU == DE_CPU_X86)
113 	// dtor returns void
114 	typedef void (*ABIFptr)(T* obj);
115 	((ABIFptr)fptr)(obj);
116 #elif (DE_CPU == DE_CPU_X86_64)
117 	// dtor returns void
118 	typedef void (*ABIFptr)(T* obj);
119 	((ABIFptr)fptr)(obj);
120 #else
121 	DE_UNREF(fptr);
122 	DE_UNREF(obj);
123 	TCU_THROW(NotSupportedError, "ABI not supported");
124 #endif
125 }
126 
127 template<typename T1, typename T2>
pointerToOffset(T2 * ptr,size_t bytes)128 T1* pointerToOffset (T2* ptr, size_t bytes)
129 {
130 	return reinterpret_cast<T1*>((deUint8*)ptr + bytes);
131 }
132 
getAndroidNativeBase(android::GraphicBuffer * gb)133 static android::android_native_base_t* getAndroidNativeBase (android::GraphicBuffer* gb)
134 {
135 	// \note: assuming Itanium ABI
136 	return pointerToOffset<android::android_native_base_t>(gb, 2 * DE_PTR_SIZE);
137 }
138 
139 //! android_native_base_t::magic for ANativeWindowBuffer
getExpectedNativeBufferVersion(void)140 static deInt32 getExpectedNativeBufferVersion (void)
141 {
142 #if (DE_PTR_SIZE == 4)
143 	return 96;
144 #elif (DE_PTR_SIZE == 8)
145 	return 168;
146 #else
147 #	error Invalid DE_PTR_SIZE
148 #endif
149 }
150 
151 //! access android_native_base_t::magic
getNativeBaseMagic(android::android_native_base_t * base)152 static deUint32 getNativeBaseMagic (android::android_native_base_t* base)
153 {
154 	return *pointerToOffset<deUint32>(base, 0);
155 }
156 
157 //! access android_native_base_t::version
getNativeBaseVersion(android::android_native_base_t * base)158 static deUint32 getNativeBaseVersion (android::android_native_base_t* base)
159 {
160 	return *pointerToOffset<deInt32>(base, 4);
161 }
162 
163 //! access android_native_base_t::incRef
getNativeBaseIncRefFunc(android::android_native_base_t * base)164 static NativeBaseFunctions::incRefFunc getNativeBaseIncRefFunc (android::android_native_base_t* base)
165 {
166 	return *pointerToOffset<NativeBaseFunctions::incRefFunc>(base, 8 + DE_PTR_SIZE*4);
167 }
168 
169 //! access android_native_base_t::decRef
getNativeBaseDecRefFunc(android::android_native_base_t * base)170 static NativeBaseFunctions::decRefFunc getNativeBaseDecRefFunc (android::android_native_base_t* base)
171 {
172 	return *pointerToOffset<NativeBaseFunctions::decRefFunc>(base, 8 + DE_PTR_SIZE*5);
173 }
174 
createGraphicBuffer(const GraphicBufferFunctions & functions,NativeBaseFunctions & baseFunctions,deUint32 w,deUint32 h,PixelFormat format,deUint32 usage)175 static android::GraphicBuffer* createGraphicBuffer (const GraphicBufferFunctions& functions, NativeBaseFunctions& baseFunctions, deUint32 w, deUint32 h, PixelFormat format, deUint32 usage)
176 {
177 	// \note: Hopefully uses the same allocator as libui
178 	void* const memory = deMalloc(GRAPHICBUFFER_SIZE);
179 	if (memory == DE_NULL)
180 		TCU_THROW(ResourceError, "Could not alloc for GraphicBuffer");
181 	else
182 	{
183 		try
184 		{
185 			android::GraphicBuffer* const			gb			= callConstructor4<android::GraphicBuffer, deUint32, deUint32, PixelFormat, deUint32>(functions.constructor,
186 																																					  memory,
187 																																					  GRAPHICBUFFER_SIZE,
188 																																					  w,
189 																																					  h,
190 																																					  format,
191 																																					  usage);
192 			android::android_native_base_t* const	base		= getAndroidNativeBase(gb);
193 			status_t								ctorStatus	= functions.initCheck(gb);
194 
195 			if (ctorStatus)
196 			{
197 				// ctor failed
198 				callDestructor<android::GraphicBuffer>(functions.destructor, gb);
199 				TCU_THROW(NotSupportedError, ("GraphicBuffer ctor failed, initCheck returned " + de::toString(ctorStatus)).c_str());
200 			}
201 
202 			// check object layout
203 			{
204 				const deUint32 magic		= getNativeBaseMagic(base);
205 				const deUint32 bufferMagic	= 0x5f626672u; // "_bfr"
206 
207 				if (magic != bufferMagic)
208 					TCU_THROW(NotSupportedError, "GraphicBuffer layout unexpected");
209 			}
210 
211 			// check object version
212 			{
213 				const deInt32 version			= getNativeBaseVersion(base);
214 				const deInt32 expectedVersion	= getExpectedNativeBufferVersion();
215 
216 				if (version != expectedVersion)
217 					TCU_THROW(NotSupportedError, "GraphicBuffer version unexpected");
218 			}
219 
220 			// locate refcounting functions
221 
222 			if (!baseFunctions.incRef || !baseFunctions.decRef)
223 			{
224 				baseFunctions.incRef = getNativeBaseIncRefFunc(base);
225 				baseFunctions.decRef = getNativeBaseDecRefFunc(base);
226 			}
227 
228 			// take the initial reference and return
229 			baseFunctions.incRef(base);
230 			return gb;
231 		}
232 		catch (...)
233 		{
234 			deFree(memory);
235 			throw;
236 		}
237 	}
238 }
239 
GraphicBuffer(const LibUI & lib,deUint32 width,deUint32 height,PixelFormat format,deUint32 usage)240 GraphicBuffer::GraphicBuffer (const LibUI& lib, deUint32 width, deUint32 height, PixelFormat format, deUint32 usage)
241 	: m_functions	(lib.getFunctions().graphicBuffer)
242 	, m_impl		(DE_NULL)
243 {
244 	m_baseFunctions.incRef = DE_NULL;
245 	m_baseFunctions.decRef = DE_NULL;
246 
247 	// \note createGraphicBuffer updates m_baseFunctions
248 	m_impl = createGraphicBuffer(m_functions, m_baseFunctions, width, height, format, usage);
249 }
250 
~GraphicBuffer(void)251 GraphicBuffer::~GraphicBuffer (void)
252 {
253 	if (m_impl && m_baseFunctions.decRef)
254 	{
255 		m_baseFunctions.decRef(getAndroidNativeBase(m_impl));
256 		m_impl = DE_NULL;
257 	}
258 }
259 
lock(deUint32 usage,void ** vaddr)260 status_t GraphicBuffer::lock (deUint32 usage, void** vaddr)
261 {
262 	return m_functions.lock(m_impl, usage, vaddr);
263 }
264 
unlock(void)265 status_t GraphicBuffer::unlock (void)
266 {
267 	return m_functions.unlock(m_impl);
268 }
269 
getNativeBuffer(void) const270 ANativeWindowBuffer* GraphicBuffer::getNativeBuffer (void) const
271 {
272 	return m_functions.getNativeBuffer(m_impl);
273 }
274 
275 } // internal
276 } // Android
277 } // tcu
278