Commit 6812a55c by Geoff Lang

Rewrite ConfigSet and make EGLConfig synonymous with egl::Config.

BUG=angle:658 Change-Id: I3c33faf18af0bfda00dc5babe6356d6c8661f032 Reviewed-on: https://chromium-review.googlesource.com/238862Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarBrandon Jones <bajones@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 5c39f688
...@@ -40,4 +40,14 @@ EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const ...@@ -40,4 +40,14 @@ EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const
return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue; return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
} }
AttributeMap::const_iterator AttributeMap::begin() const
{
return mAttributes.begin();
}
AttributeMap::const_iterator AttributeMap::end() const
{
return mAttributes.end();
}
} }
...@@ -25,6 +25,11 @@ class AttributeMap ...@@ -25,6 +25,11 @@ class AttributeMap
virtual bool contains(EGLint key) const; virtual bool contains(EGLint key) const;
virtual EGLint get(EGLint key, EGLint defaultValue) const; virtual EGLint get(EGLint key, EGLint defaultValue) const;
typedef std::map<EGLint, EGLint>::const_iterator const_iterator;
const_iterator begin() const;
const_iterator end() const;
private: private:
std::map<EGLint, EGLint> mAttributes; std::map<EGLint, EGLint> mAttributes;
}; };
......
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
// Config.cpp: Implements the egl::Config class, describing the format, type // Config.cpp: Implements the egl::Config class, describing the format, type
// and size for an egl::Surface. Implements EGLConfig and related functionality. // 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/Config.h"
#include "libANGLE/AttributeMap.h"
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
...@@ -18,10 +19,13 @@ ...@@ -18,10 +19,13 @@
#include "common/debug.h" #include "common/debug.h"
using namespace std;
namespace egl namespace egl
{ {
Config::Config()
{
}
Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight) Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
: mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample) : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
{ {
...@@ -142,58 +146,63 @@ Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLi ...@@ -142,58 +146,63 @@ Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLi
} }
} }
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) const Config &ConfigSet::get(EGLint id) const
: mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
{ {
scanForWantedComponents(attribList); return mConfigs.at(id);
} }
void SortConfig::scanForWantedComponents(const EGLint *attribList) void ConfigSet::clear()
{ {
// [EGL] section 3.4.1 page 24 mConfigs.clear();
// 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 size_t ConfigSet::size() const
{ {
EGLint total = 0; return mConfigs.size();
}
if (mWantRed) total += config.mRedSize; bool ConfigSet::contains(const Config *config) const
if (mWantGreen) total += config.mGreenSize; {
if (mWantBlue) total += config.mBlueSize; for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
if (mWantAlpha) total += config.mAlphaSize; {
if (mWantLuminance) total += config.mLuminanceSize; const Config &item = i->second;
if (config == &item)
{
return true;
}
}
return total; return false;
} }
bool SortConfig::operator()(const Config *x, const Config *y) const // 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); return (*this)(*x, *y);
} }
bool SortConfig::operator()(const Config &x, const Config &y) const bool operator()(const Config &x, const Config &y) const
{ {
#define SORT(attribute) \ #define SORT(attribute) \
if (x.attribute != y.attribute) \ if (x.attribute != y.attribute) \
{ \ { \
...@@ -226,133 +235,120 @@ bool SortConfig::operator()(const Config &x, const Config &y) const ...@@ -226,133 +235,120 @@ bool SortConfig::operator()(const Config &x, const Config &y) const
#undef SORT #undef SORT
return false; return false;
} }
// We'd like to use SortConfig to also eliminate duplicate configs. private:
// This works as long as we never have two configs with different per-RGB-component layouts, void scanForWantedComponents(const AttributeMap &attributeMap)
// but the same total. {
// 5551 and 565 are different because R+G+B is different. // [EGL 1.5] section 3.4.1.2 page 30
// 5551 and 555 are different because bufferSize is different. // Sorting rule #3: by larger total number of color bits, not considering
const EGLint ConfigSet::mSortAttribs[] = // components that are 0 or don't-care.
{ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
EGL_RED_SIZE, 1, {
EGL_GREEN_SIZE, 1, EGLint attributeKey = attribIter->first;
EGL_BLUE_SIZE, 1, EGLint attributeValue = attribIter->second;
EGL_LUMINANCE_SIZE, 1, if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
// BUT NOT ALPHA {
EGL_NONE 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;
}
}
}
}
ConfigSet::ConfigSet() EGLint wantedComponentsSize(const Config &config) const
: mSet(SortConfig(mSortAttribs)) {
{ EGLint total = 0;
}
void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight) if (mWantRed) total += config.mRedSize;
{ if (mWantGreen) total += config.mGreenSize;
Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight); if (mWantBlue) total += config.mBlueSize;
mSet.insert(config); if (mWantAlpha) total += config.mAlphaSize;
} if (mWantLuminance) total += config.mLuminanceSize;
size_t ConfigSet::size() const return total;
{ }
return mSet.size();
}
bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) bool mWantRed;
bool mWantGreen;
bool mWantBlue;
bool mWantAlpha;
bool mWantLuminance;
};
std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const
{ {
vector<const Config*> passed; std::vector<const Config*> result;
passed.reserve(mSet.size()); result.reserve(mConfigs.size());
for (Iterator config = mSet.begin(); config != mSet.end(); config++) for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
{ {
const Config &config = configIter->second;
bool match = true; bool match = true;
const EGLint *attribute = attribList;
while (attribute[0] != EGL_NONE) for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
{ {
switch (attribute[0]) EGLint attributeKey = attribIter->first;
EGLint attributeValue = attribIter->second;
switch (attributeKey)
{ {
case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break; case EGL_BUFFER_SIZE: match = config.mBufferSize >= attributeValue; break;
case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break; case EGL_ALPHA_SIZE: match = config.mAlphaSize >= attributeValue; break;
case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break; case EGL_BLUE_SIZE: match = config.mBlueSize >= attributeValue; break;
case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break; case EGL_GREEN_SIZE: match = config.mGreenSize >= attributeValue; break;
case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break; case EGL_RED_SIZE: match = config.mRedSize >= attributeValue; break;
case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break; case EGL_DEPTH_SIZE: match = config.mDepthSize >= attributeValue; break;
case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break; case EGL_STENCIL_SIZE: match = config.mStencilSize >= attributeValue; break;
case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break; case EGL_CONFIG_CAVEAT: match = config.mConfigCaveat == (EGLenum)attributeValue; break;
case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break; case EGL_CONFIG_ID: match = config.mConfigID == attributeValue; break;
case EGL_LEVEL: match = config->mLevel >= attribute[1]; break; case EGL_LEVEL: match = config.mLevel >= attributeValue; break;
case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break; case EGL_NATIVE_RENDERABLE: match = config.mNativeRenderable == (EGLBoolean)attributeValue; break;
case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break; case EGL_NATIVE_VISUAL_TYPE: match = config.mNativeVisualType == attributeValue; break;
case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break; case EGL_SAMPLES: match = config.mSamples >= attributeValue; break;
case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break; case EGL_SAMPLE_BUFFERS: match = config.mSampleBuffers >= attributeValue; break;
case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break; case EGL_SURFACE_TYPE: match = (config.mSurfaceType & attributeValue) == attributeValue; break;
case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break; case EGL_TRANSPARENT_TYPE: match = config.mTransparentType == (EGLenum)attributeValue; break;
case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break; case EGL_TRANSPARENT_BLUE_VALUE: match = config.mTransparentBlueValue == attributeValue; break;
case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break; case EGL_TRANSPARENT_GREEN_VALUE: match = config.mTransparentGreenValue == attributeValue; break;
case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break; case EGL_TRANSPARENT_RED_VALUE: match = config.mTransparentRedValue == attributeValue; break;
case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break; case EGL_BIND_TO_TEXTURE_RGB: match = config.mBindToTextureRGB == (EGLBoolean)attributeValue; break;
case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break; case EGL_BIND_TO_TEXTURE_RGBA: match = config.mBindToTextureRGBA == (EGLBoolean)attributeValue; break;
case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break; case EGL_MIN_SWAP_INTERVAL: match = config.mMinSwapInterval == attributeValue; break;
case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break; case EGL_MAX_SWAP_INTERVAL: match = config.mMaxSwapInterval == attributeValue; break;
case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break; case EGL_LUMINANCE_SIZE: match = config.mLuminanceSize >= attributeValue; break;
case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break; case EGL_ALPHA_MASK_SIZE: match = config.mAlphaMaskSize >= attributeValue; break;
case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break; case EGL_COLOR_BUFFER_TYPE: match = config.mColorBufferType == (EGLenum)attributeValue; break;
case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break; case EGL_RENDERABLE_TYPE: match = (config.mRenderableType & attributeValue) == attributeValue; break;
case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break; case EGL_CONFORMANT: match = (config.mConformant & attributeValue) == attributeValue; break;
case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break; case EGL_MAX_PBUFFER_WIDTH: match = config.mMaxPBufferWidth >= attributeValue; break;
case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break; case EGL_MAX_PBUFFER_HEIGHT: match = config.mMaxPBufferHeight >= attributeValue; break;
case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break; case EGL_MAX_PBUFFER_PIXELS: match = config.mMaxPBufferPixels >= attributeValue; break;
default: default: UNREACHABLE();
return false;
} }
if (!match) if (!match)
{ {
break; break;
} }
attribute += 2;
} }
if (match) if (match)
{ {
passed.push_back(&*config); result.push_back(&config);
} }
} }
if (configs) // Sort the result
{ std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
sort(passed.begin(), passed.end(), SortConfig(attribList));
EGLint index;
for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
{
configs[index] = passed[index]->getHandle();
}
*numConfig = index; return result;
}
else
{
*numConfig = passed.size();
}
return true;
} }
const egl::Config *ConfigSet::get(EGLConfig configHandle)
{
for (Iterator config = mSet.begin(); config != mSet.end(); config++)
{
if (config->getHandle() == configHandle)
{
return &(*config);
}
}
return NULL;
}
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// Config.h: Defines the egl::Config class, describing the format, type // Config.h: Defines the egl::Config class, describing the format, type
// and size for an egl::Surface. Implements EGLConfig and related functionality. // 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.
#ifndef INCLUDE_CONFIG_H_ #ifndef INCLUDE_CONFIG_H_
#define INCLUDE_CONFIG_H_ #define INCLUDE_CONFIG_H_
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#include <set> #include <map>
#include <vector>
namespace egl namespace egl
{ {
...@@ -26,13 +27,12 @@ class Display; ...@@ -26,13 +27,12 @@ class Display;
class Config class Config
{ {
public: public:
Config();
Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight);
EGLConfig getHandle() const; GLenum mRenderTargetFormat;
GLenum mDepthStencilFormat;
const GLenum mRenderTargetFormat; GLint mMultiSample;
const GLenum mDepthStencilFormat;
const GLint mMultiSample;
EGLint mBufferSize; // Depth of the color buffer EGLint mBufferSize; // Depth of the color buffer
EGLint mRedSize; // Bits of Red in the color buffer EGLint mRedSize; // Bits of Red in the color buffer
...@@ -69,45 +69,26 @@ class Config ...@@ -69,45 +69,26 @@ class Config
EGLint mTransparentBlueValue; // Transparent blue value EGLint mTransparentBlueValue; // Transparent blue value
}; };
// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24. class ConfigSet
class SortConfig
{ {
public: public:
explicit SortConfig(const EGLint *attribList); EGLint add(const Config &config);
const Config &get(EGLint id) const;
bool operator()(const Config *x, const Config *y) const;
bool operator()(const Config &x, const Config &y) const;
private: void clear();
void scanForWantedComponents(const EGLint *attribList);
EGLint wantedComponentsSize(const Config &config) const;
bool mWantRed;
bool mWantGreen;
bool mWantBlue;
bool mWantAlpha;
bool mWantLuminance;
};
class ConfigSet size_t size() const;
{
friend Display;
public: bool contains(const Config *config) const;
ConfigSet();
void add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); // Filter configurations based on the table in [EGL 1.5] section 3.4.1.2 page 29
size_t size() const; std::vector<const Config*> filter(const AttributeMap &attributeMap) const;
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
const egl::Config *get(EGLConfig configHandle);
private: private:
typedef std::set<Config, SortConfig> Set; typedef std::map<EGLint, const Config> ConfigMap;
typedef Set::iterator Iterator; ConfigMap mConfigs;
Set mSet;
static const EGLint mSortAttribs[];
}; };
} }
#endif // INCLUDE_CONFIG_H_ #endif // INCLUDE_CONFIG_H_
...@@ -147,19 +147,7 @@ Error Display::initialize() ...@@ -147,19 +147,7 @@ Error Display::initialize()
mCaps = mImplementation->getCaps(); mCaps = mImplementation->getCaps();
ConfigSet configSet = mImplementation->generateConfigs(); mConfigSet = mImplementation->generateConfigs();
// Give the sorted configs a unique ID and store them internally
EGLint index = 1;
for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
{
Config configuration = *config;
configuration.mConfigID = index;
index++;
mConfigSet.mSet.insert(configuration);
}
if (mConfigSet.size() == 0) if (mConfigSet.size() == 0)
{ {
mImplementation->terminate(); mImplementation->terminate();
...@@ -180,21 +168,19 @@ void Display::terminate() ...@@ -180,21 +168,19 @@ void Display::terminate()
destroyContext(*mContextSet.begin()); destroyContext(*mContextSet.begin());
} }
mConfigSet.mSet.clear(); mConfigSet.clear();
mImplementation->terminate(); mImplementation->terminate();
mInitialized = false; mInitialized = false;
} }
bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const
{ {
return mConfigSet.getConfigs(configs, attribList, configSize, numConfig); return mConfigSet.filter(attribs);
} }
bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value)
{ {
const egl::Config *configuration = mConfigSet.get(config);
switch (attribute) switch (attribute)
{ {
case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break; case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break;
...@@ -236,11 +222,8 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) ...@@ -236,11 +222,8 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
return true; return true;
} }
Error Display::createWindowSurface(EGLNativeWindowType window, const Config *configuration, const EGLint *attribList, EGLSurface *outSurface)
Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface)
{ {
const Config *configuration = mConfigSet.get(config);
EGLint postSubBufferSupported = EGL_FALSE; EGLint postSubBufferSupported = EGL_FALSE;
EGLint width = 0; EGLint width = 0;
...@@ -331,13 +314,12 @@ Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, ...@@ -331,13 +314,12 @@ Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config,
return Error(EGL_SUCCESS); return Error(EGL_SUCCESS);
} }
Error Display::createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHandle, Error Display::createOffscreenSurface(const Config *configuration, EGLClientBuffer shareHandle,
const EGLint *attribList, EGLSurface *outSurface) const EGLint *attribList, EGLSurface *outSurface)
{ {
EGLint width = 0, height = 0; EGLint width = 0, height = 0;
EGLenum textureFormat = EGL_NO_TEXTURE; EGLenum textureFormat = EGL_NO_TEXTURE;
EGLenum textureTarget = EGL_NO_TEXTURE; EGLenum textureTarget = EGL_NO_TEXTURE;
const Config *configuration = mConfigSet.get(config);
if (attribList) if (attribList)
{ {
...@@ -452,7 +434,7 @@ Error Display::createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHan ...@@ -452,7 +434,7 @@ Error Display::createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHan
return Error(EGL_SUCCESS); return Error(EGL_SUCCESS);
} }
Error Display::createContext(EGLConfig configHandle, EGLContext shareContext, const egl::AttributeMap &attribs, Error Display::createContext(const Config *configuration, EGLContext shareContext, const egl::AttributeMap &attribs,
EGLContext *outContext) EGLContext *outContext)
{ {
ASSERT(isInitialized()); ASSERT(isInitialized());
...@@ -466,7 +448,6 @@ Error Display::createContext(EGLConfig configHandle, EGLContext shareContext, co ...@@ -466,7 +448,6 @@ Error Display::createContext(EGLConfig configHandle, EGLContext shareContext, co
} }
} }
const Config *configuration = mConfigSet.get(configHandle);
if (attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1) == 3 && !(configuration->mConformant & EGL_OPENGL_ES3_BIT_KHR)) if (attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1) == 3 && !(configuration->mConformant & EGL_OPENGL_ES3_BIT_KHR))
{ {
return Error(EGL_BAD_CONFIG); return Error(EGL_BAD_CONFIG);
...@@ -542,22 +523,22 @@ bool Display::isInitialized() const ...@@ -542,22 +523,22 @@ bool Display::isInitialized() const
return mInitialized; return mInitialized;
} }
bool Display::isValidConfig(EGLConfig config) bool Display::isValidConfig(const Config *config) const
{ {
return mConfigSet.get(config) != NULL; return mConfigSet.contains(config);
} }
bool Display::isValidContext(gl::Context *context) bool Display::isValidContext(gl::Context *context) const
{ {
return mContextSet.find(context) != mContextSet.end(); return mContextSet.find(context) != mContextSet.end();
} }
bool Display::isValidSurface(Surface *surface) bool Display::isValidSurface(Surface *surface) const
{ {
return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end(); return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end();
} }
bool Display::hasExistingWindowSurface(EGLNativeWindowType window) bool Display::hasExistingWindowSurface(EGLNativeWindowType window) const
{ {
for (const auto &surfaceIt : mImplementation->getSurfaceSet()) for (const auto &surfaceIt : mImplementation->getSurfaceSet())
{ {
......
...@@ -45,21 +45,21 @@ class Display final ...@@ -45,21 +45,21 @@ class Display final
static const ClientExtensions &getClientExtensions(); static const ClientExtensions &getClientExtensions();
static const std::string &getClientExtensionString(); static const std::string &getClientExtensionString();
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); std::vector<const Config*> getConfigs(const egl::AttributeMap &attribs) const;
bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); bool getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value);
Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface); Error createWindowSurface(EGLNativeWindowType window, const Config *configuration, const EGLint *attribList, EGLSurface *outSurface);
Error createOffscreenSurface(EGLConfig config, EGLClientBuffer shareHandle, const EGLint *attribList, EGLSurface *outSurface); Error createOffscreenSurface(const Config *configuration, EGLClientBuffer shareHandle, const EGLint *attribList, EGLSurface *outSurface);
Error createContext(EGLConfig configHandle, EGLContext shareContext, const egl::AttributeMap &attribs, EGLContext *outContext); Error createContext(const Config *configuration, EGLContext shareContext, const egl::AttributeMap &attribs, EGLContext *outContext);
void destroySurface(egl::Surface *surface); void destroySurface(egl::Surface *surface);
void destroyContext(gl::Context *context); void destroyContext(gl::Context *context);
bool isInitialized() const; bool isInitialized() const;
bool isValidConfig(EGLConfig config); bool isValidConfig(const Config *config) const;
bool isValidContext(gl::Context *context); bool isValidContext(gl::Context *context) const;
bool isValidSurface(egl::Surface *surface); bool isValidSurface(egl::Surface *surface) const;
bool hasExistingWindowSurface(EGLNativeWindowType window); bool hasExistingWindowSurface(EGLNativeWindowType window) const;
bool isValidNativeWindow(EGLNativeWindowType window) const; bool isValidNativeWindow(EGLNativeWindowType window) const;
bool isValidNativeDisplay(EGLNativeDisplayType display) const; bool isValidNativeDisplay(EGLNativeDisplayType display) const;
......
...@@ -174,7 +174,7 @@ egl::ConfigSet DisplayD3D::generateConfigs() const ...@@ -174,7 +174,7 @@ egl::ConfigSet DisplayD3D::generateConfigs() const
egl::ConfigSet configSet; egl::ConfigSet configSet;
for (size_t i = 0; i < descList.size(); ++i) for (size_t i = 0; i < descList.size(); ++i)
{ {
configSet.add(descList[i], minSwapInterval, maxSwapInterval, maxTextureSize, maxTextureSize); configSet.add(egl::Config(descList[i], minSwapInterval, maxSwapInterval, maxTextureSize, maxTextureSize));
} }
return configSet; return configSet;
......
...@@ -26,7 +26,7 @@ namespace egl ...@@ -26,7 +26,7 @@ namespace egl
{ {
// EGL object validation // EGL object validation
static bool ValidateDisplay(Display *display) static bool ValidateDisplay(const Display *display)
{ {
if (display == EGL_NO_DISPLAY) if (display == EGL_NO_DISPLAY)
{ {
...@@ -43,7 +43,7 @@ static bool ValidateDisplay(Display *display) ...@@ -43,7 +43,7 @@ static bool ValidateDisplay(Display *display)
return true; return true;
} }
static bool ValidateConfig(Display *display, EGLConfig config) static bool ValidateConfig(const Display *display, const Config *config)
{ {
if (!ValidateDisplay(display)) if (!ValidateDisplay(display))
{ {
...@@ -59,7 +59,7 @@ static bool ValidateConfig(Display *display, EGLConfig config) ...@@ -59,7 +59,7 @@ static bool ValidateConfig(Display *display, EGLConfig config)
return true; return true;
} }
static bool ValidateContext(Display *display, gl::Context *context) static bool ValidateContext(const Display *display, gl::Context *context)
{ {
if (!ValidateDisplay(display)) if (!ValidateDisplay(display))
{ {
...@@ -220,13 +220,16 @@ EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint con ...@@ -220,13 +220,16 @@ EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint con
return EGL_FALSE; return EGL_FALSE;
} }
const EGLint attribList[] = {EGL_NONE}; std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap());
if (configs)
if (!display->getConfigs(configs, attribList, config_size, num_config))
{ {
SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size));
return EGL_FALSE; for (size_t i = 0; i < filteredConfigs.size(); i++)
{
configs[i] = const_cast<Config*>(filteredConfigs[i]);
}
} }
*num_config = filteredConfigs.size();
SetGlobalError(Error(EGL_SUCCESS)); SetGlobalError(Error(EGL_SUCCESS));
return EGL_TRUE; return EGL_TRUE;
...@@ -251,14 +254,16 @@ EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, E ...@@ -251,14 +254,16 @@ EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, E
return EGL_FALSE; return EGL_FALSE;
} }
const EGLint attribList[] = {EGL_NONE}; std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap(attrib_list));
if (configs)
if (!attrib_list) {
filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size));
for (size_t i = 0; i < filteredConfigs.size(); i++)
{ {
attrib_list = attribList; configs[i] = const_cast<Config*>(filteredConfigs[i]);
} }
}
display->getConfigs(configs, attrib_list, config_size, num_config); *num_config = filteredConfigs.size();
SetGlobalError(Error(EGL_SUCCESS)); SetGlobalError(Error(EGL_SUCCESS));
return EGL_TRUE; return EGL_TRUE;
...@@ -270,13 +275,14 @@ EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint ...@@ -270,13 +275,14 @@ EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint
dpy, config, attribute, value); dpy, config, attribute, value);
Display *display = static_cast<Display*>(dpy); Display *display = static_cast<Display*>(dpy);
Config *configuration = static_cast<Config*>(config);
if (!ValidateConfig(display, config)) if (!ValidateConfig(display, configuration))
{ {
return EGL_FALSE; return EGL_FALSE;
} }
if (!display->getConfigAttrib(config, attribute, value)) if (!display->getConfigAttrib(configuration, attribute, value))
{ {
SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE; return EGL_FALSE;
...@@ -292,8 +298,9 @@ EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGL ...@@ -292,8 +298,9 @@ EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGL
"const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
Display *display = static_cast<Display*>(dpy); Display *display = static_cast<Display*>(dpy);
Config *configuration = static_cast<Config*>(config);
if (!ValidateConfig(display, config)) if (!ValidateConfig(display, configuration))
{ {
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
...@@ -305,7 +312,7 @@ EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGL ...@@ -305,7 +312,7 @@ EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGL
} }
EGLSurface surface = EGL_NO_SURFACE; EGLSurface surface = EGL_NO_SURFACE;
Error error = display->createWindowSurface(win, config, attrib_list, &surface); Error error = display->createWindowSurface(win, configuration, attrib_list, &surface);
if (error.isError()) if (error.isError())
{ {
SetGlobalError(error); SetGlobalError(error);
...@@ -321,14 +328,15 @@ EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, co ...@@ -321,14 +328,15 @@ EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, co
dpy, config, attrib_list); dpy, config, attrib_list);
Display *display = static_cast<Display*>(dpy); Display *display = static_cast<Display*>(dpy);
Config *configuration = static_cast<Config*>(config);
if (!ValidateConfig(display, config)) if (!ValidateConfig(display, configuration))
{ {
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
EGLSurface surface = EGL_NO_SURFACE; EGLSurface surface = EGL_NO_SURFACE;
Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface); Error error = display->createOffscreenSurface(configuration, NULL, attrib_list, &surface);
if (error.isError()) if (error.isError())
{ {
SetGlobalError(error); SetGlobalError(error);
...@@ -344,8 +352,9 @@ EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGL ...@@ -344,8 +352,9 @@ EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGL
"const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
Display *display = static_cast<Display*>(dpy); Display *display = static_cast<Display*>(dpy);
Config *configuration = static_cast<Config*>(config);
if (!ValidateConfig(display, config)) if (!ValidateConfig(display, configuration))
{ {
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
...@@ -608,13 +617,14 @@ EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContex ...@@ -608,13 +617,14 @@ EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContex
} }
} }
if (!ValidateConfig(display, config)) Config *configuration = static_cast<Config*>(config);
if (!ValidateConfig(display, configuration))
{ {
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
} }
EGLContext context = EGL_NO_CONTEXT; EGLContext context = EGL_NO_CONTEXT;
Error error = display->createContext(config, share_context, egl::AttributeMap(attrib_list), &context); Error error = display->createContext(configuration, share_context, egl::AttributeMap(attrib_list), &context);
if (error.isError()) if (error.isError())
{ {
SetGlobalError(error); SetGlobalError(error);
...@@ -1031,7 +1041,8 @@ EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buf ...@@ -1031,7 +1041,8 @@ EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buf
Display *display = static_cast<Display*>(dpy); Display *display = static_cast<Display*>(dpy);
if (!ValidateConfig(display, config)) Config *configuration = static_cast<Config*>(config);
if (!ValidateConfig(display, configuration))
{ {
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
...@@ -1043,7 +1054,7 @@ EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buf ...@@ -1043,7 +1054,7 @@ EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buf
} }
EGLSurface surface = EGL_NO_SURFACE; EGLSurface surface = EGL_NO_SURFACE;
Error error = display->createOffscreenSurface(config, buffer, attrib_list, &surface); Error error = display->createOffscreenSurface(configuration, buffer, attrib_list, &surface);
if (error.isError()) if (error.isError())
{ {
SetGlobalError(error); SetGlobalError(error);
......
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/Config.h"
// Create a generic, valid EGL config that can be modified to test sorting and
// filtering routines
static egl::Config GenerateGenericConfig()
{
egl::Config config;
config.mBufferSize = 24;
config.mRedSize = 8;
config.mGreenSize = 8;
config.mBlueSize = 8;
config.mLuminanceSize = 0;
config.mAlphaSize = 8;
config.mAlphaMaskSize = 0;
config.mBindToTextureRGB = EGL_TRUE;
config.mBindToTextureRGBA = EGL_TRUE;
config.mColorBufferType = EGL_RGB_BUFFER;
config.mConfigCaveat = EGL_NONE;
config.mConfigID = 0;
config.mConformant = EGL_OPENGL_ES2_BIT;
config.mDepthSize = 24;
config.mLevel = 0;
config.mMatchNativePixmap = EGL_NONE;
config.mMaxPBufferWidth = 1024;
config.mMaxPBufferHeight = 1024;
config.mMaxPBufferPixels = config.mMaxPBufferWidth * config.mMaxPBufferWidth;
config.mMaxSwapInterval = 0;
config.mMinSwapInterval = 4;
config.mNativeRenderable = EGL_OPENGL_ES2_BIT;
config.mNativeVisualID = 0;
config.mNativeVisualType = 0;
config.mRenderableType = EGL_FALSE;
config.mSampleBuffers = 0;
config.mSamples = 0;
config.mStencilSize = 8;
config.mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
config.mTransparentType = EGL_NONE;
config.mTransparentRedValue = 0;
config.mTransparentGreenValue = 0;
config.mTransparentBlueValue = 0;
return config;
}
static std::vector<egl::Config> GenerateUniqueConfigs(size_t count)
{
std::vector<egl::Config> configs;
for (size_t i = 0; i < count; i++)
{
egl::Config config = GenerateGenericConfig();
config.mSamples = i;
configs.push_back(config);
}
return configs;
}
// Add unique configs to a ConfigSet and expect that the size of the
// set is equal to the number of configs added.
TEST(ConfigSetTest, Size)
{
egl::ConfigSet set;
std::vector<egl::Config> uniqueConfigs = GenerateUniqueConfigs(16);
for (size_t i = 0; i < uniqueConfigs.size(); i++)
{
set.add(uniqueConfigs[i]);
EXPECT_EQ(set.size(), i + 1);
}
}
// [EGL 1.5] section 3.4:
// EGL_CONFIG_ID is a unique integer identifying different EGLConfigs. Configuration IDs
// must be small positive integers starting at 1 and ID assignment should be compact;
// that is, if there are N EGLConfigs defined by the EGL implementation, their
// configuration IDs should be in the range [1, N].
TEST(ConfigSetTest, IDs)
{
egl::ConfigSet set;
std::set<EGLint> ids;
std::vector<egl::Config> uniqueConfigs = GenerateUniqueConfigs(16);
for (size_t i = 0; i < uniqueConfigs.size(); i++)
{
EGLint id = set.add(uniqueConfigs[i]);
// Check that the config that was inserted has the ID that was returned
// by ConfigSet::add
EXPECT_EQ(id, set.get(id).mConfigID);
ids.insert(id);
}
// Verify configCount unique IDs
EXPECT_EQ(ids.size(), set.size());
// Check that there are no gaps and the IDs are in the range [1, N].
EXPECT_EQ(*std::min_element(ids.begin(), ids.end()), 1);
EXPECT_EQ(*std::max_element(ids.begin(), ids.end()), set.size());
}
TEST(ConfigSetTest, Filtering_BitSizes)
{
egl::ConfigSet set;
struct VariableConfigBitSize
{
EGLint Name;
EGLint(egl::Config::*ConfigMember);
};
VariableConfigBitSize testMembers[] =
{
{ EGL_RED_SIZE, &egl::Config::mRedSize },
{ EGL_GREEN_SIZE, &egl::Config::mGreenSize },
{ EGL_BLUE_SIZE, &egl::Config::mBlueSize },
{ EGL_ALPHA_SIZE, &egl::Config::mAlphaSize },
{ EGL_DEPTH_SIZE, &egl::Config::mDepthSize },
{ EGL_STENCIL_SIZE, &egl::Config::mStencilSize },
};
// Generate configsPerType configs with varying bit sizes of each type
size_t configsPerType = 4;
for (size_t i = 0; i < ArraySize(testMembers); i++)
{
for (size_t j = 0; j < configsPerType; j++)
{
egl::Config config = GenerateGenericConfig();
// Set all the other tested members of this config to 0
for (size_t k = 0; k < ArraySize(testMembers); k++)
{
config.*(testMembers[k].ConfigMember) = 0;
}
// Set the tested member of this config to i so it ranges from
// [1, configsPerType]
config.*(testMembers[i].ConfigMember) = j + 1;
set.add(config);
}
}
// for each tested member, filter by it's type and verify that the correct number
// of results are returned
for (size_t i = 0; i < ArraySize(testMembers); i++)
{
// Start with a filter of 1 to not grab the other members
for (size_t j = 0; j < configsPerType; j++)
{
egl::AttributeMap filter;
filter.insert(testMembers[i].Name, j + 1);
std::vector<const egl::Config *> filteredConfigs = set.filter(filter);
EXPECT_EQ(filteredConfigs.size(), configsPerType - j);
}
}
}
// Verify the sorting, [EGL 1.5] section 3.4.1.2 pg 30:
// [configs are sorted] by larger total number of color bits (for an RGB
// color buffer this is the sum of EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE,
// and EGL_ALPHA_SIZE; for a luminance color buffer, the sum of EGL_LUMINANCE_SIZE
// and EGL_ALPHA_SIZE).If the requested number of bits in attrib list for a
// particular color component is 0 or EGL_DONT_CARE, then the number of bits
// for that component is not considered.
TEST(ConfigSetTest, Sorting_BitSizes)
{
egl::ConfigSet set;
size_t testConfigCount = 64;
for (size_t i = 0; i < testConfigCount; i++)
{
egl::Config config = GenerateGenericConfig();
// Give random-ish bit sizes to the config
config.mRedSize = (i * 2) % 3;
config.mGreenSize = (i + 5) % 7;
config.mBlueSize = (i + 7) % 11;
config.mAlphaSize = (i + 13) % 17;
set.add(config);
}
egl::AttributeMap greaterThan1BitFilter;
greaterThan1BitFilter.insert(EGL_RED_SIZE, 1);
greaterThan1BitFilter.insert(EGL_GREEN_SIZE, 1);
greaterThan1BitFilter.insert(EGL_BLUE_SIZE, 1);
greaterThan1BitFilter.insert(EGL_ALPHA_SIZE, 1);
std::vector<const egl::Config *> filteredConfigs = set.filter(greaterThan1BitFilter);
for (size_t i = 1; i < filteredConfigs.size(); i++)
{
const egl::Config &prevConfig = *filteredConfigs[i - 1];
size_t prevBitCount = prevConfig.mRedSize +
prevConfig.mGreenSize +
prevConfig.mBlueSize +
prevConfig.mAlphaSize;
const egl::Config &curConfig = *filteredConfigs[i];
size_t curBitCount = curConfig.mRedSize +
curConfig.mGreenSize +
curConfig.mBlueSize +
curConfig.mAlphaSize;
EXPECT_GE(prevBitCount, curBitCount);
}
}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
{ {
'sources': 'sources':
[ [
'Config_unittest.cpp',
'Fence_unittest.cpp', 'Fence_unittest.cpp',
'ImageIndexIterator_unittest.cpp', 'ImageIndexIterator_unittest.cpp',
'Surface_unittest.cpp', 'Surface_unittest.cpp',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment