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 Config query tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "teglQueryContextTests.hpp" 25 #include "teglRenderCase.hpp" 26 #include "teglRenderCase.hpp" 27 #include "egluCallLogWrapper.hpp" 28 #include "egluStrUtil.hpp" 29 #include "tcuCommandLine.hpp" 30 #include "tcuTestLog.hpp" 31 #include "tcuTestContext.hpp" 32 33 #include "egluUtil.hpp" 34 #include "egluNativeDisplay.hpp" 35 #include "egluNativeWindow.hpp" 36 #include "egluNativePixmap.hpp" 37 38 #include "eglwLibrary.hpp" 39 #include "eglwEnums.hpp" 40 41 #include "deUniquePtr.hpp" 42 #include "deSTLUtil.hpp" 43 44 #include <vector> 45 46 namespace deqp 47 { 48 namespace egl 49 { 50 51 using std::vector; 52 using eglu::ConfigInfo; 53 using tcu::TestLog; 54 using namespace eglw; 55 56 static EGLint getClientTypeFromAPIBit (EGLint apiBit) 57 { 58 switch (apiBit) 59 { 60 case EGL_OPENGL_BIT: return EGL_OPENGL_API; 61 case EGL_OPENGL_ES_BIT: return EGL_OPENGL_ES_API; 62 case EGL_OPENGL_ES2_BIT: return EGL_OPENGL_ES_API; 63 case EGL_OPENGL_ES3_BIT: return EGL_OPENGL_ES_API; 64 case EGL_OPENVG_BIT: return EGL_OPENVG_API; 65 default: 66 DE_ASSERT(false); 67 return 0; 68 } 69 } 70 71 static EGLint getMinClientMajorVersion (EGLint apiBit) 72 { 73 switch (apiBit) 74 { 75 case EGL_OPENGL_BIT: return 1; 76 case EGL_OPENGL_ES_BIT: return 1; 77 case EGL_OPENGL_ES2_BIT: return 2; 78 case EGL_OPENGL_ES3_BIT: return 3; 79 case EGL_OPENVG_BIT: return 1; 80 default: 81 DE_ASSERT(false); 82 return 0; 83 } 84 } 85 86 class GetCurrentContextCase : public SingleContextRenderCase, private eglu::CallLogWrapper 87 { 88 public: 89 GetCurrentContextCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask) 90 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters) 91 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog()) 92 { 93 } 94 95 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config) 96 { 97 const Library& egl = m_eglTestCtx.getLibrary(); 98 TestLog& log = m_testCtx.getLog(); 99 100 DE_UNREF(display); 101 DE_UNREF(surface); 102 DE_UNREF(config); 103 104 enableLogging(true); 105 106 const EGLContext gotContext = eglGetCurrentContext(); 107 EGLU_CHECK_MSG(egl, "eglGetCurrentContext"); 108 109 if (gotContext == context) 110 { 111 log << TestLog::Message << " Pass" << TestLog::EndMessage; 112 } 113 else if (gotContext == EGL_NO_CONTEXT) 114 { 115 log << TestLog::Message << " Fail, got EGL_NO_CONTEXT" << TestLog::EndMessage; 116 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected EGL_NO_CONTEXT"); 117 } 118 else if (gotContext != context) 119 { 120 log << TestLog::Message << " Fail, call returned the wrong context. Expected: " << tcu::toHex(context) << ", got: " << tcu::toHex(gotContext) << TestLog::EndMessage; 121 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid context"); 122 } 123 124 enableLogging(false); 125 } 126 }; 127 128 class GetCurrentSurfaceCase : public SingleContextRenderCase, private eglu::CallLogWrapper 129 { 130 public: 131 GetCurrentSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask) 132 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters) 133 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog()) 134 { 135 } 136 137 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config) 138 { 139 const Library& egl = m_eglTestCtx.getLibrary(); 140 TestLog& log = m_testCtx.getLog(); 141 142 DE_UNREF(display); 143 DE_UNREF(context); 144 DE_UNREF(config); 145 146 enableLogging(true); 147 148 const EGLContext gotReadSurface = eglGetCurrentSurface(EGL_READ); 149 EGLU_CHECK_MSG(egl, "eglGetCurrentSurface(EGL_READ)"); 150 151 const EGLContext gotDrawSurface = eglGetCurrentSurface(EGL_DRAW); 152 EGLU_CHECK_MSG(egl, "eglGetCurrentSurface(EGL_DRAW)"); 153 154 if (gotReadSurface == surface && gotDrawSurface == surface) 155 { 156 log << TestLog::Message << " Pass" << TestLog::EndMessage; 157 } 158 else 159 { 160 log << TestLog::Message << " Fail, read surface: " << tcu::toHex(gotReadSurface) 161 << ", draw surface: " << tcu::toHex(gotDrawSurface) 162 << ", expected: " << tcu::toHex(surface) << TestLog::EndMessage; 163 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface"); 164 } 165 166 enableLogging(false); 167 } 168 }; 169 170 class GetCurrentDisplayCase : public SingleContextRenderCase, private eglu::CallLogWrapper 171 { 172 public: 173 GetCurrentDisplayCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask) 174 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters) 175 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog()) 176 { 177 } 178 179 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config) 180 { 181 const Library& egl = m_eglTestCtx.getLibrary(); 182 TestLog& log = m_testCtx.getLog(); 183 184 DE_UNREF(surface && context); 185 DE_UNREF(config); 186 187 enableLogging(true); 188 189 const EGLDisplay gotDisplay = eglGetCurrentDisplay(); 190 EGLU_CHECK_MSG(egl, "eglGetCurrentDisplay"); 191 192 if (gotDisplay == display) 193 { 194 log << TestLog::Message << " Pass" << TestLog::EndMessage; 195 } 196 else if (gotDisplay == EGL_NO_DISPLAY) 197 { 198 log << TestLog::Message << " Fail, got EGL_NO_DISPLAY" << TestLog::EndMessage; 199 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected EGL_NO_DISPLAY"); 200 } 201 else if (gotDisplay != display) 202 { 203 log << TestLog::Message << " Fail, call returned the wrong display. Expected: " << tcu::toHex(display) << ", got: " << tcu::toHex(gotDisplay) << TestLog::EndMessage; 204 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid display"); 205 } 206 207 enableLogging(false); 208 } 209 }; 210 211 class QueryContextCase : public SingleContextRenderCase, private eglu::CallLogWrapper 212 { 213 public: 214 QueryContextCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask) 215 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters) 216 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog()) 217 { 218 } 219 220 EGLint getContextAttrib (EGLDisplay display, EGLContext context, EGLint attrib) 221 { 222 const Library& egl = m_eglTestCtx.getLibrary(); 223 EGLint value; 224 EGLU_CHECK_CALL(egl, queryContext(display, context, attrib, &value)); 225 226 return value; 227 } 228 229 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config) 230 { 231 const Library& egl = m_eglTestCtx.getLibrary(); 232 TestLog& log = m_testCtx.getLog(); 233 const eglu::Version version = eglu::getVersion(egl, display); 234 235 DE_UNREF(surface); 236 enableLogging(true); 237 238 // Config ID 239 { 240 const EGLint configID = getContextAttrib(display, context, EGL_CONFIG_ID); 241 const EGLint surfaceConfigID = eglu::getConfigAttribInt(egl, display, config.config, EGL_CONFIG_ID); 242 243 if (configID != surfaceConfigID) 244 { 245 log << TestLog::Message << " Fail, config ID doesn't match the one used to create the context." << TestLog::EndMessage; 246 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid config ID"); 247 } 248 } 249 250 // Client API type 251 if (version >= eglu::Version(1, 2)) 252 { 253 const EGLint clientType = getContextAttrib(display, context, EGL_CONTEXT_CLIENT_TYPE); 254 255 if (clientType != getClientTypeFromAPIBit(config.apiBits)) 256 { 257 log << TestLog::Message << " Fail, client API type doesn't match." << TestLog::EndMessage; 258 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid client API type"); 259 } 260 } 261 262 // Client API version 263 if (version >= eglu::Version(1, 3)) 264 { 265 const EGLint clientVersion = getContextAttrib(display, context, EGL_CONTEXT_CLIENT_VERSION); 266 267 // \todo [2014-10-21 mika] Query actual supported api version from client api to make this check stricter. 268 if (clientVersion < getMinClientMajorVersion(config.apiBits)) 269 { 270 log << TestLog::Message << " Fail, client API version doesn't match." << TestLog::EndMessage; 271 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid client API version"); 272 } 273 } 274 275 // Render buffer 276 if (version >= eglu::Version(1, 2)) 277 { 278 const EGLint renderBuffer = getContextAttrib(display, context, EGL_RENDER_BUFFER); 279 280 if (config.surfaceTypeBit == EGL_PIXMAP_BIT && renderBuffer != EGL_SINGLE_BUFFER) 281 { 282 log << TestLog::Message << " Fail, render buffer should be EGL_SINGLE_BUFFER for a pixmap surface." << TestLog::EndMessage; 283 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer"); 284 } 285 else if (config.surfaceTypeBit == EGL_PBUFFER_BIT && renderBuffer != EGL_BACK_BUFFER) 286 { 287 log << TestLog::Message << " Fail, render buffer should be EGL_BACK_BUFFER for a pbuffer surface." << TestLog::EndMessage; 288 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer"); 289 } 290 else if (config.surfaceTypeBit == EGL_WINDOW_BIT && renderBuffer != EGL_SINGLE_BUFFER && renderBuffer != EGL_BACK_BUFFER) 291 { 292 log << TestLog::Message << " Fail, render buffer should be either EGL_SINGLE_BUFFER or EGL_BACK_BUFFER for a window surface." << TestLog::EndMessage; 293 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer"); 294 } 295 } 296 297 enableLogging(false); 298 299 log << TestLog::Message << " Pass" << TestLog::EndMessage; 300 } 301 }; 302 303 class QueryAPICase : public TestCase, private eglu::CallLogWrapper 304 { 305 public: 306 QueryAPICase (EglTestContext& eglTestCtx, const char* name, const char* description) 307 : TestCase (eglTestCtx, name, description) 308 , CallLogWrapper(eglTestCtx.getLibrary(), eglTestCtx.getTestContext().getLog()) 309 { 310 } 311 312 void init (void) 313 { 314 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 315 } 316 317 IterateResult iterate (void) 318 { 319 const Library& egl = m_eglTestCtx.getLibrary(); 320 EGLDisplay display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()); 321 tcu::TestLog& log = m_testCtx.getLog(); 322 const EGLenum apis[] = { EGL_OPENGL_API, EGL_OPENGL_ES_API, EGL_OPENVG_API }; 323 const vector<EGLenum> supportedAPIs = eglu::getClientAPIs(egl, display); 324 325 enableLogging(true); 326 327 { 328 const EGLenum api = eglQueryAPI(); 329 330 if (api != EGL_OPENGL_ES_API && (de::contains(supportedAPIs.begin(), supportedAPIs.end(), EGL_OPENGL_ES_API))) 331 { 332 log << TestLog::Message << " Fail, initial value should be EGL_OPENGL_ES_API if OpenGL ES is supported." << TestLog::EndMessage; 333 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default value"); 334 } 335 else if (api != EGL_NONE && !(de::contains(supportedAPIs.begin(), supportedAPIs.end(), EGL_OPENGL_ES_API))) 336 { 337 log << TestLog::Message << " Fail, initial value should be EGL_NONE if OpenGL ES is not supported." << TestLog::EndMessage; 338 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default value"); 339 } 340 } 341 342 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(apis); ndx++) 343 { 344 const EGLenum api = apis[ndx]; 345 346 log << TestLog::Message << TestLog::EndMessage; 347 348 if (de::contains(supportedAPIs.begin(), supportedAPIs.end(), api)) 349 { 350 egl.bindAPI(api); 351 352 if (api != egl.queryAPI()) 353 { 354 log << TestLog::Message << " Fail, return value does not match previously bound API." << TestLog::EndMessage; 355 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid return value"); 356 } 357 } 358 else 359 { 360 log << TestLog::Message << eglu::getAPIStr(api) << " not supported." << TestLog::EndMessage; 361 } 362 } 363 364 enableLogging(false); 365 eglTerminate(display); 366 return STOP; 367 } 368 }; 369 370 QueryContextTests::QueryContextTests (EglTestContext& eglTestCtx) 371 : TestCaseGroup(eglTestCtx, "query_context", "Rendering context query tests") 372 { 373 } 374 375 QueryContextTests::~QueryContextTests (void) 376 { 377 } 378 379 template<class QueryContextClass> 380 void createQueryContextGroups (EglTestContext& eglTestCtx, tcu::TestCaseGroup* group) 381 { 382 std::vector<RenderFilterList> filterLists; 383 384 getDefaultRenderFilterLists(filterLists, eglu::FilterList()); 385 386 for (std::vector<RenderFilterList>::const_iterator listIter = filterLists.begin(); listIter != filterLists.end(); listIter++) 387 group->addChild(new QueryContextClass(eglTestCtx, listIter->getName(), "", *listIter, listIter->getSurfaceTypeMask())); 388 } 389 390 void QueryContextTests::init (void) 391 { 392 { 393 tcu::TestCaseGroup* simpleGroup = new tcu::TestCaseGroup(m_testCtx, "simple", "Simple API tests"); 394 addChild(simpleGroup); 395 396 simpleGroup->addChild(new QueryAPICase(m_eglTestCtx, "query_api", "eglQueryAPI() test")); 397 } 398 399 // eglGetCurrentContext 400 { 401 tcu::TestCaseGroup* getCurrentContextGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_context", "eglGetCurrentContext() tests"); 402 addChild(getCurrentContextGroup); 403 404 createQueryContextGroups<GetCurrentContextCase>(m_eglTestCtx, getCurrentContextGroup); 405 } 406 407 // eglGetCurrentSurface 408 { 409 tcu::TestCaseGroup* getCurrentSurfaceGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_surface", "eglGetCurrentSurface() tests"); 410 addChild(getCurrentSurfaceGroup); 411 412 createQueryContextGroups<GetCurrentSurfaceCase>(m_eglTestCtx, getCurrentSurfaceGroup); 413 } 414 415 // eglGetCurrentDisplay 416 { 417 tcu::TestCaseGroup* getCurrentDisplayGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_display", "eglGetCurrentDisplay() tests"); 418 addChild(getCurrentDisplayGroup); 419 420 createQueryContextGroups<GetCurrentDisplayCase>(m_eglTestCtx, getCurrentDisplayGroup); 421 } 422 423 // eglQueryContext 424 { 425 tcu::TestCaseGroup* queryContextGroup = new tcu::TestCaseGroup(m_testCtx, "query_context", "eglQueryContext() tests"); 426 addChild(queryContextGroup); 427 428 createQueryContextGroups<QueryContextCase>(m_eglTestCtx, queryContextGroup); 429 } 430 } 431 432 } // egl 433 } // deqp 434