Commit c339c4e5 by Geoff Lang Committed by Commit Bot

Split WebGL compatibility into two extensions.

The mechanism for requesting extensions is now a separate extension. Added a way to query the extensions that support enabling. BUG=angleproject:1523 Change-Id: I2efaa9f6d67b12ecae325f455404e34ba04d0e7c Reviewed-on: https://chromium-review.googlesource.com/414529 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 2ec65dc8
Name
ANGLE_request_extension
Name Strings
GL_ANGLE_request_extension
Contributors
Geoff Lang
Contact
Geoff Lang (geofflang 'at' google.com)
Notice
Copyright (c) 2016 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Status
Draft
Version
Version 1, November 28, 2016
Number
OpenGL ES Extension #??
Dependencies
Requires OpenGL ES 2.0
Written against the OpenGL ES 3.0 specification.
Overview
This extension allows the client to query extensions that can be enabled and
explicitly request than an extension be enabled.
New Procedures and Functions
void RequestExtension(const char *name)
New Tokens
Accepted by the <name> parameter of GetString and GetStringi:
REQUESTABLE_EXTENSIONS_ANGLE 0x93A8
Accepted by the <value> parameter of the GetInteger* functions:
NUM_REQUESTABLE_EXTENSIONS_ANGLE 0x93A9
Additions to the OpenGL ES 3.0 Specification
Add the following paragraph to the end paragraph 4 of section 6.1.6, String
Queries:
"REQUESTABLE_EXTENSIONS_ANGLE returns a list of extensions that can be
enabled at runtime by calling RequestExtension."
Change the following section of paragraph 6 of section 6.1.6, String Queries:
- "name may only be EXTENSIONS, indicating that the extension name
- corresponding to the indexth supported extension should be returned.
- <index> may range from zero to the value of NUM_EXTENSIONS minus one"
+ "name may be EXTENSIONS or REQUESTABLE_EXTENSIONS_ANGLE, indicating that
+ the extension name corresponding to the indexth supported or requestable
+ extension should be returned. <index> may range from zero to the value of
+ NUM_EXTENSIONS and NUM_REQUESTABLE_EXTENSIONS_ANGLE minus one"
The command
void RequestExtension(const char *name)
enables the requestable OpenGL ES extension named <name>. If the extension
was not requestable, INVALID_OPERATION is generated.
New State
Add to Table 6.30 (Implementation Dependent Version and Extension Support)
Get value Type Get Cmd Min Value Description Sec.
-------------------------------- ---- ----------- --------- -------------------------------- -----
NUM_REQUESTABLE_EXTENSIONS_ANGLE Z+ GetIntegerv - Number of individual requestable 6.1.6
extension names
Interactions with the OpenGL ES 2.0 specification:
Remove all references to GetStringi and NUM_REQUESTABLE_EXTENSIONS_ANGLE.
Issues
(1) How can the user determine which extensions can be enabled without
potentially generating errors?
This can be solved by:
a) Never generate an error in EnableExtensions, simply return false when
the extension is not recognized or cannot be enabled.
b) Add another query for the extensions that the context supports
enabling.
RESOLVED: Use (b) because it allows the context to explicity advertise
which extensions support enabling and doesn't generate errors in the
normal use case.
Revision History
Rev. Date Author Changes
---- ------------- --------- ----------------------------------------
1 Nov 28, 2016 geofflang Initial version
...@@ -25,7 +25,7 @@ Status ...@@ -25,7 +25,7 @@ Status
Version Version
Version 1, September 16, 2016 Version 2, November 28, 2016
Number Number
...@@ -47,7 +47,8 @@ Overview ...@@ -47,7 +47,8 @@ Overview
New Procedures and Functions New Procedures and Functions
boolean EnableExtension(const char *name) None
New Tokens New Tokens
...@@ -55,16 +56,6 @@ New Tokens ...@@ -55,16 +56,6 @@ New Tokens
Additions to the OpenGL ES Specification Additions to the OpenGL ES Specification
The command
boolean EnableExtension(const char *name)
enables the OpenGL ES extension named <name>. Returns true on success and
false otherwise. If the extension does not support being enabled or <name>
does not name a valid OpenGL ES extension, INVALID_OPERATION is generated.
If the extension is valid but is not supported by the context, no error is
generated but false is returned.
Additional validation will be performed according to the the sections of Additional validation will be performed according to the the sections of
the WebGL specification entitled "Differences Between WebGL and OpenGL ES the WebGL specification entitled "Differences Between WebGL and OpenGL ES
2.0" and "Differences Between WebGL and OpenGL ES 3.0". 2.0" and "Differences Between WebGL and OpenGL ES 3.0".
...@@ -79,17 +70,12 @@ Conformance Tests ...@@ -79,17 +70,12 @@ Conformance Tests
Issues Issues
(1) How can the user determine which extensions can be enabled without None
potentially generating errors?
This can be solved by:
a) Never generate an error in EnableExtensions, simply return false when
the extension is not recognized or cannot be enabled.
b) Add another entry point to query all extensions that the context
supports enabling.
Revision History Revision History
Rev. Date Author Changes Rev. Date Author Changes
---- ------------- --------- ---------------------------------------- ---- ------------- --------- ----------------------------------------
1 Sept 16, 2016 geofflang Initial version 1 Sept 16, 2016 geofflang Initial version
2 Nov 28, 2016 geofflang Break the extension requests into a
separate extension.
...@@ -821,11 +821,13 @@ GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GL ...@@ -821,11 +821,13 @@ GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GL
#endif #endif
#endif /* GL_ANGLE_framebuffer_blit */ #endif /* GL_ANGLE_framebuffer_blit */
#ifndef GL_ANGLE_webgl_compatibility #ifndef GL_ANGLE_request_extension
#define GL_ANGLE_webgl_compatibility 1 #define GL_ANGLE_request_extension 1
typedef GLboolean(GL_APIENTRYP PFNGLENABLEEXTENSIONANGLEPROC) (const GLchar *name); #define GL_REQUESTABLE_EXTENSIONS_ANGLE 0x93A8
#define GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE 0x93A8
typedef GLboolean(GL_APIENTRYP PFNGLREQUESTEXTENSIONANGLEPROC) (const GLchar *name);
#ifdef GL_GLEXT_PROTOTYPES #ifdef GL_GLEXT_PROTOTYPES
GL_APICALL GLboolean GL_APIENTRY glEnableExtensionANGLE (const GLchar *name); GL_APICALL GLboolean GL_APIENTRY glRequestExtensionANGLE (const GLchar *name);
#endif #endif
#endif /* GL_ANGLE_webgl_compatibility */ #endif /* GL_ANGLE_webgl_compatibility */
......
...@@ -201,6 +201,7 @@ Extensions::Extensions() ...@@ -201,6 +201,7 @@ Extensions::Extensions()
copyTexture(false), copyTexture(false),
copyCompressedTexture(false), copyCompressedTexture(false),
webglCompatibility(false), webglCompatibility(false),
requestExtension(false),
bindGeneratesResource(false), bindGeneratesResource(false),
robustClientMemory(false), robustClientMemory(false),
textureSRGBDecode(false), textureSRGBDecode(false),
...@@ -539,7 +540,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -539,7 +540,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
auto buildExtensionInfoMap = []() { auto buildExtensionInfoMap = []() {
auto enableableExtension = [](ExtensionInfo::ExtensionBool member) { auto enableableExtension = [](ExtensionInfo::ExtensionBool member) {
ExtensionInfo info; ExtensionInfo info;
info.Enableable = true; info.Requestable = true;
info.ExtensionsMember = member; info.ExtensionsMember = member;
return info; return info;
}; };
...@@ -618,6 +619,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -618,6 +619,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture); map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTexture); map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTexture);
map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility); map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
map["GL_ANGLE_request_extension"] = esOnlyExtension(&Extensions::requestExtension);
map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource); map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory); map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode); map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
......
...@@ -309,6 +309,9 @@ struct Extensions ...@@ -309,6 +309,9 @@ struct Extensions
// GL_ANGLE_webgl_compatibility // GL_ANGLE_webgl_compatibility
bool webglCompatibility; bool webglCompatibility;
// GL_ANGLE_request_extension
bool requestExtension;
// GL_CHROMIUM_bind_generates_resource // GL_CHROMIUM_bind_generates_resource
bool bindGeneratesResource; bool bindGeneratesResource;
...@@ -343,8 +346,8 @@ struct Extensions ...@@ -343,8 +346,8 @@ struct Extensions
struct ExtensionInfo struct ExtensionInfo
{ {
// If this extension can be enabled with glEnableExtension (GL_ANGLE_webgl_compatibility) // If this extension can be enabled with glRequestExtension (GL_ANGLE_request_extension)
bool Enableable = false; bool Requestable = false;
// Pointer to a boolean member of the Extensions struct // Pointer to a boolean member of the Extensions struct
typedef bool(Extensions::*ExtensionBool); typedef bool(Extensions::*ExtensionBool);
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "common/matrix_utils.h" #include "common/matrix_utils.h"
#include "common/platform.h" #include "common/platform.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "common/version.h"
#include "libANGLE/Buffer.h" #include "libANGLE/Buffer.h"
#include "libANGLE/Compiler.h" #include "libANGLE/Compiler.h"
#include "libANGLE/Display.h" #include "libANGLE/Display.h"
...@@ -457,6 +458,7 @@ void Context::makeCurrent(egl::Surface *surface) ...@@ -457,6 +458,7 @@ void Context::makeCurrent(egl::Surface *surface)
if (!mHasBeenCurrent) if (!mHasBeenCurrent)
{ {
initRendererString(); initRendererString();
initVersionStrings();
initExtensionStrings(); initExtensionStrings();
mGLState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight()); mGLState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight());
...@@ -2257,32 +2259,93 @@ void Context::initRendererString() ...@@ -2257,32 +2259,93 @@ void Context::initRendererString()
mRendererString = MakeStaticString(rendererString.str()); mRendererString = MakeStaticString(rendererString.str());
} }
const char *Context::getRendererString() const void Context::initVersionStrings()
{ {
return mRendererString; const Version &clientVersion = getClientVersion();
std::ostringstream versionString;
versionString << "OpenGL ES " << clientVersion.major << "." << clientVersion.minor << " (ANGLE "
<< ANGLE_VERSION_STRING << ")";
mVersionString = MakeStaticString(versionString.str());
std::ostringstream shadingLanguageVersionString;
shadingLanguageVersionString << "OpenGL ES GLSL ES "
<< (clientVersion.major == 2 ? 1 : clientVersion.major) << "."
<< clientVersion.minor << "0 (ANGLE " << ANGLE_VERSION_STRING
<< ")";
mShadingLanguageString = MakeStaticString(shadingLanguageVersionString.str());
} }
void Context::initExtensionStrings() void Context::initExtensionStrings()
{ {
auto mergeExtensionStrings = [](const std::vector<const char *> &strings) {
std::ostringstream combinedStringStream;
std::copy(strings.begin(), strings.end(),
std::ostream_iterator<const char *>(combinedStringStream, " "));
return MakeStaticString(combinedStringStream.str());
};
mExtensionStrings.clear();
for (const auto &extensionString : mExtensions.getStrings()) for (const auto &extensionString : mExtensions.getStrings())
{ {
mExtensionStrings.push_back(MakeStaticString(extensionString)); mExtensionStrings.push_back(MakeStaticString(extensionString));
} }
mExtensionString = mergeExtensionStrings(mExtensionStrings);
std::ostringstream combinedStringStream; mRequestableExtensionStrings.clear();
std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), for (const auto &extensionInfo : GetExtensionInfoMap())
std::ostream_iterator<const char *>(combinedStringStream, " ")); {
mExtensionString = MakeStaticString(combinedStringStream.str()); if (extensionInfo.second.Requestable &&
!(mExtensions.*(extensionInfo.second.ExtensionsMember)))
{
mRequestableExtensionStrings.push_back(MakeStaticString(extensionInfo.first));
}
}
mRequestableExtensionString = mergeExtensionStrings(mRequestableExtensionStrings);
} }
const char *Context::getExtensionString() const const GLubyte *Context::getString(GLenum name) const
{ {
return mExtensionString; switch (name)
{
case GL_VENDOR:
return reinterpret_cast<const GLubyte *>("Google Inc.");
case GL_RENDERER:
return reinterpret_cast<const GLubyte *>(mRendererString);
case GL_VERSION:
return reinterpret_cast<const GLubyte *>(mVersionString);
case GL_SHADING_LANGUAGE_VERSION:
return reinterpret_cast<const GLubyte *>(mShadingLanguageString);
case GL_EXTENSIONS:
return reinterpret_cast<const GLubyte *>(mExtensionString);
case GL_REQUESTABLE_EXTENSIONS_ANGLE:
return reinterpret_cast<const GLubyte *>(mRequestableExtensionString);
default:
UNREACHABLE();
return nullptr;
}
} }
const char *Context::getExtensionString(size_t idx) const const GLubyte *Context::getStringi(GLenum name, GLuint index) const
{ {
return mExtensionStrings[idx]; switch (name)
{
case GL_EXTENSIONS:
return reinterpret_cast<const GLubyte *>(mExtensionStrings[index]);
case GL_REQUESTABLE_EXTENSIONS_ANGLE:
return reinterpret_cast<const GLubyte *>(mRequestableExtensionStrings[index]);
default:
UNREACHABLE();
return nullptr;
}
} }
size_t Context::getExtensionStringCount() const size_t Context::getExtensionStringCount() const
...@@ -2290,6 +2353,29 @@ size_t Context::getExtensionStringCount() const ...@@ -2290,6 +2353,29 @@ size_t Context::getExtensionStringCount() const
return mExtensionStrings.size(); return mExtensionStrings.size();
} }
void Context::requestExtension(const char *name)
{
const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
ASSERT(extensionInfos.find(name) != extensionInfos.end());
const auto &extension = extensionInfos.at(name);
ASSERT(extension.Requestable);
if (mExtensions.*(extension.ExtensionsMember))
{
// Extension already enabled
return;
}
mExtensions.*(extension.ExtensionsMember) = true;
updateCaps();
initExtensionStrings();
}
size_t Context::getRequestableExtensionStringCount() const
{
return mRequestableExtensionStrings.size();
}
void Context::beginTransformFeedback(GLenum primitiveMode) void Context::beginTransformFeedback(GLenum primitiveMode)
{ {
TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback(); TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
...@@ -2337,6 +2423,7 @@ void Context::initCaps(bool webGLContext) ...@@ -2337,6 +2423,7 @@ void Context::initCaps(bool webGLContext)
mExtensions.bindUniformLocation = true; mExtensions.bindUniformLocation = true;
mExtensions.vertexArrayObject = true; mExtensions.vertexArrayObject = true;
mExtensions.bindGeneratesResource = true; mExtensions.bindGeneratesResource = true;
mExtensions.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; mExtensions.noError = mSkipValidation;
...@@ -2363,7 +2450,7 @@ void Context::initCaps(bool webGLContext) ...@@ -2363,7 +2450,7 @@ void Context::initCaps(bool webGLContext)
for (const auto &extensionInfo : GetExtensionInfoMap()) for (const auto &extensionInfo : GetExtensionInfoMap())
{ {
// If this context is for WebGL, disable all enableable extensions // If this context is for WebGL, disable all enableable extensions
if (webGLContext && extensionInfo.second.Enableable) if (webGLContext && extensionInfo.second.Requestable)
{ {
mExtensions.*(extensionInfo.second.ExtensionsMember) = false; mExtensions.*(extensionInfo.second.ExtensionsMember) = false;
} }
...@@ -2937,32 +3024,6 @@ void Context::generateMipmap(GLenum target) ...@@ -2937,32 +3024,6 @@ void Context::generateMipmap(GLenum target)
handleError(texture->generateMipmap()); handleError(texture->generateMipmap());
} }
GLboolean Context::enableExtension(const char *name)
{
const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
ASSERT(extensionInfos.find(name) != extensionInfos.end());
const auto &extension = extensionInfos.at(name);
ASSERT(extension.Enableable);
if (mExtensions.*(extension.ExtensionsMember))
{
// Extension already enabled
return GL_TRUE;
}
const auto &nativeExtensions = mImplementation->getNativeExtensions();
if (!(nativeExtensions.*(extension.ExtensionsMember)))
{
// Underlying implementation does not support this valid extension
return GL_FALSE;
}
mExtensions.*(extension.ExtensionsMember) = true;
updateCaps();
initExtensionStrings();
return GL_TRUE;
}
void Context::copyTextureCHROMIUM(GLuint sourceId, void Context::copyTextureCHROMIUM(GLuint sourceId,
GLuint destId, GLuint destId,
GLint internalFormat, GLint internalFormat,
......
...@@ -485,8 +485,6 @@ class Context final : public ValidationContext ...@@ -485,8 +485,6 @@ class Context final : public ValidationContext
void generateMipmap(GLenum target); void generateMipmap(GLenum target);
GLboolean enableExtension(const char *name);
Error flush(); Error flush();
Error finish(); Error finish();
...@@ -599,12 +597,14 @@ class Context final : public ValidationContext ...@@ -599,12 +597,14 @@ class Context final : public ValidationContext
EGLenum getClientType() const; EGLenum getClientType() const;
EGLenum getRenderBuffer() const; EGLenum getRenderBuffer() const;
const char *getRendererString() const; const GLubyte *getString(GLenum name) const;
const GLubyte *getStringi(GLenum name, GLuint index) const;
const char *getExtensionString() const;
const char *getExtensionString(size_t idx) const;
size_t getExtensionStringCount() const; size_t getExtensionStringCount() const;
void requestExtension(const char *name);
size_t getRequestableExtensionStringCount() const;
rx::ContextImpl *getImplementation() const { return mImplementation.get(); } rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
const Workarounds &getWorkarounds() const; const Workarounds &getWorkarounds() const;
...@@ -628,6 +628,7 @@ class Context final : public ValidationContext ...@@ -628,6 +628,7 @@ class Context final : public ValidationContext
void detachSampler(GLuint sampler); void detachSampler(GLuint sampler);
void initRendererString(); void initRendererString();
void initVersionStrings();
void initExtensionStrings(); void initExtensionStrings();
void initCaps(bool webGLContext); void initCaps(bool webGLContext);
...@@ -670,9 +671,13 @@ class Context final : public ValidationContext ...@@ -670,9 +671,13 @@ class Context final : public ValidationContext
ResourceMap<TransformFeedback> mTransformFeedbackMap; ResourceMap<TransformFeedback> mTransformFeedbackMap;
HandleAllocator mTransformFeedbackAllocator; HandleAllocator mTransformFeedbackAllocator;
const char *mVersionString;
const char *mShadingLanguageString;
const char *mRendererString; const char *mRendererString;
const char *mExtensionString; const char *mExtensionString;
std::vector<const char *> mExtensionStrings; std::vector<const char *> mExtensionStrings;
const char *mRequestableExtensionString;
std::vector<const char *> mRequestableExtensionStrings;
// Recorded errors // Recorded errors
typedef std::set<GLenum> ErrorSet; typedef std::set<GLenum> ErrorSet;
......
...@@ -476,6 +476,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign ...@@ -476,6 +476,17 @@ bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsign
} }
} }
if (getExtensions().requestExtension)
{
switch (pname)
{
case GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE:
*type = GL_INT;
*numParams = 1;
return true;
}
}
if (getClientVersion() < Version(3, 1)) if (getClientVersion() < Version(3, 1))
{ {
return false; return false;
......
...@@ -3521,20 +3521,20 @@ bool ValidateBufferSubData(ValidationContext *context, ...@@ -3521,20 +3521,20 @@ bool ValidateBufferSubData(ValidationContext *context,
return true; return true;
} }
bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name) bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name)
{ {
if (!context->getExtensions().webglCompatibility) if (!context->getExtensions().requestExtension)
{ {
context->handleError( context->handleError(
Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available.")); Error(GL_INVALID_OPERATION, "GL_ANGLE_request_extension is not available."));
return false; return false;
} }
const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap(); const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
auto extension = extensionInfos.find(name); auto extension = extensionInfos.find(name);
if (extension == extensionInfos.end() || !extension->second.Enableable) if (extension == extensionInfos.end() || !extension->second.Requestable)
{ {
context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name)); context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not requestable.", name));
return false; return false;
} }
...@@ -3838,4 +3838,31 @@ bool ValidateBlendFuncSeparate(ValidationContext *context, ...@@ -3838,4 +3838,31 @@ bool ValidateBlendFuncSeparate(ValidationContext *context,
return true; return true;
} }
bool ValidateGetString(Context *context, GLenum name)
{
switch (name)
{
case GL_VENDOR:
case GL_RENDERER:
case GL_VERSION:
case GL_SHADING_LANGUAGE_VERSION:
case GL_EXTENSIONS:
break;
case GL_REQUESTABLE_EXTENSIONS_ANGLE:
if (!context->getExtensions().requestExtension)
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
return false;
}
return true;
}
} // namespace gl } // namespace gl
...@@ -350,7 +350,7 @@ bool ValidateBufferSubData(ValidationContext *context, ...@@ -350,7 +350,7 @@ bool ValidateBufferSubData(ValidationContext *context,
GLsizeiptr size, GLsizeiptr size,
const GLvoid *data); const GLvoid *data);
bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name); bool ValidateRequestExtensionANGLE(ValidationContext *context, const GLchar *name);
bool ValidateActiveTexture(ValidationContext *context, GLenum texture); bool ValidateActiveTexture(ValidationContext *context, GLenum texture);
bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader); bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader);
...@@ -370,6 +370,8 @@ bool ValidateBlendFuncSeparate(ValidationContext *context, ...@@ -370,6 +370,8 @@ bool ValidateBlendFuncSeparate(ValidationContext *context,
GLenum srcAlpha, GLenum srcAlpha,
GLenum dstAlpha); GLenum dstAlpha);
bool ValidateGetString(Context *context, GLenum name);
} // namespace gl } // namespace gl
#endif // LIBANGLE_VALIDATION_ES2_H_ #endif // LIBANGLE_VALIDATION_ES2_H_
...@@ -2056,4 +2056,47 @@ bool ValidateCopyBufferSubData(ValidationContext *context, ...@@ -2056,4 +2056,47 @@ bool ValidateCopyBufferSubData(ValidationContext *context,
return true; return true;
} }
bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
{
if (context->getClientMajorVersion() < 3)
{
context->handleError(
Error(GL_INVALID_OPERATION, "glGetStringi requires OpenGL ES 3.0 or higher."));
return false;
}
switch (name)
{
case GL_EXTENSIONS:
if (index >= context->getExtensionStringCount())
{
context->handleError(Error(
GL_INVALID_VALUE, "index must be less than the number of extension strings."));
return false;
}
break;
case GL_REQUESTABLE_EXTENSIONS_ANGLE:
if (!context->getExtensions().requestExtension)
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
return false;
}
if (index >= context->getRequestableExtensionStringCount())
{
context->handleError(
Error(GL_INVALID_VALUE,
"index must be less than the number of requestable extension strings."));
return false;
}
break;
default:
context->handleError(Error(GL_INVALID_ENUM, "Invalid name."));
return false;
}
return true;
}
} // namespace gl } // namespace gl
...@@ -364,6 +364,8 @@ bool ValidateCopyBufferSubData(ValidationContext *context, ...@@ -364,6 +364,8 @@ bool ValidateCopyBufferSubData(ValidationContext *context,
GLintptr writeOffset, GLintptr writeOffset,
GLsizeiptr size); GLsizeiptr size);
bool ValidateGetStringi(Context *context, GLenum name, GLuint index);
} // namespace gl } // namespace gl
#endif // LIBANGLE_VALIDATION_ES3_H_ #endif // LIBANGLE_VALIDATION_ES3_H_
...@@ -1535,8 +1535,8 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char * ...@@ -1535,8 +1535,8 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
// GL_CHROMIUM_copy_compressed_texture // GL_CHROMIUM_copy_compressed_texture
INSERT_PROC_ADDRESS(gl, CompressedCopyTextureCHROMIUM); INSERT_PROC_ADDRESS(gl, CompressedCopyTextureCHROMIUM);
// GL_ANGLE_webgl_compatibility // GL_ANGLE_request_extension
INSERT_PROC_ADDRESS(gl, EnableExtensionANGLE); INSERT_PROC_ADDRESS(gl, RequestExtensionANGLE);
// GL_ANGLE_robust_client_memory // GL_ANGLE_robust_client_memory
INSERT_PROC_ADDRESS(gl, GetBooleanvRobustANGLE); INSERT_PROC_ADDRESS(gl, GetBooleanvRobustANGLE);
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include "common/debug.h" #include "common/debug.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "common/version.h"
namespace gl namespace gl
{ {
...@@ -1465,45 +1464,12 @@ const GLubyte *GL_APIENTRY GetString(GLenum name) ...@@ -1465,45 +1464,12 @@ const GLubyte *GL_APIENTRY GetString(GLenum name)
if (context) if (context)
{ {
switch (name) if (!context->skipValidation() && !ValidateGetString(context, name))
{ {
case GL_VENDOR:
return reinterpret_cast<const GLubyte *>("Google Inc.");
case GL_RENDERER:
return reinterpret_cast<const GLubyte *>(context->getRendererString());
case GL_VERSION:
if (context->getClientMajorVersion() == 2)
{
return reinterpret_cast<const GLubyte *>(
"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")");
}
else
{
return reinterpret_cast<const GLubyte *>(
"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")");
}
case GL_SHADING_LANGUAGE_VERSION:
if (context->getClientMajorVersion() == 2)
{
return reinterpret_cast<const GLubyte *>(
"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")");
}
else
{
return reinterpret_cast<const GLubyte *>(
"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")");
}
case GL_EXTENSIONS:
return reinterpret_cast<const GLubyte *>(context->getExtensionString());
default:
context->handleError(Error(GL_INVALID_ENUM));
return nullptr; return nullptr;
} }
return context->getString(name);
} }
return nullptr; return nullptr;
......
...@@ -1952,22 +1952,20 @@ ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLu ...@@ -1952,22 +1952,20 @@ ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLu
} }
} }
GL_APICALL GLboolean GL_APIENTRY EnableExtensionANGLE(const GLchar *name) GL_APICALL void GL_APIENTRY RequestExtensionANGLE(const GLchar *name)
{ {
EVENT("(const GLchar *name = %p)", name); EVENT("(const GLchar *name = %p)", name);
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (!context->skipValidation() && !ValidateEnableExtensionANGLE(context, name)) if (!context->skipValidation() && !ValidateRequestExtensionANGLE(context, name))
{ {
return GL_FALSE; return;
} }
return context->enableExtension(name) ? GL_TRUE : GL_FALSE; context->requestExtension(name);
} }
return GL_FALSE;
} }
ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname, ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
......
...@@ -262,8 +262,8 @@ ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId, ...@@ -262,8 +262,8 @@ ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
// GL_CHROMIUM_copy_compressed_texture // GL_CHROMIUM_copy_compressed_texture
ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId); ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
// GL_ANGLE_webgl_compatibility // GL_ANGLE_request_extension
GL_APICALL GLboolean GL_APIENTRY EnableExtensionANGLE(const GLchar *name); GL_APICALL void GL_APIENTRY RequestExtensionANGLE(const GLchar *name);
// GL_ANGLE_robust_client_memory // GL_ANGLE_robust_client_memory
ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname, ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
......
...@@ -1407,28 +1407,15 @@ const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index) ...@@ -1407,28 +1407,15 @@ const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
Context *context = GetValidGlobalContext(); Context *context = GetValidGlobalContext();
if (context) if (context)
{ {
if (context->getClientMajorVersion() < 3) if (!context->skipValidation() && !ValidateGetStringi(context, name, index))
{
context->handleError(Error(GL_INVALID_OPERATION));
return NULL;
}
if (name != GL_EXTENSIONS)
{
context->handleError(Error(GL_INVALID_ENUM));
return NULL;
}
if (index >= context->getExtensionStringCount())
{ {
context->handleError(Error(GL_INVALID_VALUE)); return nullptr;
return NULL;
} }
return reinterpret_cast<const GLubyte *>(context->getExtensionString(index)); return context->getStringi(name, index);
} }
return NULL; return nullptr;
} }
void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
......
...@@ -107,18 +107,25 @@ TEST_P(RendererTest, RequestedRendererCreated) ...@@ -107,18 +107,25 @@ TEST_P(RendererTest, RequestedRendererCreated)
} }
EGLint glesMajorVersion = GetParam().majorVersion; EGLint glesMajorVersion = GetParam().majorVersion;
EGLint glesMinorVersion = GetParam().minorVersion;
// Ensure that the renderer string contains GL ES 3.0, if we requested a GL ES 3.0 // Ensure that the renderer string contains the requested version number
if (glesMajorVersion == 3) if (glesMajorVersion == 3 && glesMinorVersion == 1)
{
ASSERT_NE(versionString.find(std::string("es 3.1")), std::string::npos);
}
else if (glesMajorVersion == 3 && glesMinorVersion == 0)
{ {
ASSERT_NE(versionString.find(std::string("es 3.0")), std::string::npos); ASSERT_NE(versionString.find(std::string("es 3.0")), std::string::npos);
} }
else if (glesMajorVersion == 2 && glesMinorVersion == 0)
// Ensure that the version string contains GL ES 2.0, if we requested GL ES 2.0
if (glesMajorVersion == 2)
{ {
ASSERT_NE(versionString.find(std::string("es 2.0")), std::string::npos); ASSERT_NE(versionString.find(std::string("es 2.0")), std::string::npos);
} }
else
{
FAIL() << "Unhandled GL ES client version.";
}
} }
// Perform a simple operation (clear and read pixels) to verify the device is working // Perform a simple operation (clear and read pixels) to verify the device is working
......
...@@ -30,13 +30,13 @@ class WebGLCompatibilityTest : public ANGLETest ...@@ -30,13 +30,13 @@ class WebGLCompatibilityTest : public ANGLETest
void SetUp() override void SetUp() override
{ {
ANGLETest::SetUp(); ANGLETest::SetUp();
glEnableExtensionANGLE = reinterpret_cast<PFNGLENABLEEXTENSIONANGLEPROC>( glRequestExtensionANGLE = reinterpret_cast<PFNGLREQUESTEXTENSIONANGLEPROC>(
eglGetProcAddress("glEnableExtensionANGLE")); eglGetProcAddress("glRequestExtensionANGLE"));
} }
void TearDown() override { ANGLETest::TearDown(); } void TearDown() override { ANGLETest::TearDown(); }
PFNGLENABLEEXTENSIONANGLEPROC glEnableExtensionANGLE = nullptr; PFNGLREQUESTEXTENSIONANGLEPROC glRequestExtensionANGLE = nullptr;
}; };
// Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so // Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so
...@@ -49,9 +49,9 @@ TEST_P(WebGLCompatibilityTest, ExtensionStringExposed) ...@@ -49,9 +49,9 @@ TEST_P(WebGLCompatibilityTest, ExtensionStringExposed)
// Verify that all extension entry points are available // Verify that all extension entry points are available
TEST_P(WebGLCompatibilityTest, EntryPoints) TEST_P(WebGLCompatibilityTest, EntryPoints)
{ {
if (extensionEnabled("GL_ANGLE_webgl_compatibility")) if (extensionEnabled("GL_ANGLE_request_extension"))
{ {
EXPECT_NE(nullptr, eglGetProcAddress("glEnableExtensionANGLE")); EXPECT_NE(nullptr, eglGetProcAddress("glRequestExtensionANGLE"));
} }
} }
...@@ -74,7 +74,7 @@ TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint) ...@@ -74,7 +74,7 @@ TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint)
// Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION // Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION
TEST_P(WebGLCompatibilityTest, EnableExtensionValidation) TEST_P(WebGLCompatibilityTest, EnableExtensionValidation)
{ {
EXPECT_EQ(GL_FALSE, glEnableExtensionANGLE("invalid_extension_string")); glRequestExtensionANGLE("invalid_extension_string");
EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_GL_ERROR(GL_INVALID_OPERATION);
} }
...@@ -102,8 +102,9 @@ TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices) ...@@ -102,8 +102,9 @@ TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices)
glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr);
EXPECT_GL_ERROR(GL_INVALID_ENUM); EXPECT_GL_ERROR(GL_INVALID_ENUM);
if (glEnableExtensionANGLE("GL_OES_element_index_uint")) if (extensionRequestable("GL_OES_element_index_uint"))
{ {
glRequestExtensionANGLE("GL_OES_element_index_uint");
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint")); EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint"));
......
...@@ -539,6 +539,12 @@ bool ANGLETest::extensionEnabled(const std::string &extName) ...@@ -539,6 +539,12 @@ bool ANGLETest::extensionEnabled(const std::string &extName)
extName); extName);
} }
bool ANGLETest::extensionRequestable(const std::string &extName)
{
return checkExtensionExists(
reinterpret_cast<const char *>(glGetString(GL_REQUESTABLE_EXTENSIONS_ANGLE)), extName);
}
bool ANGLETest::eglDisplayExtensionEnabled(EGLDisplay display, const std::string &extName) bool ANGLETest::eglDisplayExtensionEnabled(EGLDisplay display, const std::string &extName)
{ {
return checkExtensionExists(eglQueryString(display, EGL_EXTENSIONS), extName); return checkExtensionExists(eglQueryString(display, EGL_EXTENSIONS), extName);
......
...@@ -171,6 +171,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters> ...@@ -171,6 +171,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
static GLuint compileShader(GLenum type, const std::string &source); static GLuint compileShader(GLenum type, const std::string &source);
static bool extensionEnabled(const std::string &extName); static bool extensionEnabled(const std::string &extName);
static bool extensionRequestable(const std::string &extName);
static bool eglClientExtensionEnabled(const std::string &extName); static bool eglClientExtensionEnabled(const std::string &extName);
static bool eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName); static bool eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName);
......
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