LibWeb/WebGL: Implement the EXT_texture_filter_anisotropic extension

This commit is contained in:
Luke Wilde 2025-10-18 19:01:10 +01:00 committed by Jelle Raaijmakers
parent d08915a0cd
commit b15f4424f9
13 changed files with 166 additions and 2 deletions

View File

@ -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

View File

@ -1225,6 +1225,7 @@ class ANGLEInstancedArrays;
class EXTBlendMinMax;
class EXTColorBufferFloat;
class EXTRenderSnorm;
class EXTTextureFilterAnisotropic;
class EXTTextureNorm16;
class OESVertexArrayObject;
class WebGLCompressedTextureS3tc;

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/Bindings/EXTTextureFilterAnisotropicPrototype.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.h>
#include <LibWeb/WebGL/OpenGLContext.h>
namespace Web::WebGL::Extensions {
GC_DEFINE_ALLOCATOR(EXTTextureFilterAnisotropic);
JS::ThrowCompletionOr<GC::Ptr<EXTTextureFilterAnisotropic>> EXTTextureFilterAnisotropic::create(JS::Realm& realm, WebGLRenderingContextBase* context)
{
return realm.create<EXTTextureFilterAnisotropic>(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());
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/Forward.h>
#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
namespace Web::WebGL::Extensions {
class EXTTextureFilterAnisotropic : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(EXTTextureFilterAnisotropic, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(EXTTextureFilterAnisotropic);
public:
static JS::ThrowCompletionOr<GC::Ptr<EXTTextureFilterAnisotropic>> 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;
};
}

View File

@ -0,0 +1,13 @@
#import <WebGL/Types.idl>
// 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;
};

View File

@ -17,6 +17,7 @@
#include <LibWeb/WebGL/EventNames.h>
#include <LibWeb/WebGL/Extensions/EXTColorBufferFloat.h>
#include <LibWeb/WebGL/Extensions/EXTRenderSnorm.h>
#include <LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.h>
#include <LibWeb/WebGL/Extensions/EXTTextureNorm16.h>
#include <LibWeb/WebGL/Extensions/WebGLCompressedTextureS3tc.h>
#include <LibWeb/WebGL/Extensions/WebGLCompressedTextureS3tcSrgb.h>
@ -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;
}
}

View File

@ -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<Extensions::EXTColorBufferFloat> m_ext_color_buffer_float_extension;
GC::Ptr<Extensions::EXTRenderSnorm> m_ext_render_snorm;
GC::Ptr<Extensions::EXTTextureFilterAnisotropic> m_ext_texture_filter_anisotropic;
GC::Ptr<Extensions::EXTTextureNorm16> m_ext_texture_norm16;
GC::Ptr<Extensions::WebGLCompressedTextureS3tc> m_webgl_compressed_texture_s3tc_extension;
GC::Ptr<Extensions::WebGLCompressedTextureS3tcSrgb> m_webgl_compressed_texture_s3tc_srgb_extension;

View File

@ -8,6 +8,7 @@
#define GL_GLEXT_PROTOTYPES 1
#include <GLES3/gl3.h>
extern "C" {
#include <GLES2/gl2ext.h>
#include <GLES2/gl2ext_angle.h>
}
@ -394,6 +395,13 @@ void WebGL2RenderingContextImpl::sampler_parameteri(GC::Root<WebGLSampler> 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<WebGLSampler> 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<double>(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);

View File

@ -16,6 +16,7 @@
#include <LibWeb/WebGL/EventNames.h>
#include <LibWeb/WebGL/Extensions/ANGLEInstancedArrays.h>
#include <LibWeb/WebGL/Extensions/EXTBlendMinMax.h>
#include <LibWeb/WebGL/Extensions/EXTTextureFilterAnisotropic.h>
#include <LibWeb/WebGL/Extensions/OESVertexArrayObject.h>
#include <LibWeb/WebGL/Extensions/WebGLCompressedTextureS3tc.h>
#include <LibWeb/WebGL/Extensions/WebGLCompressedTextureS3tcSrgb.h>
@ -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;
}
}

View File

@ -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<Extensions::ANGLEInstancedArrays> m_angle_instanced_arrays_extension;
GC::Ptr<Extensions::EXTBlendMinMax> m_ext_blend_min_max_extension;
GC::Ptr<Extensions::EXTTextureFilterAnisotropic> m_ext_texture_filter_anisotropic;
GC::Ptr<Extensions::OESVertexArrayObject> m_oes_vertex_array_object_extension;
GC::Ptr<Extensions::WebGLCompressedTextureS3tc> m_webgl_compressed_texture_s3tc_extension;
GC::Ptr<Extensions::WebGLCompressedTextureS3tcSrgb> m_webgl_compressed_texture_s3tc_srgb_extension;

View File

@ -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<float> span_from_float32_list(Float32List& float32_list)
{

View File

@ -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);

View File

@ -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)