mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
LibWeb: Add ability to present LibGL framebuffer and add clearing
This commit is contained in:
parent
68d9d4e247
commit
076c9772a4
Notes:
sideshowbarker
2024-07-17 10:16:03 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/076c9772a4 Pull-request: https://github.com/SerenityOS/serenity/pull/14184 Reviewed-by: https://github.com/Quaker762 ✅ Reviewed-by: https://github.com/gmta ✅ Reviewed-by: https://github.com/linusg ✅ Reviewed-by: https://github.com/sunverwerth
8 changed files with 131 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue