1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program EGL Module
3e5c31af7Sopenharmony_ci * ---------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2015 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *       http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Test KHR_swap_buffer_with_damage
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "teglSwapBuffersWithDamageTests.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
27e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
28e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include "egluNativeWindow.hpp"
31e5c31af7Sopenharmony_ci#include "egluUtil.hpp"
32e5c31af7Sopenharmony_ci#include "egluConfigFilter.hpp"
33e5c31af7Sopenharmony_ci
34e5c31af7Sopenharmony_ci#include "eglwLibrary.hpp"
35e5c31af7Sopenharmony_ci#include "eglwEnums.hpp"
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci#include "gluDefs.hpp"
38e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp"
39e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci#include "glwDefs.hpp"
42e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
43e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ci#include "deRandom.hpp"
46e5c31af7Sopenharmony_ci#include "deString.h"
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ci#include <string>
49e5c31af7Sopenharmony_ci#include <vector>
50e5c31af7Sopenharmony_ci#include <sstream>
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_ciusing std::string;
53e5c31af7Sopenharmony_ciusing std::vector;
54e5c31af7Sopenharmony_ciusing glw::GLubyte;
55e5c31af7Sopenharmony_ciusing tcu::IVec2;
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ciusing namespace eglw;
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_cinamespace deqp
60e5c31af7Sopenharmony_ci{
61e5c31af7Sopenharmony_cinamespace egl
62e5c31af7Sopenharmony_ci{
63e5c31af7Sopenharmony_cinamespace
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_citypedef	tcu::Vector<GLubyte, 3> Color;
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_cienum DrawType
69e5c31af7Sopenharmony_ci{
70e5c31af7Sopenharmony_ci    DRAWTYPE_GLES2_CLEAR,
71e5c31af7Sopenharmony_ci    DRAWTYPE_GLES2_RENDER
72e5c31af7Sopenharmony_ci};
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_cienum ResizeType
75e5c31af7Sopenharmony_ci{
76e5c31af7Sopenharmony_ci	RESIZETYPE_NONE = 0,
77e5c31af7Sopenharmony_ci	RESIZETYPE_BEFORE_SWAP,
78e5c31af7Sopenharmony_ci	RESIZETYPE_AFTER_SWAP,
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ci	RESIZETYPE_LAST
81e5c31af7Sopenharmony_ci};
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_cistruct ColoredRect
84e5c31af7Sopenharmony_ci{
85e5c31af7Sopenharmony_cipublic:
86e5c31af7Sopenharmony_ci				ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_);
87e5c31af7Sopenharmony_ci	IVec2		bottomLeft;
88e5c31af7Sopenharmony_ci	IVec2		topRight;
89e5c31af7Sopenharmony_ci	Color		color;
90e5c31af7Sopenharmony_ci};
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ciColoredRect::ColoredRect (const IVec2& bottomLeft_, const IVec2& topRight_, const Color& color_)
93e5c31af7Sopenharmony_ci	: bottomLeft	(bottomLeft_)
94e5c31af7Sopenharmony_ci	, topRight		(topRight_)
95e5c31af7Sopenharmony_ci	, color			(color_)
96e5c31af7Sopenharmony_ci{
97e5c31af7Sopenharmony_ci}
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_cistruct DrawCommand
100e5c31af7Sopenharmony_ci{
101e5c31af7Sopenharmony_ci				DrawCommand (DrawType drawType_, const ColoredRect& rect_);
102e5c31af7Sopenharmony_ci    DrawType	drawType;
103e5c31af7Sopenharmony_ci	ColoredRect	rect;
104e5c31af7Sopenharmony_ci};
105e5c31af7Sopenharmony_ci
106e5c31af7Sopenharmony_ciDrawCommand::DrawCommand (DrawType drawType_, const ColoredRect& rect_)
107e5c31af7Sopenharmony_ci	: drawType	(drawType_)
108e5c31af7Sopenharmony_ci	, rect		(rect_)
109e5c31af7Sopenharmony_ci{
110e5c31af7Sopenharmony_ci}
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_cistruct Frame
113e5c31af7Sopenharmony_ci{
114e5c31af7Sopenharmony_ci						Frame (int width_, int height_);
115e5c31af7Sopenharmony_ci	int					width;
116e5c31af7Sopenharmony_ci	int					height;
117e5c31af7Sopenharmony_ci	vector<DrawCommand> draws;
118e5c31af7Sopenharmony_ci};
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ciFrame::Frame (int width_, int height_)
121e5c31af7Sopenharmony_ci	: width (width_)
122e5c31af7Sopenharmony_ci	, height(height_)
123e5c31af7Sopenharmony_ci{
124e5c31af7Sopenharmony_ci}
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_citypedef vector<Frame> FrameSequence;
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci//helper function declaration
129e5c31af7Sopenharmony_ciEGLConfig		getEGLConfig					(const Library& egl, EGLDisplay eglDisplay, bool preserveBuffer);
130e5c31af7Sopenharmony_civoid			clearColorScreen				(const glw::Functions& gl, const tcu::Vec4& clearColor);
131e5c31af7Sopenharmony_cifloat			windowToDeviceCoordinates		(int x, int length);
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ciclass GLES2Renderer
134e5c31af7Sopenharmony_ci{
135e5c31af7Sopenharmony_cipublic:
136e5c31af7Sopenharmony_ci							GLES2Renderer		(const glw::Functions& gl);
137e5c31af7Sopenharmony_ci							~GLES2Renderer		(void);
138e5c31af7Sopenharmony_ci	void					render				(int width, int height, const Frame& frame) const;
139e5c31af7Sopenharmony_ci
140e5c31af7Sopenharmony_ciprivate:
141e5c31af7Sopenharmony_ci							GLES2Renderer		(const GLES2Renderer&);
142e5c31af7Sopenharmony_ci	GLES2Renderer&			operator=			(const GLES2Renderer&);
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ci	const glw::Functions&	m_gl;
145e5c31af7Sopenharmony_ci	glu::ShaderProgram		m_glProgram;
146e5c31af7Sopenharmony_ci	glw::GLuint				m_coordLoc;
147e5c31af7Sopenharmony_ci	glw::GLuint				m_colorLoc;
148e5c31af7Sopenharmony_ci};
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ci// generate sources for vertex and fragment buffer
151e5c31af7Sopenharmony_ciglu::ProgramSources getSources (void)
152e5c31af7Sopenharmony_ci{
153e5c31af7Sopenharmony_ci	const char* const vertexShaderSource =
154e5c31af7Sopenharmony_ci		"attribute mediump vec2 a_pos;\n"
155e5c31af7Sopenharmony_ci		"attribute mediump vec4 a_color;\n"
156e5c31af7Sopenharmony_ci		"varying mediump vec4 v_color;\n"
157e5c31af7Sopenharmony_ci		"void main(void)\n"
158e5c31af7Sopenharmony_ci		"{\n"
159e5c31af7Sopenharmony_ci		"\tv_color = a_color;\n"
160e5c31af7Sopenharmony_ci		"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
161e5c31af7Sopenharmony_ci		"}";
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci	const char* const fragmentShaderSource =
164e5c31af7Sopenharmony_ci		"varying mediump vec4 v_color;\n"
165e5c31af7Sopenharmony_ci		"void main(void)\n"
166e5c31af7Sopenharmony_ci		"{\n"
167e5c31af7Sopenharmony_ci		"\tgl_FragColor = v_color;\n"
168e5c31af7Sopenharmony_ci		"}";
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ci	return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource);
171e5c31af7Sopenharmony_ci}
172e5c31af7Sopenharmony_ci
173e5c31af7Sopenharmony_ciGLES2Renderer::GLES2Renderer (const glw::Functions& gl)
174e5c31af7Sopenharmony_ci	: m_gl        (gl)
175e5c31af7Sopenharmony_ci	, m_glProgram (gl, getSources())
176e5c31af7Sopenharmony_ci	, m_coordLoc  ((glw::GLuint)-1)
177e5c31af7Sopenharmony_ci	, m_colorLoc  ((glw::GLuint)-1)
178e5c31af7Sopenharmony_ci{
179e5c31af7Sopenharmony_ci	m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color");
180e5c31af7Sopenharmony_ci	m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos");
181e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations");
182e5c31af7Sopenharmony_ci}
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ciGLES2Renderer::~GLES2Renderer (void)
185e5c31af7Sopenharmony_ci{
186e5c31af7Sopenharmony_ci}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_civoid GLES2Renderer::render (int width, int height, const Frame& frame) const
189e5c31af7Sopenharmony_ci{
190e5c31af7Sopenharmony_ci	for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
191e5c31af7Sopenharmony_ci	{
192e5c31af7Sopenharmony_ci		const ColoredRect& coloredRect = frame.draws[drawNdx].rect;
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_ci		if (frame.draws[drawNdx].drawType == DRAWTYPE_GLES2_RENDER)
195e5c31af7Sopenharmony_ci		{
196e5c31af7Sopenharmony_ci			const float x1 = windowToDeviceCoordinates(coloredRect.bottomLeft.x(), width);
197e5c31af7Sopenharmony_ci			const float y1 = windowToDeviceCoordinates(coloredRect.bottomLeft.y(), height);
198e5c31af7Sopenharmony_ci			const float x2 = windowToDeviceCoordinates(coloredRect.topRight.x(), width);
199e5c31af7Sopenharmony_ci			const float y2 = windowToDeviceCoordinates(coloredRect.topRight.y(), height);
200e5c31af7Sopenharmony_ci
201e5c31af7Sopenharmony_ci			const glw::GLfloat coords[] =
202e5c31af7Sopenharmony_ci			{
203e5c31af7Sopenharmony_ci				x1, y1,
204e5c31af7Sopenharmony_ci				x1, y2,
205e5c31af7Sopenharmony_ci				x2, y2,
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci				x2, y2,
208e5c31af7Sopenharmony_ci				x2, y1,
209e5c31af7Sopenharmony_ci				x1, y1,
210e5c31af7Sopenharmony_ci			};
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci			const glw::GLubyte colors[] =
213e5c31af7Sopenharmony_ci			{
214e5c31af7Sopenharmony_ci				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
215e5c31af7Sopenharmony_ci				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
216e5c31af7Sopenharmony_ci				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
219e5c31af7Sopenharmony_ci				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
220e5c31af7Sopenharmony_ci				coloredRect.color.x(), coloredRect.color.y(), coloredRect.color.z(), 255,
221e5c31af7Sopenharmony_ci			};
222e5c31af7Sopenharmony_ci
223e5c31af7Sopenharmony_ci			m_gl.useProgram(m_glProgram.getProgram());
224e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
225e5c31af7Sopenharmony_ci
226e5c31af7Sopenharmony_ci			m_gl.enableVertexAttribArray(m_coordLoc);
227e5c31af7Sopenharmony_ci			m_gl.enableVertexAttribArray(m_colorLoc);
228e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes");
229e5c31af7Sopenharmony_ci
230e5c31af7Sopenharmony_ci			m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords);
231e5c31af7Sopenharmony_ci			m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors);
232e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers");
233e5c31af7Sopenharmony_ci
234e5c31af7Sopenharmony_ci			m_gl.drawArrays(GL_TRIANGLES, 0, DE_LENGTH_OF_ARRAY(coords)/2);
235e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays(), failed");
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci			m_gl.disableVertexAttribArray(m_coordLoc);
238e5c31af7Sopenharmony_ci			m_gl.disableVertexAttribArray(m_colorLoc);
239e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes");
240e5c31af7Sopenharmony_ci
241e5c31af7Sopenharmony_ci			m_gl.useProgram(0);
242e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
243e5c31af7Sopenharmony_ci		}
244e5c31af7Sopenharmony_ci		else if (frame.draws[drawNdx].drawType == DRAWTYPE_GLES2_CLEAR)
245e5c31af7Sopenharmony_ci		{
246e5c31af7Sopenharmony_ci			m_gl.enable(GL_SCISSOR_TEST);
247e5c31af7Sopenharmony_ci			m_gl.scissor(coloredRect.bottomLeft.x(), coloredRect.bottomLeft.y(),
248e5c31af7Sopenharmony_ci						 coloredRect.topRight.x()-coloredRect.bottomLeft.x(), coloredRect.topRight.y()-coloredRect.bottomLeft.y());
249e5c31af7Sopenharmony_ci			m_gl.clearColor(coloredRect.color.x()/255.0f, coloredRect.color.y()/255.0f, coloredRect.color.z()/255.0f, 1.0f);
250e5c31af7Sopenharmony_ci			m_gl.clear(GL_COLOR_BUFFER_BIT);
251e5c31af7Sopenharmony_ci			m_gl.disable(GL_SCISSOR_TEST);
252e5c31af7Sopenharmony_ci		}
253e5c31af7Sopenharmony_ci		else
254e5c31af7Sopenharmony_ci			DE_FATAL("Invalid drawtype");
255e5c31af7Sopenharmony_ci	}
256e5c31af7Sopenharmony_ci}
257e5c31af7Sopenharmony_ci
258e5c31af7Sopenharmony_ciclass SwapBuffersWithDamageTest : public TestCase
259e5c31af7Sopenharmony_ci{
260e5c31af7Sopenharmony_cipublic:
261e5c31af7Sopenharmony_ci								SwapBuffersWithDamageTest		(EglTestContext&			eglTestCtx,
262e5c31af7Sopenharmony_ci																 const vector<DrawType>&	frameDrawType,
263e5c31af7Sopenharmony_ci																 int						iterationTimes,
264e5c31af7Sopenharmony_ci																 ResizeType					resizeType,
265e5c31af7Sopenharmony_ci																 const char*				name,
266e5c31af7Sopenharmony_ci																 const char*				description);
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci								~SwapBuffersWithDamageTest		(void);
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci	virtual void				init							(void);
271e5c31af7Sopenharmony_ci	void						deinit							(void);
272e5c31af7Sopenharmony_ci	virtual IterateResult		iterate							(void);
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_ciprotected:
275e5c31af7Sopenharmony_ci	virtual EGLConfig			getConfig						(const Library& egl, EGLDisplay eglDisplay);
276e5c31af7Sopenharmony_ci	virtual void				checkExtension					(const Library& egl, EGLDisplay eglDisplay);
277e5c31af7Sopenharmony_ci	void						initEGLSurface					(EGLConfig config);
278e5c31af7Sopenharmony_ci	void						initEGLContext					(EGLConfig config);
279e5c31af7Sopenharmony_ci
280e5c31af7Sopenharmony_ci	eglu::NativeWindow*			m_window;
281e5c31af7Sopenharmony_ci	EGLConfig					m_eglConfig;
282e5c31af7Sopenharmony_ci	EGLContext					m_eglContext;
283e5c31af7Sopenharmony_ci	const int					m_seed;
284e5c31af7Sopenharmony_ci	const int					m_iterationTimes;
285e5c31af7Sopenharmony_ci	const vector<DrawType>		m_frameDrawType;
286e5c31af7Sopenharmony_ci	const ResizeType			m_resizeType;
287e5c31af7Sopenharmony_ci	EGLDisplay					m_eglDisplay;
288e5c31af7Sopenharmony_ci	EGLSurface					m_eglSurface;
289e5c31af7Sopenharmony_ci	glw::Functions				m_gl;
290e5c31af7Sopenharmony_ci	GLES2Renderer*				m_gles2Renderer;
291e5c31af7Sopenharmony_ci};
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_ciSwapBuffersWithDamageTest::SwapBuffersWithDamageTest (EglTestContext& eglTestCtx, const vector<DrawType>& frameDrawType, int iterationTimes, ResizeType resizeType, const char* name, const char* description)
294e5c31af7Sopenharmony_ci	: TestCase			(eglTestCtx, name, description)
295e5c31af7Sopenharmony_ci	, m_window			(DE_NULL)
296e5c31af7Sopenharmony_ci	, m_eglContext		(EGL_NO_CONTEXT)
297e5c31af7Sopenharmony_ci	, m_seed			(deStringHash(name))
298e5c31af7Sopenharmony_ci	, m_iterationTimes	(iterationTimes)
299e5c31af7Sopenharmony_ci	, m_frameDrawType	(frameDrawType)
300e5c31af7Sopenharmony_ci	, m_resizeType		(resizeType)
301e5c31af7Sopenharmony_ci	, m_eglDisplay		(EGL_NO_DISPLAY)
302e5c31af7Sopenharmony_ci	, m_eglSurface		(EGL_NO_SURFACE)
303e5c31af7Sopenharmony_ci	, m_gles2Renderer	 (DE_NULL)
304e5c31af7Sopenharmony_ci{
305e5c31af7Sopenharmony_ci}
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ciSwapBuffersWithDamageTest::~SwapBuffersWithDamageTest (void)
308e5c31af7Sopenharmony_ci{
309e5c31af7Sopenharmony_ci	deinit();
310e5c31af7Sopenharmony_ci}
311e5c31af7Sopenharmony_ci
312e5c31af7Sopenharmony_ciEGLConfig SwapBuffersWithDamageTest::getConfig (const Library& egl, EGLDisplay eglDisplay)
313e5c31af7Sopenharmony_ci{
314e5c31af7Sopenharmony_ci	return getEGLConfig(egl, eglDisplay, false);
315e5c31af7Sopenharmony_ci}
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_civoid SwapBuffersWithDamageTest::checkExtension (const Library& egl, EGLDisplay eglDisplay)
318e5c31af7Sopenharmony_ci{
319e5c31af7Sopenharmony_ci	if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage"))
320e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported");
321e5c31af7Sopenharmony_ci}
322e5c31af7Sopenharmony_ci
323e5c31af7Sopenharmony_civoid SwapBuffersWithDamageTest::init (void)
324e5c31af7Sopenharmony_ci{
325e5c31af7Sopenharmony_ci	const Library& egl = m_eglTestCtx.getLibrary();
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ci	m_eglDisplay = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
328e5c31af7Sopenharmony_ci	m_eglConfig  = getConfig(egl, m_eglDisplay);
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci	checkExtension(egl, m_eglDisplay);
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	initEGLSurface(m_eglConfig);
333e5c31af7Sopenharmony_ci	initEGLContext(m_eglConfig);
334e5c31af7Sopenharmony_ci
335e5c31af7Sopenharmony_ci	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
336e5c31af7Sopenharmony_ci	m_gles2Renderer = new GLES2Renderer(m_gl);
337e5c31af7Sopenharmony_ci}
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_civoid SwapBuffersWithDamageTest::deinit (void)
340e5c31af7Sopenharmony_ci{
341e5c31af7Sopenharmony_ci	const Library& egl = m_eglTestCtx.getLibrary();
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_ci	delete m_gles2Renderer;
344e5c31af7Sopenharmony_ci	m_gles2Renderer = DE_NULL;
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci	if (m_eglContext != EGL_NO_CONTEXT)
347e5c31af7Sopenharmony_ci	{
348e5c31af7Sopenharmony_ci		egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
349e5c31af7Sopenharmony_ci		egl.destroyContext(m_eglDisplay, m_eglContext);
350e5c31af7Sopenharmony_ci		m_eglContext = EGL_NO_CONTEXT;
351e5c31af7Sopenharmony_ci	}
352e5c31af7Sopenharmony_ci
353e5c31af7Sopenharmony_ci	if (m_eglSurface != EGL_NO_SURFACE)
354e5c31af7Sopenharmony_ci	{
355e5c31af7Sopenharmony_ci		egl.destroySurface(m_eglDisplay, m_eglSurface);
356e5c31af7Sopenharmony_ci		m_eglSurface = EGL_NO_SURFACE;
357e5c31af7Sopenharmony_ci	}
358e5c31af7Sopenharmony_ci
359e5c31af7Sopenharmony_ci	if (m_eglDisplay != EGL_NO_DISPLAY)
360e5c31af7Sopenharmony_ci	{
361e5c31af7Sopenharmony_ci		egl.terminate(m_eglDisplay);
362e5c31af7Sopenharmony_ci		m_eglDisplay = EGL_NO_DISPLAY;
363e5c31af7Sopenharmony_ci	}
364e5c31af7Sopenharmony_ci
365e5c31af7Sopenharmony_ci	delete m_window;
366e5c31af7Sopenharmony_ci	m_window = DE_NULL;
367e5c31af7Sopenharmony_ci}
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_civoid SwapBuffersWithDamageTest::initEGLSurface (EGLConfig config)
370e5c31af7Sopenharmony_ci{
371e5c31af7Sopenharmony_ci	const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
372e5c31af7Sopenharmony_ci	m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL,
373e5c31af7Sopenharmony_ci									eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
374e5c31af7Sopenharmony_ci	m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL);
375e5c31af7Sopenharmony_ci}
376e5c31af7Sopenharmony_ci
377e5c31af7Sopenharmony_civoid SwapBuffersWithDamageTest::initEGLContext (EGLConfig config)
378e5c31af7Sopenharmony_ci{
379e5c31af7Sopenharmony_ci	const Library&	egl			 = m_eglTestCtx.getLibrary();
380e5c31af7Sopenharmony_ci	const EGLint	attribList[] =
381e5c31af7Sopenharmony_ci	{
382e5c31af7Sopenharmony_ci		EGL_CONTEXT_CLIENT_VERSION, 2,
383e5c31af7Sopenharmony_ci		EGL_NONE
384e5c31af7Sopenharmony_ci	};
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci	egl.bindAPI(EGL_OPENGL_ES_API);
387e5c31af7Sopenharmony_ci	m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList);
388e5c31af7Sopenharmony_ci	EGLU_CHECK_MSG(egl, "eglCreateContext");
389e5c31af7Sopenharmony_ci	TCU_CHECK(m_eglSurface != EGL_NO_SURFACE);
390e5c31af7Sopenharmony_ci	egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
391e5c31af7Sopenharmony_ci	EGLU_CHECK_MSG(egl, "eglMakeCurrent");
392e5c31af7Sopenharmony_ci}
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ciFrameSequence	generateFrameSequence	(const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height);
395e5c31af7Sopenharmony_civector<EGLint>	getDamageRegion			(const Frame& frame);
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ciTestCase::IterateResult SwapBuffersWithDamageTest::iterate (void)
398e5c31af7Sopenharmony_ci{
399e5c31af7Sopenharmony_ci	de::Random			rnd				(m_seed);
400e5c31af7Sopenharmony_ci	const Library&		egl				= m_eglTestCtx.getLibrary();
401e5c31af7Sopenharmony_ci	const int			width			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
402e5c31af7Sopenharmony_ci	const int			height			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
403e5c31af7Sopenharmony_ci	const float			clearRed		= rnd.getFloat();
404e5c31af7Sopenharmony_ci	const float			clearGreen		= rnd.getFloat();
405e5c31af7Sopenharmony_ci	const float			clearBlue		= rnd.getFloat();
406e5c31af7Sopenharmony_ci	const tcu::Vec4		clearColor		(clearRed, clearGreen, clearBlue, 1.0f);
407e5c31af7Sopenharmony_ci	const int			numFrames		= 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
408e5c31af7Sopenharmony_ci	const FrameSequence frameSequence	= generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
411e5c31af7Sopenharmony_ci	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
412e5c31af7Sopenharmony_ci
413e5c31af7Sopenharmony_ci	for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
414e5c31af7Sopenharmony_ci	{
415e5c31af7Sopenharmony_ci		for (int currentFrameNdx = 0; currentFrameNdx < numFrames; currentFrameNdx++)
416e5c31af7Sopenharmony_ci		{
417e5c31af7Sopenharmony_ci			vector<EGLint>	damageRegion = getDamageRegion(frameSequence[currentFrameNdx]);
418e5c31af7Sopenharmony_ci
419e5c31af7Sopenharmony_ci			clearColorScreen(m_gl, clearColor);
420e5c31af7Sopenharmony_ci			for (int ndx = 0; ndx <= currentFrameNdx; ndx++)
421e5c31af7Sopenharmony_ci				m_gles2Renderer->render(width, height, frameSequence[ndx]);
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ci			if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
424e5c31af7Sopenharmony_ci			{
425e5c31af7Sopenharmony_ci				if (currentFrameNdx % 2 == 0)
426e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(width*2, height/2));
427e5c31af7Sopenharmony_ci				else
428e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(height/2, width*2));
429e5c31af7Sopenharmony_ci			}
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci			EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
432e5c31af7Sopenharmony_ci
433e5c31af7Sopenharmony_ci			if (m_resizeType == RESIZETYPE_AFTER_SWAP)
434e5c31af7Sopenharmony_ci			{
435e5c31af7Sopenharmony_ci				if (currentFrameNdx % 2 == 0)
436e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(width*2, height/2));
437e5c31af7Sopenharmony_ci				else
438e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(height/2, width*2));
439e5c31af7Sopenharmony_ci			}
440e5c31af7Sopenharmony_ci		}
441e5c31af7Sopenharmony_ci	}
442e5c31af7Sopenharmony_ci	return STOP;
443e5c31af7Sopenharmony_ci}
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_ciclass SwapBuffersWithDamageAndPreserveBufferTest : public SwapBuffersWithDamageTest
446e5c31af7Sopenharmony_ci{
447e5c31af7Sopenharmony_cipublic:
448e5c31af7Sopenharmony_ci					SwapBuffersWithDamageAndPreserveBufferTest	(EglTestContext&			eglTestCtx,
449e5c31af7Sopenharmony_ci																 const vector<DrawType>&	frameDrawType,
450e5c31af7Sopenharmony_ci																 int						iterationTimes,
451e5c31af7Sopenharmony_ci																 ResizeType					resizeType,
452e5c31af7Sopenharmony_ci																 const char*				name,
453e5c31af7Sopenharmony_ci																 const char*				description);
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci	IterateResult	iterate										(void);
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ciprotected:
458e5c31af7Sopenharmony_ci	EGLConfig		getConfig									(const Library& egl, EGLDisplay eglDisplay);
459e5c31af7Sopenharmony_ci};
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ciSwapBuffersWithDamageAndPreserveBufferTest::SwapBuffersWithDamageAndPreserveBufferTest (EglTestContext&			eglTestCtx,
462e5c31af7Sopenharmony_ci																						const vector<DrawType>&	frameDrawType,
463e5c31af7Sopenharmony_ci																						int						iterationTimes,
464e5c31af7Sopenharmony_ci																						ResizeType				resizeType,
465e5c31af7Sopenharmony_ci																						const char*				name,
466e5c31af7Sopenharmony_ci																						const char*				description)
467e5c31af7Sopenharmony_ci	: SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, resizeType, name, description)
468e5c31af7Sopenharmony_ci{
469e5c31af7Sopenharmony_ci}
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ciEGLConfig SwapBuffersWithDamageAndPreserveBufferTest::getConfig (const Library& egl, EGLDisplay eglDisplay)
472e5c31af7Sopenharmony_ci{
473e5c31af7Sopenharmony_ci	return getEGLConfig(egl, eglDisplay, true);
474e5c31af7Sopenharmony_ci}
475e5c31af7Sopenharmony_ci
476e5c31af7Sopenharmony_ciTestCase::IterateResult SwapBuffersWithDamageAndPreserveBufferTest::iterate (void)
477e5c31af7Sopenharmony_ci{
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci	de::Random			rnd				(m_seed);
480e5c31af7Sopenharmony_ci	const Library&		egl				= m_eglTestCtx.getLibrary();
481e5c31af7Sopenharmony_ci	const int			width			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
482e5c31af7Sopenharmony_ci	const int			height			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
483e5c31af7Sopenharmony_ci	const float			clearRed		= rnd.getFloat();
484e5c31af7Sopenharmony_ci	const float			clearGreen		= rnd.getFloat();
485e5c31af7Sopenharmony_ci	const float			clearBlue		= rnd.getFloat();
486e5c31af7Sopenharmony_ci	const tcu::Vec4		clearColor		(clearRed, clearGreen, clearBlue, 1.0f);
487e5c31af7Sopenharmony_ci	const int			numFrames		= 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
488e5c31af7Sopenharmony_ci	const FrameSequence frameSequence	= generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
491e5c31af7Sopenharmony_ci	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED));
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ci	for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
494e5c31af7Sopenharmony_ci	{
495e5c31af7Sopenharmony_ci		clearColorScreen(m_gl, clearColor);
496e5c31af7Sopenharmony_ci		EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0));
497e5c31af7Sopenharmony_ci
498e5c31af7Sopenharmony_ci		for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
499e5c31af7Sopenharmony_ci		{
500e5c31af7Sopenharmony_ci			const Frame&	currentFrame = frameSequence[frameNdx];
501e5c31af7Sopenharmony_ci			vector<EGLint>	damageRegion = getDamageRegion(currentFrame);
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci			m_gles2Renderer->render(width, height, currentFrame);
504e5c31af7Sopenharmony_ci
505e5c31af7Sopenharmony_ci			if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
506e5c31af7Sopenharmony_ci			{
507e5c31af7Sopenharmony_ci				if (frameNdx % 2 == 0)
508e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(width*2, height/2));
509e5c31af7Sopenharmony_ci				else
510e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(height/2, width*2));
511e5c31af7Sopenharmony_ci			}
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci			EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ci			if (m_resizeType == RESIZETYPE_AFTER_SWAP)
516e5c31af7Sopenharmony_ci			{
517e5c31af7Sopenharmony_ci				if (frameNdx % 2 == 0)
518e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(width*2, height/2));
519e5c31af7Sopenharmony_ci				else
520e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(height/2, width*2));
521e5c31af7Sopenharmony_ci			}
522e5c31af7Sopenharmony_ci		}
523e5c31af7Sopenharmony_ci	}
524e5c31af7Sopenharmony_ci
525e5c31af7Sopenharmony_ci	return STOP;
526e5c31af7Sopenharmony_ci}
527e5c31af7Sopenharmony_ci
528e5c31af7Sopenharmony_ciclass SwapBuffersWithDamageAndBufferAgeTest : public SwapBuffersWithDamageTest
529e5c31af7Sopenharmony_ci{
530e5c31af7Sopenharmony_cipublic:
531e5c31af7Sopenharmony_ci					SwapBuffersWithDamageAndBufferAgeTest	(EglTestContext&			eglTestCtx,
532e5c31af7Sopenharmony_ci															 const vector<DrawType>&	frameDrawType,
533e5c31af7Sopenharmony_ci															 int						iterationTimes,
534e5c31af7Sopenharmony_ci															 ResizeType					resizeType,
535e5c31af7Sopenharmony_ci															 const char*				name,
536e5c31af7Sopenharmony_ci															 const char*				description);
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ci	IterateResult	iterate									(void);
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_ciprotected:
541e5c31af7Sopenharmony_ci	void			checkExtension							(const Library& egl, EGLDisplay eglDisplay);
542e5c31af7Sopenharmony_ci};
543e5c31af7Sopenharmony_ci
544e5c31af7Sopenharmony_ciSwapBuffersWithDamageAndBufferAgeTest::SwapBuffersWithDamageAndBufferAgeTest (EglTestContext&			eglTestCtx,
545e5c31af7Sopenharmony_ci																			  const vector<DrawType>&	frameDrawType,
546e5c31af7Sopenharmony_ci																			  int						iterationTimes,
547e5c31af7Sopenharmony_ci																			  ResizeType				resizeType,
548e5c31af7Sopenharmony_ci																			  const char*				name,
549e5c31af7Sopenharmony_ci																			  const char*				description)
550e5c31af7Sopenharmony_ci	: SwapBuffersWithDamageTest (eglTestCtx, frameDrawType, iterationTimes, resizeType, name, description)
551e5c31af7Sopenharmony_ci{
552e5c31af7Sopenharmony_ci}
553e5c31af7Sopenharmony_ci
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_civoid SwapBuffersWithDamageAndBufferAgeTest::checkExtension (const Library& egl, EGLDisplay eglDisplay)
556e5c31af7Sopenharmony_ci{
557e5c31af7Sopenharmony_ci	if (!eglu::hasExtension(egl, eglDisplay, "EGL_KHR_swap_buffers_with_damage"))
558e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "EGL_KHR_swap_buffers_with_damage is not supported");
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci	if (!eglu::hasExtension(egl, eglDisplay, "EGL_EXT_buffer_age"))
561e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "EGL_EXT_buffer_age not supported");
562e5c31af7Sopenharmony_ci}
563e5c31af7Sopenharmony_ci
564e5c31af7Sopenharmony_ciTestCase::IterateResult SwapBuffersWithDamageAndBufferAgeTest::iterate (void)
565e5c31af7Sopenharmony_ci{
566e5c31af7Sopenharmony_ci
567e5c31af7Sopenharmony_ci	de::Random			rnd				(m_seed);
568e5c31af7Sopenharmony_ci	const Library&		egl				= m_eglTestCtx.getLibrary();
569e5c31af7Sopenharmony_ci	const int			width			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
570e5c31af7Sopenharmony_ci	const int			height			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
571e5c31af7Sopenharmony_ci	const float			clearRed		= rnd.getFloat();
572e5c31af7Sopenharmony_ci	const float			clearGreen		= rnd.getFloat();
573e5c31af7Sopenharmony_ci	const float			clearBlue		= rnd.getFloat();
574e5c31af7Sopenharmony_ci	const tcu::Vec4		clearColor		(clearRed, clearGreen, clearBlue, 1.0f);
575e5c31af7Sopenharmony_ci	const int			numFrames		= 24; // (width, height) = (480, 480) --> numFrame = 24, divisible
576e5c31af7Sopenharmony_ci	const FrameSequence frameSequence	= generateFrameSequence(m_frameDrawType, rnd, numFrames, width, height);
577e5c31af7Sopenharmony_ci
578e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
579e5c31af7Sopenharmony_ci	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED));
580e5c31af7Sopenharmony_ci
581e5c31af7Sopenharmony_ci	for (int iterationNdx = 0; iterationNdx < m_iterationTimes; iterationNdx++)
582e5c31af7Sopenharmony_ci	{
583e5c31af7Sopenharmony_ci		clearColorScreen(m_gl, clearColor);
584e5c31af7Sopenharmony_ci		EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, DE_NULL, 0));
585e5c31af7Sopenharmony_ci
586e5c31af7Sopenharmony_ci		for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
587e5c31af7Sopenharmony_ci		{
588e5c31af7Sopenharmony_ci			vector<EGLint>	damageRegion;
589e5c31af7Sopenharmony_ci			int				bufferAge		= -1;
590e5c31af7Sopenharmony_ci			int				startFrameNdx	= -1;
591e5c31af7Sopenharmony_ci			int				endFrameNdx		= frameNdx;
592e5c31af7Sopenharmony_ci
593e5c31af7Sopenharmony_ci			EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_BUFFER_AGE_EXT, &bufferAge));
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci			if (bufferAge < 0) // invalid buffer age
596e5c31af7Sopenharmony_ci			{
597e5c31af7Sopenharmony_ci				std::ostringstream stream;
598e5c31af7Sopenharmony_ci				stream << "Fail, the age is invalid. Age: " << bufferAge << ", frameNdx: " << frameNdx;
599e5c31af7Sopenharmony_ci				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, stream.str().c_str());
600e5c31af7Sopenharmony_ci				return STOP;
601e5c31af7Sopenharmony_ci			}
602e5c31af7Sopenharmony_ci
603e5c31af7Sopenharmony_ci			if (bufferAge == 0 || bufferAge > frameNdx)
604e5c31af7Sopenharmony_ci			{
605e5c31af7Sopenharmony_ci				clearColorScreen(m_gl, clearColor);
606e5c31af7Sopenharmony_ci				startFrameNdx = 0;
607e5c31af7Sopenharmony_ci			}
608e5c31af7Sopenharmony_ci			else
609e5c31af7Sopenharmony_ci				startFrameNdx = frameNdx-bufferAge+1;
610e5c31af7Sopenharmony_ci
611e5c31af7Sopenharmony_ci			for (int ndx = startFrameNdx; ndx <= endFrameNdx; ndx++)
612e5c31af7Sopenharmony_ci			{
613e5c31af7Sopenharmony_ci				const vector<EGLint> partialDamageRegion = getDamageRegion(frameSequence[ndx]);
614e5c31af7Sopenharmony_ci
615e5c31af7Sopenharmony_ci				damageRegion.insert(damageRegion.end(), partialDamageRegion.begin(), partialDamageRegion.end());
616e5c31af7Sopenharmony_ci				m_gles2Renderer->render(width, height, frameSequence[ndx]);
617e5c31af7Sopenharmony_ci			}
618e5c31af7Sopenharmony_ci
619e5c31af7Sopenharmony_ci			if (m_resizeType == RESIZETYPE_BEFORE_SWAP)
620e5c31af7Sopenharmony_ci			{
621e5c31af7Sopenharmony_ci				if (frameNdx % 2 == 0)
622e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(width*2, height/2));
623e5c31af7Sopenharmony_ci				else
624e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(height/2, width*2));
625e5c31af7Sopenharmony_ci			}
626e5c31af7Sopenharmony_ci
627e5c31af7Sopenharmony_ci			EGLU_CHECK_CALL(egl, swapBuffersWithDamageKHR(m_eglDisplay, m_eglSurface, &damageRegion[0], (EGLint)damageRegion.size()/4));
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_ci			if (m_resizeType == RESIZETYPE_AFTER_SWAP)
630e5c31af7Sopenharmony_ci			{
631e5c31af7Sopenharmony_ci				if (frameNdx % 2 == 0)
632e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(width*2, height/2));
633e5c31af7Sopenharmony_ci				else
634e5c31af7Sopenharmony_ci					m_window->setSurfaceSize(IVec2(height/2, width*2));
635e5c31af7Sopenharmony_ci			}
636e5c31af7Sopenharmony_ci		}
637e5c31af7Sopenharmony_ci	}
638e5c31af7Sopenharmony_ci	return STOP;
639e5c31af7Sopenharmony_ci}
640e5c31af7Sopenharmony_ci
641e5c31af7Sopenharmony_ci// generate a frame sequence with certain frame for visual verification
642e5c31af7Sopenharmony_ciFrameSequence generateFrameSequence (const vector<DrawType>& frameDrawType, de::Random& rnd, int numFrames, int width, int height)
643e5c31af7Sopenharmony_ci{
644e5c31af7Sopenharmony_ci	const int			frameDiff		= height / numFrames;
645e5c31af7Sopenharmony_ci	const GLubyte		r				= rnd.getUint8();
646e5c31af7Sopenharmony_ci	const GLubyte		g				= rnd.getUint8();
647e5c31af7Sopenharmony_ci	const GLubyte		b				= rnd.getUint8();
648e5c31af7Sopenharmony_ci	const Color			color			(r, g, b);
649e5c31af7Sopenharmony_ci	FrameSequence		frameSequence;
650e5c31af7Sopenharmony_ci
651e5c31af7Sopenharmony_ci	for (int frameNdx = 0; frameNdx < numFrames; frameNdx++)
652e5c31af7Sopenharmony_ci	{
653e5c31af7Sopenharmony_ci		Frame frame (width, height);
654e5c31af7Sopenharmony_ci
655e5c31af7Sopenharmony_ci		for (int rectNdx = 0; rectNdx < (int)frameDrawType.size(); rectNdx++)
656e5c31af7Sopenharmony_ci		{
657e5c31af7Sopenharmony_ci			const int			rectHeight		= frameDiff / (int)frameDrawType.size();
658e5c31af7Sopenharmony_ci			const ColoredRect	rect			(IVec2(0, frameNdx*frameDiff+rectNdx*rectHeight), IVec2(width, frameNdx*frameDiff+(rectNdx+1)*rectHeight), color);
659e5c31af7Sopenharmony_ci			const DrawCommand	drawCommand		(frameDrawType[rectNdx], rect);
660e5c31af7Sopenharmony_ci
661e5c31af7Sopenharmony_ci			frame.draws.push_back(drawCommand);
662e5c31af7Sopenharmony_ci		}
663e5c31af7Sopenharmony_ci		frameSequence.push_back(frame);
664e5c31af7Sopenharmony_ci	}
665e5c31af7Sopenharmony_ci	return frameSequence;
666e5c31af7Sopenharmony_ci}
667e5c31af7Sopenharmony_ci
668e5c31af7Sopenharmony_civector<EGLint> getDamageRegion (const Frame& frame)
669e5c31af7Sopenharmony_ci{
670e5c31af7Sopenharmony_ci	vector<EGLint> damageRegion;
671e5c31af7Sopenharmony_ci	for (size_t drawNdx = 0; drawNdx < frame.draws.size(); drawNdx++)
672e5c31af7Sopenharmony_ci	{
673e5c31af7Sopenharmony_ci		const ColoredRect& rect = frame.draws[drawNdx].rect;
674e5c31af7Sopenharmony_ci		damageRegion.push_back(rect.bottomLeft.x());
675e5c31af7Sopenharmony_ci		damageRegion.push_back(rect.bottomLeft.y());
676e5c31af7Sopenharmony_ci		damageRegion.push_back(rect.topRight.x() - rect.bottomLeft.x());
677e5c31af7Sopenharmony_ci		damageRegion.push_back(rect.topRight.y() - rect.bottomLeft.y());
678e5c31af7Sopenharmony_ci	}
679e5c31af7Sopenharmony_ci
680e5c31af7Sopenharmony_ci	DE_ASSERT(damageRegion.size() % 4 == 0);
681e5c31af7Sopenharmony_ci	return damageRegion;
682e5c31af7Sopenharmony_ci}
683e5c31af7Sopenharmony_ci
684e5c31af7Sopenharmony_cistring generateTestName (const vector<DrawType>& frameDrawType)
685e5c31af7Sopenharmony_ci{
686e5c31af7Sopenharmony_ci	std::ostringstream stream;
687e5c31af7Sopenharmony_ci
688e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < frameDrawType.size(); ndx++)
689e5c31af7Sopenharmony_ci	{
690e5c31af7Sopenharmony_ci		if (frameDrawType[ndx] == DRAWTYPE_GLES2_RENDER)
691e5c31af7Sopenharmony_ci			stream << "render";
692e5c31af7Sopenharmony_ci		else if (frameDrawType[ndx] == DRAWTYPE_GLES2_CLEAR)
693e5c31af7Sopenharmony_ci			stream << "clear";
694e5c31af7Sopenharmony_ci		else
695e5c31af7Sopenharmony_ci			DE_ASSERT(false);
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci		if (ndx < frameDrawType.size()-1)
698e5c31af7Sopenharmony_ci			stream << "_";
699e5c31af7Sopenharmony_ci	}
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_ci	return stream.str();
702e5c31af7Sopenharmony_ci}
703e5c31af7Sopenharmony_ci
704e5c31af7Sopenharmony_cistring generateResizeGroupName (ResizeType resizeType)
705e5c31af7Sopenharmony_ci{
706e5c31af7Sopenharmony_ci	switch (resizeType)
707e5c31af7Sopenharmony_ci	{
708e5c31af7Sopenharmony_ci		case RESIZETYPE_NONE:
709e5c31af7Sopenharmony_ci			return "no_resize";
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci		case RESIZETYPE_AFTER_SWAP:
712e5c31af7Sopenharmony_ci			return "resize_after_swap";
713e5c31af7Sopenharmony_ci
714e5c31af7Sopenharmony_ci		case RESIZETYPE_BEFORE_SWAP:
715e5c31af7Sopenharmony_ci			return "resize_before_swap";
716e5c31af7Sopenharmony_ci
717e5c31af7Sopenharmony_ci		default:
718e5c31af7Sopenharmony_ci			DE_FATAL("Unknown resize type");
719e5c31af7Sopenharmony_ci			return "";
720e5c31af7Sopenharmony_ci	}
721e5c31af7Sopenharmony_ci}
722e5c31af7Sopenharmony_ci
723e5c31af7Sopenharmony_cibool isWindow (const eglu::CandidateConfig& c)
724e5c31af7Sopenharmony_ci{
725e5c31af7Sopenharmony_ci	return (c.surfaceType() & EGL_WINDOW_BIT) == EGL_WINDOW_BIT;
726e5c31af7Sopenharmony_ci}
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_cibool isES2Renderable (const eglu::CandidateConfig& c)
729e5c31af7Sopenharmony_ci{
730e5c31af7Sopenharmony_ci	return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
731e5c31af7Sopenharmony_ci}
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_cibool hasPreserveSwap (const eglu::CandidateConfig& c)
734e5c31af7Sopenharmony_ci{
735e5c31af7Sopenharmony_ci	return (c.surfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
736e5c31af7Sopenharmony_ci}
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ciEGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveBuffer)
739e5c31af7Sopenharmony_ci{
740e5c31af7Sopenharmony_ci	eglu::FilterList filters;
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci	filters << isWindow << isES2Renderable;
743e5c31af7Sopenharmony_ci	if (preserveBuffer)
744e5c31af7Sopenharmony_ci		filters << hasPreserveSwap;
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_ci	return eglu::chooseSingleConfig(egl, eglDisplay, filters);
747e5c31af7Sopenharmony_ci}
748e5c31af7Sopenharmony_ci
749e5c31af7Sopenharmony_civoid clearColorScreen (const glw::Functions& gl, const tcu::Vec4& clearColor)
750e5c31af7Sopenharmony_ci{
751e5c31af7Sopenharmony_ci	gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
752e5c31af7Sopenharmony_ci	gl.clear(GL_COLOR_BUFFER_BIT);
753e5c31af7Sopenharmony_ci}
754e5c31af7Sopenharmony_ci
755e5c31af7Sopenharmony_cifloat windowToDeviceCoordinates (int x, int length)
756e5c31af7Sopenharmony_ci{
757e5c31af7Sopenharmony_ci	return (2.0f * float(x) / float(length)) - 1.0f;
758e5c31af7Sopenharmony_ci}
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_ci} // anonymous
761e5c31af7Sopenharmony_ci
762e5c31af7Sopenharmony_ciSwapBuffersWithDamageTests::SwapBuffersWithDamageTests (EglTestContext& eglTestCtx)
763e5c31af7Sopenharmony_ci	: TestCaseGroup(eglTestCtx, "swap_buffers_with_damage", "Swap buffers with damages tests")
764e5c31af7Sopenharmony_ci{
765e5c31af7Sopenharmony_ci}
766e5c31af7Sopenharmony_ci
767e5c31af7Sopenharmony_civoid SwapBuffersWithDamageTests::init (void)
768e5c31af7Sopenharmony_ci{
769e5c31af7Sopenharmony_ci	const DrawType clearRender[2] =
770e5c31af7Sopenharmony_ci	{
771e5c31af7Sopenharmony_ci		DRAWTYPE_GLES2_CLEAR,
772e5c31af7Sopenharmony_ci		DRAWTYPE_GLES2_RENDER
773e5c31af7Sopenharmony_ci	};
774e5c31af7Sopenharmony_ci
775e5c31af7Sopenharmony_ci	const DrawType renderClear[2] =
776e5c31af7Sopenharmony_ci	{
777e5c31af7Sopenharmony_ci		DRAWTYPE_GLES2_RENDER,
778e5c31af7Sopenharmony_ci		DRAWTYPE_GLES2_CLEAR
779e5c31af7Sopenharmony_ci	};
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci	const ResizeType resizeTypes[] =
782e5c31af7Sopenharmony_ci	{
783e5c31af7Sopenharmony_ci		RESIZETYPE_NONE,
784e5c31af7Sopenharmony_ci		RESIZETYPE_BEFORE_SWAP,
785e5c31af7Sopenharmony_ci		RESIZETYPE_AFTER_SWAP
786e5c31af7Sopenharmony_ci	};
787e5c31af7Sopenharmony_ci
788e5c31af7Sopenharmony_ci	vector< vector<DrawType> > frameDrawTypes;
789e5c31af7Sopenharmony_ci	frameDrawTypes.push_back(vector<DrawType> (1, DRAWTYPE_GLES2_CLEAR));
790e5c31af7Sopenharmony_ci	frameDrawTypes.push_back(vector<DrawType> (1, DRAWTYPE_GLES2_RENDER));
791e5c31af7Sopenharmony_ci	frameDrawTypes.push_back(vector<DrawType> (2, DRAWTYPE_GLES2_CLEAR));
792e5c31af7Sopenharmony_ci	frameDrawTypes.push_back(vector<DrawType> (2, DRAWTYPE_GLES2_RENDER));
793e5c31af7Sopenharmony_ci	frameDrawTypes.push_back(vector<DrawType> (DE_ARRAY_BEGIN(clearRender), DE_ARRAY_END(clearRender)));
794e5c31af7Sopenharmony_ci	frameDrawTypes.push_back(vector<DrawType> (DE_ARRAY_BEGIN(renderClear), DE_ARRAY_END(renderClear)));
795e5c31af7Sopenharmony_ci
796e5c31af7Sopenharmony_ci	for (size_t resizeTypeNdx = 0; resizeTypeNdx < DE_LENGTH_OF_ARRAY(resizeTypes); resizeTypeNdx++)
797e5c31af7Sopenharmony_ci	{
798e5c31af7Sopenharmony_ci		const ResizeType		resizeType	= resizeTypes[resizeTypeNdx];
799e5c31af7Sopenharmony_ci		TestCaseGroup* const	resizeGroup	= new TestCaseGroup(m_eglTestCtx, generateResizeGroupName(resizeType).c_str(), "");
800e5c31af7Sopenharmony_ci
801e5c31af7Sopenharmony_ci		for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
802e5c31af7Sopenharmony_ci		{
803e5c31af7Sopenharmony_ci			string name = generateTestName(frameDrawTypes[drawTypeNdx]);
804e5c31af7Sopenharmony_ci			resizeGroup->addChild(new SwapBuffersWithDamageTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, resizeType, name.c_str(), ""));
805e5c31af7Sopenharmony_ci		}
806e5c31af7Sopenharmony_ci
807e5c31af7Sopenharmony_ci		for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
808e5c31af7Sopenharmony_ci		{
809e5c31af7Sopenharmony_ci			string name = "preserve_buffer_" + generateTestName(frameDrawTypes[drawTypeNdx]);
810e5c31af7Sopenharmony_ci			resizeGroup->addChild(new SwapBuffersWithDamageAndPreserveBufferTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, resizeType, name.c_str(), ""));
811e5c31af7Sopenharmony_ci		}
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_ci		for (size_t drawTypeNdx = 0; drawTypeNdx < frameDrawTypes.size(); drawTypeNdx++)
814e5c31af7Sopenharmony_ci		{
815e5c31af7Sopenharmony_ci			string name = "buffer_age_" + generateTestName(frameDrawTypes[drawTypeNdx]);
816e5c31af7Sopenharmony_ci			resizeGroup->addChild(new SwapBuffersWithDamageAndBufferAgeTest(m_eglTestCtx, frameDrawTypes[drawTypeNdx], 4, resizeType, name.c_str(),  ""));
817e5c31af7Sopenharmony_ci		}
818e5c31af7Sopenharmony_ci
819e5c31af7Sopenharmony_ci		addChild(resizeGroup);
820e5c31af7Sopenharmony_ci	}
821e5c31af7Sopenharmony_ci}
822e5c31af7Sopenharmony_ci
823e5c31af7Sopenharmony_ci} // egl
824e5c31af7Sopenharmony_ci} // deqp
825