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