diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index e1c847205df..a4fe7cc6b64 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -1024,6 +1024,7 @@ set(SOURCES WebGL/Extensions/EXTBlendMinMax.cpp WebGL/Extensions/EXTColorBufferFloat.cpp WebGL/Extensions/EXTRenderSnorm.cpp + WebGL/Extensions/EXTTextureFilterAnisotropic.cpp WebGL/Extensions/EXTTextureNorm16.cpp WebGL/Extensions/OESVertexArrayObject.cpp WebGL/Extensions/WebGLCompressedTextureS3tc.cpp diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 0a375f576bf..141555ddd1f 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -1225,6 +1225,7 @@ class ANGLEInstancedArrays; class EXTBlendMinMax; class EXTColorBufferFloat; class EXTRenderSnorm; +class EXTTextureFilterAnisotropic; class EXTTextureNorm16; class OESVertexArrayObject; class WebGLCompressedTextureS3tc; diff --git a/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.cpp b/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.cpp new file mode 100644 index 00000000000..c5974c90fbf --- /dev/null +++ b/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Web::WebGL::Extensions { + +GC_DEFINE_ALLOCATOR(EXTTextureFilterAnisotropic); + +JS::ThrowCompletionOr> EXTTextureFilterAnisotropic::create(JS::Realm& realm, WebGLRenderingContextBase* context) +{ + return realm.create(realm, context); +} + +EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(JS::Realm& realm, WebGLRenderingContextBase* context) + : PlatformObject(realm) + , m_context(context) +{ + m_context->context().request_extension("GL_EXT_texture_filter_anisotropic"); +} + +void EXTTextureFilterAnisotropic::initialize(JS::Realm& realm) +{ + WEB_SET_PROTOTYPE_FOR_INTERFACE(EXTTextureFilterAnisotropic); + Base::initialize(realm); +} + +void EXTTextureFilterAnisotropic::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_context->gc_cell()); +} + +} diff --git a/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.h b/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.h new file mode 100644 index 00000000000..b436d2bbf27 --- /dev/null +++ b/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::WebGL::Extensions { + +class EXTTextureFilterAnisotropic : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(EXTTextureFilterAnisotropic, Bindings::PlatformObject); + GC_DECLARE_ALLOCATOR(EXTTextureFilterAnisotropic); + +public: + static JS::ThrowCompletionOr> create(JS::Realm&, WebGLRenderingContextBase*); + +protected: + void initialize(JS::Realm&) override; + void visit_edges(Visitor&) override; + +private: + EXTTextureFilterAnisotropic(JS::Realm&, WebGLRenderingContextBase*); + + // FIXME: It should be GC::Ptr instead of raw pointer, but we need to make WebGLRenderingContextBase inherit from PlatformObject first. + WebGLRenderingContextBase* m_context; +}; + +} diff --git a/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.idl b/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.idl new file mode 100644 index 00000000000..652bfbb7564 --- /dev/null +++ b/Libraries/LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.idl @@ -0,0 +1,13 @@ +#import + +// https://registry.khronos.org/webgl/extensions/EXT_texture_filter_anisotropic/ +// NOTE: Original EXT_texture_filter_anisotropic name is changed to title case, +// so it matches corresponding C++ class name, and does not require +// IDL generator to handle snake_case to TitleCase conversion. +// Having a different name is totally fine, because LegacyNoInterfaceObject +// prevents the name from being exposed to JavaScript. +[Exposed=(Window,Worker), LegacyNoInterfaceObject] +interface EXTTextureFilterAnisotropic { + const GLenum TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE; + const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF; +}; diff --git a/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp b/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp index 0b08a3509bb..227cc87279a 100644 --- a/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp +++ b/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -79,6 +80,7 @@ void WebGL2RenderingContext::visit_edges(Cell::Visitor& visitor) visitor.visit(m_canvas_element); visitor.visit(m_ext_color_buffer_float_extension); visitor.visit(m_ext_render_snorm); + visitor.visit(m_ext_texture_filter_anisotropic); visitor.visit(m_ext_texture_norm16); visitor.visit(m_webgl_compressed_texture_s3tc_extension); visitor.visit(m_webgl_compressed_texture_s3tc_srgb_extension); @@ -206,6 +208,15 @@ JS::Object* WebGL2RenderingContext::get_extension(String const& name) return m_ext_render_snorm; } + if (name.equals_ignoring_ascii_case("EXT_texture_filter_anisotropic"sv)) { + if (!m_ext_texture_filter_anisotropic) { + m_ext_texture_filter_anisotropic = MUST(Extensions::EXTTextureFilterAnisotropic::create(realm(), this)); + } + + VERIFY(m_ext_texture_filter_anisotropic); + return m_ext_texture_filter_anisotropic; + } + if (name.equals_ignoring_ascii_case("EXT_texture_norm16"sv)) { if (!m_ext_texture_norm16) { m_ext_texture_norm16 = MUST(Extensions::EXTTextureNorm16::create(realm(), *this)); @@ -230,4 +241,9 @@ WebIDL::Long WebGL2RenderingContext::drawing_buffer_height() const return size.height(); } +bool WebGL2RenderingContext::ext_texture_filter_anisotropic_extension_enabled() const +{ + return !!m_ext_texture_filter_anisotropic; +} + } diff --git a/Libraries/LibWeb/WebGL/WebGL2RenderingContext.h b/Libraries/LibWeb/WebGL/WebGL2RenderingContext.h index cf0171db10b..b4d0f2a9f10 100644 --- a/Libraries/LibWeb/WebGL/WebGL2RenderingContext.h +++ b/Libraries/LibWeb/WebGL/WebGL2RenderingContext.h @@ -17,7 +17,7 @@ namespace Web::WebGL { -class WebGL2RenderingContext : public Bindings::PlatformObject +class WebGL2RenderingContext final : public Bindings::PlatformObject , public WebGL2RenderingContextImpl { WEB_PLATFORM_OBJECT(WebGL2RenderingContext, Bindings::PlatformObject); GC_DECLARE_ALLOCATOR(WebGL2RenderingContext); @@ -51,6 +51,8 @@ public: WebIDL::Long drawing_buffer_width() const; WebIDL::Long drawing_buffer_height() const; + virtual bool ext_texture_filter_anisotropic_extension_enabled() const override; + private: virtual void initialize(JS::Realm&) override; @@ -84,6 +86,7 @@ private: // "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_ext_color_buffer_float_extension; GC::Ptr m_ext_render_snorm; + GC::Ptr m_ext_texture_filter_anisotropic; GC::Ptr m_ext_texture_norm16; GC::Ptr m_webgl_compressed_texture_s3tc_extension; GC::Ptr m_webgl_compressed_texture_s3tc_srgb_extension; diff --git a/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp b/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp index 928a4288d20..70d37169001 100644 --- a/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp +++ b/Libraries/LibWeb/WebGL/WebGL2RenderingContextImpl.cpp @@ -8,6 +8,7 @@ #define GL_GLEXT_PROTOTYPES 1 #include extern "C" { +#include #include } @@ -394,6 +395,13 @@ void WebGL2RenderingContextImpl::sampler_parameteri(GC::Root sampl case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: { + if (ext_texture_filter_anisotropic_extension_enabled()) + break; + + set_error(GL_INVALID_ENUM); + return; + } default: dbgln("Unknown WebGL sampler parameter name: 0x{:04x}", pname); set_error(GL_INVALID_ENUM); @@ -427,6 +435,13 @@ void WebGL2RenderingContextImpl::sampler_parameterf(GC::Root sampl case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: { + if (ext_texture_filter_anisotropic_extension_enabled()) + break; + + set_error(GL_INVALID_ENUM); + return; + } default: dbgln("Unknown WebGL sampler parameter name: 0x{:04x}", pname); set_error(GL_INVALID_ENUM); @@ -2571,6 +2586,16 @@ JS::Value WebGL2RenderingContextImpl::get_parameter(WebIDL::UnsignedLong pname) glGetInteger64vRobustANGLE(GL_MAX_SERVER_WAIT_TIMEOUT, 1, nullptr, &result); return JS::Value(static_cast(result)); } + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: { + if (ext_texture_filter_anisotropic_extension_enabled()) { + GLfloat result { 0.0f }; + glGetFloatvRobustANGLE(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, 1, nullptr, &result); + return JS::Value(result); + } + + set_error(GL_INVALID_ENUM); + return JS::js_null(); + } default: dbgln("Unknown WebGL parameter name: {:x}", pname); set_error(GL_INVALID_ENUM); diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp b/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp index b701e11ef82..5243a899e87 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,7 @@ void WebGLRenderingContext::visit_edges(Cell::Visitor& visitor) visitor.visit(m_canvas_element); visitor.visit(m_angle_instanced_arrays_extension); visitor.visit(m_ext_blend_min_max_extension); + visitor.visit(m_ext_texture_filter_anisotropic); visitor.visit(m_oes_vertex_array_object_extension); visitor.visit(m_webgl_compressed_texture_s3tc_extension); visitor.visit(m_webgl_compressed_texture_s3tc_srgb_extension); @@ -206,6 +208,15 @@ JS::Object* WebGLRenderingContext::get_extension(String const& name) return m_ext_blend_min_max_extension; } + if (name.equals_ignoring_ascii_case("EXT_texture_filter_anisotropic"sv)) { + if (!m_ext_texture_filter_anisotropic) { + m_ext_texture_filter_anisotropic = MUST(Extensions::EXTTextureFilterAnisotropic::create(realm(), this)); + } + + VERIFY(m_ext_texture_filter_anisotropic); + return m_ext_texture_filter_anisotropic; + } + if (name.equals_ignoring_ascii_case("OES_vertex_array_object"sv)) { if (!m_oes_vertex_array_object_extension) { m_oes_vertex_array_object_extension = MUST(Extensions::OESVertexArrayObject::create(realm(), *this)); @@ -257,4 +268,9 @@ WebIDL::Long WebGLRenderingContext::drawing_buffer_height() const return size.height(); } +bool WebGLRenderingContext::ext_texture_filter_anisotropic_extension_enabled() const +{ + return !!m_ext_texture_filter_anisotropic; +} + } diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContext.h b/Libraries/LibWeb/WebGL/WebGLRenderingContext.h index d8823a6a8be..b7041073788 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContext.h +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContext.h @@ -16,7 +16,7 @@ namespace Web::WebGL { -class WebGLRenderingContext : public Bindings::PlatformObject +class WebGLRenderingContext final : public Bindings::PlatformObject , public WebGLRenderingContextImpl { WEB_PLATFORM_OBJECT(WebGLRenderingContext, Bindings::PlatformObject); GC_DECLARE_ALLOCATOR(WebGLRenderingContext); @@ -50,6 +50,8 @@ public: WebIDL::Long drawing_buffer_width() const; WebIDL::Long drawing_buffer_height() const; + virtual bool ext_texture_filter_anisotropic_extension_enabled() const override; + private: virtual void initialize(JS::Realm&) override; @@ -83,6 +85,7 @@ private: // "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_ext_blend_min_max_extension; + GC::Ptr m_ext_texture_filter_anisotropic; GC::Ptr m_oes_vertex_array_object_extension; GC::Ptr m_webgl_compressed_texture_s3tc_extension; GC::Ptr m_webgl_compressed_texture_s3tc_srgb_extension; diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h b/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h index ec914c2b8b5..8768f9f561a 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h @@ -26,6 +26,7 @@ public: virtual GC::Cell const* gc_cell() const = 0; virtual void visit_edges(JS::Cell::Visitor&) = 0; virtual OpenGLContext& context() = 0; + virtual bool ext_texture_filter_anisotropic_extension_enabled() const = 0; static Span span_from_float32_list(Float32List& float32_list) { diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp b/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp index d0cd05290b5..567eb8d2d57 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContextImpl.cpp @@ -1443,6 +1443,16 @@ JS::Value WebGLRenderingContextImpl::get_parameter(WebIDL::UnsignedLong pname) auto array_buffer = JS::ArrayBuffer::create(m_realm, move(byte_buffer)); return JS::Int32Array::create(m_realm, 4, array_buffer); } + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: { + if (ext_texture_filter_anisotropic_extension_enabled()) { + GLfloat result { 0.0f }; + glGetFloatvRobustANGLE(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, 1, nullptr, &result); + return JS::Value(result); + } + + set_error(GL_INVALID_ENUM); + return JS::js_null(); + } default: dbgln("Unknown WebGL parameter name: {:x}", pname); set_error(GL_INVALID_ENUM); diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index a0307a71918..36847503383 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -472,6 +472,7 @@ libweb_js_bindings(WebGL/Extensions/ANGLEInstancedArrays) libweb_js_bindings(WebGL/Extensions/EXTBlendMinMax) libweb_js_bindings(WebGL/Extensions/EXTColorBufferFloat) libweb_js_bindings(WebGL/Extensions/EXTRenderSnorm) +libweb_js_bindings(WebGL/Extensions/EXTTextureFilterAnisotropic) libweb_js_bindings(WebGL/Extensions/EXTTextureNorm16) libweb_js_bindings(WebGL/Extensions/OESVertexArrayObject) libweb_js_bindings(WebGL/Extensions/WebGLCompressedTextureS3tc)