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