Plumb robust resource init extensions.
This also cleans up a few minor glitches in the extension texts,
and renames the EGL extension for consistency.
It incidentally fixes a bug in our EGL init where we were checking
the wrong client versions for KHR_create_context.
It also implements a new feature for tests which allow them to defer
Context creation until the test body. This allows tests to check for
EGL extension available before trying to create a context with certain
extensions.
BUG=angleproject:1635
Change-Id: I9311991332c357e36214082b16f2a4a57bfa8865
Reviewed-on: https://chromium-review.googlesource.com/450920
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index 3bfdd97..8888831 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -214,7 +214,8 @@
textureNorm16(false),
pathRendering(false),
surfacelessContext(false),
- clientArrays(false)
+ clientArrays(false),
+ robustResourceInitialization(false)
{
}
@@ -648,6 +649,7 @@
map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContext);
map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArrays);
+ map["GL_ANGLE_robust_resource_initialization"] = esOnlyExtension(&Extensions::robustResourceInitialization);
// clang-format on
return map;
@@ -1037,7 +1039,8 @@
pixelFormatFloat(false),
surfacelessContext(false),
displayTextureShareGroup(false),
- createContextClientArrays(false)
+ createContextClientArrays(false),
+ createContextRobustResourceInitialization(false)
{
}
@@ -1079,6 +1082,7 @@
InsertExtensionString("EGL_KHR_surfaceless_context", surfacelessContext, &extensionStrings);
InsertExtensionString("EGL_ANGLE_display_texture_share_group", displayTextureShareGroup, &extensionStrings);
InsertExtensionString("EGL_ANGLE_create_context_client_arrays", createContextClientArrays, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_robust_resource_initialization", createContextRobustResourceInitialization, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 76ccaad..57dc0b8 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -354,6 +354,9 @@
// GL_ANGLE_client_arrays
bool clientArrays;
+
+ // GL_ANGLE_robust_resource_initialization
+ bool robustResourceInitialization;
};
struct ExtensionInfo
@@ -655,6 +658,9 @@
// EGL_ANGLE_create_context_client_arrays
bool createContextClientArrays;
+
+ // EGL_ANGLE_create_context_robust_resource_initialization
+ bool createContextRobustResourceInitialization;
};
struct DeviceExtensions
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index d3e4366..507618d 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -204,6 +204,11 @@
return (attribs.get(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE) == EGL_TRUE);
}
+bool GetRobustResourceInit(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
{
std::string labelName;
@@ -278,7 +283,8 @@
initWorkarounds();
mGLState.initialize(mCaps, mExtensions, getClientVersion(), GetDebug(attribs),
- GetBindGeneratesResource(attribs), GetClientArraysEnabled(attribs));
+ GetBindGeneratesResource(attribs), GetClientArraysEnabled(attribs),
+ GetRobustResourceInit(attribs));
mFenceNVHandleAllocator.setBaseHandle(0);
@@ -2533,6 +2539,10 @@
// Explicitly enable GL_ANGLE_robust_client_memory
mExtensions.robustClientMemory = true;
+ // Determine robust resource init availability from EGL.
+ mExtensions.robustResourceInitialization =
+ displayExtensions.createContextRobustResourceInitialization;
+
// Apply implementation limits
mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
mCaps.maxVertexAttribBindings =
diff --git a/src/libANGLE/ContextState.cpp b/src/libANGLE/ContextState.cpp
index 4694929..ad0c036 100644
--- a/src/libANGLE/ContextState.cpp
+++ b/src/libANGLE/ContextState.cpp
@@ -433,6 +433,14 @@
}
}
+ if (getExtensions().robustResourceInitialization &&
+ pname == GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE)
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
// Check for ES3.0+ parameter names which are also exposed as ES2 extensions
switch (pname)
{
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index 5ec2090..c47824c 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -62,7 +62,8 @@
mPrimitiveRestart(false),
mMultiSampling(false),
mSampleAlphaToOne(false),
- mFramebufferSRGB(true)
+ mFramebufferSRGB(true),
+ mRobustResourceInit(false)
{
}
@@ -75,7 +76,8 @@
const Version &clientVersion,
bool debug,
bool bindGeneratesResource,
- bool clientArraysEnabled)
+ bool clientArraysEnabled,
+ bool robustResourceInit)
{
mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
@@ -214,6 +216,8 @@
mPathStencilFunc = GL_ALWAYS;
mPathStencilRef = 0;
mPathStencilMask = std::numeric_limits<GLuint>::max();
+
+ mRobustResourceInit = robustResourceInit;
}
void State::reset(const Context *context)
@@ -697,6 +701,8 @@
return areClientArraysEnabled();
case GL_FRAMEBUFFER_SRGB_EXT:
return getFramebufferSRGB();
+ case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ return mRobustResourceInit;
default: UNREACHABLE(); return false;
}
}
@@ -1589,6 +1595,9 @@
case GL_FRAMEBUFFER_SRGB_EXT:
*params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
break;
+ case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *params = mRobustResourceInit ? GL_TRUE : GL_FALSE;
+ break;
default:
UNREACHABLE();
break;
diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h
index 1f13b87..b0dd0ed 100644
--- a/src/libANGLE/State.h
+++ b/src/libANGLE/State.h
@@ -45,7 +45,8 @@
const Version &clientVersion,
bool debug,
bool bindGeneratesResource,
- bool clientArraysEnabled);
+ bool clientArraysEnabled,
+ bool robustResourceInit);
void reset(const Context *context);
// State chunk getters
@@ -509,6 +510,9 @@
// GL_EXT_sRGB_write_control
bool mFramebufferSRGB;
+ // GL_ANGLE_robust_resource_intialization
+ bool mRobustResourceInit;
+
DirtyBits mDirtyBits;
DirtyObjects mDirtyObjects;
};
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index a53fc41..a3dbcbc 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -1103,6 +1103,8 @@
// Contexts are virtualized so textures can be shared globally
outExtensions->displayTextureShareGroup = true;
+
+ outExtensions->createContextRobustResourceInitialization = true;
}
gl::Error Renderer11::flush()
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
index 621928d..2140907 100644
--- a/src/libANGLE/validationEGL.cpp
+++ b/src/libANGLE/validationEGL.cpp
@@ -464,6 +464,21 @@
}
break;
+ case EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().createContextRobustResourceInitialization)
+ {
+ return Error(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+ "requires EGL_ANGLE_create_context_robust_resource_initialization.");
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return Error(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.");
+ }
+ break;
+
default:
return Error(EGL_BAD_ATTRIBUTE, "Unknown attribute.");
}
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 20413f6..6901b54 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -216,6 +216,9 @@
case GL_SAMPLE_MASK:
return context->getClientVersion() >= Version(3, 1);
+ case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ return queryOnly && context->getExtensions().robustResourceInitialization;
+
default:
return false;
}
diff --git a/src/libANGLE/validationES_unittest.cpp b/src/libANGLE/validationES_unittest.cpp
index f1171a8..17452d8 100644
--- a/src/libANGLE/validationES_unittest.cpp
+++ b/src/libANGLE/validationES_unittest.cpp
@@ -78,7 +78,7 @@
caps.maxElementIndex = 100;
caps.maxDrawBuffers = 1;
caps.maxColorAttachments = 1;
- state.initialize(caps, extensions, Version(3, 0), false, true, true);
+ state.initialize(caps, extensions, Version(3, 0), false, true, true, false);
NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
diff --git a/src/tests/angle_end2end_tests.gypi b/src/tests/angle_end2end_tests.gypi
index cb53229..d476c5a 100644
--- a/src/tests/angle_end2end_tests.gypi
+++ b/src/tests/angle_end2end_tests.gypi
@@ -67,6 +67,7 @@
'<(angle_path)/src/tests/gl_tests/ReadPixelsTest.cpp',
'<(angle_path)/src/tests/gl_tests/RendererTest.cpp',
'<(angle_path)/src/tests/gl_tests/RobustClientMemoryTest.cpp',
+ '<(angle_path)/src/tests/gl_tests/RobustResourceInitTest.cpp',
'<(angle_path)/src/tests/gl_tests/SimpleOperationTest.cpp',
'<(angle_path)/src/tests/gl_tests/SixteenBppTextureTest.cpp',
'<(angle_path)/src/tests/gl_tests/SRGBFramebufferTest.cpp',
diff --git a/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/tests/gl_tests/RobustResourceInitTest.cpp
new file mode 100644
index 0000000..8ecb29f
--- /dev/null
+++ b/src/tests/gl_tests/RobustResourceInitTest.cpp
@@ -0,0 +1,122 @@
+//
+// Copyright 2017 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.
+//
+// RobustResourceInitTest: Tests for GL_ANGLE_robust_resource_initialization.
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class RobustResourceInitTest : public ANGLETest
+{
+ protected:
+ RobustResourceInitTest()
+ {
+ setWindowWidth(128);
+ setWindowHeight(128);
+ setConfigRedBits(8);
+ setConfigGreenBits(8);
+ setConfigBlueBits(8);
+ setConfigAlphaBits(8);
+
+ // Defer context init until the test body.
+ setDeferContextInit(true);
+ setRobustResourceInit(true);
+ }
+};
+
+// Context creation should fail if EGL_ANGLE_create_context_robust_resource_initialization
+// is not available, and succeed otherwise.
+TEST_P(RobustResourceInitTest, ExtensionInit)
+{
+ EGLDisplay display = getEGLWindow()->getDisplay();
+ ASSERT_TRUE(display != EGL_NO_DISPLAY);
+
+ if (eglDisplayExtensionEnabled(display,
+ "EGL_ANGLE_create_context_robust_resource_initialization"))
+ {
+ // Context creation shold succeed with robust resource init enabled.
+ EXPECT_TRUE(getEGLWindow()->initializeContext());
+
+ // Robust resource init extension should be available.
+ EXPECT_TRUE(extensionEnabled("GL_ANGLE_robust_resource_initialization"));
+
+ // Querying the state value should return true.
+ GLboolean enabled = 0;
+ glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+ EXPECT_GL_NO_ERROR();
+ EXPECT_GL_TRUE(enabled);
+
+ EXPECT_GL_TRUE(glIsEnabled(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
+ }
+ else
+ {
+ // Context creation should fail with robust resource init enabled.
+ EXPECT_FALSE(getEGLWindow()->initializeContext());
+
+ // Context creation should succeed with robust resource init disabled.
+ setRobustResourceInit(false);
+ ASSERT_TRUE(getEGLWindow()->initializeGL(GetOSWindow()));
+
+ // If context extension string exposed, check queries.
+ if (extensionEnabled("GL_ANGLE_robust_resource_initialization"))
+ {
+ GLboolean enabled = 0;
+ glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+ EXPECT_GL_FALSE(enabled);
+
+ EXPECT_GL_FALSE(glIsEnabled(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
+ EXPECT_GL_NO_ERROR();
+ }
+ else
+ {
+ // Querying robust resource init should return INVALID_ENUM.
+ GLboolean enabled = 0;
+ glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+ EXPECT_GL_ERROR(GL_INVALID_ENUM);
+ }
+ }
+}
+
+// Test queries on a normal, non-robust enabled context.
+TEST_P(RobustResourceInitTest, QueriesOnNonRobustContext)
+{
+ EGLDisplay display = getEGLWindow()->getDisplay();
+ ASSERT_TRUE(display != EGL_NO_DISPLAY);
+
+ if (!eglDisplayExtensionEnabled(display,
+ "EGL_ANGLE_create_context_robust_resource_initialization"))
+ {
+ return;
+ }
+
+ setRobustResourceInit(false);
+ EXPECT_TRUE(getEGLWindow()->initializeContext());
+
+ // If context extension string exposed, check queries.
+ ASSERT_TRUE(extensionEnabled("GL_ANGLE_robust_resource_initialization"));
+
+ // Querying robust resource init should return INVALID_ENUM.
+ GLboolean enabled = 0;
+ glGetBooleanv(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE, &enabled);
+ EXPECT_GL_FALSE(enabled);
+
+ EXPECT_GL_FALSE(glIsEnabled(GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE));
+ EXPECT_GL_NO_ERROR();
+}
+
+ANGLE_INSTANTIATE_TEST(RobustResourceInitTest,
+ ES2_D3D9(),
+ ES2_D3D11(),
+ ES3_D3D11(),
+ ES2_D3D11_FL9_3(),
+ ES2_OPENGL(),
+ ES3_OPENGL(),
+ ES2_OPENGLES(),
+ ES3_OPENGLES());
+} // namespace
diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp
index aa9b365..79a9e5d 100644
--- a/src/tests/test_utils/ANGLETest.cpp
+++ b/src/tests/test_utils/ANGLETest.cpp
@@ -198,7 +198,8 @@
mWidth(16),
mHeight(16),
mIgnoreD3D11SDKLayersWarnings(false),
- mQuadVertexBuffer(0)
+ mQuadVertexBuffer(0),
+ mDeferContextInit(false)
{
mEGLWindow =
new EGLWindow(GetParam().majorVersion, GetParam().minorVersion, GetParam().eglParameters);
@@ -252,9 +253,14 @@
needSwap = true;
}
- if (!createEGLContext())
+ if (!mEGLWindow->initializeDisplayAndSurface(mOSWindow))
{
- FAIL() << "egl context creation failed.";
+ FAIL() << "egl display or surface init failed.";
+ }
+
+ if (!mDeferContextInit && !mEGLWindow->initializeContext())
+ {
+ FAIL() << "GL Context init failed.";
}
if (mGLESLibrary)
@@ -706,6 +712,16 @@
mEGLWindow->setClientArraysEnabled(enabled);
}
+void ANGLETest::setRobustResourceInit(bool enabled)
+{
+ mEGLWindow->setRobustResourceInit(enabled);
+}
+
+void ANGLETest::setDeferContextInit(bool enabled)
+{
+ mDeferContextInit = enabled;
+}
+
int ANGLETest::getClientMajorVersion() const
{
return mEGLWindow->getClientMajorVersion();
@@ -736,11 +752,6 @@
return mEGLWindow->isMultisample();
}
-bool ANGLETest::createEGLContext()
-{
- return mEGLWindow->initializeGL(mOSWindow);
-}
-
bool ANGLETest::destroyEGLContext()
{
mEGLWindow->destroyGL();
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index 2e18819..88c3f5f 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -238,6 +238,10 @@
void setBindGeneratesResource(bool bindGeneratesResource);
void setVulkanLayersEnabled(bool enabled);
void setClientArraysEnabled(bool enabled);
+ void setRobustResourceInit(bool enabled);
+
+ // Some EGL extension tests would like to defer the Context init until the test body.
+ void setDeferContextInit(bool enabled);
int getClientMajorVersion() const;
int getClientMinorVersion() const;
@@ -254,7 +258,6 @@
static OSWindow *GetOSWindow() { return mOSWindow; }
private:
- bool createEGLContext();
bool destroyEGLContext();
void checkD3D11SDKLayersMessages();
@@ -270,6 +273,8 @@
TestPlatformContext mPlatformContext;
+ bool mDeferContextInit;
+
static OSWindow *mOSWindow;
// Workaround for NVIDIA not being able to share a window with OpenGL and Vulkan.