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