Home | History | Annotate | Download | only in libEGL
      1 //
      2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Config.cpp: Implements the egl::Config class, describing the format, type
      8 // and size for an egl::Surface. Implements EGLConfig and related functionality.
      9 // [EGL 1.4] section 3.4 page 15.
     10 
     11 #include "libEGL/Config.h"
     12 
     13 #include <algorithm>
     14 #include <vector>
     15 
     16 #include "angle_gl.h"
     17 #include <EGL/eglext.h>
     18 
     19 #include "common/debug.h"
     20 
     21 using namespace std;
     22 
     23 namespace egl
     24 {
     25 Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
     26     : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
     27 {
     28     mBindToTextureRGB = EGL_FALSE;
     29     mBindToTextureRGBA = EGL_FALSE;
     30     switch (desc.renderTargetFormat)
     31     {
     32       case GL_RGB5_A1:
     33         mBufferSize = 16;
     34         mRedSize = 5;
     35         mGreenSize = 5;
     36         mBlueSize = 5;
     37         mAlphaSize = 1;
     38         break;
     39       case GL_BGR5_A1_ANGLEX:
     40         mBufferSize = 16;
     41         mRedSize = 5;
     42         mGreenSize = 5;
     43         mBlueSize = 5;
     44         mAlphaSize = 1;
     45         break;
     46       case GL_RGBA8_OES:
     47         mBufferSize = 32;
     48         mRedSize = 8;
     49         mGreenSize = 8;
     50         mBlueSize = 8;
     51         mAlphaSize = 8;
     52         mBindToTextureRGBA = true;
     53         break;
     54       case GL_RGB565:
     55         mBufferSize = 16;
     56         mRedSize = 5;
     57         mGreenSize = 6;
     58         mBlueSize = 5;
     59         mAlphaSize = 0;
     60         break;
     61       case GL_RGB8_OES:
     62         mBufferSize = 32;
     63         mRedSize = 8;
     64         mGreenSize = 8;
     65         mBlueSize = 8;
     66         mAlphaSize = 0;
     67         mBindToTextureRGB = true;
     68         break;
     69       case GL_BGRA8_EXT:
     70         mBufferSize = 32;
     71         mRedSize = 8;
     72         mGreenSize = 8;
     73         mBlueSize = 8;
     74         mAlphaSize = 8;
     75         mBindToTextureRGBA = true;
     76         break;
     77       default:
     78         UNREACHABLE();   // Other formats should not be valid
     79     }
     80 
     81     mLuminanceSize = 0;
     82     mAlphaMaskSize = 0;
     83     mColorBufferType = EGL_RGB_BUFFER;
     84     mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
     85     mConfigID = 0;
     86     mConformant = EGL_OPENGL_ES2_BIT;
     87 
     88     switch (desc.depthStencilFormat)
     89     {
     90       case GL_NONE:
     91         mDepthSize = 0;
     92         mStencilSize = 0;
     93         break;
     94       case GL_DEPTH_COMPONENT32_OES:
     95         mDepthSize = 32;
     96         mStencilSize = 0;
     97         break;
     98       case GL_DEPTH24_STENCIL8_OES:
     99         mDepthSize = 24;
    100         mStencilSize = 8;
    101         break;
    102       case GL_DEPTH_COMPONENT24_OES:
    103         mDepthSize = 24;
    104         mStencilSize = 0;
    105         break;
    106       case GL_DEPTH_COMPONENT16:
    107         mDepthSize = 16;
    108         mStencilSize = 0;
    109         break;
    110       default:
    111         UNREACHABLE();
    112     }
    113 
    114     mLevel = 0;
    115     mMatchNativePixmap = EGL_NONE;
    116     mMaxPBufferWidth = texWidth;
    117     mMaxPBufferHeight = texHeight;
    118     mMaxPBufferPixels = texWidth*texHeight;
    119     mMaxSwapInterval = maxInterval;
    120     mMinSwapInterval = minInterval;
    121     mNativeRenderable = EGL_FALSE;
    122     mNativeVisualID = 0;
    123     mNativeVisualType = 0;
    124     mRenderableType = EGL_OPENGL_ES2_BIT;
    125     mSampleBuffers = desc.multiSample ? 1 : 0;
    126     mSamples = desc.multiSample;
    127     mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
    128     mTransparentType = EGL_NONE;
    129     mTransparentRedValue = 0;
    130     mTransparentGreenValue = 0;
    131     mTransparentBlueValue = 0;
    132 
    133     if (desc.es3Capable)
    134     {
    135         mRenderableType |= EGL_OPENGL_ES3_BIT_KHR;
    136         mConformant |= EGL_OPENGL_ES3_BIT_KHR;
    137     }
    138 }
    139 
    140 EGLConfig Config::getHandle() const
    141 {
    142     return (EGLConfig)(size_t)mConfigID;
    143 }
    144 
    145 SortConfig::SortConfig(const EGLint *attribList)
    146     : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
    147 {
    148     scanForWantedComponents(attribList);
    149 }
    150 
    151 void SortConfig::scanForWantedComponents(const EGLint *attribList)
    152 {
    153     // [EGL] section 3.4.1 page 24
    154     // Sorting rule #3: by larger total number of color bits, not considering
    155     // components that are 0 or don't-care.
    156     for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
    157     {
    158         if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
    159         {
    160             switch (attr[0])
    161             {
    162               case EGL_RED_SIZE:       mWantRed = true; break;
    163               case EGL_GREEN_SIZE:     mWantGreen = true; break;
    164               case EGL_BLUE_SIZE:      mWantBlue = true; break;
    165               case EGL_ALPHA_SIZE:     mWantAlpha = true; break;
    166               case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
    167             }
    168         }
    169     }
    170 }
    171 
    172 EGLint SortConfig::wantedComponentsSize(const Config &config) const
    173 {
    174     EGLint total = 0;
    175 
    176     if (mWantRed)       total += config.mRedSize;
    177     if (mWantGreen)     total += config.mGreenSize;
    178     if (mWantBlue)      total += config.mBlueSize;
    179     if (mWantAlpha)     total += config.mAlphaSize;
    180     if (mWantLuminance) total += config.mLuminanceSize;
    181 
    182     return total;
    183 }
    184 
    185 bool SortConfig::operator()(const Config *x, const Config *y) const
    186 {
    187     return (*this)(*x, *y);
    188 }
    189 
    190 bool SortConfig::operator()(const Config &x, const Config &y) const
    191 {
    192     #define SORT(attribute)                        \
    193         if (x.attribute != y.attribute)            \
    194         {                                          \
    195             return x.attribute < y.attribute;      \
    196         }
    197 
    198     META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
    199     SORT(mConfigCaveat);
    200 
    201     META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
    202     SORT(mColorBufferType);
    203 
    204     // By larger total number of color bits, only considering those that are requested to be > 0.
    205     EGLint xComponentsSize = wantedComponentsSize(x);
    206     EGLint yComponentsSize = wantedComponentsSize(y);
    207     if (xComponentsSize != yComponentsSize)
    208     {
    209         return xComponentsSize > yComponentsSize;
    210     }
    211 
    212     SORT(mBufferSize);
    213     SORT(mSampleBuffers);
    214     SORT(mSamples);
    215     SORT(mDepthSize);
    216     SORT(mStencilSize);
    217     SORT(mAlphaMaskSize);
    218     SORT(mNativeVisualType);
    219     SORT(mConfigID);
    220 
    221     #undef SORT
    222 
    223     return false;
    224 }
    225 
    226 // We'd like to use SortConfig to also eliminate duplicate configs.
    227 // This works as long as we never have two configs with different per-RGB-component layouts,
    228 // but the same total.
    229 // 5551 and 565 are different because R+G+B is different.
    230 // 5551 and 555 are different because bufferSize is different.
    231 const EGLint ConfigSet::mSortAttribs[] =
    232 {
    233     EGL_RED_SIZE, 1,
    234     EGL_GREEN_SIZE, 1,
    235     EGL_BLUE_SIZE, 1,
    236     EGL_LUMINANCE_SIZE, 1,
    237     // BUT NOT ALPHA
    238     EGL_NONE
    239 };
    240 
    241 ConfigSet::ConfigSet()
    242     : mSet(SortConfig(mSortAttribs))
    243 {
    244 }
    245 
    246 void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight)
    247 {
    248     Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight);
    249     mSet.insert(config);
    250 }
    251 
    252 size_t ConfigSet::size() const
    253 {
    254     return mSet.size();
    255 }
    256 
    257 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
    258 {
    259     vector<const Config*> passed;
    260     passed.reserve(mSet.size());
    261 
    262     for (Iterator config = mSet.begin(); config != mSet.end(); config++)
    263     {
    264         bool match = true;
    265         const EGLint *attribute = attribList;
    266 
    267         while (attribute[0] != EGL_NONE)
    268         {
    269             switch (attribute[0])
    270             {
    271               case EGL_BUFFER_SIZE:               match = config->mBufferSize >= attribute[1];                      break;
    272               case EGL_ALPHA_SIZE:                match = config->mAlphaSize >= attribute[1];                       break;
    273               case EGL_BLUE_SIZE:                 match = config->mBlueSize >= attribute[1];                        break;
    274               case EGL_GREEN_SIZE:                match = config->mGreenSize >= attribute[1];                       break;
    275               case EGL_RED_SIZE:                  match = config->mRedSize >= attribute[1];                         break;
    276               case EGL_DEPTH_SIZE:                match = config->mDepthSize >= attribute[1];                       break;
    277               case EGL_STENCIL_SIZE:              match = config->mStencilSize >= attribute[1];                     break;
    278               case EGL_CONFIG_CAVEAT:             match = config->mConfigCaveat == (EGLenum) attribute[1];          break;
    279               case EGL_CONFIG_ID:                 match = config->mConfigID == attribute[1];                        break;
    280               case EGL_LEVEL:                     match = config->mLevel >= attribute[1];                           break;
    281               case EGL_NATIVE_RENDERABLE:         match = config->mNativeRenderable == (EGLBoolean) attribute[1];   break;
    282               case EGL_NATIVE_VISUAL_TYPE:        match = config->mNativeVisualType == attribute[1];                break;
    283               case EGL_SAMPLES:                   match = config->mSamples >= attribute[1];                         break;
    284               case EGL_SAMPLE_BUFFERS:            match = config->mSampleBuffers >= attribute[1];                   break;
    285               case EGL_SURFACE_TYPE:              match = (config->mSurfaceType & attribute[1]) == attribute[1];    break;
    286               case EGL_TRANSPARENT_TYPE:          match = config->mTransparentType == (EGLenum) attribute[1];       break;
    287               case EGL_TRANSPARENT_BLUE_VALUE:    match = config->mTransparentBlueValue == attribute[1];            break;
    288               case EGL_TRANSPARENT_GREEN_VALUE:   match = config->mTransparentGreenValue == attribute[1];           break;
    289               case EGL_TRANSPARENT_RED_VALUE:     match = config->mTransparentRedValue == attribute[1];             break;
    290               case EGL_BIND_TO_TEXTURE_RGB:       match = config->mBindToTextureRGB == (EGLBoolean) attribute[1];   break;
    291               case EGL_BIND_TO_TEXTURE_RGBA:      match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1];  break;
    292               case EGL_MIN_SWAP_INTERVAL:         match = config->mMinSwapInterval == attribute[1];                 break;
    293               case EGL_MAX_SWAP_INTERVAL:         match = config->mMaxSwapInterval == attribute[1];                 break;
    294               case EGL_LUMINANCE_SIZE:            match = config->mLuminanceSize >= attribute[1];                   break;
    295               case EGL_ALPHA_MASK_SIZE:           match = config->mAlphaMaskSize >= attribute[1];                   break;
    296               case EGL_COLOR_BUFFER_TYPE:         match = config->mColorBufferType == (EGLenum) attribute[1];       break;
    297               case EGL_RENDERABLE_TYPE:           match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
    298               case EGL_MATCH_NATIVE_PIXMAP:       match = false; UNIMPLEMENTED();                                   break;
    299               case EGL_CONFORMANT:                match = (config->mConformant & attribute[1]) == attribute[1];     break;
    300               case EGL_MAX_PBUFFER_WIDTH:         match = config->mMaxPBufferWidth >= attribute[1];                 break;
    301               case EGL_MAX_PBUFFER_HEIGHT:        match = config->mMaxPBufferHeight >= attribute[1];                break;
    302               case EGL_MAX_PBUFFER_PIXELS:        match = config->mMaxPBufferPixels >= attribute[1];                break;
    303               default:
    304                 return false;
    305             }
    306 
    307             if (!match)
    308             {
    309                 break;
    310             }
    311 
    312             attribute += 2;
    313         }
    314 
    315         if (match)
    316         {
    317             passed.push_back(&*config);
    318         }
    319     }
    320 
    321     if (configs)
    322     {
    323         sort(passed.begin(), passed.end(), SortConfig(attribList));
    324 
    325         EGLint index;
    326         for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
    327         {
    328             configs[index] = passed[index]->getHandle();
    329         }
    330 
    331         *numConfig = index;
    332     }
    333     else
    334     {
    335         *numConfig = passed.size();
    336     }
    337 
    338     return true;
    339 }
    340 
    341 const egl::Config *ConfigSet::get(EGLConfig configHandle)
    342 {
    343     for (Iterator config = mSet.begin(); config != mSet.end(); config++)
    344     {
    345         if (config->getHandle() == configHandle)
    346         {
    347             return &(*config);
    348         }
    349     }
    350 
    351     return NULL;
    352 }
    353 }
    354