summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Wilde <lukew@serenityos.org>2022-06-04 04:22:42 +0100
committerLinus Groh <mail@linusgroh.de>2022-06-13 21:45:27 +0100
commit58f882200cfaa6f666876f728e1dd82a2352dfe3 (patch)
treeff8ce2ead18a2e63fe51a971860bb9078ce42016
parentb0c2aee2e4d7e38913259a2fb6fc024db9a12718 (diff)
downloadserenity-58f882200cfaa6f666876f728e1dd82a2352dfe3.zip
LibWeb: Add the ability to retrieve a WebGL context from getContext
-rw-r--r--Meta/Lagom/CMakeLists.txt2
-rw-r--r--Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp4
-rw-r--r--Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h3
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt7
-rw-r--r--Userland/Libraries/LibWeb/Forward.h3
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp99
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h19
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.idl5
-rw-r--r--Userland/Libraries/LibWeb/WebGL/Types.h9
-rw-r--r--Userland/Libraries/LibWeb/WebGL/Types.idl15
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.cpp164
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.h34
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp50
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.h31
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.idl7
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp23
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h51
-rw-r--r--Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl397
-rw-r--r--Userland/Libraries/LibWeb/idl_files.cmake1
19 files changed, 903 insertions, 21 deletions
diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt
index 410378c7e7..8d4de9054c 100644
--- a/Meta/Lagom/CMakeLists.txt
+++ b/Meta/Lagom/CMakeLists.txt
@@ -500,7 +500,7 @@ if (BUILD_LAGOM)
lagom_lib(Web web
SOURCES ${LIBWEB_SOURCES} ${LIBWEB_SUBDIR_SOURCES} ${LIBWEB_SUBSUBDIR_SOURCES} ${LIBWEB_GENERATED_SOURCES}
- LIBS LagomMarkdown LagomGemini LagomGfx LagomJS LagomTextCodec LagomWasm LagomXML
+ LIBS LagomMarkdown LagomGemini LagomGfx LagomGL LagomJS LagomTextCodec LagomWasm LagomXML
)
generate_js_wrappers(LagomWeb)
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp
index 1d5fd43c74..389344d8cb 100644
--- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp
+++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp
@@ -48,6 +48,10 @@ static bool is_wrappable_type(Type const& type)
return true;
if (type.name == "AbortSignal")
return true;
+ if (type.name == "CanvasRenderingContext2D")
+ return true;
+ if (type.name == "WebGLRenderingContext")
+ return true;
return false;
}
diff --git a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h
index 83e47af739..5968c8ae5b 100644
--- a/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h
+++ b/Userland/Libraries/LibWeb/Bindings/WindowObjectHelper.h
@@ -341,6 +341,8 @@
#include <LibWeb/Bindings/URLSearchParamsPrototype.h>
#include <LibWeb/Bindings/WebGLContextEventConstructor.h>
#include <LibWeb/Bindings/WebGLContextEventPrototype.h>
+#include <LibWeb/Bindings/WebGLRenderingContextConstructor.h>
+#include <LibWeb/Bindings/WebGLRenderingContextPrototype.h>
#include <LibWeb/Bindings/WebSocketConstructor.h>
#include <LibWeb/Bindings/WebSocketPrototype.h>
#include <LibWeb/Bindings/WindowConstructor.h>
@@ -529,6 +531,7 @@
ADD_WINDOW_OBJECT_INTERFACE(URLSearchParams) \
ADD_WINDOW_OBJECT_INTERFACE(URL) \
ADD_WINDOW_OBJECT_INTERFACE(WebGLContextEvent) \
+ ADD_WINDOW_OBJECT_INTERFACE(WebGLRenderingContext) \
ADD_WINDOW_OBJECT_INTERFACE(WebSocket) \
ADD_WINDOW_OBJECT_INTERFACE(Worker) \
ADD_WINDOW_OBJECT_INTERFACE(XMLHttpRequest) \
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt
index 9e10768eef..b86615ba18 100644
--- a/Userland/Libraries/LibWeb/CMakeLists.txt
+++ b/Userland/Libraries/LibWeb/CMakeLists.txt
@@ -352,6 +352,9 @@ set(SOURCES
WebAssembly/WebAssemblyTableConstructor.cpp
WebAssembly/WebAssemblyTableObject.cpp
WebAssembly/WebAssemblyTablePrototype.cpp
+ WebGL/WebGLContextAttributes.cpp
+ WebGL/WebGLRenderingContext.cpp
+ WebGL/WebGLRenderingContextBase.cpp
WebSockets/WebSocket.cpp
XHR/EventNames.cpp
XHR/XMLHttpRequest.cpp
@@ -372,7 +375,9 @@ set(GENERATED_SOURCES
)
serenity_lib(LibWeb web)
-target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGUI LibGfx LibTextCodec LibWasm LibXML)
+
+# NOTE: We link with LibSoftGPU here instead of lazy loading it via dlopen() so that we do not have to unveil the library and pledge prot_exec.
+target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGL LibGUI LibGfx LibSoftGPU LibTextCodec LibWasm LibXML)
link_with_unicode_data(LibWeb)
generate_js_wrappers(LibWeb)
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index 58617d8829..d125df9938 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -379,6 +379,8 @@ class ResourceLoader;
namespace Web::WebGL {
class WebGLContextEvent;
+class WebGLRenderingContext;
+class WebGLRenderingContextBase;
}
namespace Web::XHR {
@@ -581,6 +583,7 @@ class URLSearchParamsPrototype;
class URLSearchParamsWrapper;
class URLWrapper;
class WebGLContextEventWrapper;
+class WebGLRenderingContextWrapper;
class WebSocketWrapper;
class WindowObject;
class WindowProxy;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp
index 413541378f..852dffe6b0 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp
@@ -35,20 +35,32 @@ unsigned HTMLCanvasElement::height() const
return attribute(HTML::AttributeNames::height).to_uint().value_or(150);
}
+void HTMLCanvasElement::reset_context_to_default_state()
+{
+ m_context.visit(
+ [](NonnullRefPtr<CanvasRenderingContext2D>& context) {
+ context->reset_to_default_state();
+ },
+ [](NonnullRefPtr<WebGL::WebGLRenderingContext>&) {
+ TODO();
+ },
+ [](Empty) {
+ // Do nothing.
+ });
+}
+
void HTMLCanvasElement::set_width(unsigned value)
{
set_attribute(HTML::AttributeNames::width, String::number(value));
m_bitmap = nullptr;
- if (m_context)
- m_context->reset_to_default_state();
+ reset_context_to_default_state();
}
void HTMLCanvasElement::set_height(unsigned value)
{
set_attribute(HTML::AttributeNames::height, String::number(value));
m_bitmap = nullptr;
- if (m_context)
- m_context->reset_to_default_state();
+ reset_context_to_default_state();
}
RefPtr<Layout::Node> HTMLCanvasElement::create_layout_node(NonnullRefPtr<CSS::StyleProperties> style)
@@ -56,19 +68,62 @@ RefPtr<Layout::Node> HTMLCanvasElement::create_layout_node(NonnullRefPtr<CSS::St
return adopt_ref(*new Layout::CanvasBox(document(), *this, move(style)));
}
-CanvasRenderingContext2D* HTMLCanvasElement::get_context(String type)
+HTMLCanvasElement::HasOrCreatedContext HTMLCanvasElement::create_2d_context()
+{
+ if (!m_context.has<Empty>())
+ return m_context.has<NonnullRefPtr<CanvasRenderingContext2D>>() ? HasOrCreatedContext::Yes : HasOrCreatedContext::No;
+
+ m_context = CanvasRenderingContext2D::create(*this);
+ return HasOrCreatedContext::Yes;
+}
+
+JS::ThrowCompletionOr<HTMLCanvasElement::HasOrCreatedContext> HTMLCanvasElement::create_webgl_context(JS::Value options)
{
- if (type != "2d")
- return nullptr;
- if (!m_context)
- m_context = CanvasRenderingContext2D::create(*this);
- return m_context;
+ if (!m_context.has<Empty>())
+ return m_context.has<NonnullRefPtr<WebGL::WebGLRenderingContext>>() ? HasOrCreatedContext::Yes : HasOrCreatedContext::No;
+
+ auto maybe_context = TRY(WebGL::WebGLRenderingContext::create(*this, options));
+ if (!maybe_context)
+ return HasOrCreatedContext::No;
+
+ m_context = maybe_context.release_nonnull();
+ return HasOrCreatedContext::Yes;
}
-static Gfx::IntSize bitmap_size_for_canvas(HTMLCanvasElement const& canvas)
+// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-getcontext
+JS::ThrowCompletionOr<HTMLCanvasElement::RenderingContext> HTMLCanvasElement::get_context(String const& type, JS::Value options)
{
- auto width = canvas.width();
- auto height = canvas.height();
+ // 1. If options is not an object, then set options to null.
+ if (!options.is_object())
+ options = JS::js_null();
+
+ // 2. Set options to the result of converting options to a JavaScript value.
+ // NOTE: No-op.
+
+ // 3. Run the steps in the cell of the following table whose column header matches this canvas element's canvas context mode and whose row header matches contextId:
+ // NOTE: See the spec for the full table.
+ if (type == "2d"sv) {
+ if (create_2d_context() == HasOrCreatedContext::Yes)
+ return m_context;
+
+ return Empty {};
+ }
+
+ // NOTE: The WebGL spec says "experimental-webgl" is also acceptable and must be equivalent to "webgl". Other engines accept this, so we do too.
+ if (type.is_one_of("webgl"sv, "experimental-webgl"sv)) {
+ if (TRY(create_webgl_context(options)) == HasOrCreatedContext::Yes)
+ return m_context;
+
+ return Empty {};
+ }
+
+ return Empty {};
+}
+
+static Gfx::IntSize bitmap_size_for_canvas(HTMLCanvasElement const& canvas, size_t minimum_width, size_t minimum_height)
+{
+ auto width = max(canvas.width(), minimum_width);
+ auto height = max(canvas.height(), minimum_height);
Checked<size_t> area = width;
area *= height;
@@ -84,9 +139,9 @@ static Gfx::IntSize bitmap_size_for_canvas(HTMLCanvasElement const& canvas)
return Gfx::IntSize(width, height);
}
-bool HTMLCanvasElement::create_bitmap()
+bool HTMLCanvasElement::create_bitmap(size_t minimum_width, size_t minimum_height)
{
- auto size = bitmap_size_for_canvas(*this);
+ auto size = bitmap_size_for_canvas(*this, minimum_width, minimum_height);
if (size.is_empty()) {
m_bitmap = nullptr;
return false;
@@ -110,4 +165,18 @@ String HTMLCanvasElement::to_data_url(String const& type, [[maybe_unused]] Optio
return AK::URL::create_with_data(type, encode_base64(encoded_bitmap), true).to_string();
}
+void HTMLCanvasElement::present()
+{
+ m_context.visit(
+ [](NonnullRefPtr<CanvasRenderingContext2D>&) {
+ // Do nothing, CRC2D writes directly to the canvas bitmap.
+ },
+ [](NonnullRefPtr<WebGL::WebGLRenderingContext>& context) {
+ context->present();
+ },
+ [](Empty) {
+ // Do nothing.
+ });
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h
index b6bda5884c..8da131068d 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.h
@@ -9,21 +9,23 @@
#include <AK/ByteBuffer.h>
#include <LibGfx/Forward.h>
#include <LibWeb/HTML/HTMLElement.h>
+#include <LibWeb/WebGL/WebGLRenderingContext.h>
namespace Web::HTML {
class HTMLCanvasElement final : public HTMLElement {
public:
using WrapperType = Bindings::HTMLCanvasElementWrapper;
+ using RenderingContext = Variant<NonnullRefPtr<CanvasRenderingContext2D>, NonnullRefPtr<WebGL::WebGLRenderingContext>, Empty>;
HTMLCanvasElement(DOM::Document&, DOM::QualifiedName);
virtual ~HTMLCanvasElement() override;
Gfx::Bitmap const* bitmap() const { return m_bitmap; }
Gfx::Bitmap* bitmap() { return m_bitmap; }
- bool create_bitmap();
+ bool create_bitmap(size_t minimum_width = 0, size_t minimum_height = 0);
- CanvasRenderingContext2D* get_context(String type);
+ JS::ThrowCompletionOr<RenderingContext> get_context(String const& type, JS::Value options);
unsigned width() const;
unsigned height() const;
@@ -33,11 +35,22 @@ public:
String to_data_url(String const& type, Optional<double> quality) const;
+ void present();
+
private:
virtual RefPtr<Layout::Node> create_layout_node(NonnullRefPtr<CSS::StyleProperties>) override;
+ enum class HasOrCreatedContext {
+ No,
+ Yes,
+ };
+
+ HasOrCreatedContext create_2d_context();
+ JS::ThrowCompletionOr<HasOrCreatedContext> create_webgl_context(JS::Value options);
+ void reset_context_to_default_state();
+
RefPtr<Gfx::Bitmap> m_bitmap;
- RefPtr<CanvasRenderingContext2D> m_context;
+ RenderingContext m_context;
};
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.idl
index 1ff0f64a46..28ad99a8c5 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.idl
+++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.idl
@@ -1,9 +1,12 @@
#import <HTML/CanvasRenderingContext2D.idl>
#import <HTML/HTMLElement.idl>
+#import <WebGL/WebGLRenderingContext.idl>
+
+typedef (CanvasRenderingContext2D or WebGLRenderingContext) RenderingContext;
interface HTMLCanvasElement : HTMLElement {
- CanvasRenderingContext2D? getContext(DOMString contextId);
+ RenderingContext? getContext(DOMString contextId, optional any options = null);
attribute unsigned long width;
attribute unsigned long height;
diff --git a/Userland/Libraries/LibWeb/WebGL/Types.h b/Userland/Libraries/LibWeb/WebGL/Types.h
new file mode 100644
index 0000000000..0d4df0e70f
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/Types.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+// FIXME: This header is here just to satisfy the IDL code generator.
diff --git a/Userland/Libraries/LibWeb/WebGL/Types.idl b/Userland/Libraries/LibWeb/WebGL/Types.idl
new file mode 100644
index 0000000000..cd1522b87d
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/Types.idl
@@ -0,0 +1,15 @@
+typedef unsigned long GLenum;
+typedef boolean GLboolean;
+typedef unsigned long GLbitfield;
+typedef long GLint;
+typedef long GLsizei;
+
+// FIXME: These should be "unrestricted float"
+typedef float GLfloat;
+typedef float GLclampf;
+
+enum WebGLPowerPreference {
+ "default",
+ "low-power",
+ "high-performance"
+};
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.cpp
new file mode 100644
index 0000000000..648c6c565e
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibJS/Runtime/Completion.h>
+#include <LibJS/Runtime/GlobalObject.h>
+#include <LibWeb/WebGL/WebGLContextAttributes.h>
+
+namespace Web::WebGL {
+
+JS::ThrowCompletionOr<WebGLContextAttributes> convert_value_to_context_attributes_dictionary(JS::GlobalObject& global_object, JS::Value value)
+{
+ auto& vm = global_object.vm();
+
+ // NOTE: This code was generated by the IDL code generator and then cleaned up.
+ if (!value.is_nullish() && !value.is_object())
+ return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebGLContextAttributes");
+
+ WebGLContextAttributes context_attributes {};
+
+ JS::Value alpha;
+ if (value.is_nullish())
+ alpha = JS::js_undefined();
+ else
+ alpha = TRY(value.as_object().get("alpha"));
+
+ bool alpha_value;
+ if (!alpha.is_undefined())
+ alpha_value = alpha.to_boolean();
+ else
+ alpha_value = true;
+
+ context_attributes.alpha = alpha_value;
+
+ JS::Value antialias;
+ if (value.is_nullish())
+ antialias = JS::js_undefined();
+ else
+ antialias = TRY(value.as_object().get("antialias"));
+
+ bool antialias_value;
+ if (!antialias.is_undefined())
+ antialias_value = antialias.to_boolean();
+ else
+ antialias_value = true;
+
+ context_attributes.antialias = antialias_value;
+
+ JS::Value depth;
+ if (value.is_nullish())
+ depth = JS::js_undefined();
+ else
+ depth = TRY(value.as_object().get("depth"));
+
+ bool depth_value;
+ if (!depth.is_undefined())
+ depth_value = depth.to_boolean();
+ else
+ depth_value = true;
+
+ context_attributes.depth = depth_value;
+
+ JS::Value desynchronized;
+ if (value.is_nullish())
+ desynchronized = JS::js_undefined();
+ else
+ desynchronized = TRY(value.as_object().get("desynchronized"));
+
+ bool desynchronized_value;
+
+ if (!desynchronized.is_undefined())
+ desynchronized_value = desynchronized.to_boolean();
+ else
+ desynchronized_value = false;
+
+ context_attributes.desynchronized = desynchronized_value;
+
+ JS::Value fail_if_major_performance_caveat;
+ if (value.is_nullish())
+ fail_if_major_performance_caveat = JS::js_undefined();
+ else
+ fail_if_major_performance_caveat = TRY(value.as_object().get("failIfMajorPerformanceCaveat"));
+
+ bool fail_if_major_performance_caveat_value;
+ if (!fail_if_major_performance_caveat.is_undefined())
+ fail_if_major_performance_caveat_value = fail_if_major_performance_caveat.to_boolean();
+ else
+ fail_if_major_performance_caveat_value = false;
+
+ context_attributes.fail_if_major_performance_caveat = fail_if_major_performance_caveat_value;
+
+ JS::Value power_preference;
+ if (value.is_nullish())
+ power_preference = JS::js_undefined();
+ else
+ power_preference = TRY(value.as_object().get("powerPreference"));
+
+ WebGLPowerPreference power_preference_value { WebGLPowerPreference::Default };
+
+ if (!power_preference.is_undefined()) {
+ auto power_preference_string = TRY(power_preference.to_string(global_object));
+
+ if (power_preference_string == "high-performance"sv)
+ power_preference_value = WebGLPowerPreference::HighPerformance;
+ else if (power_preference_string == "low-power"sv)
+ power_preference_value = WebGLPowerPreference::LowPower;
+ else if (power_preference_string == "default"sv)
+ power_preference_value = WebGLPowerPreference::Default;
+ else
+ return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::InvalidEnumerationValue, power_preference_string, "WebGLPowerPreference");
+ }
+
+ context_attributes.power_preference = power_preference_value;
+
+ JS::Value premultiplied_alpha;
+ if (value.is_nullish())
+ premultiplied_alpha = JS::js_undefined();
+ else
+ premultiplied_alpha = TRY(value.as_object().get("premultipliedAlpha"));
+
+ bool premultiplied_alpha_value;
+
+ if (!premultiplied_alpha.is_undefined())
+ premultiplied_alpha_value = premultiplied_alpha.to_boolean();
+ else
+ premultiplied_alpha_value = true;
+
+ context_attributes.premultiplied_alpha = premultiplied_alpha_value;
+
+ JS::Value preserve_drawing_buffer;
+ if (value.is_nullish())
+ preserve_drawing_buffer = JS::js_undefined();
+ else
+ preserve_drawing_buffer = TRY(value.as_object().get("preserveDrawingBuffer"));
+
+ bool preserve_drawing_buffer_value;
+ if (!preserve_drawing_buffer.is_undefined())
+ preserve_drawing_buffer_value = preserve_drawing_buffer.to_boolean();
+ else
+ preserve_drawing_buffer_value = false;
+
+ context_attributes.preserve_drawing_buffer = preserve_drawing_buffer_value;
+
+ JS::Value stencil;
+ if (value.is_nullish())
+ stencil = JS::js_undefined();
+ else
+ stencil = TRY(value.as_object().get("stencil"));
+
+ bool stencil_value;
+
+ if (!stencil.is_undefined())
+ stencil_value = stencil.to_boolean();
+ else
+ stencil_value = false;
+
+ context_attributes.stencil = stencil_value;
+
+ return context_attributes;
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.h b/Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.h
new file mode 100644
index 0000000000..8888d0771b
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLContextAttributes.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Forward.h>
+
+namespace Web::WebGL {
+
+enum class WebGLPowerPreference {
+ Default,
+ LowPower,
+ HighPerformance,
+};
+
+// https://www.khronos.org/registry/webgl/specs/latest/1.0/#WEBGLCONTEXTATTRIBUTES
+struct WebGLContextAttributes {
+ bool alpha { true };
+ bool depth { true };
+ bool stencil { false };
+ bool antialias { true };
+ bool premultiplied_alpha { true };
+ bool preserve_drawing_buffer { false };
+ WebGLPowerPreference power_preference { WebGLPowerPreference::Default };
+ bool fail_if_major_performance_caveat { false };
+ bool desynchronized { false };
+};
+
+JS::ThrowCompletionOr<WebGLContextAttributes> convert_value_to_context_attributes_dictionary(JS::GlobalObject& global_object, JS::Value value);
+
+}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp
new file mode 100644
index 0000000000..332edc1969
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/Wrapper.h>
+#include <LibWeb/HTML/HTMLCanvasElement.h>
+#include <LibWeb/WebGL/WebGLContextEvent.h>
+#include <LibWeb/WebGL/WebGLRenderingContext.h>
+
+namespace Web::WebGL {
+
+// https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-event
+static void fire_webgl_context_event(HTML::HTMLCanvasElement& canvas_element, FlyString const& type)
+{
+ // To fire a WebGL context event named e means that an event using the WebGLContextEvent interface, with its type attribute [DOM4] initialized to e, its cancelable attribute initialized to true, and its isTrusted attribute [DOM4] initialized to true, is to be dispatched at the given object.
+ // FIXME: Consider setting a status message.
+ auto event = WebGLContextEvent::create(type, WebGLContextEventInit {});
+ event->set_is_trusted(true);
+ event->set_cancelable(true);
+ canvas_element.dispatch_event(move(event));
+}
+
+// https://www.khronos.org/registry/webgl/specs/latest/1.0/#fire-a-webgl-context-creation-error
+static void fire_webgl_context_creation_error(HTML::HTMLCanvasElement& canvas_element)
+{
+ // 1. Fire a WebGL context event named "webglcontextcreationerror" at canvas, optionally with its statusMessage attribute set to a platform dependent string about the nature of the failure.
+ fire_webgl_context_event(canvas_element, "webglcontextcreationerror"sv);
+}
+
+JS::ThrowCompletionOr<RefPtr<WebGLRenderingContext>> WebGLRenderingContext::create(HTML::HTMLCanvasElement& canvas_element, JS::Value options)
+{
+ // We should be coming here from getContext being called on a wrapped <canvas> element.
+ VERIFY(canvas_element.wrapper());
+ auto context_attributes = TRY(convert_value_to_context_attributes_dictionary(canvas_element.wrapper()->global_object(), options));
+
+ bool created_bitmap = canvas_element.create_bitmap(/* minimum_width= */ 1, /* minimum_height= */ 1);
+ if (!created_bitmap) {
+ fire_webgl_context_creation_error(canvas_element);
+ return RefPtr<WebGLRenderingContext> { nullptr };
+ }
+
+ // FIXME: LibGL currently doesn't propagate context creation errors.
+ auto context = GL::create_context(*canvas_element.bitmap());
+
+ return adopt_ref(*new WebGLRenderingContext(canvas_element, move(context), context_attributes, context_attributes));
+}
+
+}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.h b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.h
new file mode 100644
index 0000000000..7798009798
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Bindings/Wrappable.h>
+#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
+
+namespace Web::WebGL {
+
+class WebGLRenderingContext
+ : public WebGLRenderingContextBase
+ , public Bindings::Wrappable {
+public:
+ using WrapperType = Bindings::WebGLRenderingContextWrapper;
+
+ static JS::ThrowCompletionOr<RefPtr<WebGLRenderingContext>> create(HTML::HTMLCanvasElement& canvas_element, JS::Value options);
+
+ virtual ~WebGLRenderingContext() override = default;
+
+private:
+ WebGLRenderingContext(HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<GL::GLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters)
+ : WebGLRenderingContextBase(canvas_element, move(context), move(context_creation_parameters), move(actual_context_parameters))
+ {
+ }
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.idl b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.idl
new file mode 100644
index 0000000000..f87b8d1023
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.idl
@@ -0,0 +1,7 @@
+#import <WebGL/WebGLRenderingContextBase.idl>
+
+[Exposed=(Window,Worker)]
+interface WebGLRenderingContext {
+};
+
+WebGLRenderingContext includes WebGLRenderingContextBase;
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp
new file mode 100644
index 0000000000..774cc6adcb
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibGL/GLContext.h>
+#include <LibWeb/HTML/HTMLCanvasElement.h>
+#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
+
+namespace Web::WebGL {
+
+WebGLRenderingContextBase::WebGLRenderingContextBase(HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<GL::GLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters)
+ : m_canvas_element(canvas_element)
+ , m_context(move(context))
+ , m_context_creation_parameters(move(context_creation_parameters))
+ , m_actual_context_parameters(move(actual_context_parameters))
+{
+}
+
+WebGLRenderingContextBase::~WebGLRenderingContextBase() = default;
+
+}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h
new file mode 100644
index 0000000000..70ba19978e
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/RefCounted.h>
+#include <AK/WeakPtr.h>
+#include <AK/Weakable.h>
+#include <LibGL/GLContext.h>
+#include <LibWeb/Forward.h>
+#include <LibWeb/WebGL/WebGLContextAttributes.h>
+
+namespace Web::WebGL {
+
+class WebGLRenderingContextBase
+ : public RefCounted<WebGLRenderingContextBase>
+ , public Weakable<WebGLRenderingContextBase> {
+public:
+ virtual ~WebGLRenderingContextBase();
+
+protected:
+ WebGLRenderingContextBase(HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr<GL::GLContext> context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters);
+
+private:
+ WeakPtr<HTML::HTMLCanvasElement> m_canvas_element;
+
+ NonnullOwnPtr<GL::GLContext> m_context;
+
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#context-creation-parameters
+ // Each WebGLRenderingContext has context creation parameters, set upon creation, in a WebGLContextAttributes object.
+ WebGLContextAttributes m_context_creation_parameters {};
+
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#actual-context-parameters
+ // Each WebGLRenderingContext has actual context parameters, set each time the drawing buffer is created, in a WebGLContextAttributes object.
+ WebGLContextAttributes m_actual_context_parameters {};
+
+ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#webgl-context-lost-flag
+ // Each WebGLRenderingContext has a webgl context lost flag, which is initially unset.
+ bool m_context_lost { false };
+
+ // WebGL presents its drawing buffer to the HTML page compositor immediately before a compositing operation, but only if at least one of the following has occurred since the previous compositing operation:
+ // - Context creation
+ // - Canvas resize
+ // - clear, drawArrays, or drawElements has been called while the drawing buffer is the currently bound framebuffer
+ bool m_should_present { true };
+};
+
+}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl
new file mode 100644
index 0000000000..b88f38acdb
--- /dev/null
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl
@@ -0,0 +1,397 @@
+#import <WebGL/Types.idl>
+
+dictionary WebGLContextAttributes {
+ boolean alpha = true;
+ boolean depth = true;
+ boolean stencil = false;
+ boolean antialias = true;
+ boolean premultipliedAlpha = true;
+ boolean preserveDrawingBuffer = false;
+ WebGLPowerPreference powerPreference = "default";
+ boolean failIfMajorPerformanceCaveat = false;
+ boolean desynchronized = false;
+};
+
+interface mixin WebGLRenderingContextBase {
+ // Enums
+ // ClearBufferMask
+ const GLenum DEPTH_BUFFER_BIT = 0x00000100;
+ const GLenum STENCIL_BUFFER_BIT = 0x00000400;
+ const GLenum COLOR_BUFFER_BIT = 0x00004000;
+
+ // BeginMode
+ const GLenum POINTS = 0x0000;
+ const GLenum LINES = 0x0001;
+ const GLenum LINE_LOOP = 0x0002;
+ const GLenum LINE_STRIP = 0x0003;
+ const GLenum TRIANGLES = 0x0004;
+ const GLenum TRIANGLE_STRIP = 0x0005;
+ const GLenum TRIANGLE_FAN = 0x0006;
+
+ // BlendingFactorDest
+ const GLenum ZERO = 0;
+ const GLenum ONE = 1;
+ const GLenum SRC_COLOR = 0x0300;
+ const GLenum ONE_MINUS_SRC_COLOR = 0x0301;
+ const GLenum SRC_ALPHA = 0x0302;
+ const GLenum ONE_MINUS_SRC_ALPHA = 0x0303;
+ const GLenum DST_ALPHA = 0x0304;
+ const GLenum ONE_MINUS_DST_ALPHA = 0x0305;
+
+ // BlendingFactorSrc
+ const GLenum DST_COLOR = 0x0306;
+ const GLenum ONE_MINUS_DST_COLOR = 0x0307;
+ const GLenum SRC_ALPHA_SATURATE = 0x0308;
+
+ // BlendEquationSeparate
+ const GLenum FUNC_ADD = 0x8006;
+ const GLenum BLEND_EQUATION = 0x8009;
+ const GLenum BLEND_EQUATION_RGB = 0x8009; // NOTE: Intentionally the same as BLEND_EQUATION
+ const GLenum BLEND_EQUATION_ALPHA = 0x883D;
+
+ // BlendSubtract
+ const GLenum FUNC_SUBTRACT = 0x800A;
+ const GLenum FUNC_REVERSE_SUBTRACT = 0x800B;
+
+ // Separate Blend Functions
+ const GLenum BLEND_DST_RGB = 0x80C8;
+ const GLenum BLEND_SRC_RGB = 0x80C9;
+ const GLenum BLEND_DST_ALPHA = 0x80CA;
+ const GLenum BLEND_SRC_ALPHA = 0x80CB;
+ const GLenum CONSTANT_COLOR = 0x8001;
+ const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002;
+ const GLenum CONSTANT_ALPHA = 0x8003;
+ const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004;
+ const GLenum BLEND_COLOR = 0x8005;
+
+ // Buffer Objects
+ const GLenum ARRAY_BUFFER = 0x8892;
+ const GLenum ELEMENT_ARRAY_BUFFER = 0x8893;
+ const GLenum ARRAY_BUFFER_BINDING = 0x8894;
+ const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895;
+
+ const GLenum STREAM_DRAW = 0x88E0;
+ const GLenum STATIC_DRAW = 0x88E4;
+ const GLenum DYNAMIC_DRAW = 0x88E8;
+
+ const GLenum BUFFER_SIZE = 0x8764;
+ const GLenum BUFFER_USAGE = 0x8765;
+
+ const GLenum CURRENT_VERTEX_ATTRIB = 0x8626;
+
+ // CullFaceMode
+ const GLenum FRONT = 0x0404;
+ const GLenum BACK = 0x0405;
+ const GLenum FRONT_AND_BACK = 0x0408;
+
+ // EnableCap
+ // TEXTURE_2D
+ const GLenum CULL_FACE = 0x0B44;
+ const GLenum BLEND = 0x0BE2;
+ const GLenum DITHER = 0x0BD0;
+ const GLenum STENCIL_TEST = 0x0B90;
+ const GLenum DEPTH_TEST = 0x0B71;
+ const GLenum SCISSOR_TEST = 0x0C11;
+ const GLenum POLYGON_OFFSET_FILL = 0x8037;
+ const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E;
+ const GLenum SAMPLE_COVERAGE = 0x80A0;
+
+ // ErrorCode
+ const GLenum NO_ERROR = 0;
+ const GLenum INVALID_ENUM = 0x0500;
+ const GLenum INVALID_VALUE = 0x0501;
+ const GLenum INVALID_OPERATION = 0x0502;
+ const GLenum OUT_OF_MEMORY = 0x0505;
+
+ // FrontFaceDirection
+ const GLenum CW = 0x0900;
+ const GLenum CCW = 0x0901;
+
+ // GetPName
+ const GLenum LINE_WIDTH = 0x0B21;
+ const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D;
+ const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E;
+ const GLenum CULL_FACE_MODE = 0x0B45;
+ const GLenum FRONT_FACE = 0x0B46;
+ const GLenum DEPTH_RANGE = 0x0B70;
+ const GLenum DEPTH_WRITEMASK = 0x0B72;
+ const GLenum DEPTH_CLEAR_VALUE = 0x0B73;
+ const GLenum DEPTH_FUNC = 0x0B74;
+ const GLenum STENCIL_CLEAR_VALUE = 0x0B91;
+ const GLenum STENCIL_FUNC = 0x0B92;
+ const GLenum STENCIL_FAIL = 0x0B94;
+ const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95;
+ const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96;
+ const GLenum STENCIL_REF = 0x0B97;
+ const GLenum STENCIL_VALUE_MASK = 0x0B93;
+ const GLenum STENCIL_WRITEMASK = 0x0B98;
+ const GLenum STENCIL_BACK_FUNC = 0x8800;
+ const GLenum STENCIL_BACK_FAIL = 0x8801;
+ const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802;
+ const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803;
+ const GLenum STENCIL_BACK_REF = 0x8CA3;
+ const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4;
+ const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5;
+ const GLenum VIEWPORT = 0x0BA2;
+ const GLenum SCISSOR_BOX = 0x0C10;
+ const GLenum COLOR_CLEAR_VALUE = 0x0C22;
+ const GLenum COLOR_WRITEMASK = 0x0C23;
+ const GLenum UNPACK_ALIGNMENT = 0x0CF5;
+ const GLenum PACK_ALIGNMENT = 0x0D05;
+ const GLenum MAX_TEXTURE_SIZE = 0x0D33;
+ const GLenum MAX_VIEWPORT_DIMS = 0x0D3A;
+ const GLenum SUBPIXEL_BITS = 0x0D50;
+ const GLenum RED_BITS = 0x0D52;
+ const GLenum GREEN_BITS = 0x0D53;
+ const GLenum BLUE_BITS = 0x0D54;
+ const GLenum ALPHA_BITS = 0x0D55;
+ const GLenum DEPTH_BITS = 0x0D56;
+ const GLenum STENCIL_BITS = 0x0D57;
+ const GLenum POLYGON_OFFSET_UNITS = 0x2A00;
+ const GLenum POLYGON_OFFSET_FACTOR = 0x8038;
+ const GLenum TEXTURE_BINDING_2D = 0x8069;
+ const GLenum SAMPLE_BUFFERS = 0x80A8;
+ const GLenum SAMPLES = 0x80A9;
+ const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA;
+ const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB;
+
+ // GetTexureParameter
+ const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3;
+
+ // HintMode
+ const GLenum DONT_CARE = 0x1100;
+ const GLenum FASTEST = 0x1101;
+ const GLenum NICEST = 0x1102;
+
+ // HintTarget
+ const GLenum GENERATE_MIPMAP_HINT = 0x8192;
+
+ // DataType
+ const GLenum BYTE = 0x1400;
+ const GLenum UNSIGNED_BYTE = 0x1401;
+ const GLenum SHORT = 0x1402;
+ const GLenum UNSIGNED_SHORT = 0x1403;
+ const GLenum INT = 0x1404;
+ const GLenum UNSIGNED_INT = 0x1405;
+ const GLenum FLOAT = 0x1406;
+
+ // PixelFormat
+ const GLenum DEPTH_COMPONENT = 0x1902;
+ const GLenum ALPHA = 0x1906;
+ const GLenum RGB = 0x1907;
+ const GLenum RGBA = 0x1908;
+ const GLenum LUMINANCE = 0x1909;
+ const GLenum LUMINANCE_ALPHA = 0x190A;
+
+ // PixelType
+ const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033;
+ const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034;
+ const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363;
+
+ // Shaders
+ const GLenum FRAGMENT_SHADER = 0x8B30;
+ const GLenum VERTEX_SHADER = 0x8B31;
+ const GLenum MAX_VERTEX_ATTRIBS = 0x8869;
+ const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB;
+ const GLenum MAX_VARYING_VECTORS = 0x8DFC;
+ const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D;
+ const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C;
+ const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872;
+ const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD;
+ const GLenum SHADER_TYPE = 0x8B4F;
+ const GLenum DELETE_STATUS = 0x8B80;
+ const GLenum LINK_STATUS = 0x8B82;
+ const GLenum VALIDATE_STATUS = 0x8B83;
+ const GLenum ATTACHED_SHADERS = 0x8B85;
+ const GLenum ACTIVE_UNIFORMS = 0x8B86;
+ const GLenum ACTIVE_ATTRIBUTES = 0x8B89;
+ const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C;
+ const GLenum CURRENT_PROGRAM = 0x8B8D;
+
+ // StencilFunction
+ const GLenum NEVER = 0x0200;
+ const GLenum LESS = 0x0201;
+ const GLenum EQUAL = 0x0202;
+ const GLenum LEQUAL = 0x0203;
+ const GLenum GREATER = 0x0204;
+ const GLenum NOTEQUAL = 0x0205;
+ const GLenum GEQUAL = 0x0206;
+ const GLenum ALWAYS = 0x0207;
+
+ // StencilOp
+ const GLenum KEEP = 0x1E00;
+ const GLenum REPLACE = 0x1E01;
+ const GLenum INCR = 0x1E02;
+ const GLenum DECR = 0x1E03;
+ const GLenum INVERT = 0x150A;
+ const GLenum INCR_WRAP = 0x8507;
+ const GLenum DECR_WRAP = 0x8508;
+
+ // StringName
+ const GLenum VENDOR = 0x1F00;
+ const GLenum RENDERER = 0x1F01;
+ const GLenum VERSION = 0x1F02;
+
+ // TextureMagFilter
+ const GLenum NEAREST = 0x2600;
+ const GLenum LINEAR = 0x2601;
+
+ // TextureMinFilter
+ const GLenum NEAREST_MIPMAP_NEAREST = 0x2700;
+ const GLenum LINEAR_MIPMAP_NEAREST = 0x2701;
+ const GLenum NEAREST_MIPMAP_LINEAR = 0x2702;
+ const GLenum LINEAR_MIPMAP_LINEAR = 0x2703;
+
+ // TextureParameterName
+ const GLenum TEXTURE_MAG_FILTER = 0x2800;
+ const GLenum TEXTURE_MIN_FILTER = 0x2801;
+ const GLenum TEXTURE_WRAP_S = 0x2802;
+ const GLenum TEXTURE_WRAP_T = 0x2803;
+
+ // TextureTarget
+ const GLenum TEXTURE_2D = 0x0DE1;
+ const GLenum TEXTURE = 0x1702;
+
+ const GLenum TEXTURE_CUBE_MAP = 0x8513;
+ const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514;
+ const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
+ const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
+ const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
+ const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
+ const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
+ const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
+ const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
+
+ // TextureUnit
+ const GLenum TEXTURE0 = 0x84C0;
+ const GLenum TEXTURE1 = 0x84C1;
+ const GLenum TEXTURE2 = 0x84C2;
+ const GLenum TEXTURE3 = 0x84C3;
+ const GLenum TEXTURE4 = 0x84C4;
+ const GLenum TEXTURE5 = 0x84C5;
+ const GLenum TEXTURE6 = 0x84C6;
+ const GLenum TEXTURE7 = 0x84C7;
+ const GLenum TEXTURE8 = 0x84C8;
+ const GLenum TEXTURE9 = 0x84C9;
+ const GLenum TEXTURE10 = 0x84CA;
+ const GLenum TEXTURE11 = 0x84CB;
+ const GLenum TEXTURE12 = 0x84CC;
+ const GLenum TEXTURE13 = 0x84CD;
+ const GLenum TEXTURE14 = 0x84CE;
+ const GLenum TEXTURE15 = 0x84CF;
+ const GLenum TEXTURE16 = 0x84D0;
+ const GLenum TEXTURE17 = 0x84D1;
+ const GLenum TEXTURE18 = 0x84D2;
+ const GLenum TEXTURE19 = 0x84D3;
+ const GLenum TEXTURE20 = 0x84D4;
+ const GLenum TEXTURE21 = 0x84D5;
+ const GLenum TEXTURE22 = 0x84D6;
+ const GLenum TEXTURE23 = 0x84D7;
+ const GLenum TEXTURE24 = 0x84D8;
+ const GLenum TEXTURE25 = 0x84D9;
+ const GLenum TEXTURE26 = 0x84DA;
+ const GLenum TEXTURE27 = 0x84DB;
+ const GLenum TEXTURE28 = 0x84DC;
+ const GLenum TEXTURE29 = 0x84DD;
+ const GLenum TEXTURE30 = 0x84DE;
+ const GLenum TEXTURE31 = 0x84DF;
+ const GLenum ACTIVE_TEXTURE = 0x84E0;
+
+ // TextureWrapMode
+ const GLenum REPEAT = 0x2901;
+ const GLenum CLAMP_TO_EDGE = 0x812F;
+ const GLenum MIRRORED_REPEAT = 0x8370;
+
+ // Uniform Types
+ const GLenum FLOAT_VEC2 = 0x8B50;
+ const GLenum FLOAT_VEC3 = 0x8B51;
+ const GLenum FLOAT_VEC4 = 0x8B52;
+ const GLenum INT_VEC2 = 0x8B53;
+ const GLenum INT_VEC3 = 0x8B54;
+ const GLenum INT_VEC4 = 0x8B55;
+ const GLenum BOOL = 0x8B56;
+ const GLenum BOOL_VEC2 = 0x8B57;
+ const GLenum BOOL_VEC3 = 0x8B58;
+ const GLenum BOOL_VEC4 = 0x8B59;
+ const GLenum FLOAT_MAT2 = 0x8B5A;
+ const GLenum FLOAT_MAT3 = 0x8B5B;
+ const GLenum FLOAT_MAT4 = 0x8B5C;
+ const GLenum SAMPLER_2D = 0x8B5E;
+ const GLenum SAMPLER_CUBE = 0x8B60;
+
+ // Vertex Arrays
+ const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622;
+ const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623;
+ const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624;
+ const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625;
+ const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A;
+ const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645;
+ const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F;
+
+ // Read Format
+ const GLenum IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A;
+ const GLenum IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B;
+
+ // Shader Source
+ const GLenum COMPILE_STATUS = 0x8B81;
+
+ // Shader Precision-Specified Types
+ const GLenum LOW_FLOAT = 0x8DF0;
+ const GLenum MEDIUM_FLOAT = 0x8DF1;
+ const GLenum HIGH_FLOAT = 0x8DF2;
+ const GLenum LOW_INT = 0x8DF3;
+ const GLenum MEDIUM_INT = 0x8DF4;
+ const GLenum HIGH_INT = 0x8DF5;
+
+ // Framebuffer Object
+ const GLenum FRAMEBUFFER = 0x8D40;
+ const GLenum RENDERBUFFER = 0x8D41;
+
+ const GLenum RGBA4 = 0x8056;
+ const GLenum RGB5_A1 = 0x8057;
+ const GLenum RGB565 = 0x8D62;
+ const GLenum DEPTH_COMPONENT16 = 0x81A5;
+ const GLenum STENCIL_INDEX8 = 0x8D48;
+ const GLenum DEPTH_STENCIL = 0x84F9;
+
+ const GLenum RENDERBUFFER_WIDTH = 0x8D42;
+ const GLenum RENDERBUFFER_HEIGHT = 0x8D43;
+ const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
+ const GLenum RENDERBUFFER_RED_SIZE = 0x8D50;
+ const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51;
+ const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52;
+ const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53;
+ const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54;
+ const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55;
+
+ const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0;
+ const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1;
+ const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2;
+ const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3;
+
+ const GLenum COLOR_ATTACHMENT0 = 0x8CE0;
+ const GLenum DEPTH_ATTACHMENT = 0x8D00;
+ const GLenum STENCIL_ATTACHMENT = 0x8D20;
+ const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A;
+
+ const GLenum NONE = 0;
+
+ const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5;
+ const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6;
+ const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7;
+ const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9;
+ const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD;
+
+ const GLenum FRAMEBUFFER_BINDING = 0x8CA6;
+ const GLenum RENDERBUFFER_BINDING = 0x8CA7;
+ const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8;
+
+ const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506;
+
+ // WebGL-specific enums
+ const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240;
+ const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
+ const GLenum CONTEXT_LOST_WEBGL = 0x9242;
+ const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
+ const GLenum BROWSER_DEFAULT_WEBGL = 0x9244;
+};
diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake
index 2bb2bcc731..b379a86e95 100644
--- a/Userland/Libraries/LibWeb/idl_files.cmake
+++ b/Userland/Libraries/LibWeb/idl_files.cmake
@@ -173,6 +173,7 @@ libweb_js_wrapper(UIEvents/UIEvent)
libweb_js_wrapper(URL/URL)
libweb_js_wrapper(URL/URLSearchParams ITERABLE)
libweb_js_wrapper(WebGL/WebGLContextEvent)
+libweb_js_wrapper(WebGL/WebGLRenderingContext)
libweb_js_wrapper(WebSockets/WebSocket)
libweb_js_wrapper(XHR/ProgressEvent)
libweb_js_wrapper(XHR/XMLHttpRequest)