diff --git a/AK/Debug.h.in b/AK/Debug.h.in
index 3002950e8ca..ff5416e4e0e 100644
--- a/AK/Debug.h.in
+++ b/AK/Debug.h.in
@@ -478,6 +478,10 @@
#cmakedefine01 WASM_VALIDATOR_DEBUG
#endif
+#ifndef WEBGL_CONTEXT_DEBUG
+#cmakedefine01 WEBGL_CONTEXT_DEBUG
+#endif
+
#ifndef WEBSERVER_DEBUG
#cmakedefine01 WEBSERVER_DEBUG
#endif
diff --git a/Base/res/html/misc/webgl-clear-color-and-multiple-contexts.html b/Base/res/html/misc/webgl-clear-color-and-multiple-contexts.html
new file mode 100644
index 00000000000..6855126558e
--- /dev/null
+++ b/Base/res/html/misc/webgl-clear-color-and-multiple-contexts.html
@@ -0,0 +1,34 @@
+
+
+
+ WebGL Demo - Multiple Contexts and glClear(Color)
+
+
+
+ WebGL Demo - Multiple Contexts and glClear(Color)
+
+
+
+
+
+
diff --git a/Base/res/html/misc/welcome.html b/Base/res/html/misc/welcome.html
index 65a648f736d..e1aafcd06f5 100644
--- a/Base/res/html/misc/welcome.html
+++ b/Base/res/html/misc/welcome.html
@@ -176,6 +176,7 @@
canvas drawImage() test
canvas path house!
canvas + trigonometry functions
+ WebGL Demo - Multiple Contexts and glClear(Color)
Wasm
WebAssembly Mandelbrot Rendering Demo
WebAssembly Game Of Life Demo
diff --git a/Meta/CMake/all_the_debug_macros.cmake b/Meta/CMake/all_the_debug_macros.cmake
index 7f49df762fd..098ca14ecfb 100644
--- a/Meta/CMake/all_the_debug_macros.cmake
+++ b/Meta/CMake/all_the_debug_macros.cmake
@@ -207,6 +207,7 @@ set(WAITQUEUE_DEBUG ON)
set(WASM_BINPARSER_DEBUG ON)
set(WASM_TRACE_DEBUG ON)
set(WASM_VALIDATOR_DEBUG ON)
+set(WEBGL_CONTEXT_DEBUG ON)
set(WEBSERVER_DEBUG ON)
set(WEB_WORKER_DEBUG ON)
set(WINDOWMANAGER_DEBUG ON)
diff --git a/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp b/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp
index 3464f136b10..6699673f315 100644
--- a/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp
+++ b/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp
@@ -35,8 +35,11 @@ void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const
if (!context.viewport_rect().intersects(enclosing_int_rect(absolute_rect())))
return;
- if (layout_box().dom_node().bitmap())
+ if (layout_box().dom_node().bitmap()) {
+ // FIXME: Remove this const_cast.
+ const_cast(layout_box().dom_node()).present();
context.painter().draw_scaled_bitmap(absolute_rect().to_rounded(), *layout_box().dom_node().bitmap(), layout_box().dom_node().bitmap()->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
+ }
}
}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp
index 774cc6adcb4..e03faa92ef6 100644
--- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
+#include
#include
#include
#include
@@ -20,4 +21,75 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(HTML::HTMLCanvasElement& ca
WebGLRenderingContextBase::~WebGLRenderingContextBase() = default;
+void WebGLRenderingContextBase::present()
+{
+ if (!m_should_present)
+ return;
+
+ m_should_present = false;
+
+ // "Before the drawing buffer is presented for compositing the implementation shall ensure that all rendering operations have been flushed to the drawing buffer."
+ // FIXME: Is this the operation it means?
+ m_context->gl_flush();
+
+ m_context->present();
+
+ // "By default, after compositing the contents of the drawing buffer shall be cleared to their default values, as shown in the table above.
+ // This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object.
+ // If this flag is true, the contents of the drawing buffer shall be preserved until the author either clears or overwrites them."
+ if (!m_context_creation_parameters.preserve_drawing_buffer) {
+ auto current_clear_color = m_context->current_clear_color();
+ auto current_clear_depth = m_context->current_clear_depth();
+ auto current_clear_stencil = m_context->current_clear_stencil();
+
+ // The implicit clear value for the color buffer is (0, 0, 0, 0)
+ m_context->gl_clear_color(0, 0, 0, 0);
+
+ // The implicit clear value for the depth buffer is 1.0.
+ m_context->gl_clear_depth(1.0);
+
+ // The implicit clear value for the stencil buffer is 0.
+ m_context->gl_clear_stencil(0);
+
+ m_context->gl_clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ // Restore the clear values.
+ m_context->gl_clear_color(current_clear_color[0], current_clear_color[1], current_clear_color[2], current_clear_color[3]);
+ m_context->gl_clear_depth(current_clear_depth);
+ m_context->gl_clear_stencil(current_clear_stencil);
+ }
+}
+
+void WebGLRenderingContextBase::needs_to_present()
+{
+ m_should_present = true;
+
+ if (!m_canvas_element)
+ return;
+ if (!m_canvas_element->layout_node())
+ return;
+ m_canvas_element->layout_node()->set_needs_display();
+}
+
+void WebGLRenderingContextBase::clear(GLbitfield mask)
+{
+ if (m_context_lost)
+ return;
+
+ dbgln_if(WEBGL_CONTEXT_DEBUG, "WebGLRenderingContextBase::clear(mask=0x{:08x})", mask);
+ m_context->gl_clear(mask);
+
+ // FIXME: This should only be done if this is targeting the front buffer.
+ needs_to_present();
+}
+
+void WebGLRenderingContextBase::clear_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ if (m_context_lost)
+ return;
+
+ dbgln_if(WEBGL_CONTEXT_DEBUG, "WebGLRenderingContextBase::clear_color(red={}, green={}, blue={}, alpha={})", red, green, blue, alpha);
+ m_context->gl_clear_color(red, green, blue, alpha);
+}
+
}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h
index 70ba19978ea..3e03e61d3bb 100644
--- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h
@@ -21,6 +21,11 @@ class WebGLRenderingContextBase
public:
virtual ~WebGLRenderingContextBase();
+ void present();
+
+ void clear(GLbitfield mask);
+ void clear_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+
protected:
WebGLRenderingContextBase(HTML::HTMLCanvasElement& canvas_element, NonnullOwnPtr context, WebGLContextAttributes context_creation_parameters, WebGLContextAttributes actual_context_parameters);
@@ -46,6 +51,8 @@ private:
// - Canvas resize
// - clear, drawArrays, or drawElements has been called while the drawing buffer is the currently bound framebuffer
bool m_should_present { true };
+
+ void needs_to_present();
};
}
diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl
index b88f38acdb0..a2bb454da12 100644
--- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl
+++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.idl
@@ -13,6 +13,14 @@ dictionary WebGLContextAttributes {
};
interface mixin WebGLRenderingContextBase {
+ // NOTE: Functions that have the [WebGLHandlesContextLoss] extended attribute in the spec do not have them here.
+ // This is because context loss is handled manually on a function by function basis instead of having to add it to the
+ // IDL code generator. This also allows us to handle the return type ourselves instead of adding the complexity of the
+ // code generator working out the return type and returning the appropriate value to return on context loss.
+
+ undefined clear(GLbitfield mask);
+ undefined clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+
// Enums
// ClearBufferMask
const GLenum DEPTH_BUFFER_BIT = 0x00000100;