Merge vk-gl-cts/vulkan-cts-1.1.1 into vk-gl-cts/vulkan-cts-1.1.2
[platform/upstream/VK-GL-CTS.git] / modules / egl / teglMultiContextTests.cpp
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
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
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
94 bool supportsPBuffer (const eglu::CandidateConfig& c)
95 {
96         return (c.get(EGL_SURFACE_TYPE) & EGL_PBUFFER_BIT) == EGL_PBUFFER_BIT;
97 }
98
99 eglw::EGLConfig getConfig (const eglw::Library& egl, eglw::EGLDisplay display)
100 {
101         eglu::FilterList filters;
102         filters << isES2Renderable;
103         filters << supportsPBuffer;
104         return eglu::chooseSingleConfig(egl, display, filters);
105 }
106
107 tcu::TestCase::IterateResult MultiContextTest::iterate (void)
108 {
109         const deUint32                                  seed                    = m_sharing == SHARING_SHARED ? 2498541716u : 8825414;
110         const size_t                                    maxContextCount = 128;
111         const size_t                                    minContextCount = 32;
112         const eglw::EGLint                              attribList[]    =
113         {
114                 EGL_CONTEXT_CLIENT_VERSION, 2,
115                 EGL_NONE
116         };
117         const eglw::EGLint                              pbufferAttribList[]     =
118         {
119                 EGL_WIDTH,      64,
120                 EGL_HEIGHT,     64,
121                 EGL_NONE
122         };
123
124         TestLog&                                                log                             = m_testCtx.getLog();
125         tcu::ResultCollector                    resultCollector (log);
126         de::Random                                              rng                             (seed);
127
128         const eglw::Library&                    egl                             = m_eglTestCtx.getLibrary();
129         const eglu::UniqueDisplay               display                 (egl, eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay()));
130         const eglw::EGLConfig                   config                  = getConfig(egl, *display);
131
132         const eglu::UniqueSurface               surface                 (egl, *display, m_use != USE_NONE ? egl.createPbufferSurface(*display, config, pbufferAttribList) : EGL_NO_SURFACE);
133         EGLU_CHECK_MSG(egl, "Failed to create pbuffer.");
134
135         std::vector<eglw::EGLContext>   contexts;
136         glw::Functions                                  gl;
137
138         contexts.reserve(maxContextCount);
139
140         log << TestLog::Message << "Trying to create " << maxContextCount << (m_sharing == SHARING_SHARED ? " shared " : " ") << "contexts." << TestLog::EndMessage;
141         log << TestLog::Message << "Requiring that at least " << minContextCount << " contexts can be created." << TestLog::EndMessage;
142
143         if (m_use == USE_CLEAR)
144                 m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
145
146         EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
147
148         try
149         {
150                 for (size_t contextCount = 0; contextCount < maxContextCount; contextCount++)
151                 {
152                         const eglw::EGLContext  sharedContext   = (m_sharing == SHARING_SHARED && contextCount > 0 ? contexts[rng.getUint32() % (deUint32)contextCount] : EGL_NO_CONTEXT);
153                         const eglw::EGLContext  context                 = egl.createContext(*display, config, sharedContext, attribList);
154                         const eglw::EGLint              error                   = egl.getError();
155
156                         if (context == EGL_NO_CONTEXT || error != EGL_SUCCESS)
157                         {
158                                 log << TestLog::Message << "Got error after creating " << contextCount << " contexts." << TestLog::EndMessage;
159
160                                 if (error == EGL_BAD_ALLOC)
161                                 {
162                                         if (contextCount < minContextCount)
163                                                 resultCollector.fail("Couldn't create the minimum number of contexts required.");
164                                         else
165                                                 log << TestLog::Message << "Got EGL_BAD_ALLOC." << TestLog::EndMessage;
166                                 }
167                                 else
168                                         resultCollector.fail("eglCreateContext() produced error that is not EGL_BAD_ALLOC: " + eglu::getErrorStr(error).toString());
169
170                                 if (context != EGL_NO_CONTEXT)
171                                         resultCollector.fail("eglCreateContext() produced error, but context is not EGL_NO_CONTEXT");
172
173                                 break;
174                         }
175                         else
176                         {
177                                 contexts.push_back(context);
178
179                                 if (m_use == USE_MAKECURRENT || m_use == USE_CLEAR)
180                                 {
181                                         const eglw::EGLBoolean  result                          = egl.makeCurrent(*display, *surface, *surface, context);
182                                         const eglw::EGLint              makeCurrentError        = egl.getError();
183
184                                         if (!result || makeCurrentError != EGL_SUCCESS)
185                                         {
186                                                 log << TestLog::Message << "Failed to make " << (contextCount + 1) << "th context current: " << eglu::getErrorStr(makeCurrentError) << TestLog::EndMessage;
187                                                 resultCollector.fail("Failed to make context current");
188
189                                                 break;
190                                         }
191                                         else if (m_use == USE_CLEAR)
192                                         {
193                                                 gl.clearColor(0.25f, 0.75f, 0.50f, 1.00f);
194                                                 gl.clear(GL_COLOR_BUFFER_BIT);
195                                                 gl.finish();
196                                                 GLU_CHECK_GLW_MSG(gl, "Failed to clear color.");
197                                         }
198                                 }
199                         }
200                 }
201
202                 for (size_t contextNdx = 0; contextNdx < contexts.size(); contextNdx++)
203                 {
204                         EGLU_CHECK_CALL(egl, destroyContext(*display, contexts[contextNdx]));
205                         contexts[contextNdx] = EGL_NO_CONTEXT;
206                 }
207
208                 if (m_use == USE_MAKECURRENT || m_use == USE_CLEAR)
209                         EGLU_CHECK_CALL(egl, makeCurrent(*display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
210         }
211         catch (...)
212         {
213                 for (size_t contextNdx = 0; contextNdx < contexts.size(); contextNdx++)
214                 {
215                         if (contexts[contextNdx] != EGL_NO_CONTEXT)
216                                 EGLU_CHECK_CALL(egl, destroyContext(*display, contexts[contextNdx]));
217                 }
218
219                 if (m_use == USE_MAKECURRENT || m_use == USE_CLEAR)
220                         EGLU_CHECK_CALL(egl, makeCurrent(*display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
221
222                 throw;
223         }
224
225         resultCollector.setTestContextResult(m_testCtx);
226         return STOP;
227 }
228
229 } // anonymous
230
231 TestCaseGroup* createMultiContextTests (EglTestContext& eglTestCtx)
232 {
233         de::MovePtr<TestCaseGroup> group (new TestCaseGroup(eglTestCtx, "multicontext", "EGL multi context tests."));
234
235         group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_NONE,        MultiContextTest::USE_NONE,                     "non_shared",                           "Create multiple non-shared contexts."));
236         group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_SHARED,      MultiContextTest::USE_NONE,                     "shared",                                       "Create multiple shared contexts."));
237
238         group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_NONE,        MultiContextTest::USE_MAKECURRENT,      "non_shared_make_current",      "Create multiple non-shared contexts."));
239         group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_SHARED,      MultiContextTest::USE_MAKECURRENT,      "shared_make_current",          "Create multiple shared contexts."));
240
241         group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_NONE,        MultiContextTest::USE_CLEAR,            "non_shared_clear",                     "Create multiple non-shared contexts."));
242         group->addChild(new MultiContextTest(eglTestCtx, MultiContextTest::SHARING_SHARED,      MultiContextTest::USE_CLEAR,            "shared_clear",                         "Create multiple shared contexts."));
243
244         return group.release();
245 }
246
247 } // egl
248 } // deqp