1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Access to Android internals that are not a part of the NDK.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuAndroidInternals.hpp"
26 #include "deStringUtil.hpp"
36 using de::DynamicLibrary;
38 template<typename Func>
39 void setFuncPtr (Func*& funcPtr, DynamicLibrary& lib, const string& symname)
41 funcPtr = reinterpret_cast<Func*>(lib.getFunction(symname.c_str()));
43 TCU_THROW(NotSupportedError, ("Unable to look up symbol from shared object: " + symname).c_str());
47 : m_library ("libui.so")
49 GraphicBufferFunctions& gb = m_functions.graphicBuffer;
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");
59 #define GRAPHICBUFFER_SIZE 1024 // Hopefully enough
61 typedef void (*GenericFptr)();
63 //! call constructor with 4 arguments
64 template <typename RT, typename T1, typename T2, typename T3, typename T4>
65 RT* callConstructor4 (GenericFptr fptr, void* memory, size_t memorySize, T1 param1, T2 param2, T3 param3, T4 param4)
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)
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)
86 typedef void (*ABIFptr)(void*, T1, T2, T3, T4);
87 ((ABIFptr)fptr)(memory, param1, param2, param3, param4);
88 return reinterpret_cast<RT*>(memory);
96 TCU_THROW(NotSupportedError, "ABI not supported");
101 template <typename T>
102 void callDestructor (GenericFptr fptr, T* obj)
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)
114 typedef void (*ABIFptr)(T* obj);
115 ((ABIFptr)fptr)(obj);
116 #elif (DE_CPU == DE_CPU_X86_64)
118 typedef void (*ABIFptr)(T* obj);
119 ((ABIFptr)fptr)(obj);
123 TCU_THROW(NotSupportedError, "ABI not supported");
127 template<typename T1, typename T2>
128 T1* pointerToOffset (T2* ptr, size_t bytes)
130 return reinterpret_cast<T1*>((deUint8*)ptr + bytes);
133 static android::android_native_base_t* getAndroidNativeBase (android::GraphicBuffer* gb)
135 // \note: assuming Itanium ABI
136 return pointerToOffset<android::android_native_base_t>(gb, 2 * DE_PTR_SIZE);
139 //! android_native_base_t::magic for ANativeWindowBuffer
140 static deInt32 getExpectedNativeBufferVersion (void)
142 #if (DE_PTR_SIZE == 4)
144 #elif (DE_PTR_SIZE == 8)
147 # error Invalid DE_PTR_SIZE
151 //! access android_native_base_t::magic
152 static deUint32 getNativeBaseMagic (android::android_native_base_t* base)
154 return *pointerToOffset<deUint32>(base, 0);
157 //! access android_native_base_t::version
158 static deUint32 getNativeBaseVersion (android::android_native_base_t* base)
160 return *pointerToOffset<deInt32>(base, 4);
163 //! access android_native_base_t::incRef
164 static NativeBaseFunctions::incRefFunc getNativeBaseIncRefFunc (android::android_native_base_t* base)
166 return *pointerToOffset<NativeBaseFunctions::incRefFunc>(base, 8 + DE_PTR_SIZE*4);
169 //! access android_native_base_t::decRef
170 static NativeBaseFunctions::decRefFunc getNativeBaseDecRefFunc (android::android_native_base_t* base)
172 return *pointerToOffset<NativeBaseFunctions::decRefFunc>(base, 8 + DE_PTR_SIZE*5);
175 static android::GraphicBuffer* createGraphicBuffer (const GraphicBufferFunctions& functions, NativeBaseFunctions& baseFunctions, deUint32 w, deUint32 h, PixelFormat format, deUint32 usage)
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");
185 android::GraphicBuffer* const gb = callConstructor4<android::GraphicBuffer, deUint32, deUint32, PixelFormat, deUint32>(functions.constructor,
192 android::android_native_base_t* const base = getAndroidNativeBase(gb);
193 status_t ctorStatus = functions.initCheck(gb);
198 callDestructor<android::GraphicBuffer>(functions.destructor, gb);
199 TCU_THROW(NotSupportedError, ("GraphicBuffer ctor failed, initCheck returned " + de::toString(ctorStatus)).c_str());
202 // check object layout
204 const deUint32 magic = getNativeBaseMagic(base);
205 const deUint32 bufferMagic = 0x5f626672u; // "_bfr"
207 if (magic != bufferMagic)
208 TCU_THROW(NotSupportedError, "GraphicBuffer layout unexpected");
211 // check object version
213 const deInt32 version = getNativeBaseVersion(base);
214 const deInt32 expectedVersion = getExpectedNativeBufferVersion();
216 if (version != expectedVersion)
217 TCU_THROW(NotSupportedError, "GraphicBuffer version unexpected");
220 // locate refcounting functions
222 if (!baseFunctions.incRef || !baseFunctions.decRef)
224 baseFunctions.incRef = getNativeBaseIncRefFunc(base);
225 baseFunctions.decRef = getNativeBaseDecRefFunc(base);
228 // take the initial reference and return
229 baseFunctions.incRef(base);
240 GraphicBuffer::GraphicBuffer (const LibUI& lib, deUint32 width, deUint32 height, PixelFormat format, deUint32 usage)
241 : m_functions (lib.getFunctions().graphicBuffer)
244 m_baseFunctions.incRef = DE_NULL;
245 m_baseFunctions.decRef = DE_NULL;
247 // \note createGraphicBuffer updates m_baseFunctions
248 m_impl = createGraphicBuffer(m_functions, m_baseFunctions, width, height, format, usage);
251 GraphicBuffer::~GraphicBuffer (void)
253 if (m_impl && m_baseFunctions.decRef)
255 m_baseFunctions.decRef(getAndroidNativeBase(m_impl));
260 status_t GraphicBuffer::lock (deUint32 usage, void** vaddr)
262 return m_functions.lock(m_impl, usage, vaddr);
265 status_t GraphicBuffer::unlock (void)
267 return m_functions.unlock(m_impl);
270 ANativeWindowBuffer* GraphicBuffer::getNativeBuffer (void) const
272 return m_functions.getNativeBuffer(m_impl);