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