Don't assume rendering complete before buffer latch
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglGetFrameTimestampsTests.cpp
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.
103 EGLnsecsANDROID getNanoseconds (void)
104 {
105         return deGetMicroseconds() * 1000;
106 }
107
108 struct FrameTimes
109 {
110         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 {
155         TimestampInfo()
156                 : required(false)
157                 , supported(false)
158                 , supportedIndex(0)
159         {
160         }
161
162         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
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
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
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
201 bool timestampPending (EGLnsecsANDROID timestamp)
202 {
203         return timestamp == EGL_TIMESTAMP_PENDING_ANDROID;
204 }
205
206 template<typename T>
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>
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
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
256 void verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result, bool verifyReadsDone)
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         if (verifyReadsDone && timestampValid(frame1.readsDone) && timestampValid(frame2.readsDone))
275                 check_lt(result, frame1.readsDone, frame2.readsDone, "Reads done times not monotonic.");
276 }
277
278 EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
279 {
280         EGLContext              context = EGL_NO_CONTEXT;
281         const EGLint    attribList[] =
282         {
283                 EGL_CONTEXT_CLIENT_VERSION, 2,
284                 EGL_NONE
285         };
286
287         EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
288
289         context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
290         EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
291         TCU_CHECK(context);
292
293         return context;
294 }
295
296 class GetFrameTimestampTest : public SimpleConfigCase
297 {
298 public:
299                                                         GetFrameTimestampTest   (EglTestContext& eglTestCtx, const NamedFilterList& filters);
300                                                         ~GetFrameTimestampTest  (void);
301
302 private:
303         void                                    executeForConfig                (EGLDisplay display, EGLConfig config);
304         void                                    initializeExtension             (const Library& egl);
305
306         // Not allowed
307                                                         GetFrameTimestampTest   (const GetFrameTimestampTest&);
308         GetFrameTimestampTest&  operator=                               (const GetFrameTimestampTest&);
309
310         // TODO: Move these to eglw::Library.
311         eglGetNextFrameIdANDROIDFunc                            m_eglGetNextFrameIdANDROID;
312         eglGetCompositorTimingANDROIDFunc                       m_eglGetCompositorTimingANDROID;
313         eglGetCompositorTimingSupportedANDROIDFunc      m_eglGetCompositorTimingSupportedANDROID;
314         eglGetFrameTimestampsANDROIDFunc                        m_eglGetFrameTimestampsANDROID;
315         eglGetFrameTimestampSupportedANDROIDFunc        m_eglGetFrameTimestampSupportedANDROID;
316
317         tcu::ResultCollector                                            m_result;
318 };
319
320 GetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
321         : SimpleConfigCase                                                      (eglTestCtx, filters.getName(), filters.getDescription(), filters)
322         , m_eglGetNextFrameIdANDROID                            (DE_NULL)
323         , m_eglGetCompositorTimingANDROID                       (DE_NULL)
324         , m_eglGetCompositorTimingSupportedANDROID      (DE_NULL)
325         , m_eglGetFrameTimestampsANDROID                        (DE_NULL)
326         , m_eglGetFrameTimestampSupportedANDROID        (DE_NULL)
327         , m_result                                                                      (m_testCtx.getLog())
328 {
329 }
330
331 GetFrameTimestampTest::~GetFrameTimestampTest (void)
332 {
333 }
334
335 void GetFrameTimestampTest::initializeExtension (const Library& egl)
336 {
337         m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID"));
338         EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed.");
339         m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID"));
340         EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed.");
341         m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID"));
342         EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed.");
343         m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID"));
344         EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed.");
345         m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID"));
346         EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed.");
347 }
348
349
350 string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
351 {
352         std::ostringstream      stream;
353         EGLint                          id;
354
355         EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));
356
357         stream << id;
358
359         return stream.str();
360 }
361
362 deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
363 {
364         const char* const vertexShaderSource =
365         "attribute highp vec2 a_pos;\n"
366         "void main (void)\n"
367         "{\n"
368         "\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
369         "}";
370
371         const char* const fragmentShaderSource =
372         "void main (void)\n"
373         "{\n"
374         "\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
375         "}";
376
377         deUint32        program                 = 0;
378         deUint32        vertexShader    = 0;
379         deUint32        fragmentShader  = 0;
380
381         deInt32         vertexCompileStatus;
382         string          vertexInfoLog;
383         deInt32         fragmentCompileStatus;
384         string          fragmentInfoLog;
385         deInt32         linkStatus;
386         string          programInfoLog;
387
388         try
389         {
390                 program                 = gl.createProgram();
391                 vertexShader    = gl.createShader(GL_VERTEX_SHADER);
392                 fragmentShader  = gl.createShader(GL_FRAGMENT_SHADER);
393
394                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
395
396                 gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
397                 gl.compileShader(vertexShader);
398                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
399
400                 gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
401                 gl.compileShader(fragmentShader);
402                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
403
404                 {
405                         deInt32         infoLogLength = 0;
406
407                         gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
408                         gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
409
410                         vertexInfoLog.resize(infoLogLength, '\0');
411
412                         gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
413                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
414
415                         vertexInfoLog.resize(infoLogLength);
416                 }
417
418                 {
419                         deInt32         infoLogLength = 0;
420
421                         gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
422                         gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
423
424                         fragmentInfoLog.resize(infoLogLength, '\0');
425
426                         gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
427                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
428
429                         fragmentInfoLog.resize(infoLogLength);
430                 }
431
432                 gl.attachShader(program, vertexShader);
433                 gl.attachShader(program, fragmentShader);
434                 gl.linkProgram(program);
435                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
436
437                 {
438                         deInt32         infoLogLength = 0;
439
440                         gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
441                         gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
442
443                         programInfoLog.resize(infoLogLength, '\0');
444
445                         gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
446                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
447
448                         programInfoLog.resize(infoLogLength);
449                 }
450
451                 if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
452                 {
453
454                         log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
455
456                         log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
457                         log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
458
459                         log.endShaderProgram();
460                 }
461
462                 gl.deleteShader(vertexShader);
463                 gl.deleteShader(fragmentShader);
464                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
465
466                 TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
467         }
468         catch (...)
469         {
470                 if (program)
471                         gl.deleteProgram(program);
472
473                 if (vertexShader)
474                         gl.deleteShader(vertexShader);
475
476                 if (fragmentShader)
477                         gl.deleteShader(fragmentShader);
478
479                 throw;
480         }
481
482         return program;
483 }
484
485 void GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config)
486 {
487         const Library&                                          egl                     = m_eglTestCtx.getLibrary();
488
489         if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps"))
490                 TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported");
491
492         initializeExtension(egl);
493
494         const string                                            configIdStr     (getConfigIdString(egl, display, config));
495         tcu::ScopedLogSection                           logSection      (m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
496         const eglu::NativeWindowFactory&        factory         = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
497
498         {
499                 TestLog& log = m_testCtx.getLog();
500
501                 log << TestLog::Message << "EGL_RED_SIZE: "             << eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE)         << TestLog::EndMessage;
502                 log << TestLog::Message << "EGL_GREEN_SIZE: "   << eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE)       << TestLog::EndMessage;
503                 log << TestLog::Message << "EGL_BLUE_SIZE: "    << eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE)        << TestLog::EndMessage;
504                 log << TestLog::Message << "EGL_ALPHA_SIZE: "   << eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE)       << TestLog::EndMessage;
505                 log << TestLog::Message << "EGL_DEPTH_SIZE: "   << eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE)       << TestLog::EndMessage;
506                 log << TestLog::Message << "EGL_STENCIL_SIZE: " << eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE)     << TestLog::EndMessage;
507                 log << TestLog::Message << "EGL_SAMPLES: "              << eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES)          << TestLog::EndMessage;
508         }
509
510         de::UniquePtr<eglu::NativeWindow>       window  (factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));
511
512         eglu::UniqueSurface                                     surface (egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
513         eglu::UniqueContext                                     context (egl, display, createGLES2Context(egl, display, config));
514         glw::Functions                                          gl;
515         deUint32                                                        program = 0;
516
517         EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE));
518
519         m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
520
521         EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));
522
523         try
524         {
525                 // EGL_DISPLAY_PRESENT_TIME_ANDROID support is currently optional
526                 // but should be required once HWC1 is no longer supported.
527                 // All HWC2 devices should support EGL_DISPLAY_PRESENT_TIME_ANDROID.
528                 TimestampInfoMap timestamps;
529                 timestamps[EGL_REQUESTED_PRESENT_TIME_ANDROID]                          =       TimestampInfo(true,             false, 0);
530                 timestamps[EGL_RENDERING_COMPLETE_TIME_ANDROID]                         =       TimestampInfo(true,             false, 0);
531                 timestamps[EGL_COMPOSITION_LATCH_TIME_ANDROID]                          =       TimestampInfo(true,             false, 0);
532                 timestamps[EGL_FIRST_COMPOSITION_START_TIME_ANDROID]            =       TimestampInfo(true,             false, 0);
533                 timestamps[EGL_LAST_COMPOSITION_START_TIME_ANDROID]                     =       TimestampInfo(true,             false, 0);
534                 timestamps[EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID]     =       TimestampInfo(true,             false, 0);
535                 timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID]                            =       TimestampInfo(false,    false, 0);
536                 timestamps[EGL_DEQUEUE_READY_TIME_ANDROID]                                      =       TimestampInfo(true,             false, 0);
537                 timestamps[EGL_READS_DONE_TIME_ANDROID]                                         =       TimestampInfo(true,             false, 0);
538
539                 const eglw::EGLint invalidTimestampName = EGL_READS_DONE_TIME_ANDROID + 1;
540
541                 // Verify required timestamps are supported and populate supportedNames.
542                 std::vector<eglw::EGLint> supportedNames;
543                 for (TimestampInfoMap::iterator i = timestamps.begin(); i != timestamps.end(); i++)
544                 {
545                         TimestampInfo& info = i->second;
546                         info.supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, i->first) != EGL_FALSE;
547                         EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
548
549                         if (info.supported)
550                         {
551                                 info.supportedIndex = supportedNames.size();
552                                 supportedNames.push_back(i->first);
553                         }
554                         else
555                                 TCU_CHECK_MSG(!info.required, "Required timestamp not supported.");
556                 }
557
558                 // Verify unsupported timestamps are reported properly.
559                 const bool invalidSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, invalidTimestampName) != EGL_FALSE;
560                 EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
561                 TCU_CHECK_MSG(!invalidSupported, "Non existant timestamp reports that it is supported.");
562
563                 // Verify compositor timings are supported.
564                 const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID) != EGL_FALSE;
565                 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
566                 TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported.");
567                 const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID) != EGL_FALSE;
568                 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
569                 TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported.");
570                 const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID) != EGL_FALSE;
571                 EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
572                 TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported.");
573
574                 const float positions1[] =
575                 {
576                          0.00f,  0.00f,
577                          0.75f,  0.00f,
578                          0.75f,  0.75f,
579
580                          0.75f,  0.75f,
581                          0.00f,  0.75f,
582                          0.00f,  0.00f
583                 };
584
585                 const float positions2[] =
586                 {
587                         -0.75f, -0.75f,
588                          0.00f, -0.75f,
589                          0.00f,  0.00f,
590
591                          0.00f,  0.00f,
592                         -0.75f,  0.00f,
593                         -0.75f, -0.75f
594                 };
595
596                 deUint32 posLocation;
597
598                 program = createGLES2Program(gl, m_testCtx.getLog());
599
600                 gl.useProgram(program);
601                 posLocation     = gl.getAttribLocation(program, "a_pos");
602                 gl.enableVertexAttribArray(posLocation);
603                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
604
605                 const size_t frameCount = 120;
606                 std::vector<FrameTimes> frameTimes(frameCount);
607                 for (size_t i = 0; i < frameCount; i++)
608                 {
609                         FrameTimes& frame = frameTimes[i];
610
611                         const eglw::EGLint compositorTimingNames[] =
612                         {
613                                 EGL_COMPOSITE_DEADLINE_ANDROID,
614                                 EGL_COMPOSITE_INTERVAL_ANDROID,
615                                 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID,
616                         };
617                         const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames);
618                         EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 };
619
620                         // Get the current time before making any API calls in case "now"
621                         // just happens to get sampled near one of the composite deadlines.
622                         EGLnsecsANDROID now = getNanoseconds();
623
624                         // Get the frame id.
625                         EGLuint64KHR nextFrameId = 0;
626                         CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId));
627                         frame.frameId                           =       nextFrameId;
628
629                         // Get the compositor timing.
630                         CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID(
631                                 display, *surface, compositorTimingCount,
632                                 compositorTimingNames, compositorTimingValues));
633                         frame.compositeDeadline                 =       compositorTimingValues[0];
634                         frame.compositeInterval                 =       compositorTimingValues[1];
635                         frame.compositeToPresentLatency =       compositorTimingValues[2];
636
637                         // Verify compositor timing is sane.
638                         check_lt<EGLnsecsANDROID>(m_result, 1000000, frame.compositeInterval, "Reported refresh rate greater than 1kHz.");
639                         check_lt<EGLnsecsANDROID>(m_result, frame.compositeInterval, 1000000000, "Reported refresh rate less than 1Hz.");
640                         check_lt<EGLnsecsANDROID>(m_result, 0, frame.compositeToPresentLatency, "Composite to present latency must be greater than 0.");
641                         check_lt(m_result, frame.compositeToPresentLatency, frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs.");
642                         const EGLnsecsANDROID minDeadline = now;
643                         check_lt(m_result, minDeadline, frame.compositeDeadline, "Next composite deadline is in the past.");
644                         const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2;
645                         check_lt(m_result, frame.compositeDeadline, maxDeadline, "Next composite deadline over two intervals away.");
646
647                         const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f;
648                         gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f);
649                         gl.clear(GL_COLOR_BUFFER_BIT);
650                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
651
652                         const bool posSelect  = ((i % 2) == 0);
653                         gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2);
654                         gl.drawArrays(GL_TRIANGLES, 0, 6);
655                         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
656
657                         frame.swapBufferBeginNs = getNanoseconds();
658                         EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
659
660                         // All timestamps from 5 frames ago should definitely be available.
661                         const size_t frameDelay = 5;
662                         if (i >= frameDelay)
663                         {
664                                 // \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed.
665                                 const bool verifyReadsDone      =       i > (frameDelay + 3);
666                                 FrameTimes&             frame5ago       =       frameTimes[i-frameDelay];
667                                 std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0);
668
669                                 CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
670                                         display, *surface, frame5ago.frameId, static_cast<eglw::EGLint>(supportedNames.size()),
671                                         &supportedNames[0], &supportedValues[0]));
672                                 populateFrameTimes(&frame5ago, timestamps, supportedValues);
673
674                                 verifySingleFrame(frame5ago, m_result, verifyReadsDone);
675                                 if (i >= frameDelay + 1)
676                                 {
677                                         FrameTimes& frame6ago = frameTimes[i-frameDelay-1];
678                                         verifyNeighboringFrames(frame6ago, frame5ago, m_result, verifyReadsDone);
679                                 }
680                         }
681                 }
682
683                 // All timestamps for the most recently swapped frame should
684                 // become available by only polling eglGetFrametimestamps.
685                 // No additional swaps should be necessary.
686                 FrameTimes&                             lastFrame                               =       frameTimes.back();
687                 const EGLnsecsANDROID   pollingDeadline                 =       lastFrame.swapBufferBeginNs + 1000000000;
688                 bool                                    finalTimestampAvailable =       false;
689
690                 do
691                 {
692                         std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0);
693                         CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
694                                 display, *surface, lastFrame.frameId, static_cast<eglw::EGLint>(supportedNames.size()),
695                                 &supportedNames[0], &supportedValues[0]));
696                         populateFrameTimes(&lastFrame, timestamps, supportedValues);
697
698                         // Poll for present if it's supported.
699                         // Otherwise, poll for firstCompositionStart.
700                         if (timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID].supported)
701                                 finalTimestampAvailable = !timestampPending(lastFrame.displayPresent);
702                         else
703                                 finalTimestampAvailable = !timestampPending(lastFrame.firstCompositionStart);
704                 } while (!finalTimestampAvailable && (getNanoseconds() < pollingDeadline));
705
706                 m_result.check(finalTimestampAvailable, "Timed out polling for timestamps of last swap.");
707                 m_result.check((lastFrame.requestedPresent >= 0), "Requested present of last swap not avaiable.");
708                 m_result.check((lastFrame.renderingComplete >= 0), "Rendering complete of last swap not avaiable.");
709                 m_result.check((lastFrame.latch >= 0), "Latch of last swap not avaiable.");
710                 m_result.check((lastFrame.firstCompositionStart >= 0), "First composite time of last swap not avaiable.");
711                 m_result.check((lastFrame.lastCompositionStart >= 0), "Last composite time of last swap not avaiable.");
712
713                 window->processEvents();
714                 gl.disableVertexAttribArray(posLocation);
715                 gl.useProgram(0);
716                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");
717
718                 gl.deleteProgram(program);
719                 program = 0;
720                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
721
722                 m_result.setTestContextResult(m_testCtx);
723         }
724         catch (...)
725         {
726                 if (program != 0)
727                         gl.deleteProgram(program);
728
729                 EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
730                 throw;
731         }
732
733         EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
734 }
735
736 class GetFrameTimestampsTests : public TestCaseGroup
737 {
738 public:
739                                                                 GetFrameTimestampsTests (EglTestContext& eglTestCtx);
740         void                                            init                                    (void);
741
742 private:
743                                                                 GetFrameTimestampsTests (const GetFrameTimestampsTests&);
744         GetFrameTimestampsTests&        operator=                               (const GetFrameTimestampsTests&);
745 };
746
747
748 GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
749         : TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
750 {
751 }
752
753 bool isWindow (const eglu::CandidateConfig& c)
754 {
755         return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
756 }
757
758 void GetFrameTimestampsTests::init (void)
759 {
760         eglu::FilterList baseFilters;
761         baseFilters << isWindow;
762
763         vector<NamedFilterList> filterLists;
764         getDefaultFilterLists(filterLists, baseFilters);
765
766         for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
767                 addChild(new GetFrameTimestampTest(m_eglTestCtx, *i));
768 }
769
770 } // anonymous
771
772 TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
773 {
774         return new GetFrameTimestampsTests(eglTestCtx);
775 }
776
777 } // egl
778 } // deqp