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