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"); 71 } 72 default: 73 DE_FATAL("Unknown GL API"); 74 } 75 76 return 0; 77 } 78 79 EGLContext createGLContext (const Library& egl, EGLDisplay display, EGLContext eglConfig, const glu::ContextType& contextType) 80 { 81 const bool khrCreateContextSupported = hasExtension(egl, display, "EGL_KHR_create_context"); 82 EGLContext context = EGL_NO_CONTEXT; 83 EGLenum api = EGL_NONE; 84 vector<EGLint> attribList; 85 86 if (glu::isContextTypeES(contextType)) 87 { 88 api = EGL_OPENGL_ES_API; 89 90 if (contextType.getMajorVersion() <= 2) 91 { 92 attribList.push_back(EGL_CONTEXT_CLIENT_VERSION); 93 attribList.push_back(contextType.getMajorVersion()); 94 } 95 else 96 { 97 if (!khrCreateContextSupported) 98 throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL ES 3.0 and newer", DE_NULL, __FILE__, __LINE__); 99 100 attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR); 101 attribList.push_back(contextType.getMajorVersion()); 102 attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR); 103 attribList.push_back(contextType.getMinorVersion()); 104 } 105 } 106 else 107 { 108 DE_ASSERT(glu::isContextTypeGLCore(contextType) || glu::isContextTypeGLCompatibility(contextType)); 109 110 if (!khrCreateContextSupported) 111 throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL context creation", DE_NULL, __FILE__, __LINE__); 112 113 api = EGL_OPENGL_API; 114 115 attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR); 116 attribList.push_back(contextType.getMajorVersion()); 117 attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR); 118 attribList.push_back(contextType.getMinorVersion()); 119 attribList.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR); 120 attribList.push_back(glu::isContextTypeGLCore(contextType) ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 121 : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR); 122 } 123 124 if (contextType.getFlags() != glu::ContextFlags(0)) 125 { 126 EGLint flags = 0; 127 128 if (!khrCreateContextSupported) 129 throw tcu::NotSupportedError("EGL_KHR_create_context is required for creating robust/debug/forward-compatible contexts"); 130 131 if ((contextType.getFlags() & glu::CONTEXT_DEBUG) != 0) 132 flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; 133 134 if ((contextType.getFlags() & glu::CONTEXT_ROBUST) != 0) 135 flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 136 137 if ((contextType.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0) 138 { 139 if (!glu::isContextTypeGLCore(contextType)) 140 throw tcu::NotSupportedError("Only OpenGL core contexts can be forward-compatible"); 141 142 flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; 143 } 144 145 attribList.push_back(EGL_CONTEXT_FLAGS_KHR); 146 attribList.push_back(flags); 147 } 148 149 attribList.push_back(EGL_NONE); 150 151 EGLU_CHECK_CALL(egl, bindAPI(api)); 152 context = egl.createContext(display, eglConfig, EGL_NO_CONTEXT, &(attribList[0])); 153 EGLU_CHECK_MSG(egl, "eglCreateContext()"); 154 155 return context; 156 } 157 158 static bool configMatches (const eglw::Library& egl, eglw::EGLDisplay display, eglw::EGLConfig eglConfig, const glu::RenderConfig& renderConfig) 159 { 160 // \todo [2014-03-12 pyry] Check other attributes like double-buffer bit. 161 162 { 163 EGLint renderableType = 0; 164 EGLint requiredRenderable = apiRenderableType(renderConfig.type.getAPI()); 165 166 EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType)); 167 168 if ((renderableType & requiredRenderable) == 0) 169 return false; 170 } 171 172 if (renderConfig.surfaceType != glu::RenderConfig::SURFACETYPE_DONT_CARE) 173 { 174 EGLint surfaceType = 0; 175 EGLint requiredSurface = 0; 176 177 switch (renderConfig.surfaceType) 178 { 179 case glu::RenderConfig::SURFACETYPE_WINDOW: requiredSurface = EGL_WINDOW_BIT; break; 180 case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE: requiredSurface = EGL_PIXMAP_BIT; break; 181 case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC: requiredSurface = EGL_PBUFFER_BIT; break; 182 default: 183 DE_ASSERT(false); 184 } 185 186 EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, EGL_SURFACE_TYPE, &surfaceType)); 187 188 if ((surfaceType & requiredSurface) == 0) 189 return false; 190 } 191 192 { 193 static const struct 194 { 195 int glu::RenderConfig::*field; 196 EGLint attrib; 197 } s_attribs[] = 198 { 199 { &glu::RenderConfig::id, EGL_CONFIG_ID }, 200 { &glu::RenderConfig::redBits, EGL_RED_SIZE }, 201 { &glu::RenderConfig::greenBits, EGL_GREEN_SIZE }, 202 { &glu::RenderConfig::blueBits, EGL_BLUE_SIZE }, 203 { &glu::RenderConfig::alphaBits, EGL_ALPHA_SIZE }, 204 { &glu::RenderConfig::depthBits, EGL_DEPTH_SIZE }, 205 { &glu::RenderConfig::stencilBits, EGL_STENCIL_SIZE }, 206 { &glu::RenderConfig::numSamples, EGL_SAMPLES }, 207 }; 208 209 for (int attribNdx = 0; attribNdx < DE_LENGTH_OF_ARRAY(s_attribs); attribNdx++) 210 { 211 if (renderConfig.*s_attribs[attribNdx].field != glu::RenderConfig::DONT_CARE) 212 { 213 EGLint value = 0; 214 EGLU_CHECK_CALL(egl, getConfigAttrib(display, eglConfig, s_attribs[attribNdx].attrib, &value)); 215 if (value != renderConfig.*s_attribs[attribNdx].field) 216 return false; 217 } 218 } 219 } 220 221 return true; 222 } 223 224 EGLConfig chooseConfig (const Library& egl, EGLDisplay display, const glu::RenderConfig& config) 225 { 226 const std::vector<EGLConfig> configs = eglu::getConfigs(egl, display); 227 228 for (vector<EGLConfig>::const_iterator iter = configs.begin(); iter != configs.end(); ++iter) 229 { 230 if (configMatches(egl, display, *iter, config)) 231 return *iter; 232 } 233 234 throw tcu::NotSupportedError("Matching EGL config not found", DE_NULL, __FILE__, __LINE__); 235 } 236 237 } 238