1e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson/*-------------------------------------------------------------------------
2e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * drawElements Quality Program EGL Module
3e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * ---------------------------------------
4e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *
5e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * Copyright 2017 The Android Open Source Project
6e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *
7e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * Licensed under the Apache License, Version 2.0 (the "License");
8e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * you may not use this file except in compliance with the License.
9e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * You may obtain a copy of the License at
10e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *
11e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *      http://www.apache.org/licenses/LICENSE-2.0
12e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *
13e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * Unless required by applicable law or agreed to in writing, software
14e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * distributed under the License is distributed on an "AS IS" BASIS,
15e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * See the License for the specific language governing permissions and
17e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * limitations under the License.
18e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *
19e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *//*!
20e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * \file
21e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson * \brief Test the EGL_ANDROID_get_frame_timestamps extension.
22e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson *//*--------------------------------------------------------------------*/
23e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
24e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "teglGetFrameTimestampsTests.hpp"
25e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
26e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "teglSimpleConfigCase.hpp"
27e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
28e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "egluNativeWindow.hpp"
29e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "egluUtil.hpp"
30e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "egluUnique.hpp"
31e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "eglwLibrary.hpp"
32e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "eglwEnums.hpp"
33e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
34e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "gluDefs.hpp"
35e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "glwEnums.hpp"
36e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "glwFunctions.hpp"
37e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
38e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuResultCollector.hpp"
39e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuTestLog.hpp"
40e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuSurface.hpp"
41e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuTexture.hpp"
42e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuTextureUtil.hpp"
43e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuImageCompare.hpp"
44e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuVector.hpp"
45e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "tcuVectorUtil.hpp"
46e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
47e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "deClock.h"
48e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "deMath.h"
49e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "deUniquePtr.hpp"
50340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson#include "deStringUtil.hpp"
51e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include "deThread.hpp"
52e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
53e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include <algorithm>
54e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include <string>
55e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include <vector>
56e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#include <sstream>
57e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
58e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson// Tentative EGL header definitions for EGL_ANDROID_get_Frame_timestamps.
59e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson// \todo [2017-01-25 brianderson] Remove once defined in the official headers.
60679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_TIMESTAMPS_ANDROID 0x3430
61679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
62679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
63679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
64679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
65679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
66679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
67679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
68679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
69679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
70679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
71679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
72679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_READS_DONE_TIME_ANDROID 0x343C
73e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersontypedef deInt64 EGLnsecsANDROID;
74e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersontypedef deUint64 EGLuint64KHR;
75679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_TIMESTAMP_PENDING_ANDROID (-2)
76679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson#define EGL_TIMESTAMP_INVALID_ANDROID (-1)
77e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersontypedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId);
78e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersontypedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values);
79e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersontypedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name);
80e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersontypedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampsANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR frameId, eglw::EGLint numTimestamps, const eglw::EGLint *timestamps, EGLnsecsANDROID *values);
81e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersontypedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint timestamp);
82e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
83e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson#define CHECK_NAKED_EGL_CALL(EGLW, CALL)	do { CALL; eglu::checkError((EGLW).getError(), #CALL, __FILE__, __LINE__); } while (deGetFalse())
84e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
85e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonnamespace deqp
86e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
87e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonnamespace egl
88e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
89e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
90e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonusing tcu::TestLog;
91e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonusing std::string;
92e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonusing std::vector;
93e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonusing namespace eglw;
94e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
95e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonnamespace
96e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
97e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
98e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson// Careful: This has microsecond precision, which can cause timestamps to
99e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson// appear non monotonic when compared to the nanosecond precision timestamps
100e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson// we get from the eglGetFrameTimestamps extension.
101e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson// Current test expectations only make sure microsecond precision timestamps
102e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson// are less than the nanosecond precision timestamps, so this is okay.
103e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian AndersonEGLnsecsANDROID getNanoseconds (void)
104e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
105e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	return deGetMicroseconds() * 1000;
106e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
107e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
108e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonstruct FrameTimes
109e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
110e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	FrameTimes (void)
111e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		: frameId						(-1)
112e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, swapBufferBeginNs				(-1)
113e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, compositeDeadline				(-1)
114e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, compositeInterval				(-1)
115e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, compositeToPresentLatency		(-1)
116e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, requestedPresent				(-1)
117e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, latch							(-1)
118e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, firstCompositionStart			(-1)
119e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, lastCompositionStart			(-1)
120e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, dequeueReady					(-1)
121e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, renderingComplete				(-1)
122e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, firstCompositionGpuFinished	(-1)
123e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, displayPresent				(-1)
124e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		, readsDone						(-1)
125e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	{
126e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	}
127e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
128e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLuint64KHR	frameId;
129e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
130e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// Timestamps sampled by the test.
131e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	swapBufferBeginNs;
132e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
133e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// Compositor info.
134e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	compositeDeadline;
135e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	compositeInterval;
136e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	compositeToPresentLatency;
137e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
138e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// CPU Timeline.
139e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	requestedPresent;
140e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	latch;
141e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	firstCompositionStart;
142e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	lastCompositionStart;
143e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	dequeueReady;
144e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
145e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// GPU Timeline.
146e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	renderingComplete;
147e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	firstCompositionGpuFinished;
148e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	displayPresent;
149e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLnsecsANDROID	readsDone;
150e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson};
151e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
152679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
153679b3e921ad5dac5d434160a317e01d6db2bff16Brian Andersonstruct TimestampInfo
154e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
155679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	TimestampInfo()
156679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		: required(false)
157679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		, supported(false)
158679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		, supportedIndex(0)
159679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	{
160679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	}
161679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
162679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	TimestampInfo(bool required_, bool supported_, size_t supportedIndex_)
163679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		: required(required_)
164679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		, supported(supported_)
165679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		, supportedIndex(supportedIndex_)
166679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	{
167679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	}
168679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
169679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	bool	required;
170679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	bool	supported;
171679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	size_t	supportedIndex;
172679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson};
173679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
174679b3e921ad5dac5d434160a317e01d6db2bff16Brian Andersontypedef std::map<eglw::EGLint, TimestampInfo> TimestampInfoMap;
175679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
176679b3e921ad5dac5d434160a317e01d6db2bff16Brian AndersonEGLnsecsANDROID getTimestamp(eglw::EGLint name, TimestampInfoMap& map, const std::vector<EGLnsecsANDROID>& supportedValues)
177679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson{
178679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	TimestampInfo& info = map[name];
179679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	return info.supported ? supportedValues[info.supportedIndex] : EGL_TIMESTAMP_INVALID_ANDROID;
180679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson}
181679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
182679b3e921ad5dac5d434160a317e01d6db2bff16Brian Andersonvoid populateFrameTimes(FrameTimes* frameTimes, TimestampInfoMap& map, const std::vector<EGLnsecsANDROID>& supportedValues)
183679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson{
184679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->requestedPresent			=	getTimestamp(EGL_REQUESTED_PRESENT_TIME_ANDROID, map, supportedValues);
185679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->renderingComplete			=	getTimestamp(EGL_RENDERING_COMPLETE_TIME_ANDROID, map, supportedValues);
186679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->latch						=	getTimestamp(EGL_COMPOSITION_LATCH_TIME_ANDROID, map, supportedValues);
187679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->firstCompositionStart		=	getTimestamp(EGL_FIRST_COMPOSITION_START_TIME_ANDROID, map, supportedValues);
188679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->lastCompositionStart		=	getTimestamp(EGL_LAST_COMPOSITION_START_TIME_ANDROID, map, supportedValues);
189679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->firstCompositionGpuFinished	=	getTimestamp(EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID, map, supportedValues);
190679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->displayPresent				=	getTimestamp(EGL_DISPLAY_PRESENT_TIME_ANDROID, map, supportedValues);
191679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->dequeueReady				=	getTimestamp(EGL_DEQUEUE_READY_TIME_ANDROID, map, supportedValues);
192679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	frameTimes->readsDone					=	getTimestamp(EGL_READS_DONE_TIME_ANDROID, map, supportedValues);
193679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson}
194679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
195679b3e921ad5dac5d434160a317e01d6db2bff16Brian Andersonbool timestampValid (EGLnsecsANDROID timestamp)
196679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson{
19750d008cc39b7e1f1a65dc579785b5be45c9c8aa7Brian Anderson	// \todo [2017-10-19 brianderson] Don't consider 0 invalid once kernel fix is in.
19850d008cc39b7e1f1a65dc579785b5be45c9c8aa7Brian Anderson	return (timestamp > 0) || (timestamp == EGL_TIMESTAMP_PENDING_ANDROID);
199679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson}
200679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
201679b3e921ad5dac5d434160a317e01d6db2bff16Brian Andersonbool timestampPending (EGLnsecsANDROID timestamp)
202679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson{
203679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	return timestamp == EGL_TIMESTAMP_PENDING_ANDROID;
204e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
205e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
206340d07c9c375cf1266d218d25683ddc18f9182b5Brian Andersontemplate<typename T>
207340d07c9c375cf1266d218d25683ddc18f9182b5Brian Andersonvoid check_lt(tcu::ResultCollector& result, const T& a, const T& b, const std::string& msg) {
208340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	if (a < b)
209340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		return;
210340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	std::string m = msg + "!(" + de::toString(a) + " < " + de::toString(b) + ")";
211340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	result.fail(m);
212340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson}
213340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson
214340d07c9c375cf1266d218d25683ddc18f9182b5Brian Andersontemplate<typename T>
215340d07c9c375cf1266d218d25683ddc18f9182b5Brian Andersonvoid check_le(tcu::ResultCollector& result, const T& a, const T& b, const std::string& msg) {
216340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	if (a <= b)
217340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		return;
218340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	std::string m = msg + "!(" + de::toString(a) + " <= " + de::toString(b) + ")";
219340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	result.fail(m);
220340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson}
221340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson
222e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonvoid verifySingleFrame (const FrameTimes& frameTimes, tcu::ResultCollector& result, bool verifyReadsDone)
223e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
224e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// Verify CPU timeline is monotonic.
225340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frameTimes.swapBufferBeginNs, frameTimes.latch, "Buffer latched before it was swapped.");
226340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frameTimes.latch, frameTimes.firstCompositionStart, "Buffer composited before it was latched.");
227340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_le(result, frameTimes.firstCompositionStart, frameTimes.lastCompositionStart, "First composition start after last composition start.");
228340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frameTimes.lastCompositionStart, frameTimes.dequeueReady, "Buffer composited after it was ready to be dequeued.");
229e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
230e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// Verify GPU timeline is monotonic.
231679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	if (timestampValid(frameTimes.firstCompositionGpuFinished))
232340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_lt(result, frameTimes.renderingComplete, frameTimes.firstCompositionGpuFinished, "Buffer rendering completed after compositor GPU work finished.");
233e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
234679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	if (timestampValid(frameTimes.displayPresent))
235340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_lt(result, frameTimes.renderingComplete, frameTimes.displayPresent, "Buffer displayed before rendering completed.");
236e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
237679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	if (timestampValid(frameTimes.firstCompositionGpuFinished) && timestampValid(frameTimes.displayPresent))
238340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_lt(result, frameTimes.firstCompositionGpuFinished, frameTimes.displayPresent, "Buffer displayed before compositor GPU work completed");
239e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
240e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// Drivers may maintain shadow copies of the buffer, so the readsDone time
241e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// of the real buffer may be earlier than apparent dependencies. We can only
242e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// be sure that the readsDone time must be after the renderingComplete time.
243340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson    // It may also be equal to the renderingComplete time if no reads were
244340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson    // peformed.
24550d008cc39b7e1f1a65dc579785b5be45c9c8aa7Brian Anderson	if (verifyReadsDone && timestampValid(frameTimes.readsDone))
246340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_le(result, frameTimes.renderingComplete, frameTimes.readsDone, "Buffer rendering completed after reads completed.");
247e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
248e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// Verify CPU/GPU dependencies
249679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	if (timestampValid(frameTimes.firstCompositionGpuFinished))
250340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_lt(result, frameTimes.firstCompositionStart, frameTimes.firstCompositionGpuFinished, "Composition CPU work started after GPU work finished.");
251e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
252679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	if (timestampValid(frameTimes.displayPresent))
253340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_lt(result, frameTimes.firstCompositionStart, frameTimes.displayPresent, "Buffer displayed before it was composited.");
254e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
255e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
256e8634c92542be54bddd428cd8fa1e977f408030bBrian Andersonvoid verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result)
257e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
258e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// CPU timeline.
259340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frame1.swapBufferBeginNs, frame2.swapBufferBeginNs, "Swap begin times not monotonic.");
260340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frame1.latch, frame2.latch, "Latch times not monotonic.");
261340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frame1.lastCompositionStart, frame2.latch, "Old buffer composited after new buffer latched.");
262340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frame1.lastCompositionStart, frame2.firstCompositionStart, "Composition times overlap.");
263340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frame1.dequeueReady, frame2.dequeueReady, "Dequeue ready times not monotonic.");
264e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
265e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// GPU timeline.
266340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson	check_lt(result, frame1.renderingComplete, frame2.renderingComplete, "Rendering complete times not monotonic.");
267e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
268679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	if (timestampValid(frame1.firstCompositionGpuFinished) && timestampValid(frame2.firstCompositionGpuFinished))
269340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_lt(result, frame1.firstCompositionGpuFinished, frame2.firstCompositionGpuFinished, "Composition GPU work complete times not monotonic.");
270e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
271679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson	if (timestampValid(frame1.displayPresent) && timestampValid(frame2.displayPresent))
272340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson		check_lt(result, frame1.displayPresent, frame2.displayPresent, "Display present times not monotonic.");
273e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
274e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
275e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian AndersonEGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
276e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
277e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLContext		context = EGL_NO_CONTEXT;
278e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	const EGLint	attribList[] =
279e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	{
280e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		EGL_CONTEXT_CLIENT_VERSION, 2,
281e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		EGL_NONE
282e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	};
283e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
284e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
285e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
286e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
287e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
288e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	TCU_CHECK(context);
289e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
290e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	return context;
291e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
292e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
293e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonclass GetFrameTimestampTest : public SimpleConfigCase
294e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
295e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonpublic:
296e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson							GetFrameTimestampTest	(EglTestContext& eglTestCtx, const NamedFilterList& filters);
297e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson							~GetFrameTimestampTest	(void);
298e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
299e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonprivate:
300e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	void					executeForConfig		(EGLDisplay display, EGLConfig config);
301e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	void					initializeExtension		(const Library& egl);
302e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
303e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// Not allowed
304e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson							GetFrameTimestampTest	(const GetFrameTimestampTest&);
305e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	GetFrameTimestampTest&	operator=				(const GetFrameTimestampTest&);
306e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
307e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	// TODO: Move these to eglw::Library.
308e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglGetNextFrameIdANDROIDFunc				m_eglGetNextFrameIdANDROID;
309e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglGetCompositorTimingANDROIDFunc			m_eglGetCompositorTimingANDROID;
310e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglGetCompositorTimingSupportedANDROIDFunc	m_eglGetCompositorTimingSupportedANDROID;
311e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglGetFrameTimestampsANDROIDFunc			m_eglGetFrameTimestampsANDROID;
312e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglGetFrameTimestampSupportedANDROIDFunc	m_eglGetFrameTimestampSupportedANDROID;
313e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
314e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	tcu::ResultCollector						m_result;
315e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson};
316e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
317e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian AndersonGetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
318e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	: SimpleConfigCase							(eglTestCtx, filters.getName(), filters.getDescription(), filters)
319e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	, m_eglGetNextFrameIdANDROID				(DE_NULL)
320e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	, m_eglGetCompositorTimingANDROID			(DE_NULL)
321e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	, m_eglGetCompositorTimingSupportedANDROID	(DE_NULL)
322e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	, m_eglGetFrameTimestampsANDROID			(DE_NULL)
323e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	, m_eglGetFrameTimestampSupportedANDROID	(DE_NULL)
324e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	, m_result									(m_testCtx.getLog())
325e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
326e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
327e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
328e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian AndersonGetFrameTimestampTest::~GetFrameTimestampTest (void)
329e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
330e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
331e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
332e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonvoid GetFrameTimestampTest::initializeExtension (const Library& egl)
333e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
334e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID"));
335e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed.");
336e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID"));
337e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed.");
338e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID"));
339e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed.");
340e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID"));
341e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed.");
342e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID"));
343e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed.");
344e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
345e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
346e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
347e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonstring getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
348e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
349e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	std::ostringstream	stream;
350e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLint				id;
351e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
352e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));
353e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
354e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	stream << id;
355e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
356e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	return stream.str();
357e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
358e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
359e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian AndersondeUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
360e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
361e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	const char* const vertexShaderSource =
362e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"attribute highp vec2 a_pos;\n"
363e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"void main (void)\n"
364e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"{\n"
365e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
366e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"}";
367e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
368e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	const char* const fragmentShaderSource =
369e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"void main (void)\n"
370e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"{\n"
371e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
372e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	"}";
373e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
374e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	deUint32	program			= 0;
375e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	deUint32	vertexShader	= 0;
376e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	deUint32	fragmentShader	= 0;
377e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
378e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	deInt32		vertexCompileStatus;
379e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	string		vertexInfoLog;
380e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	deInt32		fragmentCompileStatus;
381e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	string		fragmentInfoLog;
382e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	deInt32		linkStatus;
383e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	string		programInfoLog;
384e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
385e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	try
386e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	{
387e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		program			= gl.createProgram();
388e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		vertexShader	= gl.createShader(GL_VERTEX_SHADER);
389e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		fragmentShader	= gl.createShader(GL_FRAGMENT_SHADER);
390e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
391e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
392e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
393e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
394e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.compileShader(vertexShader);
395e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
396e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
397e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
398e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.compileShader(fragmentShader);
399e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
400e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
401e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
402e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			deInt32		infoLogLength = 0;
403e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
404e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
405e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
406e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
407e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			vertexInfoLog.resize(infoLogLength, '\0');
408e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
409e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
410e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
411e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
412e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			vertexInfoLog.resize(infoLogLength);
413e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		}
414e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
415e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
416e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			deInt32		infoLogLength = 0;
417e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
418e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
419e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
420e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
421e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			fragmentInfoLog.resize(infoLogLength, '\0');
422e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
423e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
424e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
425e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
426e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			fragmentInfoLog.resize(infoLogLength);
427e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		}
428e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
429e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.attachShader(program, vertexShader);
430e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.attachShader(program, fragmentShader);
431e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.linkProgram(program);
432e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
433e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
434e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
435e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			deInt32		infoLogLength = 0;
436e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
437e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
438e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
439e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
440e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			programInfoLog.resize(infoLogLength, '\0');
441e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
442e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
443e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
444e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
445e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			programInfoLog.resize(infoLogLength);
446e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		}
447e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
448e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
449e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
450e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
451e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
452e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
453e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
454e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
455e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
456e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			log.endShaderProgram();
457e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		}
458e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
459e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.deleteShader(vertexShader);
460e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.deleteShader(fragmentShader);
461e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
462e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
463e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
464e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	}
465e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	catch (...)
466e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	{
467e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		if (program)
468e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.deleteProgram(program);
469e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
470e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		if (vertexShader)
471e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.deleteShader(vertexShader);
472e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
473e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		if (fragmentShader)
474e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.deleteShader(fragmentShader);
475e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
476e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		throw;
477e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	}
478e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
479e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	return program;
480e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
481e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
482e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonvoid GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config)
483e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
484e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	const Library&						egl			= m_eglTestCtx.getLibrary();
485e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
486e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps"))
487e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported");
488e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
489e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	initializeExtension(egl);
490e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
491e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	const string						configIdStr	(getConfigIdString(egl, display, config));
492e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	tcu::ScopedLogSection				logSection	(m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
493e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	const eglu::NativeWindowFactory&	factory		= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
494e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
495e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	{
496e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		TestLog& log = m_testCtx.getLog();
497e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
498e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		log << TestLog::Message << "EGL_RED_SIZE: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE)		<< TestLog::EndMessage;
499e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		log << TestLog::Message << "EGL_GREEN_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE)	<< TestLog::EndMessage;
500e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		log << TestLog::Message << "EGL_BLUE_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE)	<< TestLog::EndMessage;
501e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		log << TestLog::Message << "EGL_ALPHA_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE)	<< TestLog::EndMessage;
502e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		log << TestLog::Message << "EGL_DEPTH_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE)	<< TestLog::EndMessage;
503e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		log << TestLog::Message << "EGL_STENCIL_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE)	<< TestLog::EndMessage;
504e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		log << TestLog::Message << "EGL_SAMPLES: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES)		<< TestLog::EndMessage;
505e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	}
506e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
507e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	de::UniquePtr<eglu::NativeWindow>	window	(factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));
508e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
509e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglu::UniqueSurface					surface	(egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
510e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglu::UniqueContext					context	(egl, display, createGLES2Context(egl, display, config));
511e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	glw::Functions						gl;
512e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	deUint32							program = 0;
513e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
514e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE));
515e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
516e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
517e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
518e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));
519e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
520e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	try
521e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	{
522679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		// EGL_DISPLAY_PRESENT_TIME_ANDROID support is currently optional
523679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		// but should be required once HWC1 is no longer supported.
524679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		// All HWC2 devices should support EGL_DISPLAY_PRESENT_TIME_ANDROID.
525679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		TimestampInfoMap timestamps;
526679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_REQUESTED_PRESENT_TIME_ANDROID]				=	TimestampInfo(true,		false, 0);
527679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_RENDERING_COMPLETE_TIME_ANDROID]				=	TimestampInfo(true,		false, 0);
528679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_COMPOSITION_LATCH_TIME_ANDROID]				=	TimestampInfo(true,		false, 0);
529679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_FIRST_COMPOSITION_START_TIME_ANDROID]		=	TimestampInfo(true,		false, 0);
530679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_LAST_COMPOSITION_START_TIME_ANDROID]			=	TimestampInfo(true,		false, 0);
531679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID]	=	TimestampInfo(true,		false, 0);
532679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID]				=	TimestampInfo(false,	false, 0);
533679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_DEQUEUE_READY_TIME_ANDROID]					=	TimestampInfo(true,		false, 0);
534679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		timestamps[EGL_READS_DONE_TIME_ANDROID]						=	TimestampInfo(true,		false, 0);
535e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
5361c43c4772507454f3a171b10cfe883e44d78ff7aBrian Anderson		const eglw::EGLint invalidTimestampName = EGL_READS_DONE_TIME_ANDROID + 1;
5371c43c4772507454f3a171b10cfe883e44d78ff7aBrian Anderson
538679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		// Verify required timestamps are supported and populate supportedNames.
539679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		std::vector<eglw::EGLint> supportedNames;
540679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		for (TimestampInfoMap::iterator i = timestamps.begin(); i != timestamps.end(); i++)
541e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
542679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			TimestampInfo& info = i->second;
543679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			info.supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, i->first) != EGL_FALSE;
544e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
545679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
546679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			if (info.supported)
547679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			{
548679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				info.supportedIndex = supportedNames.size();
549679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				supportedNames.push_back(i->first);
550679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			}
551679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			else
552679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				TCU_CHECK_MSG(!info.required, "Required timestamp not supported.");
553e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		}
554e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
5551c43c4772507454f3a171b10cfe883e44d78ff7aBrian Anderson		// Verify unsupported timestamps are reported properly.
5561c43c4772507454f3a171b10cfe883e44d78ff7aBrian Anderson		const bool invalidSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, invalidTimestampName) != EGL_FALSE;
557e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
5581c43c4772507454f3a171b10cfe883e44d78ff7aBrian Anderson		TCU_CHECK_MSG(!invalidSupported, "Non existant timestamp reports that it is supported.");
559e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
560e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		// Verify compositor timings are supported.
561de0c0ce818ac5967b8ea668a51ed7526ce28f534Pyry Haulos		const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID) != EGL_FALSE;
562e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
563e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported.");
564de0c0ce818ac5967b8ea668a51ed7526ce28f534Pyry Haulos		const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID) != EGL_FALSE;
565e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
566e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported.");
567de0c0ce818ac5967b8ea668a51ed7526ce28f534Pyry Haulos		const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID) != EGL_FALSE;
568e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
569e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported.");
570e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
571e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		const float positions1[] =
572e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
573e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.00f,  0.00f,
574e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.75f,  0.00f,
575e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.75f,  0.75f,
576e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
577e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.75f,  0.75f,
578e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.00f,  0.75f,
579e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.00f,  0.00f
580e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		};
581e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
582e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		const float positions2[] =
583e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
584e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			-0.75f, -0.75f,
585e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.00f, -0.75f,
586e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.00f,  0.00f,
587e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
588e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			 0.00f,  0.00f,
589e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			-0.75f,  0.00f,
590e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			-0.75f, -0.75f
591e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		};
592e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
593e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		deUint32 posLocation;
594e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
595e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		program	= createGLES2Program(gl, m_testCtx.getLog());
596e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
597e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.useProgram(program);
598e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		posLocation	= gl.getAttribLocation(program, "a_pos");
599e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.enableVertexAttribArray(posLocation);
600e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
601e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
602e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		const size_t frameCount = 120;
603e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		std::vector<FrameTimes> frameTimes(frameCount);
604e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		for (size_t i = 0; i < frameCount; i++)
605e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
606e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			FrameTimes& frame = frameTimes[i];
607e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
608e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			const eglw::EGLint compositorTimingNames[] =
609e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			{
610e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				EGL_COMPOSITE_DEADLINE_ANDROID,
611e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				EGL_COMPOSITE_INTERVAL_ANDROID,
612e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID,
613e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			};
614e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames);
615e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 };
616e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
61740fd86f16fe7c46bab2f560ad870f3228cb37284Brian Anderson			// Get the current time before making any API calls in case "now"
61840fd86f16fe7c46bab2f560ad870f3228cb37284Brian Anderson			// just happens to get sampled near one of the composite deadlines.
61940fd86f16fe7c46bab2f560ad870f3228cb37284Brian Anderson			EGLnsecsANDROID now = getNanoseconds();
62040fd86f16fe7c46bab2f560ad870f3228cb37284Brian Anderson
621e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			// Get the frame id.
622e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			EGLuint64KHR nextFrameId = 0;
623e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId));
624e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			frame.frameId				=	nextFrameId;
625e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
626e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			// Get the compositor timing.
627e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID(
628e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				display, *surface, compositorTimingCount,
629e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				compositorTimingNames, compositorTimingValues));
630e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			frame.compositeDeadline			=	compositorTimingValues[0];
631e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			frame.compositeInterval			=	compositorTimingValues[1];
632e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			frame.compositeToPresentLatency	=	compositorTimingValues[2];
633e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
634e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			// Verify compositor timing is sane.
635340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson			check_lt<EGLnsecsANDROID>(m_result, 1000000, frame.compositeInterval, "Reported refresh rate greater than 1kHz.");
636340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson			check_lt<EGLnsecsANDROID>(m_result, frame.compositeInterval, 1000000000, "Reported refresh rate less than 1Hz.");
637340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson			check_lt<EGLnsecsANDROID>(m_result, 0, frame.compositeToPresentLatency, "Composite to present latency must be greater than 0.");
638340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson			check_lt(m_result, frame.compositeToPresentLatency, frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs.");
639e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			const EGLnsecsANDROID minDeadline = now;
640340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson			check_lt(m_result, minDeadline, frame.compositeDeadline, "Next composite deadline is in the past.");
641e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2;
642340d07c9c375cf1266d218d25683ddc18f9182b5Brian Anderson			check_lt(m_result, frame.compositeDeadline, maxDeadline, "Next composite deadline over two intervals away.");
643e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
644e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f;
645e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f);
646e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.clear(GL_COLOR_BUFFER_BIT);
647e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
648e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
649e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			const bool posSelect  = ((i % 2) == 0);
650e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2);
651e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.drawArrays(GL_TRIANGLES, 0, 6);
652e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
653e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
654e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			frame.swapBufferBeginNs = getNanoseconds();
655e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
656e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
657e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			// All timestamps from 5 frames ago should definitely be available.
658e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			const size_t frameDelay = 5;
659e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			if (i >= frameDelay)
660e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			{
661e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				// \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed.
662679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				const bool verifyReadsDone	=	i > (frameDelay + 3);
663679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				FrameTimes&		frame5ago	=	frameTimes[i-frameDelay];
664679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0);
665e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
666e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
667679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson					display, *surface, frame5ago.frameId, static_cast<eglw::EGLint>(supportedNames.size()),
668679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson					&supportedNames[0], &supportedValues[0]));
669679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				populateFrameTimes(&frame5ago, timestamps, supportedValues);
670e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
671e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				verifySingleFrame(frame5ago, m_result, verifyReadsDone);
672e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				if (i >= frameDelay + 1)
673e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				{
674e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson					FrameTimes& frame6ago = frameTimes[i-frameDelay-1];
675e8634c92542be54bddd428cd8fa1e977f408030bBrian Anderson					verifyNeighboringFrames(frame6ago, frame5ago, m_result);
676e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson				}
677e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			}
678e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		}
679e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
680e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		// All timestamps for the most recently swapped frame should
681e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		// become available by only polling eglGetFrametimestamps.
682e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		// No additional swaps should be necessary.
683e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		FrameTimes&				lastFrame				=	frameTimes.back();
684e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		const EGLnsecsANDROID	pollingDeadline			=	lastFrame.swapBufferBeginNs + 1000000000;
685679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		bool					finalTimestampAvailable	=	false;
686e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
687e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		do
688e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		{
689679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			std::vector<EGLnsecsANDROID> supportedValues(supportedNames.size(), 0);
690e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
691679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				display, *surface, lastFrame.frameId, static_cast<eglw::EGLint>(supportedNames.size()),
692679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				&supportedNames[0], &supportedValues[0]));
693679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			populateFrameTimes(&lastFrame, timestamps, supportedValues);
694679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
695679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			// Poll for present if it's supported.
696679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			// Otherwise, poll for firstCompositionStart.
697679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			if (timestamps[EGL_DISPLAY_PRESENT_TIME_ANDROID].supported)
698679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				finalTimestampAvailable = !timestampPending(lastFrame.displayPresent);
699679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson			else
700679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson				finalTimestampAvailable = !timestampPending(lastFrame.firstCompositionStart);
701679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		} while (!finalTimestampAvailable && (getNanoseconds() < pollingDeadline));
702679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson
703679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		m_result.check(finalTimestampAvailable, "Timed out polling for timestamps of last swap.");
704679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		m_result.check((lastFrame.requestedPresent >= 0), "Requested present of last swap not avaiable.");
705679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		m_result.check((lastFrame.renderingComplete >= 0), "Rendering complete of last swap not avaiable.");
706679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		m_result.check((lastFrame.latch >= 0), "Latch of last swap not avaiable.");
707679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		m_result.check((lastFrame.firstCompositionStart >= 0), "First composite time of last swap not avaiable.");
708679b3e921ad5dac5d434160a317e01d6db2bff16Brian Anderson		m_result.check((lastFrame.lastCompositionStart >= 0), "Last composite time of last swap not avaiable.");
709e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
710e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		window->processEvents();
711e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.disableVertexAttribArray(posLocation);
712e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.useProgram(0);
713e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");
714e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
715e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		gl.deleteProgram(program);
716e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		program = 0;
717e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
718e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
719e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		m_result.setTestContextResult(m_testCtx);
720e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	}
721e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	catch (...)
722e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	{
723e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		if (program != 0)
724e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson			gl.deleteProgram(program);
725e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
726e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
727e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		throw;
728e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	}
729e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
730e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
731e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
732e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
733e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonclass GetFrameTimestampsTests : public TestCaseGroup
734e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
735e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonpublic:
736e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson								GetFrameTimestampsTests	(EglTestContext& eglTestCtx);
737e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	void						init					(void);
738e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
739e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonprivate:
740e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson								GetFrameTimestampsTests	(const GetFrameTimestampsTests&);
741e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	GetFrameTimestampsTests&	operator=				(const GetFrameTimestampsTests&);
742e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson};
743e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
744e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
745e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian AndersonGetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
746e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	: TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
747e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
748e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
749e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
750e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonbool isWindow (const eglu::CandidateConfig& c)
751e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
752e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
753e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
754e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
755e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Andersonvoid GetFrameTimestampsTests::init (void)
756e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
757e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	eglu::FilterList baseFilters;
758e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	baseFilters << isWindow;
759e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
760e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	vector<NamedFilterList> filterLists;
761e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	getDefaultFilterLists(filterLists, baseFilters);
762e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
763e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
764e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson		addChild(new GetFrameTimestampTest(m_eglTestCtx, *i));
765e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
766e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
767e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson} // anonymous
768e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
769e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian AndersonTestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
770e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson{
771e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson	return new GetFrameTimestampsTests(eglTestCtx);
772e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson}
773e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson
774e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson} // egl
775e288d40afc78bf4a37a84eee6c13efd0cf23fac2Brian Anderson} // deqp
776