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
72typedef deInt64 EGLnsecsANDROID;
73typedef deUint64 EGLuint64KHR;
74#define EGL_TIMESTAMP_PENDING_ANDROID (-2)
75#define EGL_TIMESTAMP_INVALID_ANDROID (-1)
76typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId);
77typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values);
78typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name);
79typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampsANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR frameId, eglw::EGLint numTimestamps, const eglw::EGLint *timestamps, EGLnsecsANDROID *values);
80typedef 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
84namespace deqp
85{
86namespace egl
87{
88
89using tcu::TestLog;
90using std::string;
91using std::vector;
92using namespace eglw;
93
94namespace
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.
102EGLnsecsANDROID getNanoseconds (void)
103{
104	return deGetMicroseconds() * 1000;
105}
106
107struct FrameTimes
108{
109	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
152struct TimestampInfo
153{
154	TimestampInfo()
155		: required(false)
156		, supported(false)
157		, supportedIndex(0)
158	{
159	}
160
161	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
173typedef std::map<eglw::EGLint, TimestampInfo> TimestampInfoMap;
174
175EGLnsecsANDROID 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
181void 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
194bool timestampValid (EGLnsecsANDROID timestamp)
195{
196	return (timestamp >= 0) || (timestamp == EGL_TIMESTAMP_PENDING_ANDROID);
197}
198
199bool timestampPending (EGLnsecsANDROID timestamp)
200{
201	return timestamp == EGL_TIMESTAMP_PENDING_ANDROID;
202}
203
204void 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
237void 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
259EGLContext 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
277class GetFrameTimestampTest : public SimpleConfigCase
278{
279public:
280							GetFrameTimestampTest	(EglTestContext& eglTestCtx, const NamedFilterList& filters);
281							~GetFrameTimestampTest	(void);
282
283private:
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
301GetFrameTimestampTest::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
312GetFrameTimestampTest::~GetFrameTimestampTest (void)
313{
314}
315
316void 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
331string 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
343deUint32 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
466void 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
717class GetFrameTimestampsTests : public TestCaseGroup
718{
719public:
720								GetFrameTimestampsTests	(EglTestContext& eglTestCtx);
721	void						init					(void);
722
723private:
724								GetFrameTimestampsTests	(const GetFrameTimestampsTests&);
725	GetFrameTimestampsTests&	operator=				(const GetFrameTimestampsTests&);
726};
727
728
729GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
730	: TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
731{
732}
733
734bool isWindow (const eglu::CandidateConfig& c)
735{
736	return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
737}
738
739void 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
753TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
754{
755	return new GetFrameTimestampsTests(eglTestCtx);
756}
757
758} // egl
759} // deqp
760