LibWeb: Add ability to present LibGL framebuffer and add clearing

This commit is contained in:
Luke Wilde 2022-06-04 04:27:48 +01:00 committed by Linus Groh
parent 68d9d4e247
commit 076c9772a4
8 changed files with 131 additions and 1 deletions

View file

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

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>WebGL Demo - Multiple Contexts and glClear(Color)</title>
<style>
.border {
border: 1px solid black;
}
</style>
</head>
<body>
<h1>WebGL Demo - Multiple Contexts and glClear(Color)</h1>
<canvas id="webgl-canvas1" class="border"></canvas>
<canvas id="webgl-canvas2" class="border"></canvas>
<script>
"use strict";
const canvas1 = document.getElementById("webgl-canvas1");
const webglContext1 = canvas1.getContext("webgl");
const canvas2 = document.getElementById("webgl-canvas2");
const webglContext2 = canvas2.getContext("webgl");
function clearWithRandomColor() {
webglContext1.clearColor(Math.random(), Math.random(), Math.random(), Math.random());
webglContext1.clear(webglContext1.COLOR_BUFFER_BIT);
webglContext2.clearColor(Math.random(), Math.random(), Math.random(), Math.random());
webglContext2.clear(webglContext2.COLOR_BUFFER_BIT);
}
clearWithRandomColor();
setInterval(clearWithRandomColor, 1000);
</script>
</body>
</html>

View file

@ -176,6 +176,7 @@
<li><a href="img-canvas.html">canvas drawImage() test</a></li>
<li><a href="canvas-path.html">canvas path house!</a></li>
<li><a href="trigonometry.html">canvas + trigonometry functions</a></li>
<li><a href="webgl-clear-color-and-multiple-contexts.html">WebGL Demo - Multiple Contexts and glClear(Color)</a></li>
<li><h3>Wasm</h3></li>
<li><a href="mandelbrot-wasm.html">WebAssembly Mandelbrot Rendering Demo</a></li>
<li><a href="gol-wasm.html">WebAssembly Game Of Life Demo</a></li>

View file

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

View file

@ -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<HTML::HTMLCanvasElement&>(layout_box().dom_node()).present();
context.painter().draw_scaled_bitmap(absolute_rect().to_rounded<int>(), *layout_box().dom_node().bitmap(), layout_box().dom_node().bitmap()->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
}
}
}

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Debug.h>
#include <LibGL/GLContext.h>
#include <LibWeb/HTML/HTMLCanvasElement.h>
#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
@ -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);
}
}

View file

@ -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<GL::GLContext> 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();
};
}

View file

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