Commit 787e3d5b by Chris Forbes

Fix eglChooseConfig behavior to match CTS expectation

When multiple instances of the same attribute are provided, CTS expects the last instance to win. Achieve this by: 1/ Reducing the attribute list in getConfigs() 2/ Adjusting the sort order's consideration of which color components are "required" to allow a later 0 or EGL_DONT_CARE to remove a component from consideration again. Affects: dEQP-EGL.functional.choose_config.* Bug: b/113679786 V2: Fix up the alignment I broke V4: Style fix Change-Id: If9375c9dc5aaadb0ee7b77ecf1e1098c82fa30ca Reviewed-on: https://swiftshader-review.googlesource.com/20448Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarChris Forbes <chrisforbes@google.com>
parent ad5c2952
...@@ -25,6 +25,7 @@ Google Inc. ...@@ -25,6 +25,7 @@ Google Inc.
Daniel Toyama <kenjitoyama@google.com> Daniel Toyama <kenjitoyama@google.com>
Meng-Lin Wu <marleymoo@google.com> Meng-Lin Wu <marleymoo@google.com>
Krzysztof Kosiński <krzysio@google.com> Krzysztof Kosiński <krzysio@google.com>
Chris Forbes <chrisforbes@google.com>
TransGaming Inc. TransGaming Inc.
Nicolas Capens Nicolas Capens
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#include <map>
using namespace std; using namespace std;
...@@ -261,16 +262,15 @@ SortConfig::SortConfig(const EGLint *attribList) ...@@ -261,16 +262,15 @@ SortConfig::SortConfig(const EGLint *attribList)
// not considering components that are 0 or don't-care. // not considering components that are 0 or don't-care.
for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2) for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
{ {
if(attr[1] != 0 && attr[1] != EGL_DONT_CARE) // When multiple instances of the same attribute are present, last wins.
{ bool isSpecified = attr[1] && attr[1] != EGL_DONT_CARE;
switch(attr[0]) switch(attr[0])
{ {
case EGL_RED_SIZE: mWantRed = true; break; case EGL_RED_SIZE: mWantRed = isSpecified; break;
case EGL_GREEN_SIZE: mWantGreen = true; break; case EGL_GREEN_SIZE: mWantGreen = isSpecified; break;
case EGL_BLUE_SIZE: mWantBlue = true; break; case EGL_BLUE_SIZE: mWantBlue = isSpecified; break;
case EGL_ALPHA_SIZE: mWantAlpha = true; break; case EGL_ALPHA_SIZE: mWantAlpha = isSpecified; break;
case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; case EGL_LUMINANCE_SIZE: mWantLuminance = isSpecified; break;
}
} }
} }
} }
...@@ -344,49 +344,60 @@ bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint ...@@ -344,49 +344,60 @@ bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint
vector<const Config*> passed; vector<const Config*> passed;
passed.reserve(mSet.size()); passed.reserve(mSet.size());
/* Conformance expects for multiple instances of the same attribute that the
* last instance `wins`. Reduce the attribute list first to comply with
* this.
*/
/* TODO: C++11: unordered_map would be fine here */
map<EGLint, EGLint> attribs;
const EGLint *attribute = attribList;
while (attribute[0] != EGL_NONE)
{
attribs[attribute[0]] = attribute[1];
attribute += 2;
}
for(Iterator config = mSet.begin(); config != mSet.end(); config++) for(Iterator config = mSet.begin(); config != mSet.end(); config++)
{ {
bool match = true; bool match = true;
bool caveatMatch = (config->mConfigCaveat == EGL_NONE); bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
const EGLint *attribute = attribList; for (map<EGLint, EGLint>::iterator attribIt = attribs.begin(); attribIt != attribs.end(); attribIt++)
while(attribute[0] != EGL_NONE)
{ {
if(attribute[1] != EGL_DONT_CARE) if(attribIt->second != EGL_DONT_CARE)
{ {
switch(attribute[0]) switch(attribIt->first)
{ {
case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break; case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribIt->second; break;
case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break; case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribIt->second; break;
case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break; case EGL_BLUE_SIZE: match = config->mBlueSize >= attribIt->second; break;
case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break; case EGL_GREEN_SIZE: match = config->mGreenSize >= attribIt->second; break;
case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break; case EGL_RED_SIZE: match = config->mRedSize >= attribIt->second; break;
case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break; case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribIt->second; break;
case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break; case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribIt->second; break;
case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum)attribute[1]; break; case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum)attribIt->second; break;
case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break; case EGL_CONFIG_ID: match = config->mConfigID == attribIt->second; break;
case EGL_LEVEL: match = config->mLevel >= attribute[1]; break; case EGL_LEVEL: match = config->mLevel >= attribIt->second; break;
case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean)attribute[1]; break; case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean)attribIt->second; break;
case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break; case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribIt->second; break;
case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break; case EGL_SAMPLES: match = config->mSamples >= attribIt->second; break;
case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break; case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribIt->second; break;
case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break; case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribIt->second) == attribIt->second; break;
case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum)attribute[1]; break; case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum)attribIt->second; break;
case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break; case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribIt->second; break;
case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break; case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribIt->second; break;
case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break; case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribIt->second; break;
case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean)attribute[1]; break; case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean)attribIt->second; break;
case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean)attribute[1]; break; case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean)attribIt->second; break;
case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break; case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribIt->second; break;
case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break; case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribIt->second; break;
case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break; case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribIt->second; break;
case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break; case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribIt->second; break;
case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum)attribute[1]; break; case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum)attribIt->second; break;
case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break; case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribIt->second) == attribIt->second; 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 & attribIt->second) == attribIt->second; break;
case EGL_RECORDABLE_ANDROID: match = config->mRecordableAndroid == (EGLBoolean)attribute[1]; break; case EGL_RECORDABLE_ANDROID: match = config->mRecordableAndroid == (EGLBoolean)attribIt->second; break;
case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribute[1]; break; case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribIt->second; break;
// Ignored attributes // Ignored attributes
case EGL_MAX_PBUFFER_WIDTH: case EGL_MAX_PBUFFER_WIDTH:
...@@ -406,12 +417,10 @@ bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint ...@@ -406,12 +417,10 @@ bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint
} }
} }
if(attribute[0] == EGL_CONFIG_CAVEAT) if(attribIt->first == EGL_CONFIG_CAVEAT)
{ {
caveatMatch = match; caveatMatch = match;
} }
attribute += 2;
} }
if(match && caveatMatch) // We require the caveats to be NONE or the requested flags if(match && caveatMatch) // We require the caveats to be NONE or the requested flags
......
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