Commit b0f917fa by Geoff Lang Committed by Commit Bot

Fix being unable to request some extensions implemented in the GL layer.

Some extensions are forced on in Context::initCaps even though the backend's native extensions do not mark the extension as supported. These extensions were not requestable because the Context::isExtensionRequestable only checks if the backend supports the extension. Make GL_OES_vertex_array_object requestable to cover the issue. BUG=angleproject:1523 Change-Id: Ie64df8e270924727ecf9cd3f993443abeb3ef658 Reviewed-on: https://chromium-review.googlesource.com/809197 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 025aafdf
...@@ -672,7 +672,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -672,7 +672,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_EXT_unpack_subimage"] = enableableExtension(&Extensions::unpackSubimage); map["GL_EXT_unpack_subimage"] = enableableExtension(&Extensions::unpackSubimage);
map["GL_NV_pack_subimage"] = enableableExtension(&Extensions::packSubimage); map["GL_NV_pack_subimage"] = enableableExtension(&Extensions::packSubimage);
map["GL_EXT_color_buffer_float"] = enableableExtension(&Extensions::colorBufferFloat); map["GL_EXT_color_buffer_float"] = enableableExtension(&Extensions::colorBufferFloat);
map["GL_OES_vertex_array_object"] = esOnlyExtension(&Extensions::vertexArrayObject); map["GL_OES_vertex_array_object"] = enableableExtension(&Extensions::vertexArrayObject);
map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug); map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug);
// TODO(jmadill): Enable this when complete. // TODO(jmadill): Enable this when complete.
//map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError); //map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError);
......
...@@ -350,15 +350,14 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -350,15 +350,14 @@ Context::Context(rx::EGLImplFactory *implFactory,
} }
} }
const Extensions &nativeExtensions = mImplementation->getNativeExtensions(); if (mSupportedExtensions.textureRectangle)
if (nativeExtensions.textureRectangle)
{ {
Texture *zeroTextureRectangle = Texture *zeroTextureRectangle =
new Texture(mImplementation.get(), 0, TextureType::Rectangle); new Texture(mImplementation.get(), 0, TextureType::Rectangle);
mZeroTextures[TextureType::Rectangle].set(this, zeroTextureRectangle); mZeroTextures[TextureType::Rectangle].set(this, zeroTextureRectangle);
} }
if (nativeExtensions.eglImageExternal || nativeExtensions.eglStreamConsumerExternal) if (mSupportedExtensions.eglImageExternal || mSupportedExtensions.eglStreamConsumerExternal)
{ {
Texture *zeroTextureExternal = new Texture(mImplementation.get(), 0, TextureType::External); Texture *zeroTextureExternal = new Texture(mImplementation.get(), 0, TextureType::External);
mZeroTextures[TextureType::External].set(this, zeroTextureExternal); mZeroTextures[TextureType::External].set(this, zeroTextureExternal);
...@@ -2871,14 +2870,12 @@ void Context::initExtensionStrings() ...@@ -2871,14 +2870,12 @@ void Context::initExtensionStrings()
} }
mExtensionString = mergeExtensionStrings(mExtensionStrings); mExtensionString = mergeExtensionStrings(mExtensionStrings);
const gl::Extensions &nativeExtensions = mImplementation->getNativeExtensions();
mRequestableExtensionStrings.clear(); mRequestableExtensionStrings.clear();
for (const auto &extensionInfo : GetExtensionInfoMap()) for (const auto &extensionInfo : GetExtensionInfoMap())
{ {
if (extensionInfo.second.Requestable && if (extensionInfo.second.Requestable &&
!(mExtensions.*(extensionInfo.second.ExtensionsMember)) && !(mExtensions.*(extensionInfo.second.ExtensionsMember)) &&
nativeExtensions.*(extensionInfo.second.ExtensionsMember)) mSupportedExtensions.*(extensionInfo.second.ExtensionsMember))
{ {
mRequestableExtensionStrings.push_back(MakeStaticString(extensionInfo.first)); mRequestableExtensionStrings.push_back(MakeStaticString(extensionInfo.first));
} }
...@@ -2940,9 +2937,8 @@ bool Context::isExtensionRequestable(const char *name) ...@@ -2940,9 +2937,8 @@ bool Context::isExtensionRequestable(const char *name)
const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap(); const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
auto extension = extensionInfos.find(name); auto extension = extensionInfos.find(name);
const Extensions &nativeExtensions = mImplementation->getNativeExtensions();
return extension != extensionInfos.end() && extension->second.Requestable && return extension != extensionInfos.end() && extension->second.Requestable &&
nativeExtensions.*(extension->second.ExtensionsMember); mSupportedExtensions.*(extension->second.ExtensionsMember);
} }
void Context::requestExtension(const char *name) void Context::requestExtension(const char *name)
...@@ -2951,7 +2947,7 @@ void Context::requestExtension(const char *name) ...@@ -2951,7 +2947,7 @@ void Context::requestExtension(const char *name)
ASSERT(extensionInfos.find(name) != extensionInfos.end()); ASSERT(extensionInfos.find(name) != extensionInfos.end());
const auto &extension = extensionInfos.at(name); const auto &extension = extensionInfos.at(name);
ASSERT(extension.Requestable); ASSERT(extension.Requestable);
ASSERT(mImplementation->getNativeExtensions().*(extension.ExtensionsMember)); ASSERT(isExtensionRequestable(name));
if (mExtensions.*(extension.ExtensionsMember)) if (mExtensions.*(extension.ExtensionsMember))
{ {
...@@ -3006,83 +3002,95 @@ bool Context::hasActiveTransformFeedback(GLuint program) const ...@@ -3006,83 +3002,95 @@ bool Context::hasActiveTransformFeedback(GLuint program) const
return false; return false;
} }
void Context::initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit) Extensions Context::generateSupportedExtensions(const egl::DisplayExtensions &displayExtensions,
bool robustResourceInit) const
{ {
mCaps = mImplementation->getNativeCaps(); Extensions supportedExtensions = mImplementation->getNativeExtensions();
mExtensions = mImplementation->getNativeExtensions(); if (getClientVersion() < ES_2_0)
mLimitations = mImplementation->getNativeLimitations();
// GLES1 emulation: Initialize caps (Table 6.20 / 6.22 in the ES 1.1 spec)
if (getClientVersion() < Version(2, 0))
{ {
mCaps.maxMultitextureUnits = 4;
mCaps.maxClipPlanes = 6;
mCaps.maxLights = 8;
mCaps.maxModelviewMatrixStackDepth = Caps::GlobalMatrixStackDepth;
mCaps.maxProjectionMatrixStackDepth = Caps::GlobalMatrixStackDepth;
mCaps.maxTextureMatrixStackDepth = Caps::GlobalMatrixStackDepth;
// Default extensions for GLES1 // Default extensions for GLES1
mExtensions.pointSizeArray = true; supportedExtensions.pointSizeArray = true;
} }
if (getClientVersion() < Version(3, 0)) if (getClientVersion() < ES_3_0)
{ {
// Disable ES3+ extensions // Disable ES3+ extensions
mExtensions.colorBufferFloat = false; supportedExtensions.colorBufferFloat = false;
mExtensions.eglImageExternalEssl3 = false; supportedExtensions.eglImageExternalEssl3 = false;
mExtensions.textureNorm16 = false; supportedExtensions.textureNorm16 = false;
mExtensions.multiview = false; supportedExtensions.multiview = false;
mExtensions.maxViews = 1u; supportedExtensions.maxViews = 1u;
} }
if (getClientVersion() < ES_3_1) if (getClientVersion() < ES_3_1)
{ {
// Disable ES3.1+ extensions // Disable ES3.1+ extensions
mExtensions.geometryShader = false; supportedExtensions.geometryShader = false;
} }
if (getClientVersion() > Version(2, 0)) if (getClientVersion() > ES_2_0)
{ {
// FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
// mExtensions.sRGB = false; // supportedExtensions.sRGB = false;
} }
// Some extensions are always available because they are implemented in the GL layer. // Some extensions are always available because they are implemented in the GL layer.
mExtensions.bindUniformLocation = true; supportedExtensions.bindUniformLocation = true;
mExtensions.vertexArrayObject = true; supportedExtensions.vertexArrayObject = true;
mExtensions.bindGeneratesResource = true; supportedExtensions.bindGeneratesResource = true;
mExtensions.clientArrays = true; supportedExtensions.clientArrays = true;
mExtensions.requestExtension = true; supportedExtensions.requestExtension = true;
// Enable the no error extension if the context was created with the flag. // Enable the no error extension if the context was created with the flag.
mExtensions.noError = mSkipValidation; supportedExtensions.noError = mSkipValidation;
// Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
mExtensions.surfacelessContext = displayExtensions.surfacelessContext; supportedExtensions.surfacelessContext = displayExtensions.surfacelessContext;
// Explicitly enable GL_KHR_debug // Explicitly enable GL_KHR_debug
mExtensions.debug = true; supportedExtensions.debug = true;
mExtensions.maxDebugMessageLength = 1024; supportedExtensions.maxDebugMessageLength = 1024;
mExtensions.maxDebugLoggedMessages = 1024; supportedExtensions.maxDebugLoggedMessages = 1024;
mExtensions.maxDebugGroupStackDepth = 1024; supportedExtensions.maxDebugGroupStackDepth = 1024;
mExtensions.maxLabelLength = 1024; supportedExtensions.maxLabelLength = 1024;
// Explicitly enable GL_ANGLE_robust_client_memory // Explicitly enable GL_ANGLE_robust_client_memory
mExtensions.robustClientMemory = true; supportedExtensions.robustClientMemory = true;
// Determine robust resource init availability from EGL. // Determine robust resource init availability from EGL.
mExtensions.robustResourceInitialization = robustResourceInit; supportedExtensions.robustResourceInitialization = robustResourceInit;
// mExtensions.robustBufferAccessBehavior is true only if robust access is true and the backend // mExtensions.robustBufferAccessBehavior is true only if robust access is true and the backend
// supports it. // supports it.
mExtensions.robustBufferAccessBehavior = supportedExtensions.robustBufferAccessBehavior =
mRobustAccess && mExtensions.robustBufferAccessBehavior; mRobustAccess && supportedExtensions.robustBufferAccessBehavior;
// Enable the cache control query unconditionally. // Enable the cache control query unconditionally.
mExtensions.programCacheControl = true; supportedExtensions.programCacheControl = true;
return supportedExtensions;
}
void Context::initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit)
{
mCaps = mImplementation->getNativeCaps();
mSupportedExtensions = generateSupportedExtensions(displayExtensions, robustResourceInit);
mExtensions = mSupportedExtensions;
mLimitations = mImplementation->getNativeLimitations();
// GLES1 emulation: Initialize caps (Table 6.20 / 6.22 in the ES 1.1 spec)
if (getClientVersion() < Version(2, 0))
{
mCaps.maxMultitextureUnits = 4;
mCaps.maxClipPlanes = 6;
mCaps.maxLights = 8;
mCaps.maxModelviewMatrixStackDepth = Caps::GlobalMatrixStackDepth;
mCaps.maxProjectionMatrixStackDepth = Caps::GlobalMatrixStackDepth;
mCaps.maxTextureMatrixStackDepth = Caps::GlobalMatrixStackDepth;
}
// Apply implementation limits // Apply implementation limits
LimitCap(&mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS); LimitCap(&mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
...@@ -3207,7 +3215,7 @@ void Context::updateCaps() ...@@ -3207,7 +3215,7 @@ void Context::updateCaps()
} }
// If program binary is disabled, blank out the memory cache pointer. // If program binary is disabled, blank out the memory cache pointer.
if (!mImplementation->getNativeExtensions().getProgramBinary) if (!mSupportedExtensions.getProgramBinary)
{ {
mMemoryProgramCache = nullptr; mMemoryProgramCache = nullptr;
} }
......
...@@ -1490,6 +1490,8 @@ class Context final : angle::NonCopyable ...@@ -1490,6 +1490,8 @@ class Context final : angle::NonCopyable
void initVersionStrings(); void initVersionStrings();
void initExtensionStrings(); void initExtensionStrings();
Extensions generateSupportedExtensions(const egl::DisplayExtensions &displayExtensions,
bool robustResourceInit) const;
void initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit); void initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit);
void updateCaps(); void updateCaps();
void initWorkarounds(); void initWorkarounds();
...@@ -1517,6 +1519,10 @@ class Context final : angle::NonCopyable ...@@ -1517,6 +1519,10 @@ class Context final : angle::NonCopyable
Extensions mExtensions; Extensions mExtensions;
Limitations mLimitations; Limitations mLimitations;
// Extensions supported by the implementation plus extensions that are implemented entirely
// within the frontend.
Extensions mSupportedExtensions;
// Shader compiler. Lazily initialized hence the mutable value. // Shader compiler. Lazily initialized hence the mutable value.
mutable BindingPointer<Compiler> mCompiler; mutable BindingPointer<Compiler> mCompiler;
......
...@@ -1085,6 +1085,41 @@ TEST_P(WebGLCompatibilityTest, EnableProgramBinaryExtension) ...@@ -1085,6 +1085,41 @@ TEST_P(WebGLCompatibilityTest, EnableProgramBinaryExtension)
} }
} }
// Test enabling the GL_OES_vertex_array_object extension
TEST_P(WebGLCompatibilityTest, EnableVertexArrayExtension)
{
EXPECT_FALSE(extensionEnabled("GL_OES_vertex_array_object"));
// This extensions become core in in ES3/WebGL2.
ANGLE_SKIP_TEST_IF(getClientMajorVersion() >= 3);
GLint result = 0;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
// Expect that GL_OES_vertex_array_object is always available. It is implemented in the GL
// frontend.
EXPECT_TRUE(extensionRequestable("GL_OES_vertex_array_object"));
glRequestExtensionANGLE("GL_OES_vertex_array_object");
EXPECT_GL_NO_ERROR();
EXPECT_TRUE(extensionEnabled("GL_OES_vertex_array_object"));
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &result);
EXPECT_GL_NO_ERROR();
GLuint vao = 0;
glGenVertexArraysOES(0, &vao);
EXPECT_GL_NO_ERROR();
glBindVertexArrayOES(vao);
EXPECT_GL_NO_ERROR();
glDeleteVertexArraysOES(1, &vao);
EXPECT_GL_NO_ERROR();
}
// Verify that the context generates the correct error when the framebuffer attachments are // Verify that the context generates the correct error when the framebuffer attachments are
// different sizes // different sizes
TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch) TEST_P(WebGLCompatibilityTest, FramebufferAttachmentSizeMismatch)
......
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