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