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;