xref: /aosp_15_r20/external/deqp/modules/egl/teglQueryContextTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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