diff --git a/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp b/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp index 32a82000097..1b254771d5f 100644 --- a/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp +++ b/Libraries/LibWeb/WebGL/WebGL2RenderingContext.cpp @@ -69,6 +69,7 @@ void WebGL2RenderingContext::initialize(JS::Realm& realm) void WebGL2RenderingContext::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + WebGL2RenderingContextImpl::visit_edges(visitor); visitor.visit(m_canvas_element); } diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp b/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp index 7a0c8937867..689db38d530 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp @@ -86,6 +86,7 @@ void WebGLRenderingContext::initialize(JS::Realm& realm) void WebGLRenderingContext::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); + WebGLRenderingContextImpl::visit_edges(visitor); visitor.visit(m_canvas_element); } diff --git a/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h b/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h index 644199a9a17..69d6d49ee91 100644 --- a/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h +++ b/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.h @@ -13,6 +13,7 @@ namespace Web::WebGL { class WebGLRenderingContextBase { public: virtual GC::Cell const* gc_cell() const = 0; + virtual void visit_edges(JS::Cell::Visitor&) = 0; }; } diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp index 4b4f172f562..1d04dfcc9cb 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp @@ -240,12 +240,11 @@ static void generate_get_parameter(SourceGenerator& generator, int webgl_version return JS::@type_name@::create(m_realm, @element_count@, array_buffer); )~~~"); } else if (type_name == "WebGLProgram"sv || type_name == "WebGLBuffer"sv || type_name == "WebGLTexture"sv || type_name == "WebGLFramebuffer"sv || type_name == "WebGLRenderbuffer"sv) { + impl_generator.set("stored_name", name_and_type.name.to_lowercase_string()); impl_generator.append(R"~~~( - GLint result; - glGetIntegerv(GL_@parameter_name@, &result); - if (!result) + if (!m_@stored_name@) return JS::js_null(); - return @type_name@::create(m_realm, *this, result); + return JS::Value(m_@stored_name@); )~~~"); } else { VERIFY_NOT_REACHED(); @@ -1206,6 +1205,122 @@ public: continue; } + if (function.name == "bindBuffer"sv) { + // FIXME: Implement Buffer Object Binding restrictions. + generate_webgl_object_handle_unwrap(function_impl_generator, "buffer"sv, ""sv); + function_impl_generator.append(R"~~~( + switch (target) { + case GL_ELEMENT_ARRAY_BUFFER: + m_element_array_buffer_binding = buffer; + break; + case GL_ARRAY_BUFFER: + m_array_buffer_binding = buffer; + break; +)~~~"); + + if (webgl_version == 2) { + function_impl_generator.append(R"~~~( + case GL_UNIFORM_BUFFER: + m_uniform_buffer_binding = buffer; + break; + case GL_COPY_READ_BUFFER: + m_copy_read_buffer_binding = buffer; + break; + case GL_COPY_WRITE_BUFFER: + m_copy_write_buffer_binding = buffer; + break; +)~~~"); + } + + function_impl_generator.append(R"~~~( + default: + dbgln("Unknown WebGL buffer object binding target for storing current binding: 0x{:04x}", target); + set_error(GL_INVALID_ENUM); + return; + } + + glBindBuffer(target, buffer_handle); +)~~~"); + continue; + } + + if (function.name == "useProgram"sv) { + generate_webgl_object_handle_unwrap(function_impl_generator, "program"sv, ""sv); + function_impl_generator.append(R"~~~( + glUseProgram(program_handle); + m_current_program = program; +)~~~"); + continue; + } + + if (function.name == "bindFramebuffer"sv) { + generate_webgl_object_handle_unwrap(function_impl_generator, "framebuffer"sv, ""sv); + function_impl_generator.append(R"~~~( + glBindFramebuffer(target, framebuffer_handle); + m_framebuffer_binding = framebuffer; +)~~~"); + continue; + } + + if (function.name == "bindRenderbuffer"sv) { + generate_webgl_object_handle_unwrap(function_impl_generator, "renderbuffer"sv, ""sv); + function_impl_generator.append(R"~~~( + glBindRenderbuffer(target, renderbuffer_handle); + m_renderbuffer_binding = renderbuffer; +)~~~"); + continue; + } + + if (function.name == "bindTexture"sv) { + generate_webgl_object_handle_unwrap(function_impl_generator, "texture"sv, ""sv); + function_impl_generator.append(R"~~~( + switch (target) { + case GL_TEXTURE_2D: + m_texture_binding_2d = texture; + break; + case GL_TEXTURE_CUBE_MAP: + m_texture_binding_cube_map = texture; + break; +)~~~"); + + if (webgl_version == 2) { + function_impl_generator.append(R"~~~( + case GL_TEXTURE_2D_ARRAY: + m_texture_binding_2d_array = texture; + break; + case GL_TEXTURE_3D: + m_texture_binding_3d = texture; + break; +)~~~"); + } + + function_impl_generator.append(R"~~~( + default: + dbgln("Unknown WebGL texture target for storing current binding: 0x{:04x}", target); + set_error(GL_INVALID_ENUM); + return; + } + glBindTexture(target, texture_handle); +)~~~"); + continue; + } + + if (function.name == "renderbufferStorage"sv) { + // To be backward compatible with WebGL 1, also accepts internal format DEPTH_STENCIL, which should be + // mapped to DEPTH24_STENCIL8 by implementations. + if (webgl_version == 2) { + function_impl_generator.append(R"~~~( + if (internalformat == GL_DEPTH_STENCIL) + internalformat = GL_DEPTH24_STENCIL8; +)~~~"); + } + + function_impl_generator.append(R"~~~( + glRenderbufferStorage(target, internalformat, width, height); +)~~~"); + continue; + } + Vector gl_call_arguments; for (size_t i = 0; i < function.parameters.size(); ++i) { auto const& parameter = function.parameters[i]; @@ -1309,8 +1424,31 @@ public: } header_file_generator.append(R"~~~( +protected: + virtual void visit_edges(JS::Cell::Visitor&) override; + private: GC::Ref m_realm; + GC::Ptr m_array_buffer_binding; + GC::Ptr m_element_array_buffer_binding; + GC::Ptr m_current_program; + GC::Ptr m_framebuffer_binding; + GC::Ptr m_renderbuffer_binding; + GC::Ptr m_texture_binding_2d; + GC::Ptr m_texture_binding_cube_map; +)~~~"); + + if (webgl_version == 2) { + header_file_generator.append(R"~~~( + GC::Ptr m_uniform_buffer_binding; + GC::Ptr m_copy_read_buffer_binding; + GC::Ptr m_copy_write_buffer_binding; + GC::Ptr m_texture_binding_2d_array; + GC::Ptr m_texture_binding_3d; +)~~~"); + } + + header_file_generator.append(R"~~~( NonnullOwnPtr m_context; }; @@ -1318,6 +1456,31 @@ private: )~~~"); implementation_file_generator.append(R"~~~( +void @class_name@::visit_edges(JS::Cell::Visitor& visitor) +{ + visitor.visit(m_realm); + visitor.visit(m_array_buffer_binding); + visitor.visit(m_element_array_buffer_binding); + visitor.visit(m_current_program); + visitor.visit(m_framebuffer_binding); + visitor.visit(m_renderbuffer_binding); + visitor.visit(m_texture_binding_2d); + visitor.visit(m_texture_binding_cube_map); +)~~~"); + + if (webgl_version == 2) { + implementation_file_generator.append(R"~~~( + visitor.visit(m_uniform_buffer_binding); + visitor.visit(m_copy_read_buffer_binding); + visitor.visit(m_copy_write_buffer_binding); + visitor.visit(m_texture_binding_2d_array); + visitor.visit(m_texture_binding_3d); +)~~~"); + } + + implementation_file_generator.append(R"~~~( +} + } )~~~");