xref: /aosp_15_r20/external/deqp/modules/egl/teglGetFrameTimestampsTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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