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 EGL Test Case 22 *//*--------------------------------------------------------------------*/ 23 24 #include "teglTestCase.hpp" 25 26 #include "tcuPlatform.hpp" 27 28 #include "egluUtil.hpp" 29 #include "egluGLFunctionLoader.hpp" 30 #include "egluPlatform.hpp" 31 32 #include "gluRenderContext.hpp" 33 #include "glwInitFunctions.hpp" 34 35 #include <set> 36 37 using std::vector; 38 using std::set; 39 40 namespace deqp 41 { 42 namespace egl 43 { 44 45 namespace 46 { 47 48 void split (std::vector<std::string>& dst, const std::string& src) 49 { 50 size_t start = 0; 51 size_t end = std::string::npos; 52 53 while ((end = src.find(' ', start)) != std::string::npos) 54 { 55 dst.push_back(src.substr(start, end-start)); 56 start = end+1; 57 } 58 59 if (start < end) 60 dst.push_back(src.substr(start, end-start)); 61 } 62 63 EGLint parseAPI (const std::string& api) 64 { 65 if (api == "OpenGL") 66 return EGL_OPENGL_API; 67 else if (api == "OpenGL_ES") 68 return EGL_OPENGL_ES_API; 69 else if (api == "OpenVG") 70 return EGL_OPENVG_API; 71 else 72 { 73 tcu::print("Warning: Unknown API '%s'", api.c_str()); 74 return 0; 75 } 76 } 77 78 } // anonymous 79 80 EglTestContext::EglTestContext (tcu::TestContext& testCtx, const eglu::NativeDisplayFactory& displayFactory, const eglu::NativeWindowFactory* windowFactory, const eglu::NativePixmapFactory* pixmapFactory) 81 : m_testCtx (testCtx) 82 , m_displayFactory (displayFactory) 83 , m_windowFactory (windowFactory) 84 , m_pixmapFactory (pixmapFactory) 85 , m_defaultNativeDisplay (DE_NULL) 86 , m_defaultEGLDisplay (DE_NULL) 87 { 88 // Temporarily allocate default display for storing config list 89 try 90 { 91 EGLDisplay eglDisplay = EGL_NO_DISPLAY; 92 EGLint majorVersion; 93 EGLint minorVersion; 94 95 m_defaultNativeDisplay = m_displayFactory.createDisplay(); 96 97 eglDisplay = eglu::getDisplay(*m_defaultNativeDisplay); 98 TCU_CHECK_EGL_CALL(eglInitialize(eglDisplay, &majorVersion, &minorVersion)); 99 100 m_defaultEGLDisplay = new tcu::egl::Display(eglDisplay, majorVersion, minorVersion); 101 102 // Create config list 103 { 104 vector<EGLConfig> configs; 105 set<EGLint> idSet; // For checking for duplicate config IDs 106 107 m_defaultEGLDisplay->getConfigs(configs); 108 109 m_configs.resize(configs.size()); 110 for (int ndx = 0; ndx < (int)configs.size(); ndx++) 111 { 112 m_defaultEGLDisplay->describeConfig(configs[ndx], m_configs[ndx]); 113 114 EGLint id = m_configs[ndx].configId; 115 if (idSet.find(id) != idSet.end()) 116 tcu::print("Warning: Duplicate config ID %d\n", id); 117 idSet.insert(id); 118 } 119 } 120 121 // Query supported APIs 122 { 123 const char* clientAPIs = eglQueryString(eglDisplay, EGL_CLIENT_APIS); 124 std::vector<std::string> apis; 125 TCU_CHECK(clientAPIs); 126 127 split(apis, clientAPIs); 128 for (std::vector<std::string>::const_iterator apiIter = apis.begin(); apiIter != apis.end(); apiIter++) 129 { 130 EGLint parsedAPI = parseAPI(*apiIter); 131 if (parsedAPI != 0) 132 m_supportedAPIs.insert(parsedAPI); 133 } 134 } 135 136 delete m_defaultEGLDisplay; 137 m_defaultEGLDisplay = DE_NULL; 138 delete m_defaultNativeDisplay; 139 m_defaultNativeDisplay = DE_NULL; 140 } 141 catch (...) 142 { 143 delete m_defaultEGLDisplay; 144 m_defaultEGLDisplay = DE_NULL; 145 delete m_defaultNativeDisplay; 146 m_defaultNativeDisplay = DE_NULL; 147 throw; 148 } 149 } 150 151 EglTestContext::~EglTestContext (void) 152 { 153 for (GLLibraryMap::iterator iter = m_glLibraries.begin(); iter != m_glLibraries.end(); ++iter) 154 delete iter->second; 155 156 delete m_defaultEGLDisplay; 157 delete m_defaultNativeDisplay; 158 } 159 160 void EglTestContext::createDefaultDisplay (void) 161 { 162 EGLDisplay eglDisplay = EGL_NO_DISPLAY; 163 EGLint majorVersion; 164 EGLint minorVersion; 165 166 DE_ASSERT(!m_defaultEGLDisplay); 167 DE_ASSERT(!m_defaultNativeDisplay); 168 169 try 170 { 171 m_defaultNativeDisplay = m_displayFactory.createDisplay(); 172 173 eglDisplay = eglu::getDisplay(*m_defaultNativeDisplay); 174 TCU_CHECK_EGL_CALL(eglInitialize(eglDisplay, &majorVersion, &minorVersion)); 175 176 m_defaultEGLDisplay = new tcu::egl::Display(eglDisplay, majorVersion, minorVersion); 177 } 178 catch (const std::exception&) 179 { 180 delete m_defaultEGLDisplay; 181 m_defaultEGLDisplay = DE_NULL; 182 delete m_defaultNativeDisplay; 183 m_defaultNativeDisplay = DE_NULL; 184 throw; 185 } 186 } 187 188 const eglu::NativeWindowFactory& EglTestContext::getNativeWindowFactory (void) const 189 { 190 if (m_windowFactory) 191 return *m_windowFactory; 192 else 193 throw tcu::NotSupportedError("No default native window factory available", "", __FILE__, __LINE__); 194 } 195 196 const eglu::NativePixmapFactory& EglTestContext::getNativePixmapFactory (void) const 197 { 198 if (m_pixmapFactory) 199 return *m_pixmapFactory; 200 else 201 throw tcu::NotSupportedError("No default native pixmap factory available", "", __FILE__, __LINE__); 202 } 203 204 void EglTestContext::destroyDefaultDisplay (void) 205 { 206 DE_ASSERT(m_defaultEGLDisplay); 207 DE_ASSERT(m_defaultNativeDisplay); 208 209 delete m_defaultEGLDisplay; 210 m_defaultEGLDisplay = DE_NULL; 211 212 delete m_defaultNativeDisplay; 213 m_defaultNativeDisplay = DE_NULL; 214 } 215 216 eglu::NativeWindow* EglTestContext::createNativeWindow (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height, eglu::WindowParams::Visibility visibility) 217 { 218 if (!m_windowFactory) 219 throw tcu::NotSupportedError("Windows not supported", "", __FILE__, __LINE__); 220 221 return m_windowFactory->createWindow(m_defaultNativeDisplay, display, config, attribList, eglu::WindowParams(width, height, visibility)); 222 } 223 224 eglu::NativePixmap* EglTestContext::createNativePixmap (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height) 225 { 226 if (!m_pixmapFactory) 227 throw tcu::NotSupportedError("Pixmaps not supported", "", __FILE__, __LINE__); 228 229 return m_pixmapFactory->createPixmap(m_defaultNativeDisplay, display, config, attribList, width, height); 230 } 231 232 // \todo [2014-10-06 pyry] Quite hacky, expose ApiType internals? 233 static deUint32 makeKey (glu::ApiType apiType) 234 { 235 return (apiType.getMajorVersion() << 8) | (apiType.getMinorVersion() << 4) | apiType.getProfile(); 236 } 237 238 const tcu::FunctionLibrary* EglTestContext::getGLLibrary (glu::ApiType apiType) const 239 { 240 tcu::FunctionLibrary* library = DE_NULL; 241 const deUint32 key = makeKey(apiType); 242 GLLibraryMap::iterator iter = m_glLibraries.find(key); 243 244 if (iter == m_glLibraries.end()) 245 { 246 library = m_testCtx.getPlatform().getEGLPlatform().createDefaultGLFunctionLibrary(apiType, m_testCtx.getCommandLine()); 247 m_glLibraries.insert(std::make_pair(key, library)); 248 } 249 else 250 library = iter->second; 251 252 return library; 253 } 254 255 deFunctionPtr EglTestContext::getGLFunction (glu::ApiType apiType, const char* name) const 256 { 257 // \todo [2014-03-11 pyry] This requires fall-back to eglGetProcAddress(), right? 258 const tcu::FunctionLibrary* const library = getGLLibrary(apiType); 259 return library->getFunction(name); 260 } 261 262 void EglTestContext::getGLFunctions (glw::Functions& gl, glu::ApiType apiType) const 263 { 264 const tcu::FunctionLibrary* const library = getGLLibrary(apiType); 265 const eglu::GLFunctionLoader loader (library); 266 267 // \note There may not be current context, so we can't use initFunctions(). 268 glu::initCoreFunctions(&gl, &loader, apiType); 269 } 270 271 TestCaseGroup::TestCaseGroup (EglTestContext& eglTestCtx, const char* name, const char* description) 272 : tcu::TestCaseGroup (eglTestCtx.getTestContext(), name, description) 273 , m_eglTestCtx (eglTestCtx) 274 { 275 } 276 277 TestCaseGroup::~TestCaseGroup (void) 278 { 279 } 280 281 TestCase::TestCase (EglTestContext& eglTestCtx, const char* name, const char* description) 282 : tcu::TestCase (eglTestCtx.getTestContext(), name, description) 283 , m_eglTestCtx (eglTestCtx) 284 { 285 } 286 287 TestCase::TestCase (EglTestContext& eglTestCtx, tcu::TestNodeType type, const char* name, const char* description) 288 : tcu::TestCase (eglTestCtx.getTestContext(), type, name, description) 289 , m_eglTestCtx (eglTestCtx) 290 { 291 } 292 293 TestCase::~TestCase (void) 294 { 295 } 296 297 } // egl 298 } // deqp 299