2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #ifndef ANDROID_UI_EGLUTILS_H
19 #define ANDROID_UI_EGLUTILS_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>
32 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
42 static inline const char *strerror(EGLint err);
44 static inline status_t selectConfigForPixelFormat(
48 EGLConfig* outConfig);
50 static inline status_t selectConfigForNativeWindow(
53 EGLNativeWindowType window,
54 EGLConfig* outConfig);
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);
68 // ----------------------------------------------------------------------------
70 const char *EGLUtils::strerror(EGLint 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";
92 status_t EGLUtils::selectConfigForPixelFormat(
98 EGLint numConfigs = -1, n=0;
103 if (outConfig == NULL)
106 // Get all the "potential match" configs...
107 if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
110 std::vector<EGLConfig> configs(numConfigs);
111 if (eglChooseConfig(dpy, attrs, configs.data(), numConfigs, &n) == EGL_FALSE) {
116 EGLConfig config = NULL;
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) {
131 return NAME_NOT_FOUND;
134 status_t EGLUtils::selectConfigForNativeWindow(
137 EGLNativeWindowType window,
138 EGLConfig* outConfig)
146 if ((err = window->query(window, NATIVE_WINDOW_FORMAT, &format)) < 0) {
150 return selectConfigForPixelFormat(dpy, attrs, format, outConfig);
153 String8 EGLUtils::printGLString(const char* name, GLenum s) {
155 const char* v = reinterpret_cast<const char*>(glGetString(s));
156 msg.appendFormat("GL %s = %s\n", name, v);
160 String8 EGLUtils::printEGLString(EGLDisplay dpy, const char* name, GLenum s) {
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);
169 String8 EGLUtils::checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
171 if (returnVal != EGL_TRUE) {
172 msg.appendFormat("%s() returned %d\n", op, returnVal);
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);
181 String8 EGLUtils::checkGlError(const char* op) {
183 for (GLint error = glGetError(); error != GL_NO_ERROR; error = glGetError()) {
184 msg.appendFormat("after %s() glError (0x%x)\n", op, error);
189 String8 EGLUtils::printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
203 X(EGL_CONFIG_CAVEAT),
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),
213 X(EGL_SAMPLE_BUFFERS),
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),
232 for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
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);
244 bool EGLUtils::printEGLConfigurations(EGLDisplay dpy, String8& msg) {
245 EGLint numConfig = 0;
246 EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
247 msg.append(checkEglError("eglGetConfigs", returnVal));
252 msg.appendFormat("Number of EGL configuration: %d\n", numConfig);
254 std::vector<EGLConfig> configs(numConfig);
256 returnVal = eglGetConfigs(dpy, configs.data(), numConfig, &numConfig);
257 msg.append(checkEglError("eglGetConfigs", returnVal));
262 for (int i = 0; i < numConfig; i++) {
263 msg.appendFormat("Configuration %d\n", i);
264 msg.append(printEGLConfiguration(dpy, configs[i]));
270 bool EGLUtils::printEGLConfigurations(FILE* output, EGLDisplay dpy) {
272 bool status = printEGLConfigurations(dpy, msg);
273 fprintf(output, "%s", msg.c_str());
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_LINEAR_KHR:
284 return String8("EGL_GL_COLORSPACE_LINEAR_KHR");
286 return String8::format("UNKNOWN ColorSpace %d", colorSpace);
290 bool EGLUtils::hasExtension(const char* exts, const char* name) {
291 size_t nameLen = strlen(name);
293 for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
294 if (match[nameLen] == '\0' || match[nameLen] == ' ') {
302 bool EGLUtils::hasEglExtension(EGLDisplay dpy, const char* name) {
303 return hasExtension(eglQueryString(dpy, EGL_EXTENSIONS), name);
306 // ----------------------------------------------------------------------------
307 }; // namespace android
308 // ----------------------------------------------------------------------------
310 #endif /* ANDROID_UI_EGLUTILS_H */