Skip to content

Commit

Permalink
Fix eglChooseConfig for attributes that have exact default values.
Browse files Browse the repository at this point in the history
The implementation of eglChooseConfig does not match the
specification for attributes not provided by the calling function.  It
is supposed to use the default value and match semantics, per the
specification.  This is fine for many attributes (where the value in
the EGLConfig doesn't matter).  Currently, this affects the following
attributes:

- EGL_COLOR_BUFFER_TYPE
- EGL_LEVEL
- EGL_RENDERABLE_TYPE
- EGL_SURFACE_TYPE
- EGL_TRANSPARENT_TYPE
- EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE
- EGL_COLOR_COMPONENT_TYPE_EXT

This change causes 55 of 65 of the dEQP-EGL.functional.choose_config.* tests
to start passing.

Bug: angleproject:3172
Change-Id: I287af5ba7d296694d9a78ded5d1e3bc4e7043d03
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1506696
Commit-Queue: Ian Elliott <ianelliott@google.com>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
  • Loading branch information
ianelliottus authored and Commit Bot committed Mar 13, 2019
1 parent 3c1f5a6 commit 4e87659
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 5 deletions.
17 changes: 13 additions & 4 deletions src/libANGLE/Config.cpp
Expand Up @@ -273,7 +273,7 @@ std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap)
match = config.configID == attributeValue;
break;
case EGL_LEVEL:
match = config.level >= attributeValue;
match = config.level == attributeValue;
break;
case EGL_NATIVE_RENDERABLE:
match = config.nativeRenderable == static_cast<EGLBoolean>(attributeValue);
Expand All @@ -294,13 +294,22 @@ std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap)
match = config.transparentType == static_cast<EGLenum>(attributeValue);
break;
case EGL_TRANSPARENT_BLUE_VALUE:
match = config.transparentBlueValue == attributeValue;
if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
{
match = config.transparentBlueValue == attributeValue;
}
break;
case EGL_TRANSPARENT_GREEN_VALUE:
match = config.transparentGreenValue == attributeValue;
if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
{
match = config.transparentGreenValue == attributeValue;
}
break;
case EGL_TRANSPARENT_RED_VALUE:
match = config.transparentRedValue == attributeValue;
if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
{
match = config.transparentRedValue == attributeValue;
}
break;
case EGL_BIND_TO_TEXTURE_RGB:
match = config.bindToTextureRGB == static_cast<EGLBoolean>(attributeValue);
Expand Down
27 changes: 27 additions & 0 deletions src/libANGLE/Display.cpp
Expand Up @@ -654,6 +654,33 @@ std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs
return mConfigSet.filter(attribs);
}

