From cfbd125e57c27af1c149a3dbfbbedf91f620db98 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Fri, 10 Jan 2025 13:39:53 +0000 Subject: [PATCH] LibWeb/WebGL: Make getExtension spec-compliant Namely: - Perform case-insensitive matching - Return the same extension objects every time - Only enable the extension if it's supported by the current context --- Libraries/LibWeb/Forward.h | 3 ++ .../LibWeb/WebGL/WebGLRenderingContext.cpp | 35 ++++++++++++++++--- .../LibWeb/WebGL/WebGLRenderingContext.h | 5 +++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index c1fbfbdbe6b..8a9d123396b 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -841,6 +841,8 @@ struct OscillatorOptions; } namespace Web::WebGL { +class ANGLEInstancedArrays; +class OESVertexArrayObject; class OpenGLContext; class WebGL2RenderingContext; class WebGLActiveInfo; @@ -858,6 +860,7 @@ class WebGLSync; class WebGLTexture; class WebGLUniformLocation; class WebGLVertexArrayObject; +class WebGLVertexArrayObjectOES; } namespace Web::WebIDL { diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp b/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp index a88b4179220..6fddb746e00 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +90,8 @@ void WebGLRenderingContext::visit_edges(Cell::Visitor& visitor) Base::visit_edges(visitor); WebGLRenderingContextImpl::visit_edges(visitor); visitor.visit(m_canvas_element); + visitor.visit(m_angle_instanced_arrays_extension); + visitor.visit(m_oes_vertex_array_object_extension); } void WebGLRenderingContext::present() @@ -174,12 +177,36 @@ Optional> WebGLRenderingContext::get_supported_extensions() JS::Object* WebGLRenderingContext::get_extension(String const& name) { - if (name == "ANGLE_instanced_arrays"sv) { - return MUST(ANGLEInstancedArrays::create(realm())); + // Returns an object if, and only if, name is an ASCII case-insensitive match [HTML] for one of the names returned + // from getSupportedExtensions; otherwise, returns null. The object returned from getExtension contains any constants + // or functions provided by the extension. A returned object may have no constants or functions if the extension does + // not define any, but a unique object must still be returned. That object is used to indicate that the extension has + // been enabled. + auto supported_extensions = get_supported_extensions(); + auto supported_extension_iterator = supported_extensions->find_if([&name](String const& supported_extension) { + return Infra::is_ascii_case_insensitive_match(supported_extension, name); + }); + if (supported_extension_iterator == supported_extensions->end()) + return nullptr; + + if (Infra::is_ascii_case_insensitive_match(name, "ANGLE_instanced_arrays"sv)) { + if (!m_angle_instanced_arrays_extension) { + m_angle_instanced_arrays_extension = MUST(ANGLEInstancedArrays::create(realm(), *this)); + } + + VERIFY(m_angle_instanced_arrays_extension); + return m_angle_instanced_arrays_extension; } - if (name == "OES_vertex_array_object"sv) { - return MUST(OESVertexArrayObject::create(realm(), *this)); + + if (Infra::is_ascii_case_insensitive_match(name, "OES_vertex_array_object"sv)) { + if (!m_oes_vertex_array_object_extension) { + m_oes_vertex_array_object_extension = MUST(OESVertexArrayObject::create(realm(), *this)); + } + + VERIFY(m_oes_vertex_array_object_extension); + return m_oes_vertex_array_object_extension; } + return nullptr; } diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContext.h b/Libraries/LibWeb/WebGL/WebGLRenderingContext.h index 3d64d119b7f..e99d665df41 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContext.h +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContext.h @@ -79,6 +79,11 @@ private: GLenum m_error { 0 }; + // Extensions + // "Multiple calls to getExtension with the same extension string, taking into account case-insensitive comparison, must return the same object as long as the extension is enabled." + GC::Ptr m_angle_instanced_arrays_extension; + GC::Ptr m_oes_vertex_array_object_extension; + virtual void set_error(GLenum error) override; };