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 "teglQueryConfigTests.hpp" 25 #include "teglSimpleConfigCase.hpp" 26 #include "tcuTestLog.hpp" 27 #include "tcuTestContext.hpp" 28 #include "tcuCommandLine.hpp" 29 #include "egluCallLogWrapper.hpp" 30 #include "egluStrUtil.hpp" 31 #include "deRandom.hpp" 32 33 #include <string> 34 #include <vector> 35 36 #if !defined(EGL_OPENGL_ES3_BIT_KHR) 37 # define EGL_OPENGL_ES3_BIT_KHR 0x0040 38 #endif 39 40 namespace deqp 41 { 42 namespace egl 43 { 44 45 using eglu::ConfigInfo; 46 using tcu::TestLog; 47 48 static void logConfigAttribute (TestLog& log, EGLenum attrib, EGLint value) 49 { 50 log << TestLog::Message << " " << eglu::getConfigAttribName(attrib) << ": " << eglu::getConfigAttribValueStr(attrib, value) << TestLog::EndMessage; 51 } 52 53 static bool isAttributePresent (const eglu::Version& version, EGLenum attribute) 54 { 55 switch (attribute) 56 { 57 case EGL_CONFORMANT: 58 if (version < eglu::Version(1, 3)) return false; 59 break; 60 case EGL_LUMINANCE_SIZE: 61 case EGL_ALPHA_MASK_SIZE: 62 case EGL_COLOR_BUFFER_TYPE: 63 case EGL_MATCH_NATIVE_PIXMAP: 64 if (version < eglu::Version(1, 2)) return false; 65 break; 66 case EGL_BIND_TO_TEXTURE_RGB: 67 case EGL_BIND_TO_TEXTURE_RGBA: 68 case EGL_MAX_SWAP_INTERVAL: 69 case EGL_MIN_SWAP_INTERVAL: 70 case EGL_RENDERABLE_TYPE: 71 if (version < eglu::Version(1, 1)) return false; 72 break; 73 default: 74 break; 75 } 76 77 return true; 78 } 79 80 class GetConfigsBoundsCase : public TestCase, protected eglu::CallLogWrapper 81 { 82 public: 83 GetConfigsBoundsCase (EglTestContext& eglTestCtx, const char* name, const char* description) 84 : TestCase (eglTestCtx, name, description) 85 , CallLogWrapper(eglTestCtx.getTestContext().getLog()) 86 { 87 } 88 89 void init (void) 90 { 91 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 92 } 93 94 void checkGetConfigsBounds(const tcu::egl::Display& display, de::Random& rnd, const int numConfigAll, const int numConfigRequested) 95 { 96 tcu::TestLog& log = m_testCtx.getLog(); 97 std::vector<EGLConfig> buffer (numConfigAll + 10); 98 99 std::vector<deUint32> magicBuffer ((buffer.size() * sizeof(EGLConfig)) / sizeof(deUint32) + 1); 100 const EGLConfig* magicConfigs = reinterpret_cast<EGLConfig*>(&magicBuffer[0]); 101 102 int numConfigReturned; 103 104 // Fill buffers with magic 105 for (size_t ndx = 0; ndx < magicBuffer.size(); ndx++) magicBuffer[ndx] = rnd.getUint32(); 106 for (size_t ndx = 0; ndx < buffer.size(); ndx++) buffer[ndx] = magicConfigs[ndx]; 107 108 eglGetConfigs(display.getEGLDisplay(), &buffer[0], numConfigRequested, &numConfigReturned); 109 TCU_CHECK_EGL(); 110 111 log << TestLog::Message << numConfigReturned << " configs returned" << TestLog::EndMessage; 112 113 // Compare results with stored magic 114 { 115 int numOverwritten = 0; 116 117 for (size_t ndx = 0; ndx < buffer.size(); ndx++) 118 { 119 if (buffer[ndx] == magicConfigs[ndx]) 120 { 121 numOverwritten = (int)ndx; 122 break; 123 } 124 } 125 126 log << TestLog::Message << numOverwritten << " values actually written" << TestLog::EndMessage; 127 128 if (numConfigReturned > deMax32(numConfigRequested, 0)) 129 { 130 log << TestLog::Message << "Fail, more configs returned than requested." << TestLog::EndMessage; 131 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Too many configs returned"); 132 } 133 134 if (numOverwritten > deMax32(numConfigReturned, 0)) 135 { 136 log << TestLog::Message << "Fail, buffer overflow detected." << TestLog::EndMessage; 137 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Buffer overflow"); 138 } 139 else if (numOverwritten != numConfigReturned) 140 { 141 log << TestLog::Message << "Fail, reported number of returned configs differs from number of values written." << TestLog::EndMessage; 142 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect size"); 143 } 144 } 145 } 146 147 IterateResult iterate (void) 148 { 149 tcu::TestLog& log = m_testCtx.getLog(); 150 tcu::egl::Display& display = m_eglTestCtx.getDisplay(); 151 EGLint numConfigAll; 152 153 enableLogging(true); 154 155 eglGetConfigs(display.getEGLDisplay(), 0, 0, &numConfigAll); 156 157 log << TestLog::Message << numConfigAll << " configs available" << TestLog::EndMessage; 158 log << TestLog::Message << TestLog::EndMessage; 159 160 if (numConfigAll > 0) 161 { 162 de::Random rnd (123); 163 164 for (int i = 0; i < 5; i++) 165 { 166 checkGetConfigsBounds(display, rnd, numConfigAll, rnd.getInt(0, numConfigAll)); 167 log << TestLog::Message << TestLog::EndMessage; 168 } 169 170 checkGetConfigsBounds(display, rnd, numConfigAll, -1); 171 } 172 else 173 { 174 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "No configs"); 175 } 176 177 enableLogging(false); 178 179 return STOP; 180 } 181 }; 182 183 class GetConfigAttribCase : public TestCase, protected eglu::CallLogWrapper 184 { 185 public: 186 GetConfigAttribCase (EglTestContext& eglTestCtx, const char* name, const char* description); 187 188 void init (); 189 IterateResult iterate (void); 190 191 EGLint getValue (EGLConfig config, EGLenum attrib, bool logValue=true); 192 193 virtual void executeTest (EGLConfig config) = 0; 194 private: 195 std::vector<EGLConfig> m_configs; 196 std::vector<EGLConfig>::const_iterator m_configsIter; 197 }; 198 199 GetConfigAttribCase::GetConfigAttribCase (EglTestContext& eglTestCtx, const char* name, const char* description) 200 : TestCase(eglTestCtx, name, description) 201 , CallLogWrapper(eglTestCtx.getTestContext().getLog()) 202 { 203 } 204 205 void GetConfigAttribCase::init (void) 206 { 207 const tcu::egl::Display& display = m_eglTestCtx.getDisplay(); 208 209 display.getConfigs(m_configs); 210 m_configsIter = m_configs.begin(); 211 212 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 213 } 214 215 tcu::TestNode::IterateResult GetConfigAttribCase::iterate (void) 216 { 217 tcu::TestLog& log = m_testCtx.getLog(); 218 tcu::egl::Display& display = m_eglTestCtx.getDisplay(); 219 220 if (m_configsIter == m_configs.end()) 221 { 222 log << TestLog::Message << "No configs available." << TestLog::EndMessage; 223 return STOP; 224 } 225 226 { 227 const EGLConfig config = *m_configsIter; 228 EGLint id; 229 230 TCU_CHECK_EGL_CALL(eglGetConfigAttrib(display.getEGLDisplay(), config, EGL_CONFIG_ID, &id)); 231 log << TestLog::Message << "Config ID " << id << TestLog::EndMessage; 232 233 executeTest(config); 234 } 235 236 log << TestLog::Message << TestLog::EndMessage; 237 238 m_configsIter++; 239 240 if (m_configsIter == m_configs.end()) 241 return STOP; 242 else 243 return CONTINUE; 244 } 245 246 EGLint GetConfigAttribCase::getValue (EGLConfig config, EGLenum attrib, bool logValue) 247 { 248 TestLog& log = m_testCtx.getLog(); 249 const tcu::egl::Display& display = m_eglTestCtx.getDisplay(); 250 EGLint value; 251 252 eglGetConfigAttrib(display.getEGLDisplay(), config, attrib, &value); 253 TCU_CHECK_EGL(); 254 255 if (logValue) logConfigAttribute(log, attrib, value); 256 257 return value; 258 } 259 260 class GetConfigAttribSimpleCase : public GetConfigAttribCase 261 { 262 public: 263 GetConfigAttribSimpleCase (EglTestContext& eglTestCtx, const char* name, const char* description, EGLenum attribute) 264 : GetConfigAttribCase(eglTestCtx, name, description) 265 , m_attrib(attribute) 266 { 267 } 268 269 void checkColorBufferType (EGLint value) 270 { 271 if (!(value == EGL_RGB_BUFFER || value == EGL_LUMINANCE_BUFFER)) 272 { 273 TestLog& log = m_testCtx.getLog(); 274 275 log << TestLog::Message << "Fail, invalid EGL_COLOR_BUFFER_TYPE value" << TestLog::EndMessage; 276 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value"); 277 } 278 } 279 280 void checkCaveat (EGLint value) 281 { 282 if (!(value == EGL_NONE || value == EGL_SLOW_CONFIG || value == EGL_NON_CONFORMANT_CONFIG)) 283 { 284 TestLog& log = m_testCtx.getLog(); 285 286 log << TestLog::Message << "Fail, invalid EGL_CONFIG_CAVEAT value" << TestLog::EndMessage; 287 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value"); 288 } 289 } 290 291 void checkTransparentType (EGLint value) 292 { 293 if (!(value == EGL_NONE || value == EGL_TRANSPARENT_RGB)) 294 { 295 TestLog& log = m_testCtx.getLog(); 296 297 log << TestLog::Message << "Fail, invalid EGL_TRANSPARENT_TYPE value" << TestLog::EndMessage; 298 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value"); 299 } 300 } 301 302 void checkBoolean (EGLenum attrib, EGLint value) 303 { 304 if (!(value == EGL_FALSE || value == EGL_TRUE)) 305 { 306 TestLog& log = m_testCtx.getLog(); 307 308 log << TestLog::Message << "Fail, " << eglu::getConfigAttribStr(attrib) << " should be a boolean value." << TestLog::EndMessage; 309 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value"); 310 } 311 } 312 313 void checkInteger (EGLenum attrib, EGLint value) 314 { 315 if (attrib == EGL_NATIVE_VISUAL_ID || attrib == EGL_NATIVE_VISUAL_TYPE) // Implementation-defined 316 return; 317 318 if (attrib == EGL_CONFIG_ID && value < 1) 319 { 320 TestLog& log = m_testCtx.getLog(); 321 322 log << TestLog::Message << "Fail, config IDs should be positive integer values beginning from 1." << TestLog::EndMessage; 323 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value"); 324 } 325 } 326 327 void checkSurfaceTypeMask (EGLint value) 328 { 329 const EGLint wantedBits = EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT; 330 331 if ((value & wantedBits) == 0) 332 { 333 TestLog& log = m_testCtx.getLog(); 334 335 log << TestLog::Message << "Fail, config does not actually support creation of any surface type?" << TestLog::EndMessage; 336 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid value"); 337 } 338 } 339 340 void checkAttribute (EGLenum attrib, EGLint value) 341 { 342 switch (attrib) 343 { 344 case EGL_COLOR_BUFFER_TYPE: 345 checkColorBufferType(value); 346 break; 347 case EGL_CONFIG_CAVEAT: 348 checkCaveat(value); 349 break; 350 case EGL_TRANSPARENT_TYPE: 351 checkTransparentType(value); 352 break; 353 case EGL_CONFORMANT: 354 case EGL_RENDERABLE_TYPE: 355 // Just print what we know 356 break; 357 case EGL_SURFACE_TYPE: 358 checkSurfaceTypeMask(value); 359 break; 360 case EGL_BIND_TO_TEXTURE_RGB: 361 case EGL_BIND_TO_TEXTURE_RGBA: 362 case EGL_NATIVE_RENDERABLE: 363 checkBoolean(attrib, value); 364 break; 365 default: 366 checkInteger(attrib, value); 367 } 368 } 369 370 void executeTest (EGLConfig config) 371 { 372 TestLog& log = m_testCtx.getLog(); 373 const tcu::egl::Display& display = m_eglTestCtx.getDisplay(); 374 375 if (!isAttributePresent(display.getVersion(), m_attrib)) 376 { 377 log << TestLog::Message << eglu::getConfigAttribStr(m_attrib) << " not supported by this EGL version"; 378 } 379 else 380 { 381 EGLint value; 382 383 enableLogging(true); 384 385 eglGetConfigAttrib(display.getEGLDisplay(), config, m_attrib, &value); 386 TCU_CHECK_EGL(); 387 388 logConfigAttribute(log, m_attrib, value); 389 checkAttribute(m_attrib, value); 390 391 enableLogging(false); 392 } 393 } 394 395 private: 396 EGLenum m_attrib; 397 }; 398 399 class GetConfigAttribBufferSizeCase : public GetConfigAttribCase 400 { 401 public: 402 GetConfigAttribBufferSizeCase (EglTestContext& eglTestCtx, const char* name, const char* description) 403 : GetConfigAttribCase(eglTestCtx, name, description) 404 { 405 } 406 407 void executeTest (EGLConfig config) 408 { 409 TestLog& log = m_testCtx.getLog(); 410 411 const EGLint colorBufferType = getValue(config, EGL_COLOR_BUFFER_TYPE); 412 413 const EGLint bufferSize = getValue(config, EGL_BUFFER_SIZE); 414 const EGLint redSize = getValue(config, EGL_RED_SIZE); 415 const EGLint greenSize = getValue(config, EGL_GREEN_SIZE); 416 const EGLint blueSize = getValue(config, EGL_BLUE_SIZE); 417 const EGLint luminanceSize = getValue(config, EGL_LUMINANCE_SIZE); 418 const EGLint alphaSize = getValue(config, EGL_ALPHA_SIZE); 419 420 if (alphaSize < 0) 421 { 422 log << TestLog::Message << "Fail, alpha size must be zero or positive." << TestLog::EndMessage; 423 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid alpha size"); 424 } 425 426 if (colorBufferType == EGL_RGB_BUFFER) 427 { 428 if (luminanceSize != 0) 429 { 430 log << TestLog::Message << "Fail, luminance size must be zero for an RGB buffer." << TestLog::EndMessage; 431 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid luminance size"); 432 } 433 434 if (redSize <= 0 || greenSize <= 0 || blueSize <= 0) 435 { 436 log << TestLog::Message << "Fail, RGB component sizes must be positive for an RGB buffer." << TestLog::EndMessage; 437 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color component size"); 438 } 439 440 if (bufferSize != (redSize + greenSize + blueSize + alphaSize)) 441 { 442 log << TestLog::Message << "Fail, buffer size must be equal to the sum of RGB component sizes and alpha size." << TestLog::EndMessage; 443 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid buffer size"); 444 } 445 } 446 else if (colorBufferType == EGL_LUMINANCE_BUFFER) 447 { 448 if (luminanceSize <= 0) 449 { 450 log << TestLog::Message << "Fail, luminance size must be positive for a luminance buffer." << TestLog::EndMessage; 451 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid luminance size"); 452 } 453 454 if (redSize != 0 || greenSize != 0 || blueSize != 0) 455 { 456 log << TestLog::Message << "Fail, RGB component sizes must be zero for a luminance buffer." << TestLog::EndMessage; 457 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color component size"); 458 } 459 460 if (bufferSize != (luminanceSize + alphaSize)) 461 { 462 log << TestLog::Message << "Fail, buffer size must be equal to the sum of luminance size and alpha size." << TestLog::EndMessage; 463 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid buffer size"); 464 } 465 } 466 } 467 }; 468 469 class GetConfigAttribTransparentValueCase : public GetConfigAttribCase 470 { 471 public: 472 GetConfigAttribTransparentValueCase (EglTestContext& eglTestCtx, const char* name, const char* description) 473 : GetConfigAttribCase(eglTestCtx, name, description) 474 { 475 } 476 477 void executeTest (EGLConfig config) 478 { 479 TestLog& log = m_testCtx.getLog(); 480 481 const EGLint transparentType = getValue(config, EGL_TRANSPARENT_TYPE); 482 const EGLint redValue = getValue(config, EGL_TRANSPARENT_RED_VALUE); 483 const EGLint greenValue = getValue(config, EGL_TRANSPARENT_GREEN_VALUE); 484 const EGLint blueValue = getValue(config, EGL_TRANSPARENT_BLUE_VALUE); 485 486 const EGLint redSize = getValue(config, EGL_RED_SIZE); 487 const EGLint greenSize = getValue(config, EGL_GREEN_SIZE); 488 const EGLint blueSize = getValue(config, EGL_BLUE_SIZE); 489 490 if (transparentType == EGL_TRANSPARENT_RGB) 491 { 492 if ( (redValue < 0 || redValue >= (1 << redSize)) 493 || (greenValue < 0 || greenValue >= (1 << greenSize)) 494 || (blueValue < 0 || blueValue >= (1 << blueSize)) ) 495 { 496 log << TestLog::Message << "Fail, transparent color values must lie between 0 and the maximum component value." << TestLog::EndMessage; 497 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid transparent color value"); 498 } 499 } 500 } 501 }; 502 503 QueryConfigTests::QueryConfigTests (EglTestContext& eglTestCtx) 504 : TestCaseGroup(eglTestCtx, "query_config", "Surface config query tests") 505 { 506 } 507 508 QueryConfigTests::~QueryConfigTests (void) 509 { 510 } 511 512 void QueryConfigTests::init (void) 513 { 514 // eglGetGonfigs 515 { 516 tcu::TestCaseGroup* getConfigsGroup = new tcu::TestCaseGroup(m_testCtx, "get_configs", "eglGetConfigs tests"); 517 addChild(getConfigsGroup); 518 519 getConfigsGroup->addChild(new GetConfigsBoundsCase(m_eglTestCtx, "get_configs_bounds", "eglGetConfigs bounds checking test")); 520 } 521 522 // eglGetConfigAttrib 523 { 524 static const struct 525 { 526 EGLenum attribute; 527 const char* testName; 528 } attributes[] = 529 { 530 { EGL_BUFFER_SIZE, "buffer_size" }, 531 { EGL_RED_SIZE, "red_size" }, 532 { EGL_GREEN_SIZE, "green_size" }, 533 { EGL_BLUE_SIZE, "blue_size" }, 534 { EGL_LUMINANCE_SIZE, "luminance_size" }, 535 { EGL_ALPHA_SIZE, "alpha_size" }, 536 { EGL_ALPHA_MASK_SIZE, "alpha_mask_size" }, 537 { EGL_BIND_TO_TEXTURE_RGB, "bind_to_texture_rgb" }, 538 { EGL_BIND_TO_TEXTURE_RGBA, "bind_to_texture_rgba" }, 539 { EGL_COLOR_BUFFER_TYPE, "color_buffer_type" }, 540 { EGL_CONFIG_CAVEAT, "config_caveat" }, 541 { EGL_CONFIG_ID, "config_id" }, 542 { EGL_CONFORMANT, "conformant" }, 543 { EGL_DEPTH_SIZE, "depth_size" }, 544 { EGL_LEVEL, "level" }, 545 { EGL_MAX_SWAP_INTERVAL, "max_swap_interval" }, 546 { EGL_MIN_SWAP_INTERVAL, "min_swap_interval" }, 547 { EGL_NATIVE_RENDERABLE, "native_renderable" }, 548 { EGL_NATIVE_VISUAL_TYPE, "native_visual_type" }, 549 { EGL_RENDERABLE_TYPE, "renderable_type" }, 550 { EGL_SAMPLE_BUFFERS, "sample_buffers" }, 551 { EGL_SAMPLES, "samples" }, 552 { EGL_STENCIL_SIZE, "stencil_size" }, 553 { EGL_SURFACE_TYPE, "surface_type" }, 554 { EGL_TRANSPARENT_TYPE, "transparent_type" }, 555 { EGL_TRANSPARENT_RED_VALUE, "transparent_red_value" }, 556 { EGL_TRANSPARENT_GREEN_VALUE, "transparent_green_value" }, 557 { EGL_TRANSPARENT_BLUE_VALUE, "transparent_blue_value" } 558 }; 559 560 tcu::TestCaseGroup* simpleGroup = new tcu::TestCaseGroup(m_testCtx, "get_config_attrib", "eglGetConfigAttrib() tests"); 561 addChild(simpleGroup); 562 563 for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(attributes); ndx++) 564 { 565 simpleGroup->addChild(new GetConfigAttribSimpleCase(m_eglTestCtx, attributes[ndx].testName, "Simple attribute query case", attributes[ndx].attribute)); 566 } 567 } 568 569 // Attribute constraints 570 { 571 tcu::TestCaseGroup* constraintsGroup = new tcu::TestCaseGroup(m_testCtx, "constraints", "Attribute constraint tests"); 572 addChild(constraintsGroup); 573 574 constraintsGroup->addChild(new GetConfigAttribBufferSizeCase(m_eglTestCtx, "color_buffer_size", "Color buffer component sizes")); 575 constraintsGroup->addChild(new GetConfigAttribTransparentValueCase(m_eglTestCtx, "transparent_value", "Transparent color value")); 576 } 577 } 578 579 } // egl 580 } // deqp 581