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