teglThreadCleanUpTests.cpp revision e12d5fa7246dca6af962249786ec7396129945d1
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 EGL thread clean up tests
22 *//*--------------------------------------------------------------------*/
23
24#include "teglThreadCleanUpTests.hpp"
25
26#include "egluUtil.hpp"
27#include "egluUnique.hpp"
28#include "egluConfigFilter.hpp"
29
30#include "eglwLibrary.hpp"
31#include "eglwEnums.hpp"
32
33#include "tcuMaybe.hpp"
34#include "tcuTestLog.hpp"
35
36#include "deThread.hpp"
37
38namespace deqp
39{
40namespace egl
41{
42namespace
43{
44
45using namespace eglw;
46using tcu::TestLog;
47
48bool isES2Renderable (const eglu::CandidateConfig& c)
49{
50	return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
51}
52
53bool isPBuffer (const eglu::CandidateConfig& c)
54{
55	return (c.surfaceType() & EGL_PBUFFER_BIT) == EGL_PBUFFER_BIT;
56}
57
58class Thread : public de::Thread
59{
60public:
61	Thread (const Library& egl, EGLDisplay display, EGLSurface surface, EGLContext context, EGLConfig config, tcu::Maybe<eglu::Error>& error)
62		: m_egl		(egl)
63		, m_display	(display)
64		, m_surface	(surface)
65		, m_context	(context)
66		, m_config	(config)
67		, m_error	(error)
68	{
69	}
70
71	void testContext (EGLContext context)
72	{
73		if (m_surface != EGL_NO_SURFACE)
74		{
75			EGLU_CHECK_MSG(m_egl, "eglCreateContext");
76			m_egl.makeCurrent(m_display, m_surface, m_surface, context);
77			EGLU_CHECK_MSG(m_egl, "eglMakeCurrent");
78		}
79		else
80		{
81			const EGLint attribs[] =
82			{
83				EGL_WIDTH, 32,
84				EGL_HEIGHT, 32,
85				EGL_NONE
86			};
87			const eglu::UniqueSurface surface (m_egl, m_display, m_egl.createPbufferSurface(m_display, m_config, attribs));
88
89			EGLU_CHECK_MSG(m_egl, "eglCreateContext");
90			m_egl.makeCurrent(m_display, *surface, *surface, context);
91			EGLU_CHECK_MSG(m_egl, "eglMakeCurrent");
92		}
93	}
94
95	void run (void)
96	{
97		try
98		{
99			const EGLint 	attribList[] =
100			{
101				EGL_CONTEXT_CLIENT_VERSION, 2,
102				EGL_NONE
103			};
104
105			m_egl.bindAPI(EGL_OPENGL_ES_API);
106
107			if (m_context == EGL_NO_CONTEXT)
108			{
109				const eglu::UniqueContext context (m_egl, m_display, m_egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList));
110
111				testContext(*context);
112			}
113			else
114			{
115				testContext(m_context);
116			}
117
118		}
119		catch (const eglu::Error& error)
120		{
121			m_error = error;
122		}
123	}
124
125private:
126	const Library&				m_egl;
127	const EGLDisplay			m_display;
128	const EGLSurface			m_surface;
129	const EGLContext			m_context;
130	const EGLConfig				m_config;
131	tcu::Maybe<eglu::Error>&	m_error;
132};
133
134class ThreadCleanUpTest : public TestCase
135{
136public:
137	enum ContextType
138	{
139		CONTEXTTYPE_SINGLE = 0,
140		CONTEXTTYPE_MULTI
141	};
142
143	enum SurfaceType
144	{
145		SURFACETYPE_SINGLE = 0,
146		SURFACETYPE_MULTI
147	};
148
149	static std::string testCaseName (ContextType contextType, SurfaceType surfaceType)
150	{
151		std::string name;
152
153		if (contextType == CONTEXTTYPE_SINGLE)
154			name += "single_context_";
155		else
156			name += "multi_context_";
157
158		if (surfaceType ==SURFACETYPE_SINGLE)
159			name += "single_surface";
160		else
161			name += "multi_surface";
162
163		return name;
164	}
165
166
167	ThreadCleanUpTest (EglTestContext& eglTestCtx, ContextType contextType, SurfaceType surfaceType)
168		: TestCase			(eglTestCtx, testCaseName(contextType, surfaceType).c_str(), "Simple thread context clean up test")
169		, m_contextType		(contextType)
170		, m_surfaceType		(surfaceType)
171		, m_iterCount		(250)
172		, m_iterNdx			(0)
173		, m_display			(EGL_NO_DISPLAY)
174		, m_config			(0)
175		, m_surface			(EGL_NO_SURFACE)
176		, m_context			(EGL_NO_CONTEXT)
177	{
178	}
179
180	~ThreadCleanUpTest (void)
181	{
182		deinit();
183	}
184
185	void init (void)
186	{
187		const Library&	egl	= m_eglTestCtx.getLibrary();
188
189		m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
190
191		{
192			eglu::FilterList filters;
193			filters << isES2Renderable << isPBuffer;
194			m_config = eglu::chooseSingleConfig(egl, m_display, filters);
195		}
196
197		if (m_contextType == CONTEXTTYPE_SINGLE)
198		{
199			const EGLint 	attribList[] =
200			{
201				EGL_CONTEXT_CLIENT_VERSION, 2,
202				EGL_NONE
203			};
204
205			egl.bindAPI(EGL_OPENGL_ES_API);
206
207			m_context = egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList);
208			EGLU_CHECK_MSG(egl, "Failed to create context");
209		}
210
211		if (m_surfaceType == SURFACETYPE_SINGLE)
212		{
213			const EGLint attribs[] =
214			{
215				EGL_WIDTH, 32,
216				EGL_HEIGHT, 32,
217				EGL_NONE
218			};
219
220			m_surface = egl.createPbufferSurface(m_display, m_config, attribs);
221			EGLU_CHECK_MSG(egl, "Failed to create surface");
222		}
223	}
224
225	void deinit (void)
226	{
227		const Library& egl = m_eglTestCtx.getLibrary();
228
229		if (m_surface != EGL_NO_SURFACE)
230		{
231			egl.destroySurface(m_display, m_surface);
232			m_surface = EGL_NO_SURFACE;
233		}
234
235		if (m_context != EGL_NO_CONTEXT)
236		{
237			egl.destroyContext(m_display, m_context);
238			m_context = EGL_NO_CONTEXT;
239		}
240
241		if (m_display != EGL_NO_DISPLAY)
242		{
243			egl.terminate(m_display);
244			m_display = EGL_NO_DISPLAY;
245		}
246	}
247
248	IterateResult iterate (void)
249	{
250		if (m_iterNdx < m_iterCount)
251		{
252			tcu::Maybe<eglu::Error> error;
253
254			Thread thread (m_eglTestCtx.getLibrary(), m_display, m_surface, m_context, m_config, error);
255
256			thread.start();
257			thread.join();
258
259			if (error)
260			{
261				m_testCtx.getLog() << TestLog::Message << "Failed. Got error: " << error->getMessage() << TestLog::EndMessage;
262				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error->getMessage());
263				return STOP;
264			}
265
266			m_iterNdx++;
267			return CONTINUE;
268		}
269		else
270		{
271			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
272			return STOP;
273		}
274	}
275
276private:
277	const ContextType	m_contextType;
278	const SurfaceType	m_surfaceType;
279	const size_t		m_iterCount;
280	size_t				m_iterNdx;
281	EGLDisplay			m_display;
282	EGLConfig			m_config;
283	EGLSurface			m_surface;
284	EGLContext			m_context;
285};
286
287} // anonymous
288
289TestCaseGroup* createThreadCleanUpTest (EglTestContext& eglTestCtx)
290{
291	de::MovePtr<TestCaseGroup> group (new TestCaseGroup(eglTestCtx, "thread_cleanup", "Thread cleanup tests"));
292
293	group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_SINGLE,	ThreadCleanUpTest::SURFACETYPE_SINGLE));
294	group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_MULTI,		ThreadCleanUpTest::SURFACETYPE_SINGLE));
295
296	group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_SINGLE,	ThreadCleanUpTest::SURFACETYPE_MULTI));
297	group->addChild(new ThreadCleanUpTest(eglTestCtx, ThreadCleanUpTest::CONTEXTTYPE_MULTI,		ThreadCleanUpTest::SURFACETYPE_MULTI));
298
299	return group.release();
300}
301
302} // egl
303} // deqp
304