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     const FrameBufferCaps &caps = fb->getCaps();
     71     EGLDisplay dpy = fb->getDisplay();
     72 
     73     if (dpy == EGL_NO_DISPLAY) {
     74         fprintf(stderr,"Could not get EGL Display\n");
     75         return ret;
     76     }
     77 
     78     //
     79     // Query the set of configs in the EGL backend
     80     //
     81     EGLint nConfigs;
     82     if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
     83         fprintf(stderr, "Could not get number of available configs\n");
     84         return ret;
     85     }
     86     EGLConfig *configs = new EGLConfig[nConfigs];
     87     s_egl.eglGetConfigs(dpy, configs, nConfigs, &nConfigs);
     88 
     89     //
     90     // copy the config attributes, filter out
     91     // configs we do not want to support.
     92     //
     93     int j = 0;
     94     s_fbConfigs = new FBConfig*[nConfigs];
     95     for (int i=0; i<nConfigs; i++) {
     96 
     97         //
     98         // filter out configs which does not support pbuffers.
     99         // we only support pbuffer configs since we use a pbuffer
    100         // handle to bind a guest created window object.
    101         //
    102         EGLint surfaceType;
    103         s_egl.eglGetConfigAttrib(dpy, configs[i],
    104                                  EGL_SURFACE_TYPE, &surfaceType);
    105         if (!(surfaceType & EGL_PBUFFER_BIT)) continue;
    106 
    107         //
    108         // Filter out not RGB configs
    109         //
    110         EGLint redSize, greenSize, blueSize;
    111         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE, &redSize);
    112         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE, &blueSize);
    113         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &greenSize);
    114         if (redSize==0 || greenSize==0 || blueSize==0) continue;
    115 
    116         s_fbConfigs[j++] = new FBConfig(dpy, configs[i]);
    117     }
    118     s_numConfigs = j;
    119 
    120     delete[] configs;
    121 
    122     return s_numConfigs > 0 ? INIT_CONFIG_PASSED : INIT_CONFIG_FAILED;
    123 }
    124 
    125 const FBConfig *FBConfig::get(int p_config)
    126 {
    127     if (p_config >= 0 && p_config < s_numConfigs) {
    128         return s_fbConfigs[p_config];
    129     }
    130     return NULL;
    131 }
    132 
    133 int FBConfig::getNumConfigs()
    134 {
    135     return s_numConfigs;
    136 }
    137 
    138 void FBConfig::packConfigsInfo(GLuint *buffer)
    139 {
    140     memcpy(buffer, s_configAttribs, s_numConfigAttribs * sizeof(GLuint));
    141     for (int i=0; i<s_numConfigs; i++) {
    142         memcpy(buffer+(i+1)*s_numConfigAttribs,
    143                s_fbConfigs[i]->m_attribValues,
    144                s_numConfigAttribs * sizeof(GLuint));
    145     }
    146 }
    147 
    148 int FBConfig::chooseConfig(FrameBuffer *fb, EGLint * attribs, uint32_t * configs, uint32_t configs_size)
    149 {
    150     EGLDisplay dpy = fb->getDisplay();
    151     int ret = 0;
    152 
    153     if (dpy == EGL_NO_DISPLAY) {
    154         fprintf(stderr,"Could not get EGL Display\n");
    155         return ret;
    156     }
    157     //
    158     // Query the num of configs in the EGL backend
    159     //
    160     EGLint nConfigs;
    161     if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
    162         fprintf(stderr, "Could not get number of available configs\n");
    163         return ret;
    164     }
    165     //
    166     // Query the max matching configs in the backend
    167     //
    168     EGLConfig *matchedConfigs = new EGLConfig[nConfigs];
    169 
    170     //
    171     //Until we have EGLImage implementation, we force pbuf configs
    172     //
    173     bool needToAddPbufAttr = true;
    174     int attribCnt = 0;
    175     EGLint * attrib_p = attribs;
    176     if (attribs) {
    177         while (attrib_p[0] != EGL_NONE) {
    178             if (attrib_p[0] == EGL_SURFACE_TYPE) {
    179                 attrib_p[1] = EGL_PBUFFER_BIT; //replace whatever was there before
    180                 needToAddPbufAttr = false;
    181             }
    182             attrib_p += 2;
    183             attribCnt += 2;
    184         }
    185     }
    186     EGLint * newAttribs = new EGLint[attribCnt + 1 + ((needToAddPbufAttr) ? 2 : 0)];
    187     attrib_p = newAttribs;
    188     if (needToAddPbufAttr) {
    189         *(attrib_p++) = EGL_SURFACE_TYPE;
    190         *(attrib_p++) = EGL_PBUFFER_BIT;
    191     }
    192     memcpy(attrib_p, attribs, attribCnt*sizeof(EGLint));
    193     attrib_p += attribCnt;
    194     *attrib_p = EGL_NONE;
    195 
    196 #if 0
    197     if (newAttribs) {
    198         EGLint * attrib_p = newAttribs;
    199         while (attrib_p[0] != EGL_NONE) {
    200             DBG("attr: 0x%x %d, ", attrib_p[0], attrib_p[1]);
    201             attrib_p += 2;
    202         }
    203     }
    204 #endif
    205 
    206     s_egl.eglChooseConfig(dpy, newAttribs, matchedConfigs, nConfigs, &nConfigs);
    207 
    208     delete[] newAttribs;
    209 
    210     //
    211     // From all matchedConfigs we need only config_size FBConfigs, so we intersect both lists compating the CONFIG_ID attribute
    212     //
    213     uint32_t nVerifiedCfgs = 0;
    214     for (int matchedIdx=0; matchedIdx<nConfigs; matchedIdx++) {
    215         if ((configs != NULL) && (configs_size > 0) && (nVerifiedCfgs >= configs_size)) break; //We have enouhgt configs
    216         int sCfgId;
    217         s_egl.eglGetConfigAttrib(dpy, matchedConfigs[matchedIdx], EGL_CONFIG_ID, &sCfgId);
    218         for (int fbIdx=0; fbIdx<s_numConfigs; fbIdx++) {
    219             int dCfgId = s_fbConfigs[fbIdx]->m_attribValues[4]; //CONFIG_ID
    220             if (sCfgId == dCfgId) {
    221                 //This config matches the requested attributes and filtered into fbConfigs, so we're happy with it
    222                 if (configs && nVerifiedCfgs < configs_size) {
    223                     configs[nVerifiedCfgs] = fbIdx;
    224                 }
    225                 nVerifiedCfgs++;
    226                 break;
    227             }
    228         }
    229     }
    230 
    231     delete[] matchedConfigs;
    232 
    233     return nVerifiedCfgs;
    234 }
    235 
    236 FBConfig::FBConfig(EGLDisplay p_eglDpy, EGLConfig p_eglCfg)
    237 {
    238     m_eglConfig = p_eglCfg;
    239     m_attribValues = new GLint[s_numConfigAttribs];
    240     for (int i=0; i<s_numConfigAttribs; i++) {
    241         m_attribValues[i] = 0;
    242         s_egl.eglGetConfigAttrib(p_eglDpy, p_eglCfg, s_configAttribs[i], &m_attribValues[i]);
    243 
    244         //
    245         // All exported configs supports android native window rendering
    246         //
    247         if (s_configAttribs[i] == EGL_SURFACE_TYPE) {
    248             m_attribValues[i] |= EGL_WINDOW_BIT;
    249         }
    250     }
    251 }
    252 
    253 FBConfig::~FBConfig()
    254 {
    255     if (m_attribValues) {
    256         delete[] m_attribValues;
    257     }
    258 }
    259