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_DEQUEUE_READY_TIME_ANDROID 0x3158
71 #define EGL_READS_DONE_TIME_ANDROID 0x3159
72 typedef deInt64 EGLnsecsANDROID;
73 typedef deUint64 EGLuint64KHR;
74 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId);
75 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values);
76 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name);
77 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);
78 typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint timestamp);
80 #define CHECK_NAKED_EGL_CALL(EGLW, CALL) do { CALL; eglu::checkError((EGLW).getError(), #CALL, __FILE__, __LINE__); } while (deGetFalse())
95 // Careful: This has microsecond precision, which can cause timestamps to
96 // appear non monotonic when compared to the nanosecond precision timestamps
97 // we get from the eglGetFrameTimestamps extension.
98 // Current test expectations only make sure microsecond precision timestamps
99 // are less than the nanosecond precision timestamps, so this is okay.
100 EGLnsecsANDROID getNanoseconds (void)
102 return deGetMicroseconds() * 1000;
109 , swapBufferBeginNs (-1)
110 , compositeDeadline (-1)
111 , compositeInterval (-1)
112 , compositeToPresentLatency (-1)
113 , requestedPresent (-1)
115 , firstCompositionStart (-1)
116 , lastCompositionStart (-1)
118 , renderingComplete (-1)
119 , firstCompositionGpuFinished (-1)
120 , displayPresent (-1)
125 EGLuint64KHR frameId;
127 // Timestamps sampled by the test.
128 EGLnsecsANDROID swapBufferBeginNs;
131 EGLnsecsANDROID compositeDeadline;
132 EGLnsecsANDROID compositeInterval;
133 EGLnsecsANDROID compositeToPresentLatency;
136 EGLnsecsANDROID requestedPresent;
137 EGLnsecsANDROID latch;
138 EGLnsecsANDROID firstCompositionStart;
139 EGLnsecsANDROID lastCompositionStart;
140 EGLnsecsANDROID dequeueReady;
143 EGLnsecsANDROID renderingComplete;
144 EGLnsecsANDROID firstCompositionGpuFinished;
145 EGLnsecsANDROID displayPresent;
146 EGLnsecsANDROID readsDone;
149 bool timestampExists (EGLnsecsANDROID timestamp)
151 return timestamp > 0;
154 void verifySingleFrame (const FrameTimes& frameTimes, tcu::ResultCollector& result, bool verifyReadsDone)
156 // Verify CPU timeline is monotonic.
157 result.check(frameTimes.swapBufferBeginNs < frameTimes.latch, "Buffer latched before it was swapped.");
158 result.check(frameTimes.latch < frameTimes.firstCompositionStart, "Buffer composited before it was latched.");
159 result.check(frameTimes.firstCompositionStart <= frameTimes.lastCompositionStart, "First composition start after last composition start.");
160 result.check(frameTimes.lastCompositionStart < frameTimes.dequeueReady, "Buffer composited after it was ready to be dequeued.");
162 // Verify GPU timeline is monotonic.
163 if (timestampExists(frameTimes.firstCompositionGpuFinished))
164 result.check(frameTimes.renderingComplete < frameTimes.firstCompositionGpuFinished, "Buffer rendering completed after compositor GPU work finished.");
166 if (timestampExists(frameTimes.displayPresent))
167 result.check(frameTimes.renderingComplete < frameTimes.displayPresent, "Buffer displayed before rendering completed.");
169 if (timestampExists(frameTimes.firstCompositionGpuFinished) && timestampExists(frameTimes.displayPresent))
170 result.check(frameTimes.firstCompositionGpuFinished < frameTimes.displayPresent, "Buffer displayed before compositor GPU work completed");
172 // Drivers may maintain shadow copies of the buffer, so the readsDone time
173 // of the real buffer may be earlier than apparent dependencies. We can only
174 // be sure that the readsDone time must be after the renderingComplete time.
176 result.check(frameTimes.renderingComplete < frameTimes.readsDone, "Buffer rendering completed after reads completed.");
178 // Verify CPU/GPU dependencies
179 result.check(frameTimes.renderingComplete < frameTimes.latch, "Buffer latched before rendering completed.");
180 if (timestampExists(frameTimes.firstCompositionGpuFinished))
181 result.check(frameTimes.firstCompositionStart < frameTimes.firstCompositionGpuFinished, "Composition CPU work started after GPU work finished.");
183 if (timestampExists(frameTimes.displayPresent))
184 result.check(frameTimes.firstCompositionStart < frameTimes.displayPresent, "Buffer displayed before it was composited.");
187 void verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result, bool verifyReadsDone)
190 result.check(frame1.swapBufferBeginNs < frame2.swapBufferBeginNs, "Swap begin times not monotonic.");
191 result.check(frame1.latch < frame2.latch, "Latch times not monotonic.");
192 result.check(frame1.lastCompositionStart < frame2.latch, "Old buffer composited after new buffer latched.");
193 result.check(frame1.lastCompositionStart < frame2.firstCompositionStart, "Composition times overlap.");
194 result.check(frame1.dequeueReady < frame2.dequeueReady, "Dequeue ready times not monotonic.");
197 result.check(frame1.renderingComplete < frame2.renderingComplete, "Rendering complete times not monotonic.");
199 if (timestampExists(frame1.firstCompositionGpuFinished) && timestampExists(frame2.firstCompositionGpuFinished))
200 result.check(frame1.firstCompositionGpuFinished < frame2.firstCompositionGpuFinished, "Composition GPU work complete times not monotonic.");
202 if (timestampExists(frame1.displayPresent) && timestampExists(frame2.displayPresent))
203 result.check(frame1.displayPresent < frame2.displayPresent, "Display present times not monotonic.");
205 if (verifyReadsDone && timestampExists(frame1.readsDone) && timestampExists(frame2.readsDone))
206 result.check(frame1.readsDone < frame2.readsDone, "Reads done times not monotonic.");
209 EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
211 EGLContext context = EGL_NO_CONTEXT;
212 const EGLint attribList[] =
214 EGL_CONTEXT_CLIENT_VERSION, 2,
218 EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
220 context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
221 EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
227 class GetFrameTimestampTest : public SimpleConfigCase
230 GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters);
231 ~GetFrameTimestampTest (void);
234 void executeForConfig (EGLDisplay display, EGLConfig config);
235 void initializeExtension (const Library& egl);
238 GetFrameTimestampTest (const GetFrameTimestampTest&);
239 GetFrameTimestampTest& operator= (const GetFrameTimestampTest&);
241 // TODO: Move these to eglw::Library.
242 eglGetNextFrameIdANDROIDFunc m_eglGetNextFrameIdANDROID;
243 eglGetCompositorTimingANDROIDFunc m_eglGetCompositorTimingANDROID;
244 eglGetCompositorTimingSupportedANDROIDFunc m_eglGetCompositorTimingSupportedANDROID;
245 eglGetFrameTimestampsANDROIDFunc m_eglGetFrameTimestampsANDROID;
246 eglGetFrameTimestampSupportedANDROIDFunc m_eglGetFrameTimestampSupportedANDROID;
248 tcu::ResultCollector m_result;
251 GetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
252 : SimpleConfigCase (eglTestCtx, filters.getName(), filters.getDescription(), filters)
253 , m_eglGetNextFrameIdANDROID (DE_NULL)
254 , m_eglGetCompositorTimingANDROID (DE_NULL)
255 , m_eglGetCompositorTimingSupportedANDROID (DE_NULL)
256 , m_eglGetFrameTimestampsANDROID (DE_NULL)
257 , m_eglGetFrameTimestampSupportedANDROID (DE_NULL)
258 , m_result (m_testCtx.getLog())
262 GetFrameTimestampTest::~GetFrameTimestampTest (void)
266 void GetFrameTimestampTest::initializeExtension (const Library& egl)
268 m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID"));
269 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed.");
270 m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID"));
271 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed.");
272 m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID"));
273 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed.");
274 m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID"));
275 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed.");
276 m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID"));
277 EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed.");
281 string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
283 std::ostringstream stream;
286 EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));
293 deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
295 const char* const vertexShaderSource =
296 "attribute highp vec2 a_pos;\n"
299 "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
302 const char* const fragmentShaderSource =
305 "\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
308 deUint32 program = 0;
309 deUint32 vertexShader = 0;
310 deUint32 fragmentShader = 0;
312 deInt32 vertexCompileStatus;
313 string vertexInfoLog;
314 deInt32 fragmentCompileStatus;
315 string fragmentInfoLog;
317 string programInfoLog;
321 program = gl.createProgram();
322 vertexShader = gl.createShader(GL_VERTEX_SHADER);
323 fragmentShader = gl.createShader(GL_FRAGMENT_SHADER);
325 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
327 gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
328 gl.compileShader(vertexShader);
329 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
331 gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
332 gl.compileShader(fragmentShader);
333 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
336 deInt32 infoLogLength = 0;
338 gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
339 gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
341 vertexInfoLog.resize(infoLogLength, '\0');
343 gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
344 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
346 vertexInfoLog.resize(infoLogLength);
350 deInt32 infoLogLength = 0;
352 gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
353 gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
355 fragmentInfoLog.resize(infoLogLength, '\0');
357 gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
358 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
360 fragmentInfoLog.resize(infoLogLength);
363 gl.attachShader(program, vertexShader);
364 gl.attachShader(program, fragmentShader);
365 gl.linkProgram(program);
366 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
369 deInt32 infoLogLength = 0;
371 gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
372 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
374 programInfoLog.resize(infoLogLength, '\0');
376 gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
377 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
379 programInfoLog.resize(infoLogLength);
382 if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
385 log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
387 log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
388 log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
390 log.endShaderProgram();
393 gl.deleteShader(vertexShader);
394 gl.deleteShader(fragmentShader);
395 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
397 TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
402 gl.deleteProgram(program);
405 gl.deleteShader(vertexShader);
408 gl.deleteShader(fragmentShader);
416 void GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config)
418 const Library& egl = m_eglTestCtx.getLibrary();
420 if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps"))
421 TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported");
423 initializeExtension(egl);
425 const string configIdStr (getConfigIdString(egl, display, config));
426 tcu::ScopedLogSection logSection (m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
427 const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
430 TestLog& log = m_testCtx.getLog();
432 log << TestLog::Message << "EGL_RED_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE) << TestLog::EndMessage;
433 log << TestLog::Message << "EGL_GREEN_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE) << TestLog::EndMessage;
434 log << TestLog::Message << "EGL_BLUE_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE) << TestLog::EndMessage;
435 log << TestLog::Message << "EGL_ALPHA_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE) << TestLog::EndMessage;
436 log << TestLog::Message << "EGL_DEPTH_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE) << TestLog::EndMessage;
437 log << TestLog::Message << "EGL_STENCIL_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE) << TestLog::EndMessage;
438 log << TestLog::Message << "EGL_SAMPLES: " << eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES) << TestLog::EndMessage;
441 de::UniquePtr<eglu::NativeWindow> window (factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));
443 eglu::UniqueSurface surface (egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
444 eglu::UniqueContext context (egl, display, createGLES2Context(egl, display, config));
446 deUint32 program = 0;
448 EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE));
450 m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
452 EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));
456 const eglw::EGLint frameTimestampNames[] =
458 EGL_REQUESTED_PRESENT_TIME_ANDROID,
459 EGL_RENDERING_COMPLETE_TIME_ANDROID,
460 EGL_COMPOSITION_LATCH_TIME_ANDROID,
461 EGL_FIRST_COMPOSITION_START_TIME_ANDROID,
462 EGL_LAST_COMPOSITION_START_TIME_ANDROID,
463 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID,
464 EGL_DISPLAY_PRESENT_TIME_ANDROID,
465 EGL_DEQUEUE_READY_TIME_ANDROID,
466 EGL_READS_DONE_TIME_ANDROID,
468 const size_t frameTimestampCount = DE_LENGTH_OF_ARRAY(frameTimestampNames);
470 const eglw::EGLint invalidTimestampName = EGL_READS_DONE_TIME_ANDROID + 1;
472 // Verify required timestamps are supported.
473 for (size_t i = 0; i < frameTimestampCount; i++)
475 const bool supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, frameTimestampNames[i]) != EGL_FALSE;
476 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
477 TCU_CHECK_MSG(supported, "Required timestamp not supported.");
480 // Verify unsupported timestamps are reported properly.
481 const bool invalidSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, invalidTimestampName) != EGL_FALSE;
482 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
483 TCU_CHECK_MSG(!invalidSupported, "Non existant timestamp reports that it is supported.");
485 // Verify compositor timings are supported.
486 const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID) != EGL_FALSE;
487 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
488 TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported.");
489 const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID) != EGL_FALSE;
490 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
491 TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported.");
492 const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID) != EGL_FALSE;
493 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
494 TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported.");
496 const float positions1[] =
507 const float positions2[] =
518 deUint32 posLocation;
520 program = createGLES2Program(gl, m_testCtx.getLog());
522 gl.useProgram(program);
523 posLocation = gl.getAttribLocation(program, "a_pos");
524 gl.enableVertexAttribArray(posLocation);
525 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
527 const size_t frameCount = 120;
528 std::vector<FrameTimes> frameTimes(frameCount);
529 for (size_t i = 0; i < frameCount; i++)
531 FrameTimes& frame = frameTimes[i];
533 const eglw::EGLint compositorTimingNames[] =
535 EGL_COMPOSITE_DEADLINE_ANDROID,
536 EGL_COMPOSITE_INTERVAL_ANDROID,
537 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID,
539 const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames);
540 EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 };
542 // Get the current time before making any API calls in case "now"
543 // just happens to get sampled near one of the composite deadlines.
544 EGLnsecsANDROID now = getNanoseconds();
547 EGLuint64KHR nextFrameId = 0;
548 CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId));
549 frame.frameId = nextFrameId;
551 // Get the compositor timing.
552 CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID(
553 display, *surface, compositorTimingCount,
554 compositorTimingNames, compositorTimingValues));
555 frame.compositeDeadline = compositorTimingValues[0];
556 frame.compositeInterval = compositorTimingValues[1];
557 frame.compositeToPresentLatency = compositorTimingValues[2];
559 // Verify compositor timing is sane.
560 m_result.check(1000000 < frame.compositeInterval, "Reported refresh rate greater than 1kHz.");
561 m_result.check(frame.compositeInterval < 1000000000, "Reported refresh rate less than 1Hz.");
562 m_result.check(0 < frame.compositeToPresentLatency, "Composite to present latency must be greater than 0.");
563 m_result.check(frame.compositeToPresentLatency < frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs.");
564 const EGLnsecsANDROID minDeadline = now;
565 m_result.check(minDeadline < frame.compositeDeadline, "Next composite deadline is in the past.");
566 const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2;
567 m_result.check(frame.compositeDeadline < maxDeadline, "Next composite deadline over two intervals away.");
569 const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f;
570 gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f);
571 gl.clear(GL_COLOR_BUFFER_BIT);
572 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
574 const bool posSelect = ((i % 2) == 0);
575 gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2);
576 gl.drawArrays(GL_TRIANGLES, 0, 6);
577 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
579 frame.swapBufferBeginNs = getNanoseconds();
580 EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
582 // All timestamps from 5 frames ago should definitely be available.
583 const size_t frameDelay = 5;
586 FrameTimes& frame5ago = frameTimes[i-frameDelay];
587 EGLnsecsANDROID frameTimestampValues[frameTimestampCount] = { 0 };
588 // \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed.
589 const bool verifyReadsDone = i > (frameDelay + 3);
591 CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
592 display, *surface, frame5ago.frameId, frameTimestampCount,
593 frameTimestampNames, frameTimestampValues));
595 frame5ago.requestedPresent = frameTimestampValues[0];
596 frame5ago.renderingComplete = frameTimestampValues[1];
597 frame5ago.latch = frameTimestampValues[2];
598 frame5ago.firstCompositionStart = frameTimestampValues[3];
599 frame5ago.lastCompositionStart = frameTimestampValues[4];
600 frame5ago.firstCompositionGpuFinished = frameTimestampValues[5];
601 frame5ago.displayPresent = frameTimestampValues[6];
602 frame5ago.dequeueReady = frameTimestampValues[7];
603 frame5ago.readsDone = frameTimestampValues[8];
605 verifySingleFrame(frame5ago, m_result, verifyReadsDone);
606 if (i >= frameDelay + 1)
608 FrameTimes& frame6ago = frameTimes[i-frameDelay-1];
609 verifyNeighboringFrames(frame6ago, frame5ago, m_result, verifyReadsDone);
614 // All timestamps for the most recently swapped frame should
615 // become available by only polling eglGetFrametimestamps.
616 // No additional swaps should be necessary.
617 FrameTimes& lastFrame = frameTimes.back();
618 const EGLnsecsANDROID pollingDeadline = lastFrame.swapBufferBeginNs + 1000000000;
619 bool finalTimestampAvaiable = false;
623 EGLnsecsANDROID frameTimestampValues[frameTimestampCount] = { 0 };
624 CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
625 display, *surface, lastFrame.frameId, frameTimestampCount,
626 frameTimestampNames, frameTimestampValues));
628 lastFrame.requestedPresent = frameTimestampValues[0];
629 lastFrame.renderingComplete = frameTimestampValues[1];
630 lastFrame.latch = frameTimestampValues[2];
631 lastFrame.firstCompositionStart = frameTimestampValues[3];
632 lastFrame.lastCompositionStart = frameTimestampValues[4];
633 lastFrame.firstCompositionGpuFinished = frameTimestampValues[5];
634 lastFrame.displayPresent = frameTimestampValues[6];
635 lastFrame.dequeueReady = frameTimestampValues[7];
636 lastFrame.readsDone = frameTimestampValues[8];
638 if (timestampExists(lastFrame.displayPresent))
639 finalTimestampAvaiable = true;
641 if (getNanoseconds() > pollingDeadline)
643 } while (!finalTimestampAvaiable);
645 m_result.check(finalTimestampAvaiable, "Timed out polling for timestamps of last swap.");
646 m_result.check(timestampExists(lastFrame.requestedPresent), "Rendering complete of last swap not avaiable.");
647 m_result.check(timestampExists(lastFrame.renderingComplete), "Rendering complete of last swap not avaiable.");
648 m_result.check(timestampExists(lastFrame.latch), "Latch of last swap not avaiable.");
649 m_result.check(timestampExists(lastFrame.firstCompositionStart), "First composite time of last swap not avaiable.");
650 m_result.check(timestampExists(lastFrame.lastCompositionStart), "Last composite time of last swap not avaiable.");
652 window->processEvents();
653 gl.disableVertexAttribArray(posLocation);
655 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");
657 gl.deleteProgram(program);
659 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
661 m_result.setTestContextResult(m_testCtx);
666 gl.deleteProgram(program);
668 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
672 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
675 class GetFrameTimestampsTests : public TestCaseGroup
678 GetFrameTimestampsTests (EglTestContext& eglTestCtx);
682 GetFrameTimestampsTests (const GetFrameTimestampsTests&);
683 GetFrameTimestampsTests& operator= (const GetFrameTimestampsTests&);
687 GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
688 : TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
692 bool isWindow (const eglu::CandidateConfig& c)
694 return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
697 void GetFrameTimestampsTests::init (void)
699 eglu::FilterList baseFilters;
700 baseFilters << isWindow;
702 vector<NamedFilterList> filterLists;
703 getDefaultFilterLists(filterLists, baseFilters);
705 for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
706 addChild(new GetFrameTimestampTest(m_eglTestCtx, *i));
711 TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
713 return new GetFrameTimestampsTests(eglTestCtx);