Home | History | Annotate | Download | only in include
      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 == NULL)
    104         return BAD_VALUE;
    105 
    106     // Get all the "potential match" configs...
    107     if (eglGetConfigs(dpy, NULL, 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 = 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) {
    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, NULL, 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_LINEAR_KHR:
    284             return String8("EGL_GL_COLORSPACE_LINEAR_KHR");
    285         default:
    286             return String8::format("UNKNOWN ColorSpace %d", colorSpace);
    287     }
    288 }
    289 
    290 bool EGLUtils::hasExtension(const char* exts, const char* name) {
    291     size_t nameLen = strlen(name);
    292     if (exts) {
    293         for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
    294             if (match[nameLen] == '\0' || match[nameLen] == ' ') {
    295                 return true;
    296             }
    297         }
    298     }
    299     return false;
    300 }
    301 
    302 bool EGLUtils::hasEglExtension(EGLDisplay dpy, const char* name) {
    303     return hasExtension(eglQueryString(dpy, EGL_EXTENSIONS), name);
    304 }
    305 
    306 // ----------------------------------------------------------------------------
    307 }; // namespace android
    308 // ----------------------------------------------------------------------------
    309 
    310 #endif /* ANDROID_UI_EGLUTILS_H */
    311