Home | History | Annotate | Download | only in libOpenglRender
      1 /*
      2 * Copyright (C) 2011 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 #include "FBConfig.h"
     17 #include "FrameBuffer.h"
     18 #include "EGLDispatch.h"
     19 #include <stdio.h>
     20 
     21 FBConfig **FBConfig::s_fbConfigs = NULL;
     22 int FBConfig::s_numConfigs = 0;
     23 
     24 const GLuint FBConfig::s_configAttribs[] = {
     25     EGL_DEPTH_SIZE,     // must be first - see getDepthSize()
     26     EGL_STENCIL_SIZE,   // must be second - see getStencilSize()
     27     EGL_RENDERABLE_TYPE,// must be third - see getRenderableType()
     28     EGL_SURFACE_TYPE,   // must be fourth - see getSurfaceType()
     29     EGL_CONFIG_ID,      // must be fifth  - see chooseConfig()
     30     EGL_BUFFER_SIZE,
     31     EGL_ALPHA_SIZE,
     32     EGL_BLUE_SIZE,
     33     EGL_GREEN_SIZE,
     34     EGL_RED_SIZE,
     35     EGL_CONFIG_CAVEAT,
     36     EGL_LEVEL,
     37     EGL_MAX_PBUFFER_HEIGHT,
     38     EGL_MAX_PBUFFER_PIXELS,
     39     EGL_MAX_PBUFFER_WIDTH,
     40     EGL_NATIVE_RENDERABLE,
     41     EGL_NATIVE_VISUAL_ID,
     42     EGL_NATIVE_VISUAL_TYPE,
     43     EGL_SAMPLES,
     44     EGL_SAMPLE_BUFFERS,
     45     EGL_TRANSPARENT_TYPE,
     46     EGL_TRANSPARENT_BLUE_VALUE,
     47     EGL_TRANSPARENT_GREEN_VALUE,
     48     EGL_TRANSPARENT_RED_VALUE,
     49     EGL_BIND_TO_TEXTURE_RGB,
     50     EGL_BIND_TO_TEXTURE_RGBA,
     51     EGL_MIN_SWAP_INTERVAL,
     52     EGL_MAX_SWAP_INTERVAL,
     53     EGL_LUMINANCE_SIZE,
     54     EGL_ALPHA_MASK_SIZE,
     55     EGL_COLOR_BUFFER_TYPE,
     56     //EGL_MATCH_NATIVE_PIXMAP,
     57     EGL_CONFORMANT
     58 };
     59 
     60 const int FBConfig::s_numConfigAttribs = sizeof(FBConfig::s_configAttribs) / sizeof(GLuint);
     61 
     62 InitConfigStatus FBConfig::initConfigList(FrameBuffer *fb)
     63 {
     64     InitConfigStatus ret = INIT_CONFIG_FAILED;
     65 
     66     if (!fb) {
     67         return ret;
     68     }
     69 
     70     EGLDisplay dpy = fb->getDisplay();
     71 
     72     if (dpy == EGL_NO_DISPLAY) {
     73         fprintf(stderr,"Could not get EGL Display\n");
     74         return ret;
     75     }
     76 
     77     //
     78     // Query the set of configs in the EGL backend
     79     //
     80     EGLint nConfigs;
     81     if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
     82         fprintf(stderr, "Could not get number of available configs\n");
     83         return ret;
     84     }
     85     EGLConfig *configs = new EGLConfig[nConfigs];
     86     s_egl.eglGetConfigs(dpy, configs, nConfigs, &nConfigs);
     87 
     88     //
     89     // copy the config attributes, filter out
     90     // configs we do not want to support.
     91     //
     92     int j = 0;
     93     s_fbConfigs = new FBConfig*[nConfigs];
     94     for (int i=0; i<nConfigs; i++) {
     95 
     96         //
     97         // filter out configs which does not support pbuffers.
     98         // we only support pbuffer configs since we use a pbuffer
     99         // handle to bind a guest created window object.
    100         //
    101         EGLint surfaceType;
    102         s_egl.eglGetConfigAttrib(dpy, configs[i],
    103                                  EGL_SURFACE_TYPE, &surfaceType);
    104         if (!(surfaceType & EGL_PBUFFER_BIT)) continue;
    105 
    106         //
    107         // Filter out not RGB configs
    108         //
    109         EGLint redSize, greenSize, blueSize;
    110         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE, &redSize);
    111         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE, &blueSize);
    112         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &greenSize);
    113         if (redSize==0 || greenSize==0 || blueSize==0) continue;
    114 
    115         s_fbConfigs[j++] = new FBConfig(dpy, configs[i]);
    116     }
    117     s_numConfigs = j;
    118 
    119     delete[] configs;
    120 
    121     return s_numConfigs > 0 ? INIT_CONFIG_PASSED : INIT_CONFIG_FAILED;
    122 }
    123 
    124 const FBConfig *FBConfig::get(int p_config)
    125 {
    126     if (p_config >= 0 && p_config < s_numConfigs) {
    127         return s_fbConfigs[p_config];
    128     }
    129     return NULL;
    130 }
    131 
    132 int FBConfig::getNumConfigs()
    133 {
    134     return s_numConfigs;
    135 }
    136 
    137 void FBConfig::packConfigsInfo(GLuint *buffer)
    138 {
    139     memcpy(buffer, s_configAttribs, s_numConfigAttribs * sizeof(GLuint));
    140     for (int i=0; i<s_numConfigs; i++) {
    141         memcpy(buffer+(i+1)*s_numConfigAttribs,
    142                s_fbConfigs[i]->m_attribValues,
    143                s_numConfigAttribs * sizeof(GLuint));
    144     }
    145 }
    146 
    147 int FBConfig::chooseConfig(FrameBuffer *fb, EGLint * attribs, uint32_t * configs, uint32_t configs_size)
    148 {
    149     EGLDisplay dpy = fb->getDisplay();
    150     int ret = 0;
    151 
    152     if (dpy == EGL_NO_DISPLAY) {
    153         fprintf(stderr,"Could not get EGL Display\n");
    154         return ret;
    155     }
    156     //
    157     // Query the num of configs in the EGL backend
    158     //
    159     EGLint nConfigs;
    160     if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
    161         fprintf(stderr, "Could not get number of available configs\n");
    162         return ret;
    163     }
    164     //
    165     // Query the max matching configs in the backend
    166     //
    167     EGLConfig *matchedConfigs = new EGLConfig[nConfigs];
    168 
    169     //
    170     //Until we have EGLImage implementation, we force pbuf configs
    171     //
    172     bool needToAddPbufAttr = true;
    173     int attribCnt = 0;
    174     EGLint * attrib_p = attribs;
    175     if (attribs) {
    176         while (attrib_p[0] != EGL_NONE) {
    177             if (attrib_p[0] == EGL_SURFACE_TYPE) {
    178                 attrib_p[1] = EGL_PBUFFER_BIT; //replace whatever was there before
    179                 needToAddPbufAttr = false;
    180             }
    181             attrib_p += 2;
    182             attribCnt += 2;
    183         }
    184     }
    185     EGLint * newAttribs = new EGLint[attribCnt + 1 + ((needToAddPbufAttr) ? 2 : 0)];
    186     attrib_p = newAttribs;
    187     if (needToAddPbufAttr) {
    188         *(attrib_p++) = EGL_SURFACE_TYPE;
    189         *(attrib_p++) = EGL_PBUFFER_BIT;
    190     }
    191     memcpy(attrib_p, attribs, attribCnt*sizeof(EGLint));
    192     attrib_p += attribCnt;
    193     *attrib_p = EGL_NONE;
    194 
    195 #if 0
    196     if (newAttribs) {
    197         EGLint * attrib_p = newAttribs;
    198         while (attrib_p[0] != EGL_NONE) {
    199             DBG("attr: 0x%x %d, ", attrib_p[0], attrib_p[1]);
    200             attrib_p += 2;
    201         }
    202     }
    203 #endif
    204 
    205     if (!s_egl.eglChooseConfig(dpy, newAttribs, matchedConfigs, nConfigs, &nConfigs)) {
    206         nConfigs = 0;
    207     }
    208 
    209     delete[] newAttribs;
    210 
    211     //
    212     // From all matchedConfigs we need only config_size FBConfigs, so we intersect both lists compating the CONFIG_ID attribute
    213     //
    214     uint32_t nVerifiedCfgs = 0;
    215     for (int matchedIdx=0; matchedIdx<nConfigs; matchedIdx++) {
    216         if ((configs != NULL) && (configs_size > 0) && (nVerifiedCfgs >= configs_size)) break; //We have enouhgt configs
    217         int sCfgId;
    218         s_egl.eglGetConfigAttrib(dpy, matchedConfigs[matchedIdx], EGL_CONFIG_ID, &sCfgId);
    219         for (int fbIdx=0; fbIdx<s_numConfigs; fbIdx++) {
    220             int dCfgId = s_fbConfigs[fbIdx]->m_attribValues[4]; //CONFIG_ID
    221             if (sCfgId == dCfgId) {
    222                 //This config matches the requested attributes and filtered into fbConfigs, so we're happy with it
    223                 if (configs && nVerifiedCfgs < configs_size) {
    224                     configs[nVerifiedCfgs] = fbIdx;
    225                 }
    226                 nVerifiedCfgs++;
    227                 break;
    228             }
    229         }
    230     }
    231 
    232     delete[] matchedConfigs;
    233 
    234     return nVerifiedCfgs;
    235 }
    236 
    237 FBConfig::FBConfig(EGLDisplay p_eglDpy, EGLConfig p_eglCfg)
    238 {
    239     m_eglConfig = p_eglCfg;
    240     m_attribValues = new GLint[s_numConfigAttribs];
    241     for (int i=0; i<s_numConfigAttribs; i++) {
    242         m_attribValues[i] = 0;
    243         s_egl.eglGetConfigAttrib(p_eglDpy, p_eglCfg, s_configAttribs[i], &m_attribValues[i]);
    244 
    245         //
    246         // All exported configs supports android native window rendering
    247         //
    248         if (s_configAttribs[i] == EGL_SURFACE_TYPE) {
    249             m_attribValues[i] |= EGL_WINDOW_BIT;
    250         }
    251     }
    252 }
    253 
    254 FBConfig::~FBConfig()
    255 {
    256     if (m_attribValues) {
    257         delete[] m_attribValues;
    258     }
    259 }
    260