1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program EGL Module
3 * ---------------------------------------
5 * Copyright 2017 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Test the EGL_ANDROID_get_frame_timestamps extension.
22 *//*--------------------------------------------------------------------*/
24 #include "teglGetFrameTimestampsTests.hpp"
26 #include "teglSimpleConfigCase.hpp"
28 #include "egluNativeWindow.hpp"
29 #include "egluUtil.hpp"
30 #include "egluUnique.hpp"
31 #include "eglwLibrary.hpp"
32 #include "eglwEnums.hpp"
34 #include "gluDefs.hpp"
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
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"
49 #include "deUniquePtr.hpp"
50 #include "deThread.hpp"
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 0x314D
60 #define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
61 #define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
62 #define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
63 #define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
64 #define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
65 #define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
66 #define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
67 #define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
68 #define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
69 #define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
70 #define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158
71 #define EGL_DEQUEUE_READY_TIME_ANDROID 0x3159
72 #define EGL_READS_DONE_TIME_ANDROID 0x315A
73 typedef deInt64 EGLnsecsANDROID;
74 typedef deUint64 EGLuint64KHR;
75 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId);
76 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values);
77 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name);
78 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);
79 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint timestamp);
81 #define CHECK_NAKED_EGL_CALL(EGLW, CALL) do { CALL; eglu::checkError((EGLW).getError(), #CALL, __FILE__, __LINE__); } while (deGetFalse())
96 // Careful: This has microsecond precision, which can cause timestamps to
97 // appear non monotonic when compared to the nanosecond precision timestamps
98 // we get from the eglGetFrameTimestamps extension.
99 // Current test expectations only make sure microsecond precision timestamps
100 // are less than the nanosecond precision timestamps, so this is okay.
101 EGLnsecsANDROID getNanoseconds (void)
103 return deGetMicroseconds() * 1000;
110 , swapBufferBeginNs (-1)
111 , compositeDeadline (-1)
112 , compositeInterval (-1)
113 , compositeToPresentLatency (-1)
114 , requestedPresent (-1)
116 , firstCompositionStart (-1)
117 , lastCompositionStart (-1)
119 , renderingComplete (-1)
120 , firstCompositionGpuFinished (-1)
121 , displayPresent (-1)
127 EGLuint64KHR frameId;
129 // Timestamps sampled by the test.
130 EGLnsecsANDROID swapBufferBeginNs;
133 EGLnsecsANDROID compositeDeadline;
134 EGLnsecsANDROID compositeInterval;
135 EGLnsecsANDROID compositeToPresentLatency;
138 EGLnsecsANDROID requestedPresent;
139 EGLnsecsANDROID latch;
140 EGLnsecsANDROID firstCompositionStart;
141 EGLnsecsANDROID lastCompositionStart;
142 EGLnsecsANDROID dequeueReady;
145 EGLnsecsANDROID renderingComplete;
146 EGLnsecsANDROID firstCompositionGpuFinished;
147 EGLnsecsANDROID displayPresent;
148 EGLnsecsANDROID displayRetire;
149 EGLnsecsANDROID readsDone;
152 bool timestampExists (EGLnsecsANDROID timestamp)
154 return timestamp > 0;
157 void verifySingleFrame (const FrameTimes& frameTimes, tcu::ResultCollector& result, bool verifyReadsDone)
159 // Verify CPU timeline is monotonic.
160 result.check(frameTimes.swapBufferBeginNs < frameTimes.latch, "Buffer latched before it was swapped.");
161 result.check(frameTimes.latch < frameTimes.firstCompositionStart, "Buffer composited before it was latched.");
162 result.check(frameTimes.firstCompositionStart <= frameTimes.lastCompositionStart, "First composition start after last composition start.");
163 result.check(frameTimes.lastCompositionStart < frameTimes.dequeueReady, "Buffer composited after it was ready to be dequeued.");
165 // Verify GPU timeline is monotonic.
166 if (timestampExists(frameTimes.firstCompositionGpuFinished))
167 result.check(frameTimes.renderingComplete < frameTimes.firstCompositionGpuFinished, "Buffer rendering completed after compositor GPU work finished.");
169 if (timestampExists(frameTimes.displayPresent))
170 result.check(frameTimes.renderingComplete < frameTimes.displayPresent, "Buffer displayed before rendering completed.");
172 if (timestampExists(frameTimes.firstCompositionGpuFinished) && timestampExists(frameTimes.displayPresent))
173 result.check(frameTimes.firstCompositionGpuFinished < frameTimes.displayPresent, "Buffer displayed before compositor GPU work completed");
175 if (timestampExists(frameTimes.displayRetire))
176 result.check(frameTimes.renderingComplete < frameTimes.displayRetire, "Buffer retired before rendering completed.");
178 if (timestampExists(frameTimes.firstCompositionGpuFinished) && timestampExists(frameTimes.displayRetire))
179 result.check(frameTimes.firstCompositionGpuFinished < frameTimes.displayRetire, "Buffer retired before compositor GPU work completed.");
181 // Drivers may maintain shadow copies of the buffer, so the readsDone time
182 // of the real buffer may be earlier than apparent dependencies. We can only
183 // be sure that the readsDone time must be after the renderingComplete time.
185 result.check(frameTimes.renderingComplete < frameTimes.readsDone, "Buffer rendering completed after reads completed.");
187 // Verify CPU/GPU dependencies
188 result.check(frameTimes.renderingComplete < frameTimes.latch, "Buffer latched before rendering completed.");
189 if (timestampExists(frameTimes.firstCompositionGpuFinished))
190 result.check(frameTimes.firstCompositionStart < frameTimes.firstCompositionGpuFinished, "Composition CPU work started after GPU work finished.");
192 if (timestampExists(frameTimes.displayPresent))
193 result.check(frameTimes.firstCompositionStart < frameTimes.displayPresent, "Buffer displayed before it was composited.");
195 if (timestampExists(frameTimes.displayRetire))
196 result.check(frameTimes.lastCompositionStart < frameTimes.displayRetire, "Buffer retired before final composition.");
198 // One of Present or retire must exist.
199 result.check(timestampExists(frameTimes.displayPresent) != timestampExists(frameTimes.displayRetire), "Either present or retire must exist.");
202 void verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result, bool verifyReadsDone)
205 result.check(frame1.swapBufferBeginNs < frame2.swapBufferBeginNs, "Swap begin times not monotonic.");
206 result.check(frame1.latch < frame2.latch, "Latch times not monotonic.");
207 result.check(frame1.lastCompositionStart < frame2.latch, "Old buffer composited after new buffer latched.");
208 result.check(frame1.lastCompositionStart < frame2.firstCompositionStart, "Composition times overlap.");
209 result.check(frame1.dequeueReady < frame2.dequeueReady, "Dequeue ready times not monotonic.");
212 result.check(frame1.renderingComplete < frame2.renderingComplete, "Rendering complete times not monotonic.");
214 if (timestampExists(frame1.firstCompositionGpuFinished) && timestampExists(frame2.firstCompositionGpuFinished))
215 result.check(frame1.firstCompositionGpuFinished < frame2.firstCompositionGpuFinished, "Composition GPU work complete times not monotonic.");
217 if (timestampExists(frame1.displayPresent) && timestampExists(frame2.displayPresent))
218 result.check(frame1.displayPresent < frame2.displayPresent, "Display present times not monotonic.");
220 if (timestampExists(frame1.displayRetire) && timestampExists(frame2.displayRetire))
221 result.check(frame1.displayRetire < frame2.displayRetire, "Display retire times not monotonic.");
223 if (verifyReadsDone && timestampExists(frame1.readsDone) && timestampExists(frame2.readsDone))
224 result.check(frame1.readsDone < frame2.readsDone, "Reads done times not monotonic.");
227 EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
229 EGLContext context = EGL_NO_CONTEXT;
230 const EGLint attribList[] =
232 EGL_CONTEXT_CLIENT_VERSION, 2,
236 EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
238 context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
239 EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
245 class GetFrameTimestampTest : public SimpleConfigCase
248 GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters);
249 ~GetFrameTimestampTest (void);
252 void executeForConfig (EGLDisplay display, EGLConfig config);
253 void initializeExtension (const Library& egl);
256 GetFrameTimestampTest (const GetFrameTimestampTest&);
257 GetFrameTimestampTest& operator= (const GetFrameTimestampTest&);
259 // TODO: Move these to eglw::Library.
260 eglGetNextFrameIdANDROIDFunc m_eglGetNextFrameIdANDROID;
261 eglGetCompositorTimingANDROIDFunc m_eglGetCompositorTimingANDROID;
262 eglGetCompositorTimingSupportedANDROIDFunc m_eglGetCompositorTimingSupportedANDROID;
263 eglGetFrameTimestampsANDROIDFunc m_eglGetFrameTimestampsANDROID;
264 eglGetFrameTimestampSupportedANDROIDFunc m_eglGetFrameTimestampSupportedANDROID;
266 tcu::ResultCollector m_result;
269 GetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
270 : SimpleConfigCase (eglTestCtx, filters.getName(), filters.getDescription(), filters)
271 , m_eglGetNextFrameIdANDROID (DE_NULL)
272 , m_eglGetCompositorTimingANDROID (DE_NULL)
273 , m_eglGetCompositorTimingSupportedANDROID (DE_NULL)
274 , m_eglGetFrameTimestampsANDROID (DE_NULL)
275 , m_eglGetFrameTimestampSupportedANDROID (DE_NULL)
276 , m_result (m_testCtx.getLog())
280 GetFrameTimestampTest::~GetFrameTimestampTest (void)
284 void GetFrameTimestampTest::initializeExtension (const Library& egl)
286 m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID"));
287 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed.");
288 m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID"));
289 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed.");
290 m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID"));
291 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed.");
292 m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID"));
293 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed.");
294 m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID"));
295 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed.");
299 string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
301 std::ostringstream stream;
304 EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));
311 deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
313 const char* const vertexShaderSource =
314 "attribute highp vec2 a_pos;\n"
317 "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
320 const char* const fragmentShaderSource =
323 "\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
326 deUint32 program = 0;
327 deUint32 vertexShader = 0;
328 deUint32 fragmentShader = 0;
330 deInt32 vertexCompileStatus;
331 string vertexInfoLog;
332 deInt32 fragmentCompileStatus;
333 string fragmentInfoLog;
335 string programInfoLog;
339 program = gl.createProgram();
340 vertexShader = gl.createShader(GL_VERTEX_SHADER);
341 fragmentShader = gl.createShader(GL_FRAGMENT_SHADER);
343 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
345 gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
346 gl.compileShader(vertexShader);
347 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
349 gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
350 gl.compileShader(fragmentShader);
351 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
354 deInt32 infoLogLength = 0;
356 gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
357 gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
359 vertexInfoLog.resize(infoLogLength, '\0');
361 gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
362 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
364 vertexInfoLog.resize(infoLogLength);
368 deInt32 infoLogLength = 0;
370 gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
371 gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
373 fragmentInfoLog.resize(infoLogLength, '\0');
375 gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
376 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
378 fragmentInfoLog.resize(infoLogLength);
381 gl.attachShader(program, vertexShader);
382 gl.attachShader(program, fragmentShader);
383 gl.linkProgram(program);
384 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
387 deInt32 infoLogLength = 0;
389 gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
390 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
392 programInfoLog.resize(infoLogLength, '\0');
394 gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
395 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
397 programInfoLog.resize(infoLogLength);
400 if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
403 log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
405 log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
406 log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
408 log.endShaderProgram();
411 gl.deleteShader(vertexShader);
412 gl.deleteShader(fragmentShader);
413 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
415 TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
420 gl.deleteProgram(program);
423 gl.deleteShader(vertexShader);
426 gl.deleteShader(fragmentShader);
434 void GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config)
436 const Library& egl = m_eglTestCtx.getLibrary();
438 if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps"))
439 TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported");
441 initializeExtension(egl);
443 const string configIdStr (getConfigIdString(egl, display, config));
444 tcu::ScopedLogSection logSection (m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
445 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
448 TestLog& log = m_testCtx.getLog();
450 log << TestLog::Message << "EGL_RED_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE) << TestLog::EndMessage;
451 log << TestLog::Message << "EGL_GREEN_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE) << TestLog::EndMessage;
452 log << TestLog::Message << "EGL_BLUE_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE) << TestLog::EndMessage;
453 log << TestLog::Message << "EGL_ALPHA_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE) << TestLog::EndMessage;
454 log << TestLog::Message << "EGL_DEPTH_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE) << TestLog::EndMessage;
455 log << TestLog::Message << "EGL_STENCIL_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE) << TestLog::EndMessage;
456 log << TestLog::Message << "EGL_SAMPLES: " << eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES) << TestLog::EndMessage;
459 de::UniquePtr<eglu::NativeWindow> window (factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));
461 eglu::UniqueSurface surface (egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
462 eglu::UniqueContext context (egl, display, createGLES2Context(egl, display, config));
464 deUint32 program = 0;
466 EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE));
468 m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
470 EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));
474 // Verify required timestamps are supported.
475 const eglw::EGLint requiredTimestamps[] =
477 EGL_REQUESTED_PRESENT_TIME_ANDROID,
478 EGL_RENDERING_COMPLETE_TIME_ANDROID,
479 EGL_COMPOSITION_LATCH_TIME_ANDROID,
480 EGL_FIRST_COMPOSITION_START_TIME_ANDROID,
481 EGL_LAST_COMPOSITION_START_TIME_ANDROID,
482 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID,
483 EGL_DEQUEUE_READY_TIME_ANDROID,
484 EGL_READS_DONE_TIME_ANDROID,
486 const size_t requiredTimestampsCount = DE_LENGTH_OF_ARRAY(requiredTimestamps);
488 for (size_t i = 0; i < requiredTimestampsCount; i++)
490 const bool supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, requiredTimestamps[i]) != EGL_FALSE;
491 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
492 TCU_CHECK_MSG(supported, "Required timestamp not supported.");
495 // Verify either retire or present is supported.
496 const bool retireSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, EGL_DISPLAY_RETIRE_TIME_ANDROID) != EGL_FALSE;
497 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
498 const bool presentSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, EGL_DISPLAY_PRESENT_TIME_ANDROID) != EGL_FALSE;
499 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
500 TCU_CHECK_MSG(retireSupported != presentSupported, "DISPLAY_RETIRE or DISPLAY_PRESENT must be supported, but not both.");
502 // Verify compositor timings are supported.
503 const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID) != EGL_FALSE;
504 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
505 TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported.");
506 const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID) != EGL_FALSE;
507 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
508 TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported.");
509 const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID) != EGL_FALSE;
510 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
511 TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported.");
514 const eglw::EGLint frameTimestampNames[] =
516 EGL_REQUESTED_PRESENT_TIME_ANDROID,
517 EGL_RENDERING_COMPLETE_TIME_ANDROID,
518 EGL_COMPOSITION_LATCH_TIME_ANDROID,
519 EGL_FIRST_COMPOSITION_START_TIME_ANDROID,
520 EGL_LAST_COMPOSITION_START_TIME_ANDROID,
521 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID,
522 presentSupported ? EGL_DISPLAY_PRESENT_TIME_ANDROID : EGL_DISPLAY_RETIRE_TIME_ANDROID,
523 EGL_DEQUEUE_READY_TIME_ANDROID,
524 EGL_READS_DONE_TIME_ANDROID,
526 const size_t frameTimestampCount = DE_LENGTH_OF_ARRAY(frameTimestampNames);
528 const float positions1[] =
539 const float positions2[] =
550 deUint32 posLocation;
552 program = createGLES2Program(gl, m_testCtx.getLog());
554 gl.useProgram(program);
555 posLocation = gl.getAttribLocation(program, "a_pos");
556 gl.enableVertexAttribArray(posLocation);
557 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
559 const size_t frameCount = 120;
560 std::vector<FrameTimes> frameTimes(frameCount);
561 for (size_t i = 0; i < frameCount; i++)
563 FrameTimes& frame = frameTimes[i];
565 const eglw::EGLint compositorTimingNames[] =
567 EGL_COMPOSITE_DEADLINE_ANDROID,
568 EGL_COMPOSITE_INTERVAL_ANDROID,
569 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID,
571 const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames);
572 EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 };
574 // Get the current time before making any API calls in case "now"
575 // just happens to get sampled near one of the composite deadlines.
576 EGLnsecsANDROID now = getNanoseconds();
579 EGLuint64KHR nextFrameId = 0;
580 CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId));
581 frame.frameId = nextFrameId;
583 // Get the compositor timing.
584 CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID(
585 display, *surface, compositorTimingCount,
586 compositorTimingNames, compositorTimingValues));
587 frame.compositeDeadline = compositorTimingValues[0];
588 frame.compositeInterval = compositorTimingValues[1];
589 frame.compositeToPresentLatency = compositorTimingValues[2];
591 // Verify compositor timing is sane.
592 m_result.check(1000000 < frame.compositeInterval, "Reported refresh rate greater than 1kHz.");
593 m_result.check(frame.compositeInterval < 1000000000, "Reported refresh rate less than 1Hz.");
594 m_result.check(0 < frame.compositeToPresentLatency, "Composite to present latency must be greater than 0.");
595 m_result.check(frame.compositeToPresentLatency < frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs.");
596 const EGLnsecsANDROID minDeadline = now;
597 m_result.check(minDeadline < frame.compositeDeadline, "Next composite deadline is in the past.");
598 const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2;
599 m_result.check(frame.compositeDeadline < maxDeadline, "Next composite deadline over two intervals away.");
601 const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f;
602 gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f);
603 gl.clear(GL_COLOR_BUFFER_BIT);
604 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
606 const bool posSelect = ((i % 2) == 0);
607 gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2);
608 gl.drawArrays(GL_TRIANGLES, 0, 6);
609 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
611 frame.swapBufferBeginNs = getNanoseconds();
612 EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
614 // All timestamps from 5 frames ago should definitely be available.
615 const size_t frameDelay = 5;
618 FrameTimes& frame5ago = frameTimes[i-frameDelay];
619 EGLnsecsANDROID frameTimestampValues[frameTimestampCount] = { 0 };
620 // \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed.
621 const bool verifyReadsDone = i > (frameDelay + 3);
623 CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
624 display, *surface, frame5ago.frameId, frameTimestampCount,
625 frameTimestampNames, frameTimestampValues));
627 frame5ago.requestedPresent = frameTimestampValues[0];
628 frame5ago.renderingComplete = frameTimestampValues[1];
629 frame5ago.latch = frameTimestampValues[2];
630 frame5ago.firstCompositionStart = frameTimestampValues[3];
631 frame5ago.lastCompositionStart = frameTimestampValues[4];
632 frame5ago.firstCompositionGpuFinished = frameTimestampValues[5];
633 frame5ago.dequeueReady = frameTimestampValues[7];
634 frame5ago.readsDone = frameTimestampValues[8];
635 if (presentSupported)
636 frame5ago.displayPresent = frameTimestampValues[6];
638 frame5ago.displayRetire = frameTimestampValues[6];
640 verifySingleFrame(frame5ago, m_result, verifyReadsDone);
641 if (i >= frameDelay + 1)
643 FrameTimes& frame6ago = frameTimes[i-frameDelay-1];
644 verifyNeighboringFrames(frame6ago, frame5ago, m_result, verifyReadsDone);
649 // All timestamps for the most recently swapped frame should
650 // become available by only polling eglGetFrametimestamps.
651 // No additional swaps should be necessary.
652 FrameTimes& lastFrame = frameTimes.back();
653 const EGLnsecsANDROID pollingDeadline = lastFrame.swapBufferBeginNs + 1000000000;
654 bool finalTimestampAvaiable = false;
658 EGLnsecsANDROID frameTimestampValues[frameTimestampCount] = { 0 };
659 CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
660 display, *surface, lastFrame.frameId, frameTimestampCount,
661 frameTimestampNames, frameTimestampValues));
663 lastFrame.requestedPresent = frameTimestampValues[0];
664 lastFrame.renderingComplete = frameTimestampValues[1];
665 lastFrame.latch = frameTimestampValues[2];
666 lastFrame.firstCompositionStart = frameTimestampValues[3];
667 lastFrame.lastCompositionStart = frameTimestampValues[4];
668 lastFrame.firstCompositionGpuFinished = frameTimestampValues[5];
669 lastFrame.dequeueReady = frameTimestampValues[7];
670 lastFrame.readsDone = frameTimestampValues[8];
671 if (presentSupported)
673 lastFrame.displayPresent = frameTimestampValues[6];
674 if (timestampExists(lastFrame.displayPresent))
675 finalTimestampAvaiable = true;
679 lastFrame.displayRetire = frameTimestampValues[6];
680 if (timestampExists(lastFrame.firstCompositionStart))
681 finalTimestampAvaiable = true;
684 if (getNanoseconds() > pollingDeadline)
686 } while (!finalTimestampAvaiable);
688 m_result.check(finalTimestampAvaiable, "Timed out polling for timestamps of last swap.");
689 m_result.check(timestampExists(lastFrame.requestedPresent), "Rendering complete of last swap not avaiable.");
690 m_result.check(timestampExists(lastFrame.renderingComplete), "Rendering complete of last swap not avaiable.");
691 m_result.check(timestampExists(lastFrame.latch), "Latch of last swap not avaiable.");
692 m_result.check(timestampExists(lastFrame.firstCompositionStart), "First composite time of last swap not avaiable.");
693 m_result.check(timestampExists(lastFrame.lastCompositionStart), "Last composite time of last swap not avaiable.");
695 window->processEvents();
696 gl.disableVertexAttribArray(posLocation);
698 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");
700 gl.deleteProgram(program);
702 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
704 m_result.setTestContextResult(m_testCtx);
709 gl.deleteProgram(program);
711 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
715 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
718 class GetFrameTimestampsTests : public TestCaseGroup
721 GetFrameTimestampsTests (EglTestContext& eglTestCtx);
725 GetFrameTimestampsTests (const GetFrameTimestampsTests&);
726 GetFrameTimestampsTests& operator= (const GetFrameTimestampsTests&);
730 GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
731 : TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
735 bool isWindow (const eglu::CandidateConfig& c)
737 return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
740 void GetFrameTimestampsTests::init (void)
742 eglu::FilterList baseFilters;
743 baseFilters << isWindow;
745 vector<NamedFilterList> filterLists;
746 getDefaultFilterLists(filterLists, baseFilters);
748 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
749 addChild(new GetFrameTimestampTest(m_eglTestCtx, *i));
754 TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
756 return new GetFrameTimestampsTests(eglTestCtx);