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