LibWeb's WebGL implementation currently reaches ANGLE by calling glFoo() throughout the WebGL context and extension code. That ties the WebGL spec layer to the concrete GL executor. A future backend that records operations, sends them to another process, or executes them from the Compositor would otherwise need to duplicate the WebGL logic or edit every call site again. Introduce GLFunctions as an explicit boundary between WebGL semantics and GL execution. GLFunctions.json lists the GL entry points used by the implementation, and the generator emits one forwarding method per entry point. OpenGLContext implements those methods today, so the current in-process ANGLE path keeps the same behavior while all callers go through a single replaceable interface. That boundary is needed before canvas/WebGL rendering can move to the Compositor: the WebGL context code can keep doing validation, state tracking, and spec-visible error handling in LibWeb, while a later implementation can record the same GL calls and replay them where the canvas surface is produced. The JSON source also gives the recorder and replayer one shared description of argument shapes, avoiding two hand-written views of the GL API drifting apart.
104 lines
3 KiB
C++
104 lines
3 KiB
C++
/*
|
|
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibJS/Runtime/Realm.h>
|
|
#include <LibWeb/Bindings/Intrinsics.h>
|
|
#include <LibWeb/Bindings/OESVertexArrayObject.h>
|
|
#include <LibWeb/WebGL/Extensions/OESVertexArrayObject.h>
|
|
#include <LibWeb/WebGL/Extensions/WebGLVertexArrayObjectOES.h>
|
|
#include <LibWeb/WebGL/OpenGLContext.h>
|
|
#include <LibWeb/WebGL/WebGLRenderingContextBase.h>
|
|
|
|
#include <GLES2/gl2.h>
|
|
#include <GLES2/gl2ext.h>
|
|
|
|
namespace Web::WebGL {
|
|
|
|
GC_DEFINE_ALLOCATOR(OESVertexArrayObject);
|
|
|
|
JS::ThrowCompletionOr<GC::Ref<JS::Object>> OESVertexArrayObject::create(JS::Realm& realm, GC::Ref<WebGLRenderingContextBase> context)
|
|
{
|
|
return realm.create<OESVertexArrayObject>(realm, context);
|
|
}
|
|
|
|
OESVertexArrayObject::OESVertexArrayObject(JS::Realm& realm, GC::Ref<WebGLRenderingContextBase> context)
|
|
: PlatformObject(realm)
|
|
, m_context(context)
|
|
{
|
|
}
|
|
|
|
GC::Ref<WebGLVertexArrayObjectOES> OESVertexArrayObject::create_vertex_array_oes()
|
|
{
|
|
m_context->context().make_current();
|
|
|
|
GLuint handle = 0;
|
|
m_context->context().gen_vertex_arrays_oes(1, &handle);
|
|
return WebGLVertexArrayObjectOES::create(realm(), m_context, handle);
|
|
}
|
|
|
|
void OESVertexArrayObject::delete_vertex_array_oes(GC::Ptr<WebGLVertexArrayObjectOES> array_object)
|
|
{
|
|
m_context->context().make_current();
|
|
|
|
GLuint vertex_array_handle = 0;
|
|
if (array_object) {
|
|
auto handle_or_error = array_object->handle(m_context.ptr());
|
|
if (handle_or_error.is_error()) {
|
|
// FIXME: m_context->set_error(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
vertex_array_handle = handle_or_error.release_value();
|
|
}
|
|
|
|
m_context->context().delete_vertex_arrays_oes(1, &vertex_array_handle);
|
|
}
|
|
|
|
bool OESVertexArrayObject::is_vertex_array_oes(GC::Ptr<WebGLVertexArrayObjectOES> array_object)
|
|
{
|
|
m_context->context().make_current();
|
|
|
|
GLuint vertex_array_handle = 0;
|
|
if (array_object) {
|
|
auto handle_or_error = array_object->handle(m_context.ptr());
|
|
if (handle_or_error.is_error()) {
|
|
return false;
|
|
}
|
|
vertex_array_handle = handle_or_error.release_value();
|
|
}
|
|
|
|
return m_context->context().is_vertex_array_oes(vertex_array_handle) == GL_TRUE;
|
|
}
|
|
|
|
void OESVertexArrayObject::bind_vertex_array_oes(GC::Ptr<WebGLVertexArrayObjectOES> array_object)
|
|
{
|
|
m_context->context().make_current();
|
|
|
|
GLuint vertex_array_handle = 0;
|
|
if (array_object) {
|
|
auto handle_or_error = array_object->handle(m_context.ptr());
|
|
if (handle_or_error.is_error()) {
|
|
// FIXME: m_context->set_error(GL_INVALID_OPERATION);
|
|
return;
|
|
}
|
|
vertex_array_handle = handle_or_error.release_value();
|
|
}
|
|
|
|
m_context->context().bind_vertex_array_oes(vertex_array_handle);
|
|
}
|
|
|
|
void OESVertexArrayObject::initialize(JS::Realm& realm)
|
|
{
|
|
WEB_SET_PROTOTYPE_FOR_INTERFACE(OESVertexArrayObject);
|
|
Base::initialize(realm);
|
|
}
|
|
|
|
void OESVertexArrayObject::visit_edges(Visitor& visitor)
|
|
{
|
|
Base::visit_edges(visitor);
|
|
visitor.visit(m_context);
|
|
}
|
|
|
|
}
|