std::vector<const Config *> Display::chooseConfig(const egl::AttributeMap &attribs) const
{
egl::AttributeMap attribsWithDefaults = AttributeMap();

// Insert default values for attributes that have either an Exact or Mask selection criteria,
// and a default value that matters (e.g. isn't EGL_DONT_CARE):
attribsWithDefaults.insert(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
attribsWithDefaults.insert(EGL_LEVEL, 0);
attribsWithDefaults.insert(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
attribsWithDefaults.insert(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
attribsWithDefaults.insert(EGL_TRANSPARENT_TYPE, EGL_NONE);
if (getExtensions().pixelFormatFloat)
{
attribsWithDefaults.insert(EGL_COLOR_COMPONENT_TYPE_EXT,
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
}

// Add the caller-specified values (Note: the poorly-named insert() method will replace any
// of the default values from above):
for (auto attribIter = attribs.begin(); attribIter != attribs.end(); attribIter++)
{
attribsWithDefaults.insert(attribIter->first, attribIter->second);
}

return mConfigSet.filter(attribsWithDefaults);
}

Error Display::createWindowSurface(const Config *configuration,
EGLNativeWindowType window,
const AttributeMap &attribs,
Expand Down
1 change: 1 addition & 0 deletions src/libANGLE/Display.h
Expand Up @@ -77,6 +77,7 @@ class Display final : public LabeledObject, angle::NonCopyable
static const std::string &GetClientExtensionString();

std::vector<const Config *> getConfigs(const AttributeMap &attribs) const;
std::vector<const Config *> chooseConfig(const AttributeMap &attribs) const;

Error createWindowSurface(const Config *configuration,
EGLNativeWindowType window,
Expand Down
2 changes: 1 addition & 1 deletion src/libGLESv2/entry_points_egl.cpp
Expand Up @@ -205,7 +205,7 @@ EGLBoolean EGLAPIENTRY EGL_ChooseConfig(EGLDisplay dpy,
ANGLE_EGL_TRY_RETURN(thread, ValidateChooseConfig(display, attribMap, config_size, num_config),
"eglChooseConfig", GetDisplayIfValid(display), EGL_FALSE);

ClipConfigs(display->getConfigs(attribMap), configs, config_size, num_config);
ClipConfigs(display->chooseConfig(attribMap), configs, config_size, num_config);

thread->setSuccess();
return EGL_TRUE;
Expand Down
1 change: 1 addition & 0 deletions src/tests/angle_end2end_tests.gni
Expand Up @@ -126,6 +126,7 @@ angle_end2end_tests_sources = [
"gl_tests/WebGLFramebufferTest.cpp",
"gl_tests/WebGLReadOutsideFramebufferTest.cpp",
"egl_tests/EGLBlobCacheTest.cpp",
"egl_tests/EGLChooseConfigTest.cpp",
"egl_tests/EGLContextCompatibilityTest.cpp",
"egl_tests/EGLContextSharingTest.cpp",
"egl_tests/EGLDebugTest.cpp",
Expand Down
122 changes: 122 additions & 0 deletions src/tests/egl_tests/EGLChooseConfigTest.cpp
@@ -0,0 +1,122 @@
//
// Copyright 2019 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.
//
// EGLChooseConfigTest.cpp:
// Tests of proper default-value semantics for eglChooseConfig

#include <gtest/gtest.h>

#include "test_utils/ANGLETest.h"
#include "test_utils/angle_test_configs.h"
#include "util/EGLWindow.h"

using namespace angle;

namespace angle
{
class EGLChooseConfigTest : public ANGLETest
{
protected:
EGLChooseConfigTest() {}
};

// Test that the EGL_COLOR_BUFFER_TYPE is defaulted to EGL_RGB_BUFFER
TEST_P(EGLChooseConfigTest, Defaults)
{
EGLDisplay display = getEGLWindow()->getDisplay();

EGLint nConfigs = 0;
EGLint allConfigCount = 0;
ASSERT_EGL_TRUE(eglGetConfigs(display, nullptr, 0, &nConfigs));
ASSERT_NE(nConfigs, 0);

std::vector<EGLConfig> allConfigs(nConfigs);
ASSERT_EGL_TRUE(eglGetConfigs(display, allConfigs.data(), nConfigs, &allConfigCount));
ASSERT_EQ(nConfigs, allConfigCount);

// Choose configs that have the default attribute values:
const EGLint defaultConfigAttributes[] = {EGL_NONE};
EGLint defaultConfigCount;
std::vector<EGLConfig> defaultConfigs(allConfigCount);
ASSERT_EGL_TRUE(eglChooseConfig(display, defaultConfigAttributes, defaultConfigs.data(),
defaultConfigs.size(), &defaultConfigCount));
ASSERT_EGL_SUCCESS();
ASSERT_LE(defaultConfigCount, allConfigCount);

// Check that the default configs all have the default attribute values we care about:
for (EGLConfig config : defaultConfigs)
{
EGLint colorBufferType, level, renderableType, surfaceType, transparentType;
EGLint colorComponentType;

eglGetConfigAttrib(display, config, EGL_COLOR_BUFFER_TYPE, &colorBufferType);
ASSERT_EQ(colorBufferType, EGL_RGB_BUFFER);

eglGetConfigAttrib(display, config, EGL_LEVEL, &level);
ASSERT_EQ(level, 0);

eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
ASSERT_EQ(renderableType & EGL_OPENGL_ES_BIT, EGL_OPENGL_ES_BIT);

eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
ASSERT_EQ(surfaceType & EGL_WINDOW_BIT, EGL_WINDOW_BIT);

eglGetConfigAttrib(display, config, EGL_TRANSPARENT_TYPE, &transparentType);
ASSERT_EQ(transparentType, EGL_NONE);

if (ANGLETest::eglDisplayExtensionEnabled(display, "EGL_EXT_pixel_format_float"))
{
eglGetConfigAttrib(display, config, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType);
ASSERT_EQ(colorComponentType, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
}
}

// Check that all of the configs that have the default attribute values are are defaultConfigs,
// and all that don't aren't:
for (EGLConfig config : allConfigs)
{
EGLint colorBufferType, level, renderableType, surfaceType, transparentType;
EGLint colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;

eglGetConfigAttrib(display, config, EGL_COLOR_BUFFER_TYPE, &colorBufferType);
eglGetConfigAttrib(display, config, EGL_LEVEL, &level);
eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
eglGetConfigAttrib(display, config, EGL_TRANSPARENT_TYPE, &transparentType);
if (ANGLETest::eglDisplayExtensionEnabled(display, "EGL_EXT_pixel_format_float"))
{
eglGetConfigAttrib(display, config, EGL_COLOR_COMPONENT_TYPE_EXT, &colorComponentType);
}

bool isADefault =
((colorBufferType == EGL_RGB_BUFFER) && (level == 0) &&
((renderableType & EGL_OPENGL_ES_BIT) == EGL_OPENGL_ES_BIT) &&
((surfaceType & EGL_WINDOW_BIT) == EGL_WINDOW_BIT) && (transparentType == EGL_NONE) &&
(colorComponentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT));
EGLint thisConfigID;
eglGetConfigAttrib(display, config, EGL_CONFIG_ID, &thisConfigID);
bool foundInDefaultConfigs = false;
// Attempt to find this config ID in defaultConfigs:
for (EGLConfig defaultConfig : defaultConfigs)
{
EGLint defaultConfigID;
eglGetConfigAttrib(display, defaultConfig, EGL_CONFIG_ID, &defaultConfigID);
if (defaultConfigID == thisConfigID)
{
foundInDefaultConfigs = true;
}
}
ASSERT_EQ(isADefault, foundInDefaultConfigs);
}
}

} // namespace angle

ANGLE_INSTANTIATE_TEST(EGLChooseConfigTest,
ES2_D3D11(),
ES2_D3D9(),
ES2_OPENGL(),
ES2_OPENGLES(),
ES2_VULKAN());

0 comments on commit 4e87659

Please sign in to comment.