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