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
strerror(EGLint err)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
selectConfigForPixelFormat(EGLDisplay dpy,EGLint const * attrs,int32_t format,EGLConfig * outConfig)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
selectConfigForNativeWindow(EGLDisplay dpy,EGLint const * attrs,EGLNativeWindowType window,EGLConfig * outConfig)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
printGLString(const char * name,GLenum s)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
printEGLString(EGLDisplay dpy,const char * name,GLenum s)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
checkGlError(const char * op)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
printEGLConfiguration(EGLDisplay dpy,EGLConfig config)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
printEGLConfigurations(EGLDisplay dpy,String8 & msg)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
printEGLConfigurations(FILE * output,EGLDisplay dpy)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
decodeColorSpace(EGLint colorSpace)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
hasExtension(const char * exts,const char * name)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
hasEglExtension(EGLDisplay dpy,const char * name)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