1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program EGL Module
3 * ---------------------------------------
4 *
5 * Copyright 2014 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 Config query tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "teglQueryContextTests.hpp"
25 #include "teglRenderCase.hpp"
26 #include "teglRenderCase.hpp"
27 #include "egluCallLogWrapper.hpp"
28 #include "egluStrUtil.hpp"
29 #include "tcuCommandLine.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuTestContext.hpp"
32
33 #include "egluUtil.hpp"
34 #include "egluNativeDisplay.hpp"
35 #include "egluNativeWindow.hpp"
36 #include "egluNativePixmap.hpp"
37
38 #include "eglwLibrary.hpp"
39 #include "eglwEnums.hpp"
40
41 #include "deUniquePtr.hpp"
42 #include "deSTLUtil.hpp"
43
44 #include <vector>
45
46 namespace deqp
47 {
48 namespace egl
49 {
50
51 using std::vector;
52 using eglu::ConfigInfo;
53 using tcu::TestLog;
54 using namespace eglw;
55
getClientTypeFromAPIBit(EGLint apiBit)56 static EGLint getClientTypeFromAPIBit (EGLint apiBit)
57 {
58 switch (apiBit)
59 {
60 case EGL_OPENGL_BIT: return EGL_OPENGL_API;
61 case EGL_OPENGL_ES_BIT: return EGL_OPENGL_ES_API;
62 case EGL_OPENGL_ES2_BIT: return EGL_OPENGL_ES_API;
63 case EGL_OPENGL_ES3_BIT: return EGL_OPENGL_ES_API;
64 case EGL_OPENVG_BIT: return EGL_OPENVG_API;
65 default:
66 DE_ASSERT(false);
67 return 0;
68 }
69 }
70
getMinClientMajorVersion(EGLint apiBit)71 static EGLint getMinClientMajorVersion (EGLint apiBit)
72 {
73 switch (apiBit)
74 {
75 case EGL_OPENGL_BIT: return 1;
76 case EGL_OPENGL_ES_BIT: return 1;
77 case EGL_OPENGL_ES2_BIT: return 2;
78 case EGL_OPENGL_ES3_BIT: return 3;
79 case EGL_OPENVG_BIT: return 1;
80 default:
81 DE_ASSERT(false);
82 return 0;
83 }
84 }
85
86 class GetCurrentContextCase : public SingleContextRenderCase, private eglu::CallLogWrapper
87 {
88 public:
GetCurrentContextCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters,EGLint surfaceTypeMask)89 GetCurrentContextCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
90 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
91 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog())
92 {
93 }
94
executeForContext(EGLDisplay display,EGLContext context,EGLSurface surface,const Config & config)95 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
96 {
97 const Library& egl = m_eglTestCtx.getLibrary();
98 TestLog& log = m_testCtx.getLog();
99
100 DE_UNREF(display);
101 DE_UNREF(surface);
102 DE_UNREF(config);
103
104 enableLogging(true);
105
106 const EGLContext gotContext = eglGetCurrentContext();
107 EGLU_CHECK_MSG(egl, "eglGetCurrentContext");
108
109 if (gotContext == context)
110 {
111 log << TestLog::Message << " Pass" << TestLog::EndMessage;
112 }
113 else if (gotContext == EGL_NO_CONTEXT)
114 {
115 log << TestLog::Message << " Fail, got EGL_NO_CONTEXT" << TestLog::EndMessage;
116 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected EGL_NO_CONTEXT");
117 }
118 else if (gotContext != context)
119 {
120 log << TestLog::Message << " Fail, call returned the wrong context. Expected: " << tcu::toHex(context) << ", got: " << tcu::toHex(gotContext) << TestLog::EndMessage;
121 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid context");
122 }
123
124 enableLogging(false);
125 }
126 };
127
128 class GetCurrentSurfaceCase : public SingleContextRenderCase, private eglu::CallLogWrapper
129 {
130 public:
GetCurrentSurfaceCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters,EGLint surfaceTypeMask)131 GetCurrentSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
132 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
133 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog())
134 {
135 }
136
executeForContext(EGLDisplay display,EGLContext context,EGLSurface surface,const Config & config)137 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
138 {
139 const Library& egl = m_eglTestCtx.getLibrary();
140 TestLog& log = m_testCtx.getLog();
141
142 DE_UNREF(display);
143 DE_UNREF(context);
144 DE_UNREF(config);
145
146 enableLogging(true);
147
148 const EGLContext gotReadSurface = eglGetCurrentSurface(EGL_READ);
149 EGLU_CHECK_MSG(egl, "eglGetCurrentSurface(EGL_READ)");
150
151 const EGLContext gotDrawSurface = eglGetCurrentSurface(EGL_DRAW);
152 EGLU_CHECK_MSG(egl, "eglGetCurrentSurface(EGL_DRAW)");
153
154 if (gotReadSurface == surface && gotDrawSurface == surface)
155 {
156 log << TestLog::Message << " Pass" << TestLog::EndMessage;
157 }
158 else
159 {
160 log << TestLog::Message << " Fail, read surface: " << tcu::toHex(gotReadSurface)
161 << ", draw surface: " << tcu::toHex(gotDrawSurface)
162 << ", expected: " << tcu::toHex(surface) << TestLog::EndMessage;
163 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface");
164 }
165
166 enableLogging(false);
167 }
168 };
169
170 class GetCurrentDisplayCase : public SingleContextRenderCase, private eglu::CallLogWrapper
171 {
172 public:
GetCurrentDisplayCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters,EGLint surfaceTypeMask)173 GetCurrentDisplayCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
174 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
175 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog())
176 {
177 }
178
executeForContext(EGLDisplay display,EGLContext context,EGLSurface surface,const Config & config)179 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
180 {
181 const Library& egl = m_eglTestCtx.getLibrary();
182 TestLog& log = m_testCtx.getLog();
183
184 DE_UNREF(surface && context);
185 DE_UNREF(config);
186
187 enableLogging(true);
188
189 const EGLDisplay gotDisplay = eglGetCurrentDisplay();
190 EGLU_CHECK_MSG(egl, "eglGetCurrentDisplay");
191
192 if (gotDisplay == display)
193 {
194 log << TestLog::Message << " Pass" << TestLog::EndMessage;
195 }
196 else if (gotDisplay == EGL_NO_DISPLAY)
197 {
198 log << TestLog::Message << " Fail, got EGL_NO_DISPLAY" << TestLog::EndMessage;
199 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected EGL_NO_DISPLAY");
200 }
201 else if (gotDisplay != display)
202 {
203 log << TestLog::Message << " Fail, call returned the wrong display. Expected: " << tcu::toHex(display) << ", got: " << tcu::toHex(gotDisplay) << TestLog::EndMessage;
204 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid display");
205 }
206
207 enableLogging(false);
208 }
209 };
210
211 class QueryContextCase : public SingleContextRenderCase, private eglu::CallLogWrapper
212 {
213 public:
QueryContextCase(EglTestContext & eglTestCtx,const char * name,const char * description,const eglu::FilterList & filters,EGLint surfaceTypeMask)214 QueryContextCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
215 : SingleContextRenderCase (eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
216 , eglu::CallLogWrapper (eglTestCtx.getLibrary(), m_testCtx.getLog())
217 {
218 }
219
getContextAttrib(EGLDisplay display,EGLContext context,EGLint attrib)220 EGLint getContextAttrib (EGLDisplay display, EGLContext context, EGLint attrib)
221 {
222 const Library& egl = m_eglTestCtx.getLibrary();
223 EGLint value;
224 EGLU_CHECK_CALL(egl, queryContext(display, context, attrib, &value));
225
226 return value;
227 }
228
executeForContext(EGLDisplay display,EGLContext context,EGLSurface surface,const Config & config)229 void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
230 {
231 const Library& egl = m_eglTestCtx.getLibrary();
232 TestLog& log = m_testCtx.getLog();
233 const eglu::Version version = eglu::getVersion(egl, display);
234
235 DE_UNREF(surface);
236 enableLogging(true);
237
238 // Config ID
239 {
240 const EGLint configID = getContextAttrib(display, context, EGL_CONFIG_ID);
241 const EGLint surfaceConfigID = eglu::getConfigAttribInt(egl, display, config.config, EGL_CONFIG_ID);
242
243 if (configID != surfaceConfigID)
244 {
245 log << TestLog::Message << " Fail, config ID doesn't match the one used to create the context." << TestLog::EndMessage;
246 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid config ID");
247 }
248 }
249
250 // Client API type
251 if (version >= eglu::Version(1, 2))
252 {
253 const EGLint clientType = getContextAttrib(display, context, EGL_CONTEXT_CLIENT_TYPE);
254
255 if (clientType != getClientTypeFromAPIBit(config.apiBits))
256 {
257 log << TestLog::Message << " Fail, client API type doesn't match." << TestLog::EndMessage;
258 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid client API type");
259 }
260 }
261
262 // Client API version
263 if (version >= eglu::Version(1, 3))
264 {
265 const EGLint clientVersion = getContextAttrib(display, context, EGL_CONTEXT_CLIENT_VERSION);
266
267 // \todo [2014-10-21 mika] Query actual supported api version from client api to make this check stricter.
268 if (clientVersion < getMinClientMajorVersion(config.apiBits))
269 {
270 log << TestLog::Message << " Fail, client API version doesn't match." << TestLog::EndMessage;
271 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid client API version");
272 }
273 }
274
275 // Render buffer
276 if (version >= eglu::Version(1, 2))
277 {
278 const EGLint renderBuffer = getContextAttrib(display, context, EGL_RENDER_BUFFER);
279
280 if (config.surfaceTypeBit == EGL_PIXMAP_BIT && renderBuffer != EGL_SINGLE_BUFFER)
281 {
282 log << TestLog::Message << " Fail, render buffer should be EGL_SINGLE_BUFFER for a pixmap surface." << TestLog::EndMessage;
283 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer");
284 }
285 else if (config.surfaceTypeBit == EGL_PBUFFER_BIT && renderBuffer != EGL_BACK_BUFFER)
286 {
287 log << TestLog::Message << " Fail, render buffer should be EGL_BACK_BUFFER for a pbuffer surface." << TestLog::EndMessage;
288 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer");
289 }
290 else if (config.surfaceTypeBit == EGL_WINDOW_BIT && renderBuffer != EGL_SINGLE_BUFFER && renderBuffer != EGL_BACK_BUFFER)
291 {
292 log << TestLog::Message << " Fail, render buffer should be either EGL_SINGLE_BUFFER or EGL_BACK_BUFFER for a window surface." << TestLog::EndMessage;
293 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer");
294 }
295 }
296
297 enableLogging(false);
298
299 log << TestLog::Message << " Pass" << TestLog::EndMessage;
300 }
301 };
302
303 class QueryAPICase : public TestCase, private eglu::CallLogWrapper
304 {
305 public:
QueryAPICase(EglTestContext & eglTestCtx,const char * name,const char * description)306 QueryAPICase (EglTestContext& eglTestCtx, const char* name, const char* description)
307 : TestCase (eglTestCtx, name, description)
308 , CallLogWrapper(eglTestCtx.getLibrary(), eglTestCtx.getTestContext().getLog())
309 {
310 }
311
init(void)312 void init (void)
313 {
314 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
315 }
316
iterate(void)317 IterateResult iterate (void)
318 {
319 const Library& egl = m_eglTestCtx.getLibrary();
320 EGLDisplay display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
321 tcu::TestLog& log = m_testCtx.getLog();
322 const EGLenum apis[] = { EGL_OPENGL_API, EGL_OPENGL_ES_API, EGL_OPENVG_API };
323 const vector<EGLenum> supportedAPIs = eglu::getClientAPIs(egl, display);
324
325 enableLogging(true);
326
327 {
328 const EGLenum api = eglQueryAPI();
329
330 if (api != EGL_OPENGL_ES_API && (de::contains(supportedAPIs.begin(), supportedAPIs.end(), EGL_OPENGL_ES_API)))
331 {
332 log << TestLog::Message << " Fail, initial value should be EGL_OPENGL_ES_API if OpenGL ES is supported." << TestLog::EndMessage;
333 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default value");
334 }
335 else if (api != EGL_NONE && !(de::contains(supportedAPIs.begin(), supportedAPIs.end(), EGL_OPENGL_ES_API)))
336 {
337 log << TestLog::Message << " Fail, initial value should be EGL_NONE if OpenGL ES is not supported." << TestLog::EndMessage;
338 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default value");
339 }
340 }
341
342 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(apis); ndx++)
343 {
344 const EGLenum api = apis[ndx];
345
346 log << TestLog::Message << TestLog::EndMessage;
347
348 if (de::contains(supportedAPIs.begin(), supportedAPIs.end(), api))
349 {
350 egl.bindAPI(api);
351
352 if (api != egl.queryAPI())
353 {
354 log << TestLog::Message << " Fail, return value does not match previously bound API." << TestLog::EndMessage;
355 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid return value");
356 }
357 }
358 else
359 {
360 log << TestLog::Message << eglu::getAPIStr(api) << " not supported." << TestLog::EndMessage;
361 }
362 }
363
364 enableLogging(false);
365 eglTerminate(display);
366 return STOP;
367 }
368 };
369
QueryContextTests(EglTestContext & eglTestCtx)370 QueryContextTests::QueryContextTests (EglTestContext& eglTestCtx)
371 : TestCaseGroup(eglTestCtx, "query_context", "Rendering context query tests")
372 {
373 }
374
~QueryContextTests(void)375 QueryContextTests::~QueryContextTests (void)
376 {
377 }
378
379 template<class QueryContextClass>
createQueryContextGroups(EglTestContext & eglTestCtx,tcu::TestCaseGroup * group)380 void createQueryContextGroups (EglTestContext& eglTestCtx, tcu::TestCaseGroup* group)
381 {
382 std::vector<RenderFilterList> filterLists;
383
384 getDefaultRenderFilterLists(filterLists, eglu::FilterList());
385
386 for (std::vector<RenderFilterList>::const_iterator listIter = filterLists.begin(); listIter != filterLists.end(); listIter++)
387 group->addChild(new QueryContextClass(eglTestCtx, listIter->getName(), "", *listIter, listIter->getSurfaceTypeMask()));
388 }
389
init(void)390 void QueryContextTests::init (void)
391 {
392 {
393 tcu::TestCaseGroup* simpleGroup = new tcu::TestCaseGroup(m_testCtx, "simple", "Simple API tests");
394 addChild(simpleGroup);
395
396 simpleGroup->addChild(new QueryAPICase(m_eglTestCtx, "query_api", "eglQueryAPI() test"));
397 }
398
399 // eglGetCurrentContext
400 {
401 tcu::TestCaseGroup* getCurrentContextGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_context", "eglGetCurrentContext() tests");
402 addChild(getCurrentContextGroup);
403
404 createQueryContextGroups<GetCurrentContextCase>(m_eglTestCtx, getCurrentContextGroup);
405 }
406
407 // eglGetCurrentSurface
408 {
409 tcu::TestCaseGroup* getCurrentSurfaceGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_surface", "eglGetCurrentSurface() tests");
410 addChild(getCurrentSurfaceGroup);
411
412 createQueryContextGroups<GetCurrentSurfaceCase>(m_eglTestCtx, getCurrentSurfaceGroup);
413 }
414
415 // eglGetCurrentDisplay
416 {
417 tcu::TestCaseGroup* getCurrentDisplayGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_display", "eglGetCurrentDisplay() tests");
418 addChild(getCurrentDisplayGroup);
419
420 createQueryContextGroups<GetCurrentDisplayCase>(m_eglTestCtx, getCurrentDisplayGroup);
421 }
422
423 // eglQueryContext
424 {
425 tcu::TestCaseGroup* queryContextGroup = new tcu::TestCaseGroup(m_testCtx, "query_context", "eglQueryContext() tests");
426 addChild(queryContextGroup);
427
428 createQueryContextGroups<QueryContextCase>(m_eglTestCtx, queryContextGroup);
429 }
430 }
431
432 } // egl
433 } // deqp
434