Rewrite ConfigSet and make EGLConfig synonymous with egl::Config.
BUG=angle:658
Change-Id: I3c33faf18af0bfda00dc5babe6356d6c8661f032
Reviewed-on: https://chromium-review.googlesource.com/238862
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Config.cpp b/src/libANGLE/Config.cpp
index 6e59db7..68d1b08 100644
--- a/src/libANGLE/Config.cpp
+++ b/src/libANGLE/Config.cpp
@@ -6,9 +6,10 @@
// Config.cpp: Implements the egl::Config class, describing the format, type
// and size for an egl::Surface. Implements EGLConfig and related functionality.
-// [EGL 1.4] section 3.4 page 15.
+// [EGL 1.5] section 3.4 page 19.
#include "libANGLE/Config.h"
+#include "libANGLE/AttributeMap.h"
#include <algorithm>
#include <vector>
@@ -18,10 +19,13 @@
#include "common/debug.h"
-using namespace std;
-
namespace egl
{
+
+Config::Config()
+{
+}
+
Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
: mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
{
@@ -142,217 +146,209 @@
}
}
-EGLConfig Config::getHandle() const
+EGLint ConfigSet::add(const Config &config)
{
- return (EGLConfig)(size_t)mConfigID;
+ // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
+ EGLint id = mConfigs.size() + 1;
+
+ Config copyConfig(config);
+ copyConfig.mConfigID = id;
+ mConfigs.insert(std::make_pair(id, copyConfig));
+
+ return id;
}
-SortConfig::SortConfig(const EGLint *attribList)
- : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
+const Config &ConfigSet::get(EGLint id) const
{
- scanForWantedComponents(attribList);
+ return mConfigs.at(id);
}
-void SortConfig::scanForWantedComponents(const EGLint *attribList)
+void ConfigSet::clear()
{
- // [EGL] section 3.4.1 page 24
- // Sorting rule #3: by larger total number of color bits, not considering
- // components that are 0 or don't-care.
- for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
- {
- if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
- {
- switch (attr[0])
- {
- case EGL_RED_SIZE: mWantRed = true; break;
- case EGL_GREEN_SIZE: mWantGreen = true; break;
- case EGL_BLUE_SIZE: mWantBlue = true; break;
- case EGL_ALPHA_SIZE: mWantAlpha = true; break;
- case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
- }
- }
- }
-}
-
-EGLint SortConfig::wantedComponentsSize(const Config &config) const
-{
- EGLint total = 0;
-
- if (mWantRed) total += config.mRedSize;
- if (mWantGreen) total += config.mGreenSize;
- if (mWantBlue) total += config.mBlueSize;
- if (mWantAlpha) total += config.mAlphaSize;
- if (mWantLuminance) total += config.mLuminanceSize;
-
- return total;
-}
-
-bool SortConfig::operator()(const Config *x, const Config *y) const
-{
- return (*this)(*x, *y);
-}
-
-bool SortConfig::operator()(const Config &x, const Config &y) const
-{
- #define SORT(attribute) \
- if (x.attribute != y.attribute) \
- { \
- return x.attribute < y.attribute; \
- }
-
- META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
- SORT(mConfigCaveat);
-
- META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
- SORT(mColorBufferType);
-
- // By larger total number of color bits, only considering those that are requested to be > 0.
- EGLint xComponentsSize = wantedComponentsSize(x);
- EGLint yComponentsSize = wantedComponentsSize(y);
- if (xComponentsSize != yComponentsSize)
- {
- return xComponentsSize > yComponentsSize;
- }
-
- SORT(mBufferSize);
- SORT(mSampleBuffers);
- SORT(mSamples);
- SORT(mDepthSize);
- SORT(mStencilSize);
- SORT(mAlphaMaskSize);
- SORT(mNativeVisualType);
- SORT(mConfigID);
-
- #undef SORT
-
- return false;
-}
-
-// We'd like to use SortConfig to also eliminate duplicate configs.
-// This works as long as we never have two configs with different per-RGB-component layouts,
-// but the same total.
-// 5551 and 565 are different because R+G+B is different.
-// 5551 and 555 are different because bufferSize is different.
-const EGLint ConfigSet::mSortAttribs[] =
-{
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_LUMINANCE_SIZE, 1,
- // BUT NOT ALPHA
- EGL_NONE
-};
-
-ConfigSet::ConfigSet()
- : mSet(SortConfig(mSortAttribs))
-{
-}
-
-void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight)
-{
- Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight);
- mSet.insert(config);
+ mConfigs.clear();
}
size_t ConfigSet::size() const
{
- return mSet.size();
+ return mConfigs.size();
}
-bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
+bool ConfigSet::contains(const Config *config) const
{
- vector<const Config*> passed;
- passed.reserve(mSet.size());
-
- for (Iterator config = mSet.begin(); config != mSet.end(); config++)
+ for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
{
- bool match = true;
- const EGLint *attribute = attribList;
-
- while (attribute[0] != EGL_NONE)
+ const Config &item = i->second;
+ if (config == &item)
{
- switch (attribute[0])
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28.
+class ConfigSorter
+{
+ public:
+ explicit ConfigSorter(const AttributeMap &attributeMap)
+ {
+ scanForWantedComponents(attributeMap);
+ }
+
+ bool operator()(const Config *x, const Config *y) const
+ {
+ return (*this)(*x, *y);
+ }
+
+ bool operator()(const Config &x, const Config &y) const
+ {
+ #define SORT(attribute) \
+ if (x.attribute != y.attribute) \
+ { \
+ return x.attribute < y.attribute; \
+ }
+
+ META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
+ SORT(mConfigCaveat);
+
+ META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
+ SORT(mColorBufferType);
+
+ // By larger total number of color bits, only considering those that are requested to be > 0.
+ EGLint xComponentsSize = wantedComponentsSize(x);
+ EGLint yComponentsSize = wantedComponentsSize(y);
+ if (xComponentsSize != yComponentsSize)
+ {
+ return xComponentsSize > yComponentsSize;
+ }
+
+ SORT(mBufferSize);
+ SORT(mSampleBuffers);
+ SORT(mSamples);
+ SORT(mDepthSize);
+ SORT(mStencilSize);
+ SORT(mAlphaMaskSize);
+ SORT(mNativeVisualType);
+ SORT(mConfigID);
+
+ #undef SORT
+
+ return false;
+ }
+
+ private:
+ void scanForWantedComponents(const AttributeMap &attributeMap)
+ {
+ // [EGL 1.5] section 3.4.1.2 page 30
+ // Sorting rule #3: by larger total number of color bits, not considering
+ // components that are 0 or don't-care.
+ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+ {
+ EGLint attributeKey = attribIter->first;
+ EGLint attributeValue = attribIter->second;
+ if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
{
- case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
- case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
- case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
- case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
- case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
- case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
- case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
- case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break;
- case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
- case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
- case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break;
- case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
- case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
- case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
- case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
- case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break;
- case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
- case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
- case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
- case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break;
- case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break;
- case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
- case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
- case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
- case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
- case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break;
- case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
- case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
- case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
- case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
- case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
- case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
- default:
- return false;
+ switch (attributeKey)
+ {
+ case EGL_RED_SIZE: mWantRed = true; break;
+ case EGL_GREEN_SIZE: mWantGreen = true; break;
+ case EGL_BLUE_SIZE: mWantBlue = true; break;
+ case EGL_ALPHA_SIZE: mWantAlpha = true; break;
+ case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+ }
+ }
+ }
+ }
+
+ EGLint wantedComponentsSize(const Config &config) const
+ {
+ EGLint total = 0;
+
+ if (mWantRed) total += config.mRedSize;
+ if (mWantGreen) total += config.mGreenSize;
+ if (mWantBlue) total += config.mBlueSize;
+ if (mWantAlpha) total += config.mAlphaSize;
+ if (mWantLuminance) total += config.mLuminanceSize;
+
+ return total;
+ }
+
+ bool mWantRed;
+ bool mWantGreen;
+ bool mWantBlue;
+ bool mWantAlpha;
+ bool mWantLuminance;
+};
+
+std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const
+{
+ std::vector<const Config*> result;
+ result.reserve(mConfigs.size());
+
+ for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
+ {
+ const Config &config = configIter->second;
+ bool match = true;
+
+ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+ {
+ EGLint attributeKey = attribIter->first;
+ EGLint attributeValue = attribIter->second;
+
+ switch (attributeKey)
+ {
+ case EGL_BUFFER_SIZE: match = config.mBufferSize >= attributeValue; break;
+ case EGL_ALPHA_SIZE: match = config.mAlphaSize >= attributeValue; break;
+ case EGL_BLUE_SIZE: match = config.mBlueSize >= attributeValue; break;
+ case EGL_GREEN_SIZE: match = config.mGreenSize >= attributeValue; break;
+ case EGL_RED_SIZE: match = config.mRedSize >= attributeValue; break;
+ case EGL_DEPTH_SIZE: match = config.mDepthSize >= attributeValue; break;
+ case EGL_STENCIL_SIZE: match = config.mStencilSize >= attributeValue; break;
+ case EGL_CONFIG_CAVEAT: match = config.mConfigCaveat == (EGLenum)attributeValue; break;
+ case EGL_CONFIG_ID: match = config.mConfigID == attributeValue; break;
+ case EGL_LEVEL: match = config.mLevel >= attributeValue; break;
+ case EGL_NATIVE_RENDERABLE: match = config.mNativeRenderable == (EGLBoolean)attributeValue; break;
+ case EGL_NATIVE_VISUAL_TYPE: match = config.mNativeVisualType == attributeValue; break;
+ case EGL_SAMPLES: match = config.mSamples >= attributeValue; break;
+ case EGL_SAMPLE_BUFFERS: match = config.mSampleBuffers >= attributeValue; break;
+ case EGL_SURFACE_TYPE: match = (config.mSurfaceType & attributeValue) == attributeValue; break;
+ case EGL_TRANSPARENT_TYPE: match = config.mTransparentType == (EGLenum)attributeValue; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: match = config.mTransparentBlueValue == attributeValue; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: match = config.mTransparentGreenValue == attributeValue; break;
+ case EGL_TRANSPARENT_RED_VALUE: match = config.mTransparentRedValue == attributeValue; break;
+ case EGL_BIND_TO_TEXTURE_RGB: match = config.mBindToTextureRGB == (EGLBoolean)attributeValue; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: match = config.mBindToTextureRGBA == (EGLBoolean)attributeValue; break;
+ case EGL_MIN_SWAP_INTERVAL: match = config.mMinSwapInterval == attributeValue; break;
+ case EGL_MAX_SWAP_INTERVAL: match = config.mMaxSwapInterval == attributeValue; break;
+ case EGL_LUMINANCE_SIZE: match = config.mLuminanceSize >= attributeValue; break;
+ case EGL_ALPHA_MASK_SIZE: match = config.mAlphaMaskSize >= attributeValue; break;
+ case EGL_COLOR_BUFFER_TYPE: match = config.mColorBufferType == (EGLenum)attributeValue; break;
+ case EGL_RENDERABLE_TYPE: match = (config.mRenderableType & attributeValue) == attributeValue; break;
+ case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
+ case EGL_CONFORMANT: match = (config.mConformant & attributeValue) == attributeValue; break;
+ case EGL_MAX_PBUFFER_WIDTH: match = config.mMaxPBufferWidth >= attributeValue; break;
+ case EGL_MAX_PBUFFER_HEIGHT: match = config.mMaxPBufferHeight >= attributeValue; break;
+ case EGL_MAX_PBUFFER_PIXELS: match = config.mMaxPBufferPixels >= attributeValue; break;
+ default: UNREACHABLE();
}
if (!match)
{
break;
}
-
- attribute += 2;
}
if (match)
{
- passed.push_back(&*config);
+ result.push_back(&config);
}
}
- if (configs)
- {
- sort(passed.begin(), passed.end(), SortConfig(attribList));
+ // Sort the result
+ std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
- EGLint index;
- for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
- {
- configs[index] = passed[index]->getHandle();
- }
-
- *numConfig = index;
- }
- else
- {
- *numConfig = passed.size();
- }
-
- return true;
+ return result;
}
-const egl::Config *ConfigSet::get(EGLConfig configHandle)
-{
- for (Iterator config = mSet.begin(); config != mSet.end(); config++)
- {
- if (config->getHandle() == configHandle)
- {
- return &(*config);
- }
- }
-
- return NULL;
-}
}