egluUtil.cpp revision 3c827367444ee418f129b2c238299f49d3264554
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 22 *//*--------------------------------------------------------------------*/ 23 24#include "egluUtil.hpp" 25#include "egluDefs.hpp" 26#include "egluNativeDisplay.hpp" 27#include "tcuCommandLine.hpp" 28#include "deSTLUtil.hpp" 29 30#include <algorithm> 31#include <sstream> 32 33using std::string; 34using std::vector; 35 36#if !defined(EGL_EXT_platform_base) 37# define EGL_EXT_platform_base 1 38 typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); 39 typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); 40 typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); 41#endif // EGL_EXT_platform_base 42 43namespace eglu 44{ 45 46vector<string> getPlatformExtensions (void) 47{ 48 const char* const extensionStr = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); 49 const EGLint result = eglGetError(); 50 51 if (result == EGL_SUCCESS) 52 { 53 std::istringstream stream (extensionStr); 54 string currentExtension; 55 vector<string> extensions; 56 57 while (std::getline(stream, currentExtension, ' ')) 58 extensions.push_back(currentExtension); 59 60 return extensions; 61 } 62 else if (result != EGL_BAD_DISPLAY) 63 throw Error(result, "eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS)", DE_NULL, __FILE__, __LINE__); 64 else 65 return vector<string>(); 66} 67 68vector<string> getClientExtensions (EGLDisplay display) 69{ 70 const char* const extensionStr = eglQueryString(display, EGL_EXTENSIONS); 71 const EGLint result = eglGetError(); 72 73 if (result == EGL_SUCCESS) 74 { 75 std::istringstream stream (extensionStr); 76 string currentExtension; 77 vector<string> extensions; 78 79 while (std::getline(stream, currentExtension, ' ')) 80 extensions.push_back(currentExtension); 81 82 return extensions; 83 } 84 else 85 throw Error(result, "eglQueryString(display, EGL_EXTENSIONS)", DE_NULL, __FILE__, __LINE__); 86} 87 88vector<EGLConfig> getConfigs (EGLDisplay display) 89{ 90 vector<EGLConfig> configs; 91 EGLint configCount = 0; 92 EGLU_CHECK_CALL(eglGetConfigs(display, DE_NULL, 0, &configCount)); 93 94 if (configCount > 0) 95 { 96 configs.resize(configCount); 97 EGLU_CHECK_CALL(eglGetConfigs(display, &(configs[0]), (EGLint)configs.size(), &configCount)); 98 } 99 100 return configs; 101} 102 103vector<EGLConfig> chooseConfig (EGLDisplay display, const AttribMap& attribs) 104{ 105 vector<EGLint> attribList; 106 107 for (AttribMap::const_iterator it = attribs.begin(); it != attribs.end(); ++it) 108 { 109 attribList.push_back(it->first); 110 attribList.push_back(it->second); 111 } 112 113 attribList.push_back(EGL_NONE); 114 115 { 116 EGLint numConfigs = 0; 117 EGLU_CHECK_CALL(eglChooseConfig(display, &attribList.front(), DE_NULL, 0, &numConfigs)); 118 119 { 120 vector<EGLConfig> configs(numConfigs); 121 122 if (numConfigs > 0) 123 EGLU_CHECK_CALL(eglChooseConfig(display, &attribList.front(), &configs.front(), numConfigs, &numConfigs)); 124 125 return configs; 126 } 127 } 128} 129 130EGLConfig chooseSingleConfig (EGLDisplay display, const AttribMap& attribs) 131{ 132 vector<EGLConfig> configs (chooseConfig(display, attribs)); 133 if (configs.empty()) 134 TCU_THROW(NotSupportedError, "No suitable EGL configuration found"); 135 136 return configs.front(); 137} 138 139EGLint getConfigAttribInt (EGLDisplay display, EGLConfig config, EGLint attrib) 140{ 141 EGLint value = 0; 142 EGLU_CHECK_CALL(eglGetConfigAttrib(display, config, attrib, &value)); 143 return value; 144} 145 146EGLint querySurfaceInt (EGLDisplay display, EGLSurface surface, EGLint attrib) 147{ 148 EGLint value = 0; 149 EGLU_CHECK_CALL(eglQuerySurface(display, surface, attrib, &value)); 150 return value; 151} 152 153tcu::IVec2 getSurfaceSize (EGLDisplay display, EGLSurface surface) 154{ 155 const EGLint width = querySurfaceInt(display, surface, EGL_WIDTH); 156 const EGLint height = querySurfaceInt(display, surface, EGL_HEIGHT); 157 return tcu::IVec2(width, height); 158} 159 160tcu::IVec2 getSurfaceResolution (EGLDisplay display, EGLSurface surface) 161{ 162 const EGLint hRes = querySurfaceInt(display, surface, EGL_HORIZONTAL_RESOLUTION); 163 const EGLint vRes = querySurfaceInt(display, surface, EGL_VERTICAL_RESOLUTION); 164 165 if (hRes == EGL_UNKNOWN || vRes == EGL_UNKNOWN) 166 TCU_THROW(NotSupportedError, "Surface doesn't support pixel density queries"); 167 return tcu::IVec2(hRes, vRes); 168} 169 170//! Get EGLdisplay using eglGetDisplay() or eglGetPlatformDisplayEXT() 171EGLDisplay getDisplay (NativeDisplay& nativeDisplay) 172{ 173 const bool supportsLegacyGetDisplay = (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY) != 0; 174 const bool supportsPlatformGetDisplay = (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM) != 0; 175 bool usePlatformExt = false; 176 EGLDisplay display = EGL_NO_DISPLAY; 177 178 TCU_CHECK_INTERNAL(supportsLegacyGetDisplay || supportsPlatformGetDisplay); 179 180 if (supportsPlatformGetDisplay) 181 { 182 const vector<string> platformExts = getPlatformExtensions(); 183 usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) && 184 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName())); 185 } 186 187 if (usePlatformExt) 188 { 189 const PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); 190 191 EGLU_CHECK_MSG("eglGetProcAddress()"); 192 TCU_CHECK(getPlatformDisplay); 193 194 display = getPlatformDisplay(nativeDisplay.getPlatformType(), nativeDisplay.getPlatformNative(), DE_NULL); 195 EGLU_CHECK_MSG("eglGetPlatformDisplayEXT()"); 196 TCU_CHECK(display != EGL_NO_DISPLAY); 197 } 198 else if (supportsLegacyGetDisplay) 199 { 200 display = eglGetDisplay(nativeDisplay.getLegacyNative()); 201 EGLU_CHECK_MSG("eglGetDisplay()"); 202 TCU_CHECK(display != EGL_NO_DISPLAY); 203 } 204 else 205 throw tcu::InternalError("No supported way to get EGL display", DE_NULL, __FILE__, __LINE__); 206 207 DE_ASSERT(display != EGL_NO_DISPLAY); 208 return display; 209} 210 211//! Create EGL window surface using eglCreateWindowSurface() or eglCreatePlatformWindowSurfaceEXT() 212EGLSurface createWindowSurface (NativeDisplay& nativeDisplay, NativeWindow& window, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList) 213{ 214 const bool supportsLegacyCreate = (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY) != 0; 215 const bool supportsPlatformCreate = (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0; 216 bool usePlatformExt = false; 217 EGLSurface surface = EGL_NO_SURFACE; 218 219 TCU_CHECK_INTERNAL(supportsLegacyCreate || supportsPlatformCreate); 220 221 if (supportsPlatformCreate) 222 { 223 const vector<string> platformExts = getPlatformExtensions(); 224 usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) && 225 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName())); 226 } 227 228 // \todo [2014-03-13 pyry] EGL 1.5 core support 229 if (usePlatformExt) 230 { 231 const PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); 232 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList); 233 234 EGLU_CHECK_MSG("eglGetProcAddress()"); 235 TCU_CHECK(createPlatformWindowSurface); 236 237 surface = createPlatformWindowSurface(display, config, window.getPlatformNative(), &legacyAttribs[0]); 238 EGLU_CHECK_MSG("eglCreatePlatformWindowSurfaceEXT()"); 239 TCU_CHECK(surface != EGL_NO_SURFACE); 240 } 241 else if (supportsLegacyCreate) 242 { 243 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList); 244 surface = eglCreateWindowSurface(display, config, window.getLegacyNative(), &legacyAttribs[0]); 245 EGLU_CHECK_MSG("eglCreateWindowSurface()"); 246 TCU_CHECK(surface != EGL_NO_SURFACE); 247 } 248 else 249 throw tcu::InternalError("No supported way to create EGL window surface", DE_NULL, __FILE__, __LINE__); 250 251 DE_ASSERT(surface != EGL_NO_SURFACE); 252 return surface; 253} 254 255//! Create EGL pixmap surface using eglCreatePixmapSurface() or eglCreatePlatformPixmapSurfaceEXT() 256EGLSurface createPixmapSurface (NativeDisplay& nativeDisplay, NativePixmap& pixmap, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList) 257{ 258 const bool supportsLegacyCreate = (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) != 0; 259 const bool supportsPlatformCreate = (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0; 260 bool usePlatformExt = false; 261 EGLSurface surface = EGL_NO_SURFACE; 262 263 TCU_CHECK_INTERNAL(supportsLegacyCreate || supportsPlatformCreate); 264 265 if (supportsPlatformCreate) 266 { 267 const vector<string> platformExts = getPlatformExtensions(); 268 usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) && 269 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName())); 270 } 271 272 if (usePlatformExt) 273 { 274 const PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC createPlatformPixmapSurface = (PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformPixmapSurfaceEXT"); 275 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList); 276 277 EGLU_CHECK_MSG("eglGetProcAddress()"); 278 TCU_CHECK(createPlatformPixmapSurface); 279 280 surface = createPlatformPixmapSurface(display, config, pixmap.getPlatformNative(), &legacyAttribs[0]); 281 EGLU_CHECK_MSG("eglCreatePlatformPixmapSurfaceEXT()"); 282 TCU_CHECK(surface != EGL_NO_SURFACE); 283 } 284 else if (supportsLegacyCreate) 285 { 286 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList); 287 surface = eglCreatePixmapSurface(display, config, pixmap.getLegacyNative(), &legacyAttribs[0]); 288 EGLU_CHECK_MSG("eglCreatePixmapSurface()"); 289 TCU_CHECK(surface != EGL_NO_SURFACE); 290 } 291 else 292 throw tcu::InternalError("No supported way to create EGL pixmap surface", DE_NULL, __FILE__, __LINE__); 293 294 DE_ASSERT(surface != EGL_NO_SURFACE); 295 return surface; 296} 297 298static WindowParams::Visibility getWindowVisibility (tcu::WindowVisibility visibility) 299{ 300 switch (visibility) 301 { 302 case tcu::WINDOWVISIBILITY_WINDOWED: return WindowParams::VISIBILITY_VISIBLE; 303 case tcu::WINDOWVISIBILITY_FULLSCREEN: return WindowParams::VISIBILITY_FULLSCREEN; 304 case tcu::WINDOWVISIBILITY_HIDDEN: return WindowParams::VISIBILITY_HIDDEN; 305 306 default: 307 DE_ASSERT(false); 308 return WindowParams::VISIBILITY_DONT_CARE; 309 } 310} 311 312WindowParams::Visibility parseWindowVisibility (const tcu::CommandLine& commandLine) 313{ 314 return getWindowVisibility(commandLine.getVisibility()); 315} 316 317vector<EGLint> toLegacyAttribList (const EGLAttrib* attribs) 318{ 319 const deUint64 attribMask = 0xffffffffull; //!< Max bits that can be used 320 vector<EGLint> legacyAttribs; 321 322 if (attribs) 323 { 324 for (const EGLAttrib* attrib = attribs; *attrib != EGL_NONE; attrib += 2) 325 { 326 if ((attrib[0] & ~attribMask) || (attrib[1] & ~attribMask)) 327 throw tcu::InternalError("Failed to translate EGLAttrib to EGLint", DE_NULL, __FILE__, __LINE__); 328 329 legacyAttribs.push_back((EGLint)attrib[0]); 330 legacyAttribs.push_back((EGLint)attrib[1]); 331 } 332 } 333 334 legacyAttribs.push_back(EGL_NONE); 335 336 return legacyAttribs; 337} 338 339} // eglu 340