• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL Module
3  * ---------------------------------------
4  *
5  * Copyright 2016 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *       http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Test KHR_mutable_render_buffer
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglMutableRenderBufferTests.hpp"
25 
26 #include "egluUtil.hpp"
27 
28 #include "eglwLibrary.hpp"
29 #include "eglwEnums.hpp"
30 
31 #include "gluDefs.hpp"
32 #include "gluRenderContext.hpp"
33 
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 
37 using namespace eglw;
38 
39 using std::vector;
40 
41 namespace deqp
42 {
43 namespace egl
44 {
45 namespace
46 {
47 
48 class MutableRenderBufferTest : public TestCase
49 {
50 public:
51 						MutableRenderBufferTest		(EglTestContext&	eglTestCtx,
52 													 const char*		name,
53 													 const char*		description,
54 													 bool				enableConfigBit);
55 						~MutableRenderBufferTest	(void);
56 	void				init						(void);
57 	void				deinit						(void);
58 	IterateResult		iterate						(void);
59 
60 protected:
61 	deUint32			drawAndSwap					(const Library&		egl,
62 													 deUint32			color,
63 													 bool				flush);
64 	bool				m_enableConfigBit;
65 	EGLDisplay			m_eglDisplay;
66 	EGLSurface			m_eglSurface;
67 	EGLConfig			m_eglConfig;
68 	eglu::NativeWindow*	m_window;
69 	EGLContext			m_eglContext;
70 	glw::Functions		m_gl;
71 };
72 
MutableRenderBufferTest(EglTestContext & eglTestCtx,const char * name,const char * description,bool enableConfigBit)73 MutableRenderBufferTest::MutableRenderBufferTest (EglTestContext& eglTestCtx,
74 												  const char* name, const char* description,
75 												  bool enableConfigBit)
76 	: TestCase			(eglTestCtx, name, description)
77 	, m_enableConfigBit	(enableConfigBit)
78 	, m_eglDisplay		(EGL_NO_DISPLAY)
79 	, m_eglSurface		(EGL_NO_SURFACE)
80 	, m_eglConfig		(DE_NULL)
81 	, m_window			(DE_NULL)
82 	, m_eglContext		(EGL_NO_CONTEXT)
83 {
84 }
85 
~MutableRenderBufferTest(void)86 MutableRenderBufferTest::~MutableRenderBufferTest (void)
87 {
88 	deinit();
89 }
90 
init(void)91 void MutableRenderBufferTest::init (void)
92 {
93 	const Library&	egl	= m_eglTestCtx.getLibrary();
94 
95 	// create display
96 	m_eglDisplay		= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
97 
98 	if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_KHR_mutable_render_buffer"))
99 	{
100 		TCU_THROW(NotSupportedError, "EGL_KHR_mutable_render_buffer is not supported");
101 	}
102 
103 	// get mutable render buffer config
104 	const EGLint	attribs[]	=
105 	{
106         EGL_RED_SIZE,			8,
107         EGL_GREEN_SIZE,			8,
108         EGL_BLUE_SIZE,			8,
109 		EGL_ALPHA_SIZE,			8,
110 		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT | EGL_MUTABLE_RENDER_BUFFER_BIT_KHR,
111 		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
112 		EGL_NONE
113 	};
114 	const EGLint	attribsNoBit[]	=
115 	{
116         EGL_RED_SIZE,			8,
117         EGL_GREEN_SIZE,			8,
118         EGL_BLUE_SIZE,			8,
119 		EGL_ALPHA_SIZE,			8,
120 		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,
121 		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
122 		EGL_NONE
123 	};
124 
125 	if (m_enableConfigBit)
126 	{
127 		m_eglConfig = eglu::chooseSingleConfig(egl, m_eglDisplay, attribs);
128 	}
129 	else
130 	{
131 		const vector<EGLConfig> configs = eglu::chooseConfigs(egl, m_eglDisplay, attribsNoBit);
132 
133 		for (vector<EGLConfig>::const_iterator config = configs.begin(); config != configs.end(); ++config)
134 		{
135 			EGLint surfaceType = -1;
136 			EGLU_CHECK_CALL(egl, getConfigAttrib(m_eglDisplay, *config, EGL_SURFACE_TYPE, &surfaceType));
137 
138 			if (!(surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR))
139 			{
140 				m_eglConfig = *config;
141 				break;
142 			}
143 		}
144 
145 		if (m_eglConfig == DE_NULL)
146 			TCU_THROW(NotSupportedError, "No config without support for mutable_render_buffer found");
147 	}
148 
149 	// create surface
150 	const eglu::NativeWindowFactory& factory = eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
151 	m_window = factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, m_eglConfig, DE_NULL,
152 									eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
153 	m_eglSurface = eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, m_eglConfig, DE_NULL);
154 
155 	// create context and make current
156 	const EGLint	contextAttribList[]	=
157 	{
158 		EGL_CONTEXT_CLIENT_VERSION, 2,
159 		EGL_NONE
160 	};
161 
162 	egl.bindAPI(EGL_OPENGL_ES_API);
163 	m_eglContext = egl.createContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttribList);
164 	EGLU_CHECK_MSG(egl, "eglCreateContext");
165 	TCU_CHECK(m_eglSurface != EGL_NO_SURFACE);
166 	egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
167 	EGLU_CHECK_MSG(egl, "eglMakeCurrent");
168 
169 	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
170 }
171 
deinit(void)172 void MutableRenderBufferTest::deinit (void)
173 {
174 	const Library&	egl	= m_eglTestCtx.getLibrary();
175 
176 	if (m_eglContext != EGL_NO_CONTEXT)
177 	{
178 		egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
179 		egl.destroyContext(m_eglDisplay, m_eglContext);
180 		m_eglContext = EGL_NO_CONTEXT;
181 	}
182 
183 	if (m_eglSurface != EGL_NO_SURFACE)
184 	{
185 		egl.destroySurface(m_eglDisplay, m_eglSurface);
186 		m_eglSurface = EGL_NO_SURFACE;
187 	}
188 
189 	if (m_eglDisplay != EGL_NO_DISPLAY)
190 	{
191 		egl.terminate(m_eglDisplay);
192 		m_eglDisplay = EGL_NO_DISPLAY;
193 	}
194 
195 	if (m_window != DE_NULL)
196 	{
197 		delete m_window;
198 		m_window = DE_NULL;
199 	}
200 }
201 
drawAndSwap(const Library & egl,deUint32 color,bool flush)202 deUint32 MutableRenderBufferTest::drawAndSwap (const Library& egl, deUint32 color, bool flush)
203 {
204 	DE_ASSERT(color < 256);
205 	m_gl.clearColor((float)color/255.f, (float)color/255.f, (float)color/255.f, (float)color/255.f);
206 	m_gl.clear(GL_COLOR_BUFFER_BIT);
207 	if (flush)
208 	{
209 		m_gl.flush();
210 	}
211 	else
212 	{
213 		EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
214 	}
215 	return (color | color << 8 | color << 16 | color << 24);
216 }
217 
iterate(void)218 TestCase::IterateResult MutableRenderBufferTest::iterate (void)
219 {
220 	const Library&	egl	= m_eglTestCtx.getLibrary();
221 
222 	int frameNumber = 1;
223 
224 	// run a few back-buffered frames even if we can't verify their contents
225 	for (; frameNumber < 5; frameNumber++)
226 	{
227 		drawAndSwap(egl, frameNumber, false);
228 	}
229 
230 	// switch to single-buffer rendering
231 	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
232 
233 	// Use eglSwapBuffers for the first frame
234 	drawAndSwap(egl, frameNumber, false);
235 	frameNumber++;
236 
237 	// test a few single-buffered frames
238 	for (; frameNumber < 10; frameNumber++)
239 	{
240 		deUint32 backBufferPixel = 0xFFFFFFFF;
241 		deUint32 frontBufferPixel = drawAndSwap(egl, frameNumber, true);
242 		m_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &backBufferPixel);
243 
244 		// when single buffered, front-buffer == back-buffer
245 		if (backBufferPixel != frontBufferPixel)
246 		{
247 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface isn't single-buffered");
248 			return STOP;
249 		}
250 	}
251 
252 	// switch back to back-buffer rendering
253 	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER));
254 
255 	// run a few back-buffered frames even if we can't verify their contents
256 	for (; frameNumber < 14; frameNumber++)
257 	{
258 		drawAndSwap(egl, frameNumber, false);
259 	}
260 
261 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
262 	return STOP;
263 }
264 
265 class MutableRenderBufferQueryTest : public MutableRenderBufferTest
266 {
267 public:
268 						MutableRenderBufferQueryTest	(EglTestContext&	eglTestCtx,
269 														 const char*		name,
270 														 const char*		description);
271 						~MutableRenderBufferQueryTest	(void);
272 	IterateResult		iterate							(void);
273 };
274 
MutableRenderBufferQueryTest(EglTestContext & eglTestCtx,const char * name,const char * description)275 MutableRenderBufferQueryTest::MutableRenderBufferQueryTest (EglTestContext& eglTestCtx,
276 															const char* name, const char* description)
277 	: MutableRenderBufferTest	(eglTestCtx, name, description, true)
278 {
279 }
280 
~MutableRenderBufferQueryTest(void)281 MutableRenderBufferQueryTest::~MutableRenderBufferQueryTest (void)
282 {
283 	deinit();
284 }
285 
iterate(void)286 TestCase::IterateResult MutableRenderBufferQueryTest::iterate (void)
287 {
288 	const Library&	egl	= m_eglTestCtx.getLibrary();
289 
290 	// check that by default the query returns back buffered
291 	EGLint curRenderBuffer = -1;
292 	EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
293 	if (curRenderBuffer != EGL_BACK_BUFFER)
294 	{
295 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering");
296 		return STOP;
297 	}
298 
299 	// switch to single-buffer rendering and check that the query output changed
300 	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER));
301 	EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
302 	if (curRenderBuffer != EGL_SINGLE_BUFFER)
303 	{
304 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch to single-buffer rendering");
305 		return STOP;
306 	}
307 
308 	// switch back to back-buffer rendering and check the query again
309 	EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_BACK_BUFFER));
310 	EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
311 	if (curRenderBuffer != EGL_BACK_BUFFER)
312 	{
313 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't switch back to back-buffer rendering");
314 		return STOP;
315 	}
316 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
317 	return STOP;
318 }
319 
320 class MutableRenderBufferQueryNegativeTest : public MutableRenderBufferTest
321 {
322 public:
323 						MutableRenderBufferQueryNegativeTest	(EglTestContext&	eglTestCtx,
324 																 const char*		name,
325 																 const char*		description);
326 						~MutableRenderBufferQueryNegativeTest	(void);
327 	IterateResult		iterate									(void);
328 };
329 
MutableRenderBufferQueryNegativeTest(EglTestContext & eglTestCtx,const char * name,const char * description)330 MutableRenderBufferQueryNegativeTest::MutableRenderBufferQueryNegativeTest (EglTestContext& eglTestCtx,
331 															const char* name, const char* description)
332 	: MutableRenderBufferTest	(eglTestCtx, name, description, false)
333 {
334 }
335 
~MutableRenderBufferQueryNegativeTest(void)336 MutableRenderBufferQueryNegativeTest::~MutableRenderBufferQueryNegativeTest (void)
337 {
338 	deinit();
339 }
340 
iterate(void)341 TestCase::IterateResult MutableRenderBufferQueryNegativeTest::iterate (void)
342 {
343 	const Library&	egl	= m_eglTestCtx.getLibrary();
344 
345 	// check that by default the query returns back buffered
346 	EGLint curRenderBuffer = -1;
347 	EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
348 	if (curRenderBuffer != EGL_BACK_BUFFER)
349 	{
350 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't default to back-buffered rendering");
351 		return STOP;
352 	}
353 
354 	// check that trying to switch to single-buffer rendering fails when the config bit is not set
355 	EGLBoolean ret = egl.surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
356 	EGLint err = egl.getError();
357 	if (ret != EGL_FALSE)
358 	{
359 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL,
360 			"eglSurfaceAttrib didn't return false when trying to enable single-buffering on a context without the mutable render buffer bit set");
361 		return STOP;
362 	}
363 	if (err != EGL_BAD_MATCH)
364 	{
365 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL,
366 			"eglSurfaceAttrib didn't set the EGL_BAD_MATCH error when trying to enable single-buffering on a context without the mutable render buffer bit set");
367 		return STOP;
368 	}
369 
370     EGLU_CHECK_CALL(egl, querySurface(m_eglDisplay, m_eglSurface, EGL_RENDER_BUFFER, &curRenderBuffer));
371     if (curRenderBuffer != EGL_BACK_BUFFER)
372     {
373         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Surface didn't stay in back-buffered rendering after error");
374         return STOP;
375     }
376 
377 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
378 	return STOP;
379 }
380 
381 } // anonymous
382 
MutableRenderBufferTests(EglTestContext & eglTestCtx)383 MutableRenderBufferTests::MutableRenderBufferTests (EglTestContext& eglTestCtx)
384 	: TestCaseGroup(eglTestCtx, "mutable_render_buffer", "Mutable render buffer tests")
385 {
386 }
387 
init(void)388 void MutableRenderBufferTests::init (void)
389 {
390 	addChild(new MutableRenderBufferQueryTest(m_eglTestCtx, "querySurface",
391 		"Tests if querySurface returns the correct value after surfaceAttrib is called"));
392 	addChild(new MutableRenderBufferQueryNegativeTest(m_eglTestCtx, "negativeConfigBit",
393 		"Tests trying to enable single-buffering on a context without the mutable render buffer bit set"));
394 	addChild(new MutableRenderBufferTest(m_eglTestCtx, "basic",
395 		"Tests enabling/disabling single-buffer rendering and checks the buffering behavior", true));
396 }
397 
398 } // egl
399 } // deqp
400