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 28namespace tcu 29{ 30namespace Android 31{ 32namespace internal 33{ 34 35using std::string; 36using de::DynamicLibrary; 37 38template<typename Func> 39void 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 46LibUI::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 61typedef void (*GenericFptr)(); 62 63//! call constructor with 4 arguments 64template <typename RT, typename T1, typename T2, typename T3, typename T4> 65RT* 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 101template <typename T> 102void 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 127template<typename T1, typename T2> 128T1* pointerToOffset (T2* ptr, size_t bytes) 129{ 130 return reinterpret_cast<T1*>((deUint8*)ptr + bytes); 131} 132 133static 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 140static 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 152static deUint32 getNativeBaseMagic (android::android_native_base_t* base) 153{ 154 return *pointerToOffset<deUint32>(base, 0); 155} 156 157//! access android_native_base_t::version 158static deUint32 getNativeBaseVersion (android::android_native_base_t* base) 159{ 160 return *pointerToOffset<deInt32>(base, 4); 161} 162 163//! access android_native_base_t::incRef 164static 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 170static NativeBaseFunctions::decRefFunc getNativeBaseDecRefFunc (android::android_native_base_t* base) 171{ 172 return *pointerToOffset<NativeBaseFunctions::decRefFunc>(base, 8 + DE_PTR_SIZE*5); 173} 174 175static 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 240GraphicBuffer::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 251GraphicBuffer::~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 260status_t GraphicBuffer::lock (deUint32 usage, void** vaddr) 261{ 262 return m_functions.lock(m_impl, usage, vaddr); 263} 264 265status_t GraphicBuffer::unlock (void) 266{ 267 return m_functions.unlock(m_impl); 268} 269 270ANativeWindowBuffer* GraphicBuffer::getNativeBuffer (void) const 271{ 272 return m_functions.getNativeBuffer(m_impl); 273} 274 275} // internal 276} // Android 277} // tcu 278