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.
getNanoseconds(void)103 EGLnsecsANDROID getNanoseconds (void)
104 {
105 return deGetMicroseconds() * 1000;
106 }
107
108 struct FrameTimes
109 {
FrameTimesdeqp::egl::__anonc9c68c580111::FrameTimes110 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 {
TimestampInfodeqp::egl::__anonc9c68c580111::TimestampInfo155 TimestampInfo()
156 : required(false)
157 , supported(false)
158 , supportedIndex(0)
159 {
160 }
161
TimestampInfodeqp::egl::__anonc9c68c580111::TimestampInfo162 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
getTimestamp(eglw::EGLint name,TimestampInfoMap & map,const std::vector<EGLnsecsANDROID> & supportedValues)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
populateFrameTimes(FrameTimes * frameTimes,TimestampInfoMap & map,const std::vector<EGLnsecsANDROID> & supportedValues)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
timestampValid(EGLnsecsANDROID timestamp)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
timestampPending(EGLnsecsANDROID timestamp)201 bool timestampPending (EGLnsecsANDROID timestamp)
202 {
203 return timestamp == EGL_TIMESTAMP_PENDING_ANDROID;
204 }
205
206 template<typename T>
check_lt(tcu::ResultCollector & result,const T & a,const T & b,const std::string & msg)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>
check_le(tcu::ResultCollector & result,const T & a,const T & b,const std::string & msg)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
verifySingleFrame(const FrameTimes & frameTimes,tcu::ResultCollector & result,bool verifyReadsDone)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
verifyNeighboringFrames(const FrameTimes & frame1,const FrameTimes & frame2,tcu::ResultCollector & result)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
createGLES2Context(const Library & egl,EGLDisplay display,EGLConfig config)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
GetFrameTimestampTest(EglTestContext & eglTestCtx,const NamedFilterList & filters)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
~GetFrameTimestampTest(void)328 GetFrameTimestampTest::~GetFrameTimestampTest (void)
329 {
330 }
331
initializeExtension(const Library & egl)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
getConfigIdString(const Library & egl,EGLDisplay display,EGLConfig config)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
createGLES2Program(const glw::Functions & gl,TestLog & log)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
executeForConfig(EGLDisplay display,EGLConfig config)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
GetFrameTimestampsTests(EglTestContext & eglTestCtx)745 GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
746 : TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
747 {
748 }
749
isWindow(const eglu::CandidateConfig & c)750 bool isWindow (const eglu::CandidateConfig& c)
751 {
752 return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
753 }
754
init(void)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
createGetFrameTimestampsTests(EglTestContext & eglTestCtx)769 TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
770 {
771 return new GetFrameTimestampsTests(eglTestCtx);
772 }
773
774 } // egl
775 } // deqp
776