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 Extension function pointer query tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "teglGetProcAddressTests.hpp" 25 #include "teglTestCase.hpp" 26 #include "egluCallLogWrapper.hpp" 27 #include "egluStrUtil.hpp" 28 #include "egluUtil.hpp" 29 #include "eglwLibrary.hpp" 30 #include "eglwEnums.hpp" 31 #include "tcuTestLog.hpp" 32 #include "deSTLUtil.hpp" 33 #include "deStringUtil.hpp" 34 35 namespace deqp 36 { 37 namespace egl 38 { 39 40 namespace 41 { 42 43 using tcu::TestLog; 44 using namespace eglw; 45 46 // Function name strings generated from API headers 47 48 #include "teglGetProcAddressTests.inl" 49 50 struct FunctionNames 51 { 52 int numFunctions; 53 const char* const* functions; 54 55 FunctionNames (int numFunctions_, const char* const* functions_) 56 : numFunctions (numFunctions_) 57 , functions (functions_) 58 { 59 } 60 }; 61 62 FunctionNames getExtFunctionNames (const std::string& extName) 63 { 64 for (int ndx = 0; ndx <= DE_LENGTH_OF_ARRAY(s_extensions); ndx++) 65 { 66 if (extName == s_extensions[ndx].name) 67 return FunctionNames(s_extensions[ndx].numFunctions, s_extensions[ndx].functions); 68 } 69 70 DE_ASSERT(false); 71 return FunctionNames(0, DE_NULL); 72 } 73 74 FunctionNames getCoreFunctionNames (EGLint apiBit) 75 { 76 switch (apiBit) 77 { 78 case 0: return FunctionNames(DE_LENGTH_OF_ARRAY(s_EGL14), s_EGL14); 79 case EGL_OPENGL_ES_BIT: return FunctionNames(DE_LENGTH_OF_ARRAY(s_GLES10), s_GLES10); 80 case EGL_OPENGL_ES2_BIT: return FunctionNames(DE_LENGTH_OF_ARRAY(s_GLES20), s_GLES20); 81 case EGL_OPENGL_ES3_BIT_KHR: return FunctionNames(DE_LENGTH_OF_ARRAY(s_GLES30), s_GLES30); 82 default: 83 DE_ASSERT(false); 84 } 85 86 return FunctionNames(0, DE_NULL); 87 } 88 89 } // anonymous 90 91 // Base class for eglGetProcAddress() test cases 92 93 class GetProcAddressCase : public TestCase, protected eglu::CallLogWrapper 94 { 95 public: 96 GetProcAddressCase (EglTestContext& eglTestCtx, const char* name, const char* description); 97 virtual ~GetProcAddressCase (void); 98 99 void init (void); 100 void deinit (void); 101 IterateResult iterate (void); 102 103 bool isSupported (const std::string& extName); 104 105 virtual void executeTest (void) = 0; 106 107 protected: 108 EGLDisplay m_display; 109 110 private: 111 std::vector<std::string> m_supported; 112 }; 113 114 GetProcAddressCase::GetProcAddressCase (EglTestContext& eglTestCtx, const char* name, const char* description) 115 : TestCase (eglTestCtx, name, description) 116 , CallLogWrapper (eglTestCtx.getLibrary(), eglTestCtx.getTestContext().getLog()) 117 , m_display (EGL_NO_DISPLAY) 118 { 119 } 120 121 GetProcAddressCase::~GetProcAddressCase (void) 122 { 123 } 124 125 void GetProcAddressCase::init (void) 126 { 127 try 128 { 129 m_supported = eglu::getClientExtensions(m_eglTestCtx.getLibrary()); 130 } 131 catch (const eglu::Error& error) 132 { 133 // EGL_BAD_DISPLAY is generated if client extensions are not supported. 134 if (error.getError() != EGL_BAD_DISPLAY) 135 throw; 136 } 137 138 DE_ASSERT(m_display == EGL_NO_DISPLAY); 139 140 m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); 141 142 { 143 const std::vector<std::string> displayExtensios = eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_display); 144 m_supported.insert(m_supported.end(), displayExtensios.begin(), displayExtensios.end()); 145 } 146 147 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 148 } 149 150 void GetProcAddressCase::deinit (void) 151 { 152 m_eglTestCtx.getLibrary().terminate(m_display); 153 m_display = EGL_NO_DISPLAY; 154 } 155 156 tcu::TestNode::IterateResult GetProcAddressCase::iterate (void) 157 { 158 enableLogging(true); 159 160 executeTest(); 161 162 enableLogging(false); 163 164 return STOP; 165 } 166 167 bool GetProcAddressCase::isSupported (const std::string& extName) 168 { 169 return de::contains(m_supported.begin(), m_supported.end(), extName); 170 } 171 172 // Test by extension 173 174 class GetProcAddressExtensionCase : public GetProcAddressCase 175 { 176 public: 177 GetProcAddressExtensionCase (EglTestContext& eglTestCtx, const char* name, const char* description, const std::string& extName) 178 : GetProcAddressCase (eglTestCtx, name, description) 179 , m_extName (extName) 180 { 181 } 182 183 virtual ~GetProcAddressExtensionCase (void) 184 { 185 } 186 187 void executeTest (void) 188 { 189 TestLog& log = m_testCtx.getLog(); 190 bool supported = isSupported(m_extName); 191 const FunctionNames funcNames = getExtFunctionNames(m_extName); 192 193 DE_ASSERT(funcNames.numFunctions > 0); 194 195 log << TestLog::Message << m_extName << ": " << (supported ? "supported" : "not supported") << TestLog::EndMessage; 196 log << TestLog::Message << TestLog::EndMessage; 197 198 for (int funcNdx = 0; funcNdx < funcNames.numFunctions; funcNdx++) 199 { 200 const char* funcName = funcNames.functions[funcNdx]; 201 void (*funcPtr)(void); 202 203 funcPtr = eglGetProcAddress(funcName); 204 eglu::checkError(eglGetError(), "eglGetProcAddress()", __FILE__, __LINE__); 205 206 if (supported && funcPtr == 0) 207 { 208 log << TestLog::Message << "Fail, received null pointer for supported extension function: " << funcName << TestLog::EndMessage; 209 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected null pointer"); 210 } 211 } 212 } 213 214 private: 215 std::string m_extName; 216 }; 217 218 // Test core functions 219 220 class GetProcAddressCoreFunctionsCase : public GetProcAddressCase 221 { 222 public: 223 GetProcAddressCoreFunctionsCase (EglTestContext& eglTestCtx, const char* name, const char* description, const EGLint apiBit) 224 : GetProcAddressCase (eglTestCtx, name, description) 225 , m_apiBit (apiBit) 226 { 227 } 228 229 virtual ~GetProcAddressCoreFunctionsCase (void) 230 { 231 } 232 233 void executeTest (void) 234 { 235 TestLog& log = m_testCtx.getLog(); 236 const bool funcPtrSupported = isSupported("EGL_KHR_get_all_proc_addresses"); 237 const bool apiSupported = (eglu::getRenderableAPIsMask(m_eglTestCtx.getLibrary(), m_display) & m_apiBit) == m_apiBit; 238 const FunctionNames funcNames = getCoreFunctionNames(m_apiBit); 239 240 log << TestLog::Message << "EGL_KHR_get_all_proc_addresses: " << (funcPtrSupported ? "supported" : "not supported") << TestLog::EndMessage; 241 log << TestLog::Message << TestLog::EndMessage; 242 243 if (!apiSupported) 244 { 245 log << TestLog::Message << eglu::getConfigAttribValueStr(EGL_RENDERABLE_TYPE, m_apiBit) << " not supported by any available configuration." << TestLog::EndMessage; 246 log << TestLog::Message << TestLog::EndMessage; 247 } 248 249 for (int funcNdx = 0; funcNdx < funcNames.numFunctions; funcNdx++) 250 { 251 const char* funcName = funcNames.functions[funcNdx]; 252 void (*funcPtr)(void); 253 254 funcPtr = eglGetProcAddress(funcName); 255 eglu::checkError(eglGetError(), "eglGetProcAddress()", __FILE__, __LINE__); 256 257 if (apiSupported && funcPtrSupported && (funcPtr == 0)) 258 { 259 log << TestLog::Message << "Fail, received null pointer for supported function: " << funcName << TestLog::EndMessage; 260 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected null pointer"); 261 } 262 else if (!apiSupported && (funcPtr != 0)) 263 { 264 log << TestLog::Message << "Warning, received non-null value for unsupported function: " << funcName << TestLog::EndMessage; 265 m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Non-null value for unsupported function"); 266 } 267 } 268 } 269 270 private: 271 const EGLint m_apiBit; 272 }; 273 274 GetProcAddressTests::GetProcAddressTests (EglTestContext& eglTestCtx) 275 : TestCaseGroup(eglTestCtx, "get_proc_address", "eglGetProcAddress() tests") 276 { 277 } 278 279 GetProcAddressTests::~GetProcAddressTests (void) 280 { 281 } 282 283 void GetProcAddressTests::init (void) 284 { 285 // extensions 286 { 287 tcu::TestCaseGroup* extensionsGroup = new tcu::TestCaseGroup(m_testCtx, "extension", "Test EGL extensions"); 288 addChild(extensionsGroup); 289 290 for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(s_extensions); extNdx++) 291 { 292 const std::string& extName = s_extensions[extNdx].name; 293 std::string testName (extName); 294 295 for (size_t ndx = 0; ndx < extName.length(); ndx++) 296 testName[ndx] = de::toLower(extName[ndx]); 297 298 extensionsGroup->addChild(new GetProcAddressExtensionCase(m_eglTestCtx, testName.c_str(), ("Test " + extName).c_str(), extName)); 299 } 300 } 301 302 // core functions 303 { 304 tcu::TestCaseGroup* coreFuncGroup = new tcu::TestCaseGroup(m_testCtx, "core", "Test core functions"); 305 addChild(coreFuncGroup); 306 307 coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase (m_eglTestCtx, "egl", "Test EGL core functions", 0)); 308 coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase (m_eglTestCtx, "gles", "Test OpenGL ES core functions", EGL_OPENGL_ES_BIT)); 309 coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase (m_eglTestCtx, "gles2", "Test OpenGL ES 2 core functions", EGL_OPENGL_ES2_BIT)); 310 coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase (m_eglTestCtx, "gles3", "Test OpenGL ES 3 core functions", EGL_OPENGL_ES3_BIT_KHR)); 311 } 312 } 313 314 } // egl 315 } // deqp 316