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,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)
{ {
attrib_list = attribList; filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size));
for (size_t i = 0; i < filteredConfigs.size(); i++)
{
configs[i] = const_cast<Config*>(filteredConfigs[i]);
}
} }
*num_config = filteredConfigs.size();
display->getConfigs(configs, attrib_list, config_size, num_config);
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