Add WebGL validation extensions to ANGLE.
BUG=angleproject:1523
Change-Id: I6fecb5055ed8087665aeee34b3a066ea8f38d51b
Reviewed-on: https://chromium-review.googlesource.com/386281
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Antoine Labour <piman@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/extensions/ANGLE_webgl_compatibility.txt b/extensions/ANGLE_webgl_compatibility.txt
new file mode 100644
index 0000000..dd3637c
--- /dev/null
+++ b/extensions/ANGLE_webgl_compatibility.txt
@@ -0,0 +1,95 @@
+Name
+
+ ANGLE_webgl_compatibility
+
+Name Strings
+
+ GL_ANGLE_webgl_compatibility
+
+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, September 16, 2016
+
+Number
+
+ OpenGL ES Extension #??
+
+Dependencies
+
+ Requires OpenGL ES 2.0
+
+ Written against the OpenGL ES 2.0 specification.
+
+ Interacts with EGL_ANGLE_create_context_webgl_compatibility (or equivalent)
+ extension.
+
+Overview
+
+ With this extension enabled, the OpenGL ES context will have additional
+ features and validation to be compatible with the WebGL specification.
+
+New Procedures and Functions
+
+ boolean EnableExtension(const char *name)
+
+New Tokens
+
+ None
+
+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
+ the WebGL specification entitled "Differences Between WebGL and OpenGL ES
+ 2.0" and "Differences Between WebGL and OpenGL ES 3.0".
+
+New State
+
+ None
+
+Conformance Tests
+
+ TBD
+
+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 entry point to query all extensions that the context
+ supports enabling.
+
+Revision History
+
+ Rev. Date Author Changes
+ ---- ------------- --------- ----------------------------------------
+ 1 Sept 16, 2016 geofflang Initial version
diff --git a/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt b/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt
new file mode 100644
index 0000000..2e7fb82
--- /dev/null
+++ b/extensions/EGL_ANGLE_create_context_webgl_compatibility.txt
@@ -0,0 +1,88 @@
+Name
+
+ ANGLE_create_context_webgl_compatibility
+
+Name Strings
+
+ EGL_ANGLE_create_context_webgl_compatibility
+
+Contributors
+
+ Geoff Lang
+
+Contacts
+
+ Geoff Lang (geofflang 'at' google.com)
+
+Status
+
+ Draft
+
+Version
+
+ Version 1, September 16, 2016
+
+Number
+
+ EGL Extension #??
+
+Dependencies
+
+ Requires EGL 1.4.
+
+ Written against the EGL 1.4 specification.
+
+ This spec interacts with GL_ANGLE_webgl_compatibility (or equivalent)
+ extension.
+
+Overview
+
+ This extension allows the creation of an OpenGL or OpenGL ES context that
+ provides additional WebGL features and validation.
+
+New Types
+
+ None
+
+New Procedures and Functions
+
+ None
+
+New Tokens
+
+ Accepted as an attribute name in the <*attrib_list> argument to
+ eglCreateContext:
+
+ EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
+
+Additions to the EGL 1.4 Specification
+
+ Add the following to section 3.7.1 "Creating Rendering Contexts":
+
+ EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE indicates whether a WebGL mode should
+ be enabled for the OpenGL ES context. In this mode, the OpenGL ES context
+ will provide additional features and validation to be compatible with the
+ WebGL specification. The default value of
+ EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE is EGL_FALSE.
+
+Errors
+
+ None
+
+New State
+
+ None
+
+Conformance Tests
+
+ TBD
+
+Issues
+
+ None
+
+Revision History
+
+ Rev. Date Author Changes
+ ---- ------------- --------- ----------------------------------------
+ 1 Sept 16, 2016 geofflang Initial version
diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
index fc0a377..7a513e0 100644
--- a/include/EGL/eglext.h
+++ b/include/EGL/eglext.h
@@ -567,6 +567,11 @@
#endif
#endif /* EGL_ANGLE_stream_producer_d3d_texture_nv12 */
+#ifndef EGL_ANGLE_create_context_webgl_compatibility
+#define EGL_ANGLE_create_context_webgl_compatibility 1
+#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
+#endif /* EGL_ANGLE_create_context_webgl_compatibility */
+
#ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286
diff --git a/include/GLES2/gl2ext.h b/include/GLES2/gl2ext.h
index 9e92a03..4ba2ea9 100644
--- a/include/GLES2/gl2ext.h
+++ b/include/GLES2/gl2ext.h
@@ -821,6 +821,14 @@
#endif
#endif /* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_webgl_compatibility
+#define GL_ANGLE_webgl_compatibility 1
+typedef GLboolean(GL_APIENTRYP PFNGLENABLEEXTENSIONANGLEPROC) (const GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLboolean GL_APIENTRY glEnableExtensionANGLE (const GLchar *name);
+#endif
+#endif /* GL_ANGLE_webgl_compatibility */
+
#ifndef GL_CHROMIUM_framebuffer_mixed_samples
#define GL_CHROMIUM_frambuffer_mixed_samples 1
#define GL_COVERAGE_MODULATION_CHROMIUM 0x9332
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index 985d798..7663aa9 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -70,6 +70,11 @@
}
}
+void TextureCapsMap::clear()
+{
+ mCapsMap.clear();
+}
+
const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const
{
static TextureCaps defaultUnsupportedTexture;
@@ -161,6 +166,7 @@
bindUniformLocation(false),
syncQuery(false),
copyTexture(false),
+ webglCompatibility(false),
colorBufferFloat(false),
multisampleCompatibility(false),
framebufferMixedSamples(false),
@@ -173,78 +179,13 @@
{
std::vector<std::string> extensionStrings;
- // clang-format off
- // | Extension name | Supported flag | Output vector |
- InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings);
- InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings);
- InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings);
- InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings);
- InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings);
- InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings);
- InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings);
- InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings);
- InsertExtensionString("GL_EXT_color_buffer_half_float", colorBufferHalfFloat, &extensionStrings);
- InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings);
- InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings);
- InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings);
- InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings);
- InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings);
- InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings);
- InsertExtensionString("GL_KHR_texture_compression_astc_hdr", textureCompressionASTCHDR, &extensionStrings);
- InsertExtensionString("GL_KHR_texture_compression_astc_ldr", textureCompressionASTCLDR, &extensionStrings);
- InsertExtensionString("GL_OES_compressed_ETC1_RGB8_texture", compressedETC1RGB8Texture, &extensionStrings);
- InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings);
- InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings);
- InsertExtensionString("GL_OES_depth32", depth32, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings);
- InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings);
- InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings);
- InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings);
- InsertExtensionString("GL_NV_fence", fence, &extensionStrings);
- InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings);
- InsertExtensionString("GL_EXT_disjoint_timer_query", disjointTimerQuery, &extensionStrings);
- InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings);
- InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings);
- InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings);
- InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings);
- InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings);
- InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings);
- InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings);
- InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings);
- InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings);
- InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch, &extensionStrings);
- InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings);
- InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings);
- InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings);
- InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings);
- InsertExtensionString("GL_OES_fbo_render_mipmap", fboRenderMipmap, &extensionStrings);
- InsertExtensionString("GL_EXT_discard_framebuffer", discardFramebuffer, &extensionStrings);
- InsertExtensionString("GL_EXT_debug_marker", debugMarker, &extensionStrings);
- InsertExtensionString("GL_OES_EGL_image", eglImage, &extensionStrings);
- InsertExtensionString("GL_OES_EGL_image_external", eglImageExternal, &extensionStrings);
- InsertExtensionString("GL_OES_EGL_image_external_essl3", eglImageExternalEssl3, &extensionStrings);
- InsertExtensionString("GL_NV_EGL_stream_consumer_external", eglStreamConsumerExternal, &extensionStrings);
- InsertExtensionString("GL_EXT_unpack_subimage", unpackSubimage, &extensionStrings);
- InsertExtensionString("GL_NV_pack_subimage", packSubimage, &extensionStrings);
- InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
- InsertExtensionString("GL_OES_vertex_array_object", vertexArrayObject, &extensionStrings);
- InsertExtensionString("GL_KHR_debug", debug, &extensionStrings);
- // TODO(jmadill): Enable this when complete.
- //InsertExtensionString("GL_KHR_no_error", noError, &extensionStrings);
-
- InsertExtensionString("GL_ANGLE_lossy_etc_decode", lossyETCDecode, &extensionStrings);
- InsertExtensionString("GL_CHROMIUM_bind_uniform_location", bindUniformLocation, &extensionStrings);
- InsertExtensionString("GL_CHROMIUM_sync_query", syncQuery, &extensionStrings);
- InsertExtensionString("GL_CHROMIUM_copy_texture", copyTexture, &extensionStrings);
- InsertExtensionString("GL_EXT_multisample_compatibility", multisampleCompatibility, &extensionStrings);
- InsertExtensionString("GL_CHROMIUM_framebuffer_mixed_samples", framebufferMixedSamples, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_norm16", textureNorm16, &extensionStrings);
- InsertExtensionString("GL_CHROMIUM_path_rendering", pathRendering, &extensionStrings);
- // clang-format on
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ if (this->*(extensionInfo.second.ExtensionsMember))
+ {
+ extensionStrings.push_back(extensionInfo.first);
+ }
+ }
return extensionStrings;
}
@@ -555,6 +496,102 @@
textureNorm16 = DetermineTextureNorm16Support(textureCaps);
}
+const ExtensionInfoMap &GetExtensionInfoMap()
+{
+ auto buildExtensionInfoMap = []() {
+ auto enableableExtension = [](ExtensionInfo::ExtensionBool member) {
+ ExtensionInfo info;
+ info.Enableable = true;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ auto esOnlyExtension = [](ExtensionInfo::ExtensionBool member) {
+ ExtensionInfo info;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ // clang-format off
+ ExtensionInfoMap map;
+ map["GL_OES_element_index_uint"] = enableableExtension(&Extensions::elementIndexUint);
+ map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencil);
+ map["GL_OES_get_program_binary"] = esOnlyExtension(&Extensions::getProgramBinary);
+ map["GL_OES_rgb8_rgba8"] = esOnlyExtension(&Extensions::rgb8rgba8);
+ map["GL_EXT_texture_format_BGRA8888"] = esOnlyExtension(&Extensions::textureFormatBGRA8888);
+ map["GL_EXT_read_format_bgra"] = esOnlyExtension(&Extensions::readFormatBGRA);
+ map["GL_NV_pixel_buffer_object"] = esOnlyExtension(&Extensions::pixelBufferObject);
+ map["GL_OES_mapbuffer"] = esOnlyExtension(&Extensions::mapBuffer);
+ map["GL_EXT_map_buffer_range"] = esOnlyExtension(&Extensions::mapBufferRange);
+ map["GL_EXT_color_buffer_half_float"] = esOnlyExtension(&Extensions::colorBufferHalfFloat);
+ map["GL_OES_texture_half_float"] = esOnlyExtension(&Extensions::textureHalfFloat);
+ map["GL_OES_texture_half_float_linear"] = esOnlyExtension(&Extensions::textureHalfFloatLinear);
+ map["GL_OES_texture_float"] = esOnlyExtension(&Extensions::textureFloat);
+ map["GL_OES_texture_float_linear"] = esOnlyExtension(&Extensions::textureFloatLinear);
+ map["GL_EXT_texture_rg"] = esOnlyExtension(&Extensions::textureRG);
+ map["GL_EXT_texture_compression_dxt1"] = esOnlyExtension(&Extensions::textureCompressionDXT1);
+ map["GL_ANGLE_texture_compression_dxt3"] = esOnlyExtension(&Extensions::textureCompressionDXT3);
+ map["GL_ANGLE_texture_compression_dxt5"] = esOnlyExtension(&Extensions::textureCompressionDXT5);
+ map["GL_KHR_texture_compression_astc_hdr"] = esOnlyExtension(&Extensions::textureCompressionASTCHDR);
+ map["GL_KHR_texture_compression_astc_ldr"] = esOnlyExtension(&Extensions::textureCompressionASTCLDR);
+ map["GL_OES_compressed_ETC1_RGB8_texture"] = esOnlyExtension(&Extensions::compressedETC1RGB8Texture);
+ map["GL_EXT_sRGB"] = esOnlyExtension(&Extensions::sRGB);
+ map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextures);
+ map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32);
+ map["GL_EXT_texture_storage"] = esOnlyExtension(&Extensions::textureStorage);
+ map["GL_OES_texture_npot"] = esOnlyExtension(&Extensions::textureNPOT);
+ map["GL_EXT_draw_buffers"] = esOnlyExtension(&Extensions::drawBuffers);
+ map["GL_EXT_texture_filter_anisotropic"] = esOnlyExtension(&Extensions::textureFilterAnisotropic);
+ map["GL_EXT_occlusion_query_boolean"] = esOnlyExtension(&Extensions::occlusionQueryBoolean);
+ map["GL_NV_fence"] = esOnlyExtension(&Extensions::fence);
+ map["GL_ANGLE_timer_query"] = esOnlyExtension(&Extensions::timerQuery);
+ map["GL_EXT_disjoint_timer_query"] = esOnlyExtension(&Extensions::disjointTimerQuery);
+ map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustness);
+ map["GL_EXT_blend_minmax"] = esOnlyExtension(&Extensions::blendMinMax);
+ map["GL_ANGLE_framebuffer_blit"] = esOnlyExtension(&Extensions::framebufferBlit);
+ map["GL_ANGLE_framebuffer_multisample"] = esOnlyExtension(&Extensions::framebufferMultisample);
+ map["GL_ANGLE_instanced_arrays"] = esOnlyExtension(&Extensions::instancedArrays);
+ map["GL_ANGLE_pack_reverse_row_order"] = esOnlyExtension(&Extensions::packReverseRowOrder);
+ map["GL_OES_standard_derivatives"] = esOnlyExtension(&Extensions::standardDerivatives);
+ map["GL_EXT_shader_texture_lod"] = esOnlyExtension(&Extensions::shaderTextureLOD);
+ map["GL_NV_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::NVshaderFramebufferFetch);
+ map["GL_ARM_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::ARMshaderFramebufferFetch);
+ map["GL_EXT_shader_framebuffer_fetch"] = esOnlyExtension(&Extensions::shaderFramebufferFetch);
+ map["GL_EXT_frag_depth"] = esOnlyExtension(&Extensions::fragDepth);
+ map["GL_ANGLE_texture_usage"] = esOnlyExtension(&Extensions::textureUsage);
+ map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSource);
+ map["GL_OES_fbo_render_mipmap"] = esOnlyExtension(&Extensions::fboRenderMipmap);
+ map["GL_EXT_discard_framebuffer"] = esOnlyExtension(&Extensions::discardFramebuffer);
+ map["GL_EXT_debug_marker"] = esOnlyExtension(&Extensions::debugMarker);
+ map["GL_OES_EGL_image"] = esOnlyExtension(&Extensions::eglImage);
+ map["GL_OES_EGL_image_external"] = esOnlyExtension(&Extensions::eglImageExternal);
+ map["GL_OES_EGL_image_external_essl3"] = esOnlyExtension(&Extensions::eglImageExternalEssl3);
+ map["GL_NV_EGL_stream_consumer_external"] = esOnlyExtension(&Extensions::eglStreamConsumerExternal);
+ map["GL_EXT_unpack_subimage"] = esOnlyExtension(&Extensions::unpackSubimage);
+ map["GL_NV_pack_subimage"] = esOnlyExtension(&Extensions::packSubimage);
+ map["GL_EXT_color_buffer_float"] = esOnlyExtension(&Extensions::colorBufferFloat);
+ map["GL_OES_vertex_array_object"] = esOnlyExtension(&Extensions::vertexArrayObject);
+ map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug);
+ // TODO(jmadill): Enable this when complete.
+ //map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError);
+ map["GL_ANGLE_lossy_etc_decode"] = esOnlyExtension(&Extensions::lossyETCDecode);
+ map["GL_CHROMIUM_bind_uniform_location"] = esOnlyExtension(&Extensions::bindUniformLocation);
+ map["GL_CHROMIUM_sync_query"] = esOnlyExtension(&Extensions::syncQuery);
+ map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
+ map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
+ map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
+ map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
+ map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
+ map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
+ // clang-format on
+
+ return map;
+ };
+
+ static const ExtensionInfoMap extensionInfo = buildExtensionInfoMap();
+ return extensionInfo;
+}
+
TypePrecision::TypePrecision()
{
range[0] = 0;
@@ -739,7 +776,8 @@
stream(false),
streamConsumerGLTexture(false),
streamConsumerGLTextureYUV(false),
- streamProducerD3DTextureNV12(false)
+ streamProducerD3DTextureNV12(false),
+ createContextWebGLCompatibility(false)
{
}
@@ -773,6 +811,7 @@
InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility,&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 6382830..0a0619c 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -52,6 +52,7 @@
void insert(GLenum internalFormat, const TextureCaps &caps);
void remove(GLenum internalFormat);
+ void clear();
const TextureCaps &get(GLenum internalFormat) const;
@@ -292,6 +293,9 @@
// GL_CHROMIUM_copy_texture
bool copyTexture;
+ // GL_ANGLE_webgl_compatibility
+ bool webglCompatibility;
+
// ES3 Extension support
// GL_EXT_color_buffer_float
@@ -312,6 +316,19 @@
bool pathRendering;
};
+struct ExtensionInfo
+{
+ // If this extension can be enabled with glEnableExtension (GL_ANGLE_webgl_compatibility)
+ bool Enableable = false;
+
+ // Pointer to a boolean member of the Extensions struct
+ typedef bool(Extensions::*ExtensionBool);
+ ExtensionBool ExtensionsMember = nullptr;
+};
+
+using ExtensionInfoMap = std::map<std::string, ExtensionInfo>;
+const ExtensionInfoMap &GetExtensionInfoMap();
+
struct Limitations
{
Limitations();
@@ -572,6 +589,9 @@
// EGL_ANGLE_stream_producer_d3d_texture_nv12
bool streamProducerD3DTextureNV12;
+
+ // EGL_ANGLE_create_context_webgl_compatibility
+ bool createContextWebGLCompatibility;
};
struct DeviceExtensions
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 32d4fea..48e3933 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -179,6 +179,11 @@
return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE);
}
+bool GetWebGLContext(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
{
std::string labelName;
@@ -244,7 +249,7 @@
{
ASSERT(!mRobustAccess); // Unimplemented
- initCaps();
+ initCaps(GetWebGLContext(attribs));
mGLState.initialize(mCaps, mExtensions, mClientMajorVersion, GetDebug(attribs));
@@ -2292,26 +2297,30 @@
mRendererString = MakeStaticString(rendererString.str());
}
-const std::string &Context::getRendererString() const
+const char *Context::getRendererString() const
{
return mRendererString;
}
void Context::initExtensionStrings()
{
- mExtensionStrings = mExtensions.getStrings();
+ for (const auto &extensionString : mExtensions.getStrings())
+ {
+ mExtensionStrings.push_back(MakeStaticString(extensionString));
+ }
std::ostringstream combinedStringStream;
- std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator<std::string>(combinedStringStream, " "));
- mExtensionString = combinedStringStream.str();
+ std::copy(mExtensionStrings.begin(), mExtensionStrings.end(),
+ std::ostream_iterator<const char *>(combinedStringStream, " "));
+ mExtensionString = MakeStaticString(combinedStringStream.str());
}
-const std::string &Context::getExtensionString() const
+const char *Context::getExtensionString() const
{
return mExtensionString;
}
-const std::string &Context::getExtensionString(size_t idx) const
+const char *Context::getExtensionString(size_t idx) const
{
return mExtensionStrings[idx];
}
@@ -2342,7 +2351,7 @@
return false;
}
-void Context::initCaps()
+void Context::initCaps(bool webGLContext)
{
mCaps = mImplementation->getNativeCaps();
@@ -2385,7 +2394,25 @@
mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+ // WebGL compatibility
+ mExtensions.webglCompatibility = webGLContext;
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ // If this context is for WebGL, disable all enableable extensions
+ if (webGLContext && extensionInfo.second.Enableable)
+ {
+ mExtensions.*(extensionInfo.second.ExtensionsMember) = false;
+ }
+ }
+
+ // Generate texture caps
+ updateCaps();
+}
+
+void Context::updateCaps()
+{
mCaps.compressedTextureFormats.clear();
+ mTextureCaps.clear();
const TextureCapsMap &rendererFormats = mImplementation->getNativeTextureCaps();
for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++)
@@ -2924,6 +2951,32 @@
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,
GLuint destId,
GLint internalFormat,
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index f69ddca..97b3158 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -481,6 +481,8 @@
void generateMipmap(GLenum target);
+ GLboolean enableExtension(const char *name);
+
Error flush();
Error finish();
@@ -582,10 +584,10 @@
EGLenum getClientType() const;
EGLenum getRenderBuffer() const;
- const std::string &getRendererString() const;
+ const char *getRendererString() const;
- const std::string &getExtensionString() const;
- const std::string &getExtensionString(size_t idx) const;
+ const char *getExtensionString() const;
+ const char *getExtensionString(size_t idx) const;
size_t getExtensionStringCount() const;
rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
@@ -612,7 +614,8 @@
void initRendererString();
void initExtensionStrings();
- void initCaps();
+ void initCaps(bool webGLContext);
+ void updateCaps();
LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
@@ -653,9 +656,9 @@
ResourceMap<TransformFeedback> mTransformFeedbackMap;
HandleAllocator mTransformFeedbackAllocator;
- std::string mRendererString;
- std::string mExtensionString;
- std::vector<std::string> mExtensionStrings;
+ const char *mRendererString;
+ const char *mExtensionString;
+ std::vector<const char *> mExtensionStrings;
// Recorded errors
typedef std::set<GLenum> ErrorSet;
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp
index 26bd0d2..e2a60fc 100644
--- a/src/libANGLE/Display.cpp
+++ b/src/libANGLE/Display.cpp
@@ -918,6 +918,7 @@
// Some extensions are always available because they are implemented in the EGL layer.
mDisplayExtensions.createContext = true;
mDisplayExtensions.createContextNoError = true;
+ mDisplayExtensions.createContextWebGLCompatibility = true;
// Force EGL_KHR_get_all_proc_addresses on.
mDisplayExtensions.getAllProcAddresses = true;
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
index 6b6893b..3ff51f1 100644
--- a/src/libANGLE/validationEGL.cpp
+++ b/src/libANGLE/validationEGL.cpp
@@ -327,6 +327,21 @@
}
break;
+ case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
+ if (!display->getExtensions().createContextWebGLCompatibility)
+ {
+ return Error(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
+ "EGL_ANGLE_create_context_webgl_compatibility.");
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return Error(
+ EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be EGL_TRUE or EGL_FALSE.");
+ }
+ break;
+
default:
return Error(EGL_BAD_ATTRIBUTE);
}
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 339624c..0846f0d 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -482,7 +482,8 @@
break;
case GL_DEPTH_STENCIL_ATTACHMENT:
- if (context->getClientMajorVersion() < 3)
+ if (!context->getExtensions().webglCompatibility &&
+ context->getClientMajorVersion() < 3)
{
context->handleError(Error(GL_INVALID_ENUM));
return false;
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 2775fe9..68285ce 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -3433,4 +3433,24 @@
return true;
}
+bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name)
+{
+ if (!context->getExtensions().webglCompatibility)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "GL_ANGLE_webgl_compatibility is not available."));
+ return false;
+ }
+
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ auto extension = extensionInfos.find(name);
+ if (extension == extensionInfos.end() || !extension->second.Enableable)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Extension %s is not enableable.", name));
+ return false;
+ }
+
+ return true;
+}
+
} // namespace gl
diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h
index b9cf587..1ebb262 100644
--- a/src/libANGLE/validationES2.h
+++ b/src/libANGLE/validationES2.h
@@ -317,6 +317,8 @@
GLsizeiptr size,
const GLvoid *data);
+bool ValidateEnableExtensionANGLE(ValidationContext *context, const GLchar *name);
+
} // namespace gl
#endif // LIBANGLE_VALIDATION_ES2_H_
diff --git a/src/libGLESv2/entry_points_egl.cpp b/src/libGLESv2/entry_points_egl.cpp
index 1ed04ea..b3fec07 100644
--- a/src/libGLESv2/entry_points_egl.cpp
+++ b/src/libGLESv2/entry_points_egl.cpp
@@ -1472,6 +1472,9 @@
INSERT_PROC_ADDRESS(gl, CopyTextureCHROMIUM);
INSERT_PROC_ADDRESS(gl, CopySubTextureCHROMIUM);
+ // GL_ANGLE_webgl_compatibility
+ INSERT_PROC_ADDRESS(gl, EnableExtensionANGLE);
+
// GLES3 core
INSERT_PROC_ADDRESS(gl, ReadBuffer);
INSERT_PROC_ADDRESS(gl, DrawRangeElements);
diff --git a/src/libGLESv2/entry_points_gles_2_0.cpp b/src/libGLESv2/entry_points_gles_2_0.cpp
index 7dcca39..a86e696 100644
--- a/src/libGLESv2/entry_points_gles_2_0.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0.cpp
@@ -2101,7 +2101,7 @@
return reinterpret_cast<const GLubyte *>("Google Inc.");
case GL_RENDERER:
- return reinterpret_cast<const GLubyte *>(context->getRendererString().c_str());
+ return reinterpret_cast<const GLubyte *>(context->getRendererString());
case GL_VERSION:
if (context->getClientMajorVersion() == 2)
@@ -2128,7 +2128,7 @@
}
case GL_EXTENSIONS:
- return reinterpret_cast<const GLubyte *>(context->getExtensionString().c_str());
+ return reinterpret_cast<const GLubyte *>(context->getExtensionString());
default:
context->handleError(Error(GL_INVALID_ENUM));
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
index cfd64c8..7b114f8 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -1935,4 +1935,22 @@
}
}
+GL_APICALL GLboolean GL_APIENTRY EnableExtensionANGLE(const GLchar *name)
+{
+ EVENT("(const GLchar *name = %p)", name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateEnableExtensionANGLE(context, name))
+ {
+ return GL_FALSE;
+ }
+
+ return context->enableExtension(name) ? GL_TRUE : GL_FALSE;
+ }
+
+ return GL_FALSE;
+}
+
} // gl
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/libGLESv2/entry_points_gles_2_0_ext.h
index 86216d2..1f1f7b4 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.h
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.h
@@ -259,6 +259,9 @@
GLboolean unpackPremultiplyAlpha,
GLboolean unpackUnmultiplyAlpha);
+// GL_ANGLE_webgl_compatibility
+GL_APICALL GLboolean GL_APIENTRY EnableExtensionANGLE(const GLchar *name);
+
} // namespace gl
#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
diff --git a/src/libGLESv2/entry_points_gles_3_0.cpp b/src/libGLESv2/entry_points_gles_3_0.cpp
index dabb334..f5dcd5d 100644
--- a/src/libGLESv2/entry_points_gles_3_0.cpp
+++ b/src/libGLESv2/entry_points_gles_3_0.cpp
@@ -1441,7 +1441,7 @@
return NULL;
}
- return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str());
+ return reinterpret_cast<const GLubyte *>(context->getExtensionString(index));
}
return NULL;
diff --git a/src/tests/angle_end2end_tests.gypi b/src/tests/angle_end2end_tests.gypi
index 9941e96..d23d481 100644
--- a/src/tests/angle_end2end_tests.gypi
+++ b/src/tests/angle_end2end_tests.gypi
@@ -75,6 +75,7 @@
'<(angle_path)/src/tests/gl_tests/UnpackRowLength.cpp',
'<(angle_path)/src/tests/gl_tests/VertexAttributeTest.cpp',
'<(angle_path)/src/tests/gl_tests/ViewportTest.cpp',
+ '<(angle_path)/src/tests/gl_tests/WebGLCompatibilityTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLContextCompatibilityTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLContextSharingTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLQueryContextTest.cpp',
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
new file mode 100644
index 0000000..087247f
--- /dev/null
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
@@ -0,0 +1,127 @@
+//
+// Copyright 2015 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.
+//
+
+// WebGLCompatibilityTest.cpp : Tests of the GL_ANGLE_webgl_compatibility extension.
+
+#include "test_utils/ANGLETest.h"
+
+#include "test_utils/gl_raii.h"
+
+namespace angle
+{
+
+class WebGLCompatibilityTest : public ANGLETest
+{
+ protected:
+ WebGLCompatibilityTest()
+ {
+ setWindowWidth(128);
+ setWindowHeight(128);
+ setConfigRedBits(8);
+ setConfigGreenBits(8);
+ setConfigBlueBits(8);
+ setConfigAlphaBits(8);
+ setWebGLCompatibilityEnabled(true);
+ }
+
+ void SetUp() override
+ {
+ ANGLETest::SetUp();
+ glEnableExtensionANGLE = reinterpret_cast<PFNGLENABLEEXTENSIONANGLEPROC>(
+ eglGetProcAddress("glEnableExtensionANGLE"));
+ }
+
+ void TearDown() override { ANGLETest::TearDown(); }
+
+ PFNGLENABLEEXTENSIONANGLEPROC glEnableExtensionANGLE = nullptr;
+};
+
+// Context creation would fail if EGL_ANGLE_create_context_webgl_compatibility was not available so
+// the GL extension should always be present
+TEST_P(WebGLCompatibilityTest, ExtensionStringExposed)
+{
+ EXPECT_TRUE(extensionEnabled("GL_ANGLE_webgl_compatibility"));
+}
+
+// Verify that all extension entry points are available
+TEST_P(WebGLCompatibilityTest, EntryPoints)
+{
+ if (extensionEnabled("GL_ANGLE_webgl_compatibility"))
+ {
+ EXPECT_NE(nullptr, eglGetProcAddress("glEnableExtensionANGLE"));
+ }
+}
+
+// WebGL 1 allows GL_DEPTH_STENCIL_ATTACHMENT as a valid binding point. Make sure it is usable,
+// even in ES2 contexts.
+TEST_P(WebGLCompatibilityTest, DepthStencilBindingPoint)
+{
+ GLRenderbuffer renderbuffer;
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
+
+ GLFramebuffer framebuffer;
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
+ renderbuffer.get());
+
+ EXPECT_GL_NO_ERROR();
+}
+
+// Test that attempting to enable an extension that doesn't exist generates GL_INVALID_OPERATION
+TEST_P(WebGLCompatibilityTest, EnableExtensionValidation)
+{
+ EXPECT_EQ(GL_FALSE, glEnableExtensionANGLE("invalid_extension_string"));
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+}
+
+// Test enabling the GL_OES_element_index_uint extension
+TEST_P(WebGLCompatibilityTest, EnableExtensionUintIndices)
+{
+ if (getClientMajorVersion() != 2)
+ {
+ // This test only works on ES2 where uint indices are not available by default
+ return;
+ }
+
+ EXPECT_FALSE(extensionEnabled("GL_OES_element_index_uint"));
+
+ GLBuffer indexBuffer;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.get());
+
+ GLuint data[] = {0, 1, 2, 1, 3, 2};
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
+
+ ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
+ "void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
+ glUseProgram(program.get());
+
+ glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr);
+ EXPECT_GL_ERROR(GL_INVALID_ENUM);
+
+ if (glEnableExtensionANGLE("GL_OES_element_index_uint"))
+ {
+ EXPECT_GL_NO_ERROR();
+ EXPECT_TRUE(extensionEnabled("GL_OES_element_index_uint"));
+
+ glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, nullptr);
+ EXPECT_GL_NO_ERROR();
+ }
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
+ 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 1a9d8b5..7bec1e1 100644
--- a/src/tests/test_utils/ANGLETest.cpp
+++ b/src/tests/test_utils/ANGLETest.cpp
@@ -643,6 +643,11 @@
mEGLWindow->setNoErrorEnabled(enabled);
}
+void ANGLETest::setWebGLCompatibilityEnabled(bool webglCompatibility)
+{
+ mEGLWindow->setWebGLCompatibilityEnabled(webglCompatibility);
+}
+
int ANGLETest::getClientMajorVersion() const
{
return mEGLWindow->getClientMajorVersion();
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index e1c6fba..73b69cd 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -211,6 +211,7 @@
void setMultisampleEnabled(bool enabled);
void setDebugEnabled(bool enabled);
void setNoErrorEnabled(bool enabled);
+ void setWebGLCompatibilityEnabled(bool webglCompatibility);
int getClientMajorVersion() const;
int getClientMinorVersion() const;
diff --git a/util/EGLWindow.cpp b/util/EGLWindow.cpp
index 2f436d9..a59391f 100644
--- a/util/EGLWindow.cpp
+++ b/util/EGLWindow.cpp
@@ -110,6 +110,7 @@
mMultisample(false),
mDebug(false),
mNoError(false),
+ mWebGLCompatibility(false),
mSwapInterval(-1)
{
}
@@ -207,6 +208,14 @@
return false;
}
+ bool hasWebGLCompatibility =
+ strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr;
+ if (mWebGLCompatibility && !hasWebGLCompatibility)
+ {
+ destroyGL();
+ return false;
+ }
+
eglBindAPI(EGL_OPENGL_ES_API);
if (eglGetError() != EGL_SUCCESS)
{
@@ -275,6 +284,12 @@
contextAttributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
contextAttributes.push_back(mNoError ? EGL_TRUE : EGL_FALSE);
+
+ if (hasWebGLCompatibility)
+ {
+ contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
+ contextAttributes.push_back(mWebGLCompatibility ? EGL_TRUE : EGL_FALSE);
+ }
}
contextAttributes.push_back(EGL_NONE);
diff --git a/util/EGLWindow.h b/util/EGLWindow.h
index 4352a2b..11b6470 100644
--- a/util/EGLWindow.h
+++ b/util/EGLWindow.h
@@ -68,6 +68,10 @@
void setMultisample(bool multisample) { mMultisample = multisample; }
void setDebugEnabled(bool debug) { mDebug = debug; }
void setNoErrorEnabled(bool noError) { mNoError = noError; }
+ void setWebGLCompatibilityEnabled(bool webglCompatibility)
+ {
+ mWebGLCompatibility = webglCompatibility;
+ }
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
@@ -113,6 +117,7 @@
bool mMultisample;
bool mDebug;
bool mNoError;
+ bool mWebGLCompatibility;
EGLint mSwapInterval;
};