OSDN Git Service

Fix eglChooseConfig behavior to match CTS expectation
authorChris Forbes <chrisforbes@google.com>
Sat, 1 Sep 2018 01:26:20 +0000 (18:26 -0700)
committerChris Forbes <chrisforbes@google.com>
Thu, 6 Sep 2018 17:31:31 +0000 (17:31 +0000)
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/20448
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
CONTRIBUTORS.txt
src/OpenGL/libEGL/Config.cpp

index 81d1149..b03eaa4 100644 (file)
@@ -25,6 +25,7 @@ Google Inc.
  Daniel Toyama <kenjitoyama@google.com>\r
  Meng-Lin Wu <marleymoo@google.com>\r
  Krzysztof KosiƄski <krzysio@google.com>\r
+ Chris Forbes <chrisforbes@google.com>\r
 \r
 TransGaming Inc.\r
  Nicolas Capens\r
index 66f4260..4c35f6b 100644 (file)
@@ -29,6 +29,7 @@
 #include <algorithm>
 #include <cstring>
 #include <vector>
+#include <map>
 
 using namespace std;
 
@@ -261,16 +262,15 @@ SortConfig::SortConfig(const EGLint *attribList)
        // 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)
+               // 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_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;
-                       }
+                       case EGL_RED_SIZE:       mWantRed = isSpecified;       break;
+                       case EGL_GREEN_SIZE:     mWantGreen = isSpecified;     break;
+                       case EGL_BLUE_SIZE:      mWantBlue = isSpecified;      break;
+                       case EGL_ALPHA_SIZE:     mWantAlpha = isSpecified;     break;
+                       case EGL_LUMINANCE_SIZE: mWantLuminance = isSpecified; break;
                }
        }
 }
@@ -344,49 +344,60 @@ bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint
        vector<const Config*> passed;
        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++)
        {
                bool match = true;
                bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
-               const EGLint *attribute = attribList;
-
-               while(attribute[0] != EGL_NONE)
+               for (map<EGLint, EGLint>::iterator attribIt = attribs.begin(); attribIt != attribs.end(); attribIt++)
                {
-                       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_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_RECORDABLE_ANDROID:         match = config->mRecordableAndroid == (EGLBoolean)attribute[1];        break;
-                               case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribute[1]; break;
+                               case EGL_BUFFER_SIZE:                match = config->mBufferSize >= attribIt->second;                           break;
+                               case EGL_ALPHA_SIZE:                 match = config->mAlphaSize >= attribIt->second;                            break;
+                               case EGL_BLUE_SIZE:                  match = config->mBlueSize >= attribIt->second;                             break;
+                               case EGL_GREEN_SIZE:                 match = config->mGreenSize >= attribIt->second;                            break;
+                               case EGL_RED_SIZE:                   match = config->mRedSize >= attribIt->second;                              break;
+                               case EGL_DEPTH_SIZE:                 match = config->mDepthSize >= attribIt->second;                            break;
+                               case EGL_STENCIL_SIZE:               match = config->mStencilSize >= attribIt->second;                          break;
+                               case EGL_CONFIG_CAVEAT:              match = config->mConfigCaveat == (EGLenum)attribIt->second;                break;
+                               case EGL_CONFIG_ID:                  match = config->mConfigID == attribIt->second;                             break;
+                               case EGL_LEVEL:                      match = config->mLevel >= attribIt->second;                                break;
+                               case EGL_NATIVE_RENDERABLE:          match = config->mNativeRenderable == (EGLBoolean)attribIt->second;         break;
+                               case EGL_NATIVE_VISUAL_TYPE:         match = config->mNativeVisualType == attribIt->second;                     break;
+                               case EGL_SAMPLES:                    match = config->mSamples >= attribIt->second;                              break;
+                               case EGL_SAMPLE_BUFFERS:             match = config->mSampleBuffers >= attribIt->second;                        break;
+                               case EGL_SURFACE_TYPE:               match = (config->mSurfaceType & attribIt->second) == attribIt->second;     break;
+                               case EGL_TRANSPARENT_TYPE:           match = config->mTransparentType == (EGLenum)attribIt->second;             break;
+                               case EGL_TRANSPARENT_BLUE_VALUE:     match = config->mTransparentBlueValue == attribIt->second;                 break;
+                               case EGL_TRANSPARENT_GREEN_VALUE:    match = config->mTransparentGreenValue == attribIt->second;                break;
+                               case EGL_TRANSPARENT_RED_VALUE:      match = config->mTransparentRedValue == attribIt->second;                  break;
+                               case EGL_BIND_TO_TEXTURE_RGB:        match = config->mBindToTextureRGB == (EGLBoolean)attribIt->second;         break;
+                               case EGL_BIND_TO_TEXTURE_RGBA:       match = config->mBindToTextureRGBA == (EGLBoolean)attribIt->second;        break;
+                               case EGL_MIN_SWAP_INTERVAL:          match = config->mMinSwapInterval == attribIt->second;                      break;
+                               case EGL_MAX_SWAP_INTERVAL:          match = config->mMaxSwapInterval == attribIt->second;                      break;
+                               case EGL_LUMINANCE_SIZE:             match = config->mLuminanceSize >= attribIt->second;                        break;
+                               case EGL_ALPHA_MASK_SIZE:            match = config->mAlphaMaskSize >= attribIt->second;                        break;
+                               case EGL_COLOR_BUFFER_TYPE:          match = config->mColorBufferType == (EGLenum)attribIt->second;             break;
+                               case EGL_RENDERABLE_TYPE:            match = (config->mRenderableType & attribIt->second) == attribIt->second;  break;
+                               case EGL_MATCH_NATIVE_PIXMAP:        match = false; UNIMPLEMENTED();                                            break;
+                               case EGL_CONFORMANT:                 match = (config->mConformant & attribIt->second) == attribIt->second;      break;
+                               case EGL_RECORDABLE_ANDROID:         match = config->mRecordableAndroid == (EGLBoolean)attribIt->second;        break;
+                               case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribIt->second; break;
 
                                // Ignored attributes
                                case EGL_MAX_PBUFFER_WIDTH:
@@ -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;
                        }
-
-                       attribute += 2;
                }
 
                if(match && caveatMatch)   // We require the caveats to be NONE or the requested flags