1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program EGL Module 3 * --------------------------------------- 4 * 5 * Copyright 2017 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 Test the EGL_ANDROID_get_frame_timestamps extension. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "teglGetFrameTimestampsTests.hpp" 25 26 #include "teglSimpleConfigCase.hpp" 27 28 #include "egluNativeWindow.hpp" 29 #include "egluUtil.hpp" 30 #include "egluUnique.hpp" 31 #include "eglwLibrary.hpp" 32 #include "eglwEnums.hpp" 33 34 #include "gluDefs.hpp" 35 #include "glwEnums.hpp" 36 #include "glwFunctions.hpp" 37 38 #include "tcuResultCollector.hpp" 39 #include "tcuTestLog.hpp" 40 #include "tcuSurface.hpp" 41 #include "tcuTexture.hpp" 42 #include "tcuTextureUtil.hpp" 43 #include "tcuImageCompare.hpp" 44 #include "tcuVector.hpp" 45 #include "tcuVectorUtil.hpp" 46 47 #include "deClock.h" 48 #include "deMath.h" 49 #include "deUniquePtr.hpp" 50 #include "deStringUtil.hpp" 51 #include "deThread.hpp" 52 53 #include <algorithm> 54 #include <string> 55 #include <vector> 56 #include <sstream> 57 58 // Tentative EGL header definitions for EGL_ANDROID_get_Frame_timestamps. 59 // \todo [2017-01-25 brianderson] Remove once defined in the official headers. 60 #define EGL_TIMESTAMPS_ANDROID 0x3430 61 #define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431 62 #define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432 63 #define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433 64 #define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434 65 #define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435 66 #define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436 67 #define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437 68 #define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438 69 #define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439 70 #define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A 71 #define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B 72 #define EGL_READS_DONE_TIME_ANDROID 0x343C 73 typedef deInt64 EGLnsecsANDROID; 74 typedef deUint64 EGLuint64KHR; 75 #define EGL_TIMESTAMP_PENDING_ANDROID (-2) 76 #define EGL_TIMESTAMP_INVALID_ANDROID (-1) 77 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId); 78 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values); 79 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name); 80 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampsANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR frameId, eglw::EGLint numTimestamps, const eglw::EGLint *timestamps, EGLnsecsANDROID *values); 81 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint timestamp); 82 83 #define CHECK_NAKED_EGL_CALL(EGLW, CALL) do { CALL; eglu::checkError((EGLW).getError(), #CALL, __FILE__, __LINE__); } while (deGetFalse()) 84 85 namespace deqp 86 { 87 namespace egl 88 { 89 90 using tcu::TestLog; 91 using std::string; 92 using std::vector; 93 using namespace eglw; 94 95 namespace 96 { 97 98 // Careful: This has microsecond precision, which can cause timestamps to 99 // appear non monotonic when compared to the nanosecond precision timestamps 100 // we get from the eglGetFrameTimestamps extension. 101 // Current test expectations only make sure microsecond precision timestamps 102 // are less than the nanosecond precision timestamps, so this is okay. 103 EGLnsecsANDROID getNanoseconds (void) 104 { 105 return deGetMicroseconds() * 1000; 106 } 107 108 struct FrameTimes 109 { 110 FrameTimes (void) 111 : frameId (-1) 112 , swapBufferBeginNs (-1) 113 , compositeDeadline (-1) 114 , compositeInterval (-1) 115 , compositeToPresentLatency (-1) 116 , requestedPresent (-1) 117 , latch (-1) 118 , firstCompositionStart (-1) 119 , lastCompositionStart (-1) 120 , dequeueReady (-1) 121 , renderingComplete (-1) 122 , firstCompositionGpuFinished (-1) 123 , displayPresent (-1) 124 , readsDone (-1) 125 { 126 } 127 128 EGLuint64KHR frameId; 129 130 // Timestamps sampled by the test. 131 EGLnsecsANDROID swapBufferBeginNs; 132 133 // Compositor info. 134 EGLnsecsANDROID compositeDeadline; 135 EGLnsecsANDROID compositeInterval; 136 EGLnsecsANDROID compositeToPresentLatency; 137 138 // CPU Timeline. 139 EGLnsecsANDROID requestedPresent; 140 EGLnsecsANDROID latch; 141 EGLnsecsANDROID firstCompositionStart; 142 EGLnsecsANDROID lastCompositionStart; 143 EGLnsecsANDROID dequeueReady; 144 145 // GPU Timeline. 146 EGLnsecsANDROID renderingComplete; 147 EGLnsecsANDROID firstCompositionGpuFinished; 148 EGLnsecsANDROID displayPresent; 149 EGLnsecsANDROID readsDone; 150 }; 151 152 153 struct TimestampInfo 154 { 155 TimestampInfo() 156 : required(false) 157 , supported(false) 158 , supportedIndex(0) 159 { 160 } 161 162 TimestampInfo(bool required_, bool supported_, size_t supportedIndex_) 163 : required(required_) 164 , supported(supported_) 165 , supportedIndex(supportedIndex_) 166 { 167 } 168 169 bool required; 170 bool supported; 171 size_t supportedIndex; 172 }; 173 174 typedef std::map<eglw::EGLint, TimestampInfo> TimestampInfoMap; 175 176 EGLnsecsANDROID getTimestamp(eglw::EGLint name, TimestampInfoMap& map, const std::vector<EGLnsecsANDROID>& supportedValues) 177 { 178 TimestampInfo& info = map[name]; 179 return info.supported ? supportedValues[info.supportedIndex] : EGL_TIMESTAMP_INVALID_ANDROID; 180 } 181 182 void populateFrameTimes(FrameTimes* frameTimes, TimestampInfoMap& map, const std::vector<EGLnsecsANDROID>& supportedValues) 183 { 184 frameTimes->requestedPresent = getTimestamp(EGL_REQUESTED_PRESENT_TIME_ANDROID, map, supportedValues); 185 frameTimes->renderingComplete = getTimestamp(EGL_RENDERING_COMPLETE_TIME_ANDROID, map, supportedValues); 186 frameTimes->latch = getTimestamp(EGL_COMPOSITION_LATCH_TIME_ANDROID, map, supportedValues); 187 frameTimes->firstCompositionStart = getTimestamp(EGL_FIRST_COMPOSITION_START_TIME_ANDROID, map, supportedValues); 188 frameTimes->lastCompositionStart = getTimestamp(EGL_LAST_COMPOSITION_START_TIME_ANDROID, map, supportedValues); 189 frameTimes->firstCompositionGpuFinished = getTimestamp(EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID, map, supportedValues); 190 frameTimes->displayPresent = getTimestamp(EGL_DISPLAY_PRESENT_TIME_ANDROID, map, supportedValues); 191 frameTimes->dequeueReady = getTimestamp(EGL_DEQUEUE_READY_TIME_ANDROID, map, supportedValues); 192 frameTimes->readsDone = getTimestamp(EGL_READS_DONE_TIME_ANDROID, map, supportedValues); 193 } 194 195 bool timestampValid (EGLnsecsANDROID timestamp) 196 { 197 // \todo [2017-10-19 brianderson] Don't consider 0 invalid once kernel fix is in. 198 return (timestamp > 0) || (timestamp == EGL_TIMESTAMP_PENDING_ANDROID); 199 } 200 201 bool timestampPending (EGLnsecsANDROID timestamp) 202 { 203 return timestamp == EGL_TIMESTAMP_PENDING_ANDROID; 204 } 205 206 template<typename T> 207 void check_lt(tcu::ResultCollector& result, const T& a, const T& b, const std::string& msg) { 208 if (a < b) 209 return; 210 std::string m = msg + "!(" + de::toString(a) + " < " + de::toString(b) + ")"; 211 result.fail(m); 212 } 213 214 template<typename T> 215 void check_le(tcu::ResultCollector& result, const T& a, const T& b, const std::string& msg) { 216 if (a <= b) 217 return; 218 std::string m = msg + "!(" + de::toString(a) + " <= " + de::toString(b) + ")"; 219 result.fail(m); 220 } 221 222 void verifySingleFrame (const FrameTimes& frameTimes, tcu::ResultCollector& result, bool verifyReadsDone) 223 { 224 // Verify CPU timeline is monotonic. 225 check_lt(result, frameTimes.swapBufferBeginNs, frameTimes.latch, "Buffer latched before it was swapped."); 226 check_lt(result, frameTimes.latch, frameTimes.firstCompositionStart, "Buffer composited before it was latched."); 227 check_le(result, frameTimes.firstCompositionStart, frameTimes.lastCompositionStart, "First composition start after last composition start."); 228 check_lt(result, frameTimes.lastCompositionStart, frameTimes.dequeueReady, "Buffer composited after it was ready to be dequeued."); 229 230 // Verify GPU timeline is monotonic. 231 if (timestampValid(frameTimes.firstCompositionGpuFinished)) 232 check_lt(result, frameTimes.renderingComplete, frameTimes.firstCompositionGpuFinished, "Buffer rendering completed after compositor GPU work finished."); 233 234 if (timestampValid(frameTimes.displayPresent)) 235 check_lt(result, frameTimes.renderingComplete, frameTimes.displayPresent, "Buffer displayed before rendering completed."); 236 237 if (timestampValid(frameTimes.firstCompositionGpuFinished) && timestampValid(frameTimes.displayPresent)) 238 check_lt(result, frameTimes.firstCompositionGpuFinished, frameTimes.displayPresent, "Buffer displayed before compositor GPU work completed"); 239 240 // Drivers may maintain shadow copies of the buffer, so the readsDone time 241 // of the real buffer may be earlier than apparent dependencies. We can only 242 // be sure that the readsDone time must be after the renderingComplete time. 243 // It may also be equal to the renderingComplete time if no reads were 244 // peformed. 245 if (verifyReadsDone && timestampValid(frameTimes.readsDone)) 246 check_le(result, frameTimes.renderingComplete, frameTimes.readsDone, "Buffer rendering completed after reads completed."); 247 248 // Verify CPU/GPU dependencies 249 if (timestampValid(frameTimes.firstCompositionGpuFinished)) 250 check_lt(result, frameTimes.firstCompositionStart, frameTimes.firstCompositionGpuFinished, "Composition CPU work started after GPU work finished."); 251 252 if (timestampValid(frameTimes.displayPresent)) 253 check_lt(result, frameTimes.firstCompositionStart, frameTimes.displayPresent, "Buffer displayed before it was composited."); 254 } 255 256 void verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result) 257 { 258 // CPU timeline. 259 check_lt(result, frame1.swapBufferBeginNs, frame2.swapBufferBeginNs, "Swap begin times not monotonic."); 260 check_lt(result, frame1.latch, frame2.latch, "Latch times not monotonic."); 261 check_lt(result, frame1.lastCompositionStart, frame2.latch, "Old buffer composited after new buffer latched."); 262 check_lt(result, frame1.lastCompositionStart, frame2.firstCompositionStart, "Composition times overlap."); 263 check_lt(result, frame1.dequeueReady, frame2.dequeueReady, "Dequeue ready times not monotonic."); 264 265 // GPU timeline. 266 check_lt(result, frame1.renderingComplete, frame2.renderingComplete, "Rendering complete times not monotonic."); 267 268 if (timestampValid(frame1.firstCompositionGpuFinished) && timestampValid(frame2.firstCompositionGpuFinished)) 269 check_lt(result, frame1.firstCompositionGpuFinished, frame2.firstCompositionGpuFinished, "Composition GPU work complete times not monotonic."); 270 271 if (timestampValid(frame1.displayPresent) && timestampValid(frame2.displayPresent)) 272 check_lt(result, frame1.displayPresent, frame2.displayPresent, "Display present times not monotonic."); 273 } 274 275 EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config) 276 { 277 EGLContext context = EGL_NO_CONTEXT; 278 const EGLint attribList[] = 279 { 280 EGL_CONTEXT_CLIENT_VERSION, 2, 281 EGL_NONE 282 }; 283 284 EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API)); 285 286 context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList); 287 EGLU_CHECK_MSG(egl, "eglCreateContext() failed"); 288 TCU_CHECK(context); 289 290 return context; 291 } 292 293 class GetFrameTimestampTest : public SimpleConfigCase 294 { 295 public: 296 GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters); 297 ~GetFrameTimestampTest (void); 298 299 private: 300 void executeForConfig (EGLDisplay display, EGLConfig config); 301 void initializeExtension (const Library& egl); 302 303 // Not allowed 304 GetFrameTimestampTest (const GetFrameTimestampTest&); 305 GetFrameTimestampTest& operator= (const GetFrameTimestampTest&); 306 307 // TODO: Move these to eglw::Library. 308 eglGetNextFrameIdANDROIDFunc m_eglGetNextFrameIdANDROID; 309 eglGetCompositorTimingANDROIDFunc m_eglGetCompositorTimingANDROID; 310 eglGetCompositorTimingSupportedANDROIDFunc m_eglGetCompositorTimingSupportedANDROID; 311 eglGetFrameTimestampsANDROIDFunc m_eglGetFrameTimestampsANDROID; 312 eglGetFrameTimestampSupportedANDROIDFunc m_eglGetFrameTimestampSupportedANDROID; 313 314 tcu::ResultCollector m_result; 315 }; 316 317 GetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters) 318 : SimpleConfigCase (eglTestCtx, filters.getName(), filters.getDescription(), filters) 319 , m_eglGetNextFrameIdANDROID (DE_NULL) 320 , m_eglGetCompositorTimingANDROID (DE_NULL) 321 , m_eglGetCompositorTimingSupportedANDROID (DE_NULL) 322 , m_eglGetFrameTimestampsANDROID (DE_NULL) 323 , m_eglGetFrameTimestampSupportedANDROID (DE_NULL) 324 , m_result (m_testCtx.getLog()) 325 { 326 } 327 328 GetFrameTimestampTest::~GetFrameTimestampTest (void) 329 { 330 } 331 332 void GetFrameTimestampTest::initializeExtension (const Library& egl) 333 { 334 m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID")); 335 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed."); 336 m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID")); 337 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed."); 338 m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID")); 339 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed."); 340 m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID")); 341 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed."); 342 m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID")); 343 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed."); 344 } 345 346 347 string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config) 348 { 349 std::ostringstream stream; 350 EGLint id; 351 352 EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id)); 353 354 stream << id; 355 356 return stream.str(); 357 } 358 359 deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log) 360 { 361 const char* const vertexShaderSource = 362 "attribute highp vec2 a_pos;\n" 363 "void main (void)\n" 364 "{\n" 365 "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n" 366 "}"; 367 368 const char* const fragmentShaderSource = 369 "void main (void)\n" 370 "{\n" 371 "\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n" 372 "}"; 373 374 deUint32 program = 0; 375 deUint32 vertexShader = 0; 376 deUint32 fragmentShader = 0; 377 378 deInt32 vertexCompileStatus; 379 string vertexInfoLog; 380 deInt32 fragmentCompileStatus; 381 string fragmentInfoLog; 382 deInt32 linkStatus; 383 string programInfoLog; 384 385 try 386 { 387 program = gl.createProgram(); 388 vertexShader = gl.createShader(GL_VERTEX_SHADER); 389 fragmentShader = gl.createShader(GL_FRAGMENT_SHADER); 390 391 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program"); 392 393 gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL); 394 gl.compileShader(vertexShader); 395 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader"); 396 397 gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL); 398 gl.compileShader(fragmentShader); 399 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader"); 400 401 { 402 deInt32 infoLogLength = 0; 403 404 gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus); 405 gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength); 406 407 vertexInfoLog.resize(infoLogLength, '\0'); 408 409 gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0])); 410 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info"); 411 412 vertexInfoLog.resize(infoLogLength); 413 } 414 415 { 416 deInt32 infoLogLength = 0; 417 418 gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus); 419 gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength); 420 421 fragmentInfoLog.resize(infoLogLength, '\0'); 422 423 gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0])); 424 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info"); 425 426 fragmentInfoLog.resize(infoLogLength); 427 } 428 429 gl.attachShader(program, vertexShader); 430 gl.attachShader(program, fragmentShader); 431 gl.linkProgram(program); 432 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program"); 433 434 { 435 deInt32 infoLogLength = 0; 436 437 gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus); 438 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); 439 440 programInfoLog.resize(infoLogLength, '\0'); 441 442 gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0])); 443 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info"); 444 445 programInfoLog.resize(infoLogLength); 446 } 447 448 if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0) 449 { 450 451 log.startShaderProgram(linkStatus != 0, programInfoLog.c_str()); 452 453 log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog); 454 log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog); 455 456 log.endShaderProgram(); 457 } 458 459 gl.deleteShader(vertexShader); 460 gl.deleteShader(fragmentShader); 461 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders"); 462 463 TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0); 464 } 465 catch (...) 466 { 467 if (program) 468 gl.deleteProgram(program); 469 470 if (vertexShader) 471 gl.deleteShader(vertexShader); 472 473 if (fragmentShader) 474 gl.deleteShader(fragmentShader); 475 476 throw; 477 } 478 479 return program; 480 } 481 482 void GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config) 483 { 484 const Library& egl = m_eglTestCtx.getLibrary(); 485 486 if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps")) 487 TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported"); 488 489 initializeExtension(egl); 490 491 const string configIdStr (getConfigIdString(egl, display, config)); 492 tcu::ScopedLogSection logSection (m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str()); 493 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine()); 494 495 { 496 TestLog& log = m_testCtx.getLog(); 497 498 log << TestLog::Message << "EGL_RED_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE) << TestLog::EndMessage; 499 log << TestLog::Message << "EGL_GREEN_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE) << TestLog::EndMessage; 500 log << TestLog::Message << "EGL_BLUE_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE) << TestLog::EndMessage; 501 log << TestLog::Message << "EGL_ALPHA_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE) << TestLog::EndMessage; 502 log << TestLog::Message << "EGL_DEPTH_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE) << TestLog::EndMessage; 503 log << TestLog::Message << "EGL_STENCIL_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE) << TestLog::EndMessage; 504 log << TestLog::Message << "EGL_SAMPLES: " << eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES) << TestLog::EndMessage; 505 } 506 507 de::UniquePtr<eglu::NativeWindow> window (factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE))); 508 509 eglu::UniqueSurface surface (egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL)); 510 eglu::UniqueContext context (egl, display, createGLES2Context(egl, display, config)); 511 glw::Functions gl; 512 deUint32 program = 0; 513 514 EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE)); 515 516 m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0)); 517 518 EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context)); 519 520 try 521 { 522 // EGL_DISPLAY_PRESENT_TIME_ANDROID support is currently optional 523 // but should be required once HWC1 is no longer supported. 524 // All HWC2 devices should support EGL_DISPLAY_PRESENT_TIME_ANDROID. 525 TimestampInfoMap timestamps; 526 timestamps[EGL_REQUESTED_PRESENT_TIME_ANDROID] = TimestampInfo(true, false, 0); 527 timestamps[EGL_RENDERING_COMPLETE_TIME_ANDROID] = TimestampInfo(true, false, 0); 528 timestamps[EGL_COMPOSITION_LATCH_TIME_ANDROID] = TimestampInfo(true, false, 0); 529 timestamps[EGL_FIRST_COMPOSITION_START_TIME_ANDROID] = TimestampInfo(true, false, 0); 530 timestamps[EGL_LAST_COMPOSITION_START_TIME_ANDROID] = TimestampInfo(true, false, 0); 531 timestamps[EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID] = TimestampInfo(true, false, 0); 532 timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID] = TimestampInfo(false, false, 0); 533 timestamps[EGL_DEQUEUE_READY_TIME_ANDROID] = TimestampInfo(true, false, 0); 534 timestamps[EGL_READS_DONE_TIME_ANDROID] = TimestampInfo(true, false, 0); 535 536 const eglw::EGLint invalidTimestampName = EGL_READS_DONE_TIME_ANDROID + 1; 537 538 // Verify required timestamps are supported and populate supportedNames. 539 std::vector<eglw::EGLint> supportedNames; 540 for (TimestampInfoMap::iterator i = timestamps.begin(); i != timestamps.end(); i++) 541 { 542 TimestampInfo& info = i->second; 543 info.supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, i->first) != EGL_FALSE; 544 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed."); 545 546 if (info.supported) 547 { 548 info.supportedIndex = supportedNames.size(); 549 supportedNames.push_back(i->first); 550 } 551 else 552 TCU_CHECK_MSG(!info.required, "Required timestamp not supported."); 553 } 554 555 // Verify unsupported timestamps are reported properly. 556 const bool invalidSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, invalidTimestampName) != EGL_FALSE; 557 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed."); 558 TCU_CHECK_MSG(!invalidSupported, "Non existant timestamp reports that it is supported."); 559 560 // Verify compositor timings are supported. 561 const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID) != EGL_FALSE; 562 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed."); 563 TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported."); 564 const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID) != EGL_FALSE; 565 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed."); 566 TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported."); 567 const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID) != EGL_FALSE; 568 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed."); 569 TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported."); 570 571 const float positions1[] = 572 { 573 0.00f, 0.00f, 574 0.75f, 0.00f, 575 0.75f, 0.75f, 576 577 0.75f, 0.75f, 578 0.00f, 0.75f, 579 0.00f, 0.00f 580 }; 581 582 const float positions2[] = 583 { 584 -0.75f, -0.75f, 585 0.00f, -0.75f, 586 0.00f, 0.00f, 587 588 0.00f, 0.00f, 589 -0.75f, 0.00f, 590 -0.75f, -0.75f 591 }; 592 593 deUint32 posLocation; 594 595 program = createGLES2Program(gl, m_testCtx.getLog()); 596 597 gl.useProgram(program); 598 posLocation = gl.getAttribLocation(program, "a_pos"); 599 gl.enableVertexAttribArray(posLocation); 600 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering"); 601 602 const size_t frameCount = 120; 603 std::vector<FrameTimes> frameTimes(frameCount); 604 for (size_t i = 0; i < frameCount; i++) 605 { 606 FrameTimes& frame = frameTimes[i]; 607 608 const eglw::EGLint compositorTimingNames[] = 609 { 610 EGL_COMPOSITE_DEADLINE_ANDROID, 611 EGL_COMPOSITE_INTERVAL_ANDROID, 612 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID, 613 }; 614 const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames); 615 EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 }; 616 617 // Get the current time before making any API calls in case "now" 618 // just happens to get sampled near one of the composite deadlines. 619 EGLnsecsANDROID now = getNanoseconds(); 620 621 // Get the frame id. 622 EGLuint64KHR nextFrameId = 0; 623 CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId)); 624 frame.frameId = nextFrameId; 625 626 // Get the compositor timing. 627 CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID( 628 display, *surface, compositorTimingCount, 629 compositorTimingNames, compositorTimingValues)); 630 frame.compositeDeadline = compositorTimingValues[0]; 631 frame.compositeInterval = compositorTimingValues[1]; 632 frame.compositeToPresentLatency = compositorTimingValues[2]; 633 634 // Verify compositor timing is sane. 635 check_lt<EGLnsecsANDROID>(m_result, 1000000, frame.compositeInterval, "Reported refresh rate greater than 1kHz."); 636 check_lt<EGLnsecsANDROID>(m_result, frame.compositeInterval, 1000000000, "Reported refresh rate less than 1Hz."); 637 check_lt<EGLnsecsANDROID>(m_result, 0, frame.compositeToPresentLatency, "Composite to present latency must be greater than 0."); 638 check_lt(m_result, frame.compositeToPresentLatency, frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs."); 639 const EGLnsecsANDROID minDeadline = now; 640 check_lt(m_result, minDeadline, frame.compositeDeadline, "Next composite deadline is in the past."); 641 const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2; 642 check_lt(m_result, frame.compositeDeadline, maxDeadline, "Next composite deadline over two intervals away."); 643 644 const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f; 645 gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f); 646 gl.clear(GL_COLOR_BUFFER_BIT); 647 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface"); 648 649 const bool posSelect = ((i % 2) == 0); 650 gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2); 651 gl.drawArrays(GL_TRIANGLES, 0, 6); 652 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render"); 653 654 frame.swapBufferBeginNs = getNanoseconds(); 655 EGLU_CHECK_CALL(egl, swapBuffers(display, *surface)); 656 657 // All timestamps from 5 frames ago should definitely be available. 658 const size_t frameDelay = 5; 659 if (i >= frameDelay) 660 { 661 // \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed. 662 const bool verifyReadsDone = i > (frameDelay + 3); 663 FrameTimes& frame5ago = frameTimes[i-frameDelay]; 664 std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0); 665 666 CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID( 667 display, *surface, frame5ago.frameId, static_cast<eglw::EGLint>(supportedNames.size()), 668 &supportedNames[0], &supportedValues[0])); 669 populateFrameTimes(&frame5ago, timestamps, supportedValues); 670 671 verifySingleFrame(frame5ago, m_result, verifyReadsDone); 672 if (i >= frameDelay + 1) 673 { 674 FrameTimes& frame6ago = frameTimes[i-frameDelay-1]; 675 verifyNeighboringFrames(frame6ago, frame5ago, m_result); 676 } 677 } 678 } 679 680 // All timestamps for the most recently swapped frame should 681 // become available by only polling eglGetFrametimestamps. 682 // No additional swaps should be necessary. 683 FrameTimes& lastFrame = frameTimes.back(); 684 const EGLnsecsANDROID pollingDeadline = lastFrame.swapBufferBeginNs + 1000000000; 685 bool finalTimestampAvailable = false; 686 687 do 688 { 689 std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0); 690 CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID( 691 display, *surface, lastFrame.frameId, static_cast<eglw::EGLint>(supportedNames.size()), 692 &supportedNames[0], &supportedValues[0])); 693 populateFrameTimes(&lastFrame, timestamps, supportedValues); 694 695 // Poll for present if it's supported. 696 // Otherwise, poll for firstCompositionStart. 697 if (timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID].supported) 698 finalTimestampAvailable = !timestampPending(lastFrame.displayPresent); 699 else 700 finalTimestampAvailable = !timestampPending(lastFrame.firstCompositionStart); 701 } while (!finalTimestampAvailable && (getNanoseconds() < pollingDeadline)); 702 703 m_result.check(finalTimestampAvailable, "Timed out polling for timestamps of last swap."); 704 m_result.check((lastFrame.requestedPresent >= 0), "Requested present of last swap not avaiable."); 705 m_result.check((lastFrame.renderingComplete >= 0), "Rendering complete of last swap not avaiable."); 706 m_result.check((lastFrame.latch >= 0), "Latch of last swap not avaiable."); 707 m_result.check((lastFrame.firstCompositionStart >= 0), "First composite time of last swap not avaiable."); 708 m_result.check((lastFrame.lastCompositionStart >= 0), "Last composite time of last swap not avaiable."); 709 710 window->processEvents(); 711 gl.disableVertexAttribArray(posLocation); 712 gl.useProgram(0); 713 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state"); 714 715 gl.deleteProgram(program); 716 program = 0; 717 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()"); 718 719 m_result.setTestContextResult(m_testCtx); 720 } 721 catch (...) 722 { 723 if (program != 0) 724 gl.deleteProgram(program); 725 726 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); 727 throw; 728 } 729 730 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); 731 } 732 733 class GetFrameTimestampsTests : public TestCaseGroup 734 { 735 public: 736 GetFrameTimestampsTests (EglTestContext& eglTestCtx); 737 void init (void); 738 739 private: 740 GetFrameTimestampsTests (const GetFrameTimestampsTests&); 741 GetFrameTimestampsTests& operator= (const GetFrameTimestampsTests&); 742 }; 743 744 745 GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx) 746 : TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests") 747 { 748 } 749 750 bool isWindow (const eglu::CandidateConfig& c) 751 { 752 return (c.surfaceType() & EGL_WINDOW_BIT) != 0; 753 } 754 755 void GetFrameTimestampsTests::init (void) 756 { 757 eglu::FilterList baseFilters; 758 baseFilters << isWindow; 759 760 vector<NamedFilterList> filterLists; 761 getDefaultFilterLists(filterLists, baseFilters); 762 763 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++) 764 addChild(new GetFrameTimestampTest(m_eglTestCtx, *i)); 765 } 766 767 } // anonymous 768 769 TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx) 770 { 771 return new GetFrameTimestampsTests(eglTestCtx); 772 } 773 774 } // egl 775 } // deqp 776