1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 #ifndef ANDROID_UI_EGLUTILS_H 19 #define ANDROID_UI_EGLUTILS_H 20 21 #include <stdint.h> 22 #include <stdlib.h> 23 #include <vector> 24 25 #include <EGL/egl.h> 26 #include <EGL/eglext.h> 27 #include <GLES2/gl2.h> 28 #include <system/window.h> 29 #include <utils/Errors.h> 30 #include <utils/String8.h> 31 32 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); 33 34 // ---------------------------------------------------------------------------- 35 namespace android { 36 // ---------------------------------------------------------------------------- 37 38 class EGLUtils 39 { 40 public: 41 42 static inline const char *strerror(EGLint err); 43 44 static inline status_t selectConfigForPixelFormat( 45 EGLDisplay dpy, 46 EGLint const* attrs, 47 int32_t format, 48 EGLConfig* outConfig); 49 50 static inline status_t selectConfigForNativeWindow( 51 EGLDisplay dpy, 52 EGLint const* attrs, 53 EGLNativeWindowType window, 54 EGLConfig* outConfig); 55 56 static inline String8 printGLString(const char* name, GLenum s); 57 static inline String8 printEGLString(EGLDisplay dpy, const char* name, GLenum s); 58 static inline String8 checkEglError(const char* op, EGLBoolean returnVal); 59 static inline String8 checkGlError(const char* op); 60 static inline String8 printEGLConfiguration(EGLDisplay dpy, EGLConfig config); 61 static inline bool printEGLConfigurations(EGLDisplay dpy, String8& msg); 62 static inline bool printEGLConfigurations(FILE* output, EGLDisplay dpy); 63 static inline String8 decodeColorSpace(EGLint colorSpace); 64 static inline bool hasEglExtension(EGLDisplay dpy, const char* name); 65 static inline bool hasExtension(const char* exts, const char* name); 66 }; 67 68 // ---------------------------------------------------------------------------- 69 70 const char *EGLUtils::strerror(EGLint err) 71 { 72 switch (err){ 73 case EGL_SUCCESS: return "EGL_SUCCESS"; 74 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 75 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 76 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 77 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 78 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 79 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 80 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 81 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 82 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 83 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 84 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 85 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 86 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 87 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 88 default: return "UNKNOWN"; 89 } 90 } 91 92 status_t EGLUtils::selectConfigForPixelFormat( 93 EGLDisplay dpy, 94 EGLint const* attrs, 95 int32_t format, 96 EGLConfig* outConfig) 97 { 98 EGLint numConfigs = -1, n=0; 99 100 if (!attrs) 101 return BAD_VALUE; 102 103 if (outConfig == nullptr) 104 return BAD_VALUE; 105 106 // Get all the "potential match" configs... 107 if (eglGetConfigs(dpy, nullptr, 0, &numConfigs) == EGL_FALSE) 108 return BAD_VALUE; 109 110 std::vector<EGLConfig> configs(numConfigs); 111 if (eglChooseConfig(dpy, attrs, configs.data(), numConfigs, &n) == EGL_FALSE) { 112 return BAD_VALUE; 113 } 114 115 int i; 116 EGLConfig config = nullptr; 117 for (i=0 ; i<n ; i++) { 118 EGLint nativeVisualId = 0; 119 eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId); 120 if (nativeVisualId>0 && format == nativeVisualId) { 121 config = configs[i]; 122 break; 123 } 124 } 125 126 if (i<n) { 127 *outConfig = config; 128 return NO_ERROR; 129 } 130 131 return NAME_NOT_FOUND; 132 } 133 134 status_t EGLUtils::selectConfigForNativeWindow( 135 EGLDisplay dpy, 136 EGLint const* attrs, 137 EGLNativeWindowType window, 138 EGLConfig* outConfig) 139 { 140 int err; 141 int format; 142 143 if (!window) 144 return BAD_VALUE; 145 146 if ((err = window->query(window, NATIVE_WINDOW_FORMAT, &format)) < 0) { 147 return err; 148 } 149 150 return selectConfigForPixelFormat(dpy, attrs, format, outConfig); 151 } 152 153 String8 EGLUtils::printGLString(const char* name, GLenum s) { 154 String8 msg; 155 const char* v = reinterpret_cast<const char*>(glGetString(s)); 156 msg.appendFormat("GL %s = %s\n", name, v); 157 return msg; 158 } 159 160 String8 EGLUtils::printEGLString(EGLDisplay dpy, const char* name, GLenum s) { 161 String8 msg; 162 const char* v = static_cast<const char*>(eglQueryString(dpy, s)); 163 msg.appendFormat("GL %s = %s\n", name, v); 164 const char* va = (const char*)eglQueryStringImplementationANDROID(dpy, s); 165 msg.appendFormat("ImplementationANDROID: %s = %s\n", name, va); 166 return msg; 167 } 168 169 String8 EGLUtils::checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { 170 String8 msg; 171 if (returnVal != EGL_TRUE) { 172 msg.appendFormat("%s() returned %d\n", op, returnVal); 173 } 174 175 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { 176 msg.appendFormat("after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), error); 177 } 178 return msg; 179 } 180 181 String8 EGLUtils::checkGlError(const char* op) { 182 String8 msg; 183 for (GLint error = glGetError(); error != GL_NO_ERROR; error = glGetError()) { 184 msg.appendFormat("after %s() glError (0x%x)\n", op, error); 185 } 186 return msg; 187 } 188 189 String8 EGLUtils::printEGLConfiguration(EGLDisplay dpy, EGLConfig config) { 190 #define X(VAL) \ 191 { VAL, #VAL } 192 struct { 193 EGLint attribute; 194 const char* name; 195 } names[] = { 196 X(EGL_BUFFER_SIZE), 197 X(EGL_ALPHA_SIZE), 198 X(EGL_BLUE_SIZE), 199 X(EGL_GREEN_SIZE), 200 X(EGL_RED_SIZE), 201 X(EGL_DEPTH_SIZE), 202 X(EGL_STENCIL_SIZE), 203 X(EGL_CONFIG_CAVEAT), 204 X(EGL_CONFIG_ID), 205 X(EGL_LEVEL), 206 X(EGL_MAX_PBUFFER_HEIGHT), 207 X(EGL_MAX_PBUFFER_PIXELS), 208 X(EGL_MAX_PBUFFER_WIDTH), 209 X(EGL_NATIVE_RENDERABLE), 210 X(EGL_NATIVE_VISUAL_ID), 211 X(EGL_NATIVE_VISUAL_TYPE), 212 X(EGL_SAMPLES), 213 X(EGL_SAMPLE_BUFFERS), 214 X(EGL_SURFACE_TYPE), 215 X(EGL_TRANSPARENT_TYPE), 216 X(EGL_TRANSPARENT_RED_VALUE), 217 X(EGL_TRANSPARENT_GREEN_VALUE), 218 X(EGL_TRANSPARENT_BLUE_VALUE), 219 X(EGL_BIND_TO_TEXTURE_RGB), 220 X(EGL_BIND_TO_TEXTURE_RGBA), 221 X(EGL_MIN_SWAP_INTERVAL), 222 X(EGL_MAX_SWAP_INTERVAL), 223 X(EGL_LUMINANCE_SIZE), 224 X(EGL_ALPHA_MASK_SIZE), 225 X(EGL_COLOR_BUFFER_TYPE), 226 X(EGL_RENDERABLE_TYPE), 227 X(EGL_CONFORMANT), 228 }; 229 #undef X 230 231 String8 msg; 232 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) { 233 EGLint value = -1; 234 EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value); 235 EGLint error = eglGetError(); 236 if (returnVal && error == EGL_SUCCESS) { 237 msg.appendFormat(" %s: %d (0x%x)", names[j].name, value, value); 238 } 239 } 240 msg.append("\n"); 241 return msg; 242 } 243 244 bool EGLUtils::printEGLConfigurations(EGLDisplay dpy, String8& msg) { 245 EGLint numConfig = 0; 246 EGLint returnVal = eglGetConfigs(dpy, nullptr, 0, &numConfig); 247 msg.append(checkEglError("eglGetConfigs", returnVal)); 248 if (!returnVal) { 249 return false; 250 } 251 252 msg.appendFormat("Number of EGL configuration: %d\n", numConfig); 253 254 std::vector<EGLConfig> configs(numConfig); 255 256 returnVal = eglGetConfigs(dpy, configs.data(), numConfig, &numConfig); 257 msg.append(checkEglError("eglGetConfigs", returnVal)); 258 if (!returnVal) { 259 return false; 260 } 261 262 for (int i = 0; i < numConfig; i++) { 263 msg.appendFormat("Configuration %d\n", i); 264 msg.append(printEGLConfiguration(dpy, configs[i])); 265 } 266 267 return true; 268 } 269 270 bool EGLUtils::printEGLConfigurations(FILE* output, EGLDisplay dpy) { 271 String8 msg; 272 bool status = printEGLConfigurations(dpy, msg); 273 fprintf(output, "%s", msg.c_str()); 274 return status; 275 } 276 277 String8 EGLUtils::decodeColorSpace(EGLint colorSpace) { 278 switch (colorSpace) { 279 case EGL_GL_COLORSPACE_SRGB_KHR: 280 return String8("EGL_GL_COLORSPACE_SRGB_KHR"); 281 case EGL_GL_COLORSPACE_DISPLAY_P3_EXT: 282 return String8("EGL_GL_COLORSPACE_DISPLAY_P3_EXT"); 283 case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT: 284 return String8("EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT"); 285 case EGL_GL_COLORSPACE_LINEAR_KHR: 286 return String8("EGL_GL_COLORSPACE_LINEAR_KHR"); 287 default: 288 return String8::format("UNKNOWN ColorSpace %d", colorSpace); 289 } 290 } 291 292 bool EGLUtils::hasExtension(const char* exts, const char* name) { 293 size_t nameLen = strlen(name); 294 if (exts) { 295 for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) { 296 if (match[nameLen] == '\0' || match[nameLen] == ' ') { 297 return true; 298 } 299 } 300 } 301 return false; 302 } 303 304 bool EGLUtils::hasEglExtension(EGLDisplay dpy, const char* name) { 305 return hasExtension(eglQueryString(dpy, EGL_EXTENSIONS), name); 306 } 307 308 // ---------------------------------------------------------------------------- 309 }; // namespace android 310 // ---------------------------------------------------------------------------- 311 312 #endif /* ANDROID_UI_EGLUTILS_H */ 313