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