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