Commit 4e87659e by Ian Elliott Committed by Commit Bot

Fix eglChooseConfig for attributes that have exact default values.

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: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 3c1f5a6b
......@@ -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);
......@@ -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);
......
......@@ -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,
......
......@@ -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,
......
......@@ -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;
......
......@@ -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",
......
//
// 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());
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