• 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 EGL multi context tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglMultiContextTests.hpp"
25 
26 #include "egluUtil.hpp"
27 #include "egluUnique.hpp"
28 #include "egluStrUtil.hpp"
29 #include "egluConfigFilter.hpp"
30 
31 #include "eglwLibrary.hpp"
32 #include "eglwEnums.hpp"
33 
34 #include "gluDefs.hpp"
35 
36 #include "glwFunctions.hpp"
37 #include "glwEnums.hpp"
38 
39 #include "tcuResultCollector.hpp"
40 #include "tcuTestLog.hpp"
41 
42 #include "deRandom.hpp"
43 
44 #include <vector>
45 
46 namespace deqp
47 {
48 namespace egl
49 {
50 namespace
51 {
52 
53 using tcu::TestLog;
54 
55 class MultiContextTest : public TestCase
56 {
57 public:
58 	enum Use
59 	{
60 		USE_NONE = 0,
61 		USE_MAKECURRENT,
62 		USE_CLEAR,
63 
64 		USE_LAST
65 	};
66 
67 	enum Sharing
68 	{
69 		SHARING_NONE = 0,
70 		SHARING_SHARED,
71 		SHARING_LAST
72 	};
73 					MultiContextTest	(EglTestContext& eglTestCtx, Sharing sharing, Use use, const char* name, const char* description);
74 
75 	IterateResult	iterate				(void);
76 
77 private:
78 	const Sharing	m_sharing;
79 	const Use		m_use;
80 };
81 
MultiContextTest(EglTestContext & eglTestCtx,Sharing sharing,Use use,const char * name,const char * description)82 MultiContextTest::MultiContextTest (EglTestContext& eglTestCtx, Sharing sharing, Use use, const char* name, const char* description)
83 	: TestCase	(eglTestCtx, name, description)
84 	, m_sharing	(sharing)
85 	, m_use		(use)
86 {
87 }
88 
isES2Renderable(const eglu::CandidateConfig & c)89 bool isES2Renderable (const eglu::CandidateConfig& c)
90 {
91 	return (c.get(EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT) == EGL_OPENGL_ES2_BIT;
92 }
93 
getConfig(const eglw::Library & egl,eglw::EGLDisplay display)94 eglw::EGLConfig getConfig (const eglw::Library& egl, eglw::EGLDisplay display)
95 {
96 	eglu::FilterList filters;
97 	filters << isES2Renderable;
98 	return eglu::chooseSingleConfig(egl, display, filters);
99 }
100 
iterate(void)101 tcu::TestCase::IterateResult MultiContextTest::iterate (void)
102 {
103 	const deUint32					seed			= m_sharing == SHARING_SHARED ? 2498541716u : 8825414;
104 	const size_t					maxContextCount	= 128;
105 	const size_t					minContextCount	= 32;
106 	const eglw::EGLint				attribList[]	=
107 	{
108 		EGL_CONTEXT_CLIENT_VERSION, 2,
109 		EGL_NONE
110 	};
111 	const eglw::EGLint				pbufferAttribList[]	=
112 	{
113 		EGL_WIDTH,	64,
114 		EGL_HEIGHT,	64,
115 		EGL_NONE
116 	};
117 
118 	TestLog&						log				= m_testCtx.getLog();
119 	tcu::ResultCollector			resultCollector	(log);
120 	de::Random						rng				(seed);
121 
122 	const eglw::Library&			egl				= m_eglTestCtx.getLibrary();
123 	const eglu::UniqueDisplay		display			(egl, eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()));
124 	const eglw::EGLConfig			config			= getConfig(egl, *display);
125 
126 	const eglu::UniqueSurface		surface			(egl, *display, m_use != USE_NONE ? egl.createPbufferSurface(*display, config, pbufferAttribList) : EGL_NO_SURFACE);
127 	EGLU_CHECK_MSG(egl, "Failed to create pbuffer.");
128 
129 	std::vector<eglw::EGLContext>	contexts;
130 	glw::Functions					gl;
131 
132 	contexts.reserve(maxContextCount);
133 
134 	log << TestLog::Message << "Trying to create " << maxContextCount << (m_sharing == SHARING_SHARED ? " shared " : " ") << "contexts." << TestLog::EndMessage;
135 	log << TestLog::Message << "Requiring that at least " << minContextCount << " contexts can be created." << TestLog::EndMessage;
136 
137 	if (m_use == USE_CLEAR)
138 		m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
139 
140 	EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
141 
142 	try
143 	{
144 		for (size_t contextCount = 0; contextCount < maxContextCount; contextCount++)
145 		{
146 			const eglw::EGLContext	sharedContext	= (m_sharing == SHARING_SHARED && contextCount > 0 ? contexts[rng.getUint32() % (deUint32)contextCount] : EGL_NO_CONTEXT);
147 			const eglw::EGLContext	context			= egl.createContext(*display, config, sharedContext, attribList);
148 			const eglw::EGLint		error			= egl.getError();
149 
150 			if (context == EGL_NO_CONTEXT || error != EGL_SUCCESS)
151 			{
152 				log << TestLog::Message << "Got error after creating " << contextCount << " contexts." << TestLog::EndMessage;
153 
154 				if (error == EGL_BAD_ALLOC)
155 				{
156 					if (contextCount < minContextCount)
157 						resultCollector.fail("Couldn't create the minimum number of contexts required.");
158 					else
159 						log << TestLog::Message << "Got EGL_BAD_ALLOC." << TestLog::EndMessage;
160 				}
161 				else
162 					resultCollector.fail("eglCreateContext() produced error that is not EGL_BAD_ALLOC: " + eglu::getErrorStr(error).toString());
163 
164 				if (context != EGL_NO_CONTEXT)
165 					resultCollector.fail("eglCreateContext() produced error, but context is not EGL_NO_CONTEXT");
166 
167 				break;
168 			}
169 			else
170 			{
171 				contexts.push_back(context);
172 
173 				if (m_use == USE_MAKECURRENT || m_use == USE_CLEAR)
174 				{
175 					const eglw::EGLBoolean	result				= egl.makeCurrent(*display, *surface, *surface, context);
176 					const eglw::EGLint		makeCurrentError	= egl.getError();
177 
178 					if (!result || makeCurrentError != EGL_SUCCESS)
179 					{
180 						log << TestLog::Message << "Failed to make " << (contextCount + 1) << "th context current: " << eglu::getErrorStr(makeCurrentError) << TestLog::EndMessage;
181 						resultCollector.fail("Failed to make context current");
182 
183 						break;
184 					}
185 					else if (m_use == USE_CLEAR)
186 					{
187 						gl.clearColor(0.25f, 0.75f, 0.50f, 1.00f);
188 						gl.clear(GL_COLOR_BUFFER_BIT);
189 						gl.finish();
190 						GLU_CHECK_GLW_MSG(gl, "Failed to clear color.");
191 					}
192 				}
193 			}
194 		}
195 
196 		for (size_t contextNdx = 0; contextNdx < contexts.size(); contextNdx++)
197 		{
198 			EGLU_CHECK_CALL(egl, destroyContext(*display, contexts[contextNdx]));
199 			contexts[contextNdx] = EGL_NO_CONTEXT;
200 		}
201 
202 		if (m_use == USE_MAKECURRENT || m_use == USE_CLEAR)
203 			EGLU_CHECK_CALL(egl, makeCurrent(*display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
204 	}
205 	catch (...)
206 	{
207 		for (size_t contextNdx = 0; contextNdx < contexts.size(); contextNdx++)
208 		{
209 			if (contexts[contextNdx] != EGL_NO_CONTEXT)
210 				EGLU_CHECK_CALL(egl, destroyContext(*display, contexts[contextNdx]));
211 		}
212 
213 		if (m_use == USE_MAKECURRENT || m_use == USE_CLEAR)
214 			EGLU_CHECK_CALL(egl, makeCurrent(*display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
215 
216 		throw;
217 	}
218 
219 	resultCollector.setTestContextResult(m_testCtx);
220 	return STOP;
221 }
222 
223 } // anonymous
224 
createMultiContextTests(EglTestContext & eglTestCtx)225 TestCaseGroup* createMultiContextTests (EglTestContext& eglTestCtx)
226 {
227 	de::MovePtr<TestCaseGroup> group (new TestCaseGroup(eglTestCtx, "multicontext", "EGL multi context tests."));
228 
229 	group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_NONE,	MultiContextTest::USE_NONE,			"non_shared",				"Create multiple non-shared contexts."));
230 	group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_SHARED,	MultiContextTest::USE_NONE,			"shared",					"Create multiple shared contexts."));
231 
232 	group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_NONE,	MultiContextTest::USE_MAKECURRENT,	"non_shared_make_current",	"Create multiple non-shared contexts."));
233 	group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_SHARED,	MultiContextTest::USE_MAKECURRENT,	"shared_make_current",		"Create multiple shared contexts."));
234 
235 	group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_NONE,	MultiContextTest::USE_CLEAR,		"non_shared_clear",			"Create multiple non-shared contexts."));
236 	group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_SHARED,	MultiContextTest::USE_CLEAR,		"shared_clear",				"Create multiple shared contexts."));
237 
238 	return group.release();
239 }
240 
241 } // egl
242 } // deqp
243