xref: /aosp_15_r20/external/deqp/framework/egl/egluGLUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
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 EGL utilities for interfacing with GL APIs.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "egluGLUtil.hpp"
25 
26 #include "egluUtil.hpp"
27 #include "eglwLibrary.hpp"
28 #include "eglwEnums.hpp"
29 #include "glwEnums.hpp"
30 
31 #include <vector>
32 
33 using std::vector;
34 
35 namespace eglu
36 {
37 
38 using namespace eglw;
39 
getImageGLTarget(EGLenum source)40 glw::GLenum getImageGLTarget(EGLenum source)
41 {
42     switch (source)
43     {
44     case EGL_GL_TEXTURE_2D_KHR:
45         return GL_TEXTURE_2D;
46     case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
47         return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
48     case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
49         return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
50     case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
51         return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
52     case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
53         return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
54     case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
55         return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
56     case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
57         return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
58     case EGL_GL_TEXTURE_3D_KHR:
59         return GL_TEXTURE_3D;
60     case EGL_GL_RENDERBUFFER_KHR:
61         return GL_RENDERBUFFER;
62     default:
63         DE_FATAL("Impossible");
64         return GL_NONE;
65     }
66 }
67 
apiRenderableType(glu::ApiType apiType)68 EGLint apiRenderableType(glu::ApiType apiType)
69 {
70     switch (apiType.getProfile())
71     {
72     case glu::PROFILE_CORE:
73     case glu::PROFILE_COMPATIBILITY:
74         return EGL_OPENGL_BIT;
75     case glu::PROFILE_ES:
76         switch (apiType.getMajorVersion())
77         {
78         case 1:
79             return EGL_OPENGL_ES_BIT;
80         case 2:
81             return EGL_OPENGL_ES2_BIT;
82         case 3:
83             return EGL_OPENGL_ES3_BIT_KHR;
84         default:
85             DE_FATAL("Unknown OpenGL ES version");
86             break;
87         }
88         break;
89     default:
90         DE_FATAL("Unknown GL API");
91     }
92 
93     return 0;
94 }
95 
createGLContext(const Library & egl,EGLDisplay display,EGLContext eglConfig,const glu::ContextType & contextType,eglw::EGLContext sharedContext,glu::ResetNotificationStrategy resetNotificationStrategy)96 EGLContext createGLContext(const Library &egl, EGLDisplay display, EGLContext eglConfig,
97                            const glu::ContextType &contextType, eglw::EGLContext sharedContext,
98                            glu::ResetNotificationStrategy resetNotificationStrategy)
99 {
100     const bool khrCreateContextSupported        = hasExtension(egl, display, "EGL_KHR_create_context");
101     const bool khrCreateContextNoErrorSupported = hasExtension(egl, display, "EGL_KHR_create_context_no_error");
102     EGLContext context                          = EGL_NO_CONTEXT;
103     EGLenum api                                 = EGL_NONE;
104     vector<EGLint> attribList;
105 
106     if (glu::isContextTypeES(contextType))
107     {
108         api = EGL_OPENGL_ES_API;
109 
110         if (contextType.getMajorVersion() <= 2)
111         {
112             attribList.push_back(EGL_CONTEXT_CLIENT_VERSION);
113             attribList.push_back(contextType.getMajorVersion());
114         }
115         else
116         {
117             if (!khrCreateContextSupported)
118                 TCU_THROW(NotSupportedError, "EGL_KHR_create_context is required for OpenGL ES 3.0 and newer");
119 
120             attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
121             attribList.push_back(contextType.getMajorVersion());
122             attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
123             attribList.push_back(contextType.getMinorVersion());
124         }
125     }
126     else
127     {
128         DE_ASSERT(glu::isContextTypeGLCore(contextType) || glu::isContextTypeGLCompatibility(contextType));
129 
130         if (!khrCreateContextSupported)
131             TCU_THROW(NotSupportedError, "EGL_KHR_create_context is required for OpenGL context creation");
132 
133         api = EGL_OPENGL_API;
134 
135         attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
136         attribList.push_back(contextType.getMajorVersion());
137         attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
138         attribList.push_back(contextType.getMinorVersion());
139         attribList.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
140         attribList.push_back(glu::isContextTypeGLCore(contextType) ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR :
141                                                                      EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
142     }
143 
144     if (contextType.getFlags() != glu::ContextFlags(0))
145     {
146         EGLint flags = 0;
147 
148         if (!khrCreateContextSupported)
149             TCU_THROW(NotSupportedError,
150                       "EGL_KHR_create_context is required for creating robust/debug/forward-compatible contexts");
151 
152         if ((contextType.getFlags() & glu::CONTEXT_DEBUG) != 0)
153             flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
154 
155         if ((contextType.getFlags() & glu::CONTEXT_ROBUST) != 0)
156         {
157             if (glu::isContextTypeES(contextType))
158             {
159                 if (!hasExtension(egl, display, "EGL_EXT_create_context_robustness") &&
160                     (getVersion(egl, display) < Version(1, 5)))
161                     TCU_THROW(NotSupportedError,
162                               "EGL_EXT_create_context_robustness is required for creating robust context");
163 
164                 attribList.push_back(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
165                 attribList.push_back(EGL_TRUE);
166             }
167             else
168                 flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
169         }
170 
171         if ((contextType.getFlags() & glu::CONTEXT_NO_ERROR) != 0)
172         {
173             if (khrCreateContextNoErrorSupported)
174             {
175                 attribList.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
176                 attribList.push_back(EGL_TRUE);
177             }
178             else
179                 throw tcu::NotSupportedError(
180                     "EGL_KHR_create_context_no_error is required for creating no-error contexts");
181         }
182 
183         if ((contextType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
184         {
185             if (!glu::isContextTypeGLCore(contextType))
186                 TCU_THROW(InternalError, "Only OpenGL core contexts can be forward-compatible");
187 
188             flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
189         }
190 
191         attribList.push_back(EGL_CONTEXT_FLAGS_KHR);
192         attribList.push_back(flags);
193 
194         if (resetNotificationStrategy != glu::RESET_NOTIFICATION_STRATEGY_NOT_SPECIFIED)
195         {
196             if (getVersion(egl, display) >= Version(1, 5) || glu::isContextTypeGLCore(contextType) ||
197                 glu::isContextTypeGLCompatibility(contextType))
198                 attribList.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
199             else if (hasExtension(egl, display, "EGL_EXT_create_context_robustness"))
200                 attribList.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
201             else
202                 TCU_THROW(NotSupportedError,
203                           "EGL 1.5 or EGL_EXT_create_context_robustness is required for creating robust context");
204 
205             if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION)
206                 attribList.push_back(EGL_NO_RESET_NOTIFICATION_KHR);
207             else if (resetNotificationStrategy == glu::RESET_NOTIFICATION_STRATEGY_LOSE_CONTEXT_ON_RESET)
208                 attribList.push_back(EGL_LOSE_CONTEXT_ON_RESET_KHR);
209             else
210                 TCU_THROW(InternalError, "Unknown reset notification strategy");
211         }
212     }
213 
214     attribList.push_back(EGL_NONE);
215 
216     EGLU_CHECK_CALL(egl, bindAPI(api));
217     context = egl.createContext(display, eglConfig, sharedContext, &(attribList[0]));
218     EGLU_CHECK_MSG(egl, "eglCreateContext()");
219 
220     return context;
221 }
222 
configMatches(const eglw::Library & egl,eglw::EGLDisplay display,eglw::EGLConfig eglConfig,const glu::RenderConfig & renderConfig)223 static bool configMatches(const eglw::Library &egl, eglw::EGLDisplay display, eglw::EGLConfig eglConfig,
224                           const glu::RenderConfig &renderConfig)
225 {
226     // \todo [2014-03-12 pyry] Check other attributes like double-buffer bit.
227 
228     {
229         EGLint renderableType     = 0;
230         EGLint requiredRenderable = apiRenderableType(renderConfig.type.getAPI());
231 
232         EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType));
233 
234         if ((renderableType & requiredRenderable) == 0)
235             return false;
236     }
237 
238     if (renderConfig.surfaceType != glu::RenderConfig::SURFACETYPE_DONT_CARE)
239     {
240         EGLint surfaceType     = 0;
241         EGLint requiredSurface = 0;
242 
243         switch (renderConfig.surfaceType)
244         {
245         case glu::RenderConfig::SURFACETYPE_WINDOW:
246             requiredSurface = EGL_WINDOW_BIT;
247             break;
248         case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
249             requiredSurface = EGL_PIXMAP_BIT;
250             break;
251         case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
252             requiredSurface = EGL_PBUFFER_BIT;
253             break;
254         default:
255             DE_ASSERT(false);
256         }
257 
258         EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_SURFACE_TYPE, &surfaceType));
259 
260         if ((surfaceType & requiredSurface) == 0)
261             return false;
262     }
263 
264     if (renderConfig.componentType != glu::RenderConfig::COMPONENT_TYPE_DONT_CARE)
265     {
266         EGLint componentType = 0;
267         EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType));
268 
269         if (componentType != glu::toEGLComponentType(renderConfig.componentType))
270             return false;
271     }
272 
273     {
274         static const struct
275         {
276             int glu::RenderConfig::*field;
277             EGLint attrib;
278         } s_attribs[] = {
279             {&glu::RenderConfig::id, EGL_CONFIG_ID},
280             {&glu::RenderConfig::redBits, EGL_RED_SIZE},
281             {&glu::RenderConfig::greenBits, EGL_GREEN_SIZE},
282             {&glu::RenderConfig::blueBits, EGL_BLUE_SIZE},
283             {&glu::RenderConfig::alphaBits, EGL_ALPHA_SIZE},
284             {&glu::RenderConfig::depthBits, EGL_DEPTH_SIZE},
285             {&glu::RenderConfig::stencilBits, EGL_STENCIL_SIZE},
286             {&glu::RenderConfig::numSamples, EGL_SAMPLES},
287         };
288 
289         for (int attribNdx = 0; attribNdx < DE_LENGTH_OF_ARRAY(s_attribs); attribNdx++)
290         {
291             if (renderConfig.*s_attribs[attribNdx].field != glu::RenderConfig::DONT_CARE)
292             {
293                 EGLint value = 0;
294                 EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, s_attribs[attribNdx].attrib, &value));
295                 if (value != renderConfig.*s_attribs[attribNdx].field)
296                     return false;
297             }
298         }
299     }
300 
301     return true;
302 }
303 
chooseConfig(const Library & egl,EGLDisplay display,const glu::RenderConfig & config)304 EGLConfig chooseConfig(const Library &egl, EGLDisplay display, const glu::RenderConfig &config)
305 {
306     const std::vector<EGLConfig> configs = eglu::getConfigs(egl, display);
307 
308     for (vector<EGLConfig>::const_iterator iter = configs.begin(); iter != configs.end(); ++iter)
309     {
310         if (configMatches(egl, display, *iter, config))
311             return *iter;
312     }
313 
314     throw tcu::NotSupportedError("Matching EGL config not found", DE_NULL, __FILE__, __LINE__);
315 }
316 
317 } // namespace eglu
318