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