diff --git a/Libraries/LibWeb/WebGL/WebGL2RenderingContextOverloads.idl b/Libraries/LibWeb/WebGL/WebGL2RenderingContextOverloads.idl index 37da23a1da4..cfba80deca4 100644 --- a/Libraries/LibWeb/WebGL/WebGL2RenderingContextOverloads.idl +++ b/Libraries/LibWeb/WebGL/WebGL2RenderingContextOverloads.idl @@ -10,7 +10,7 @@ interface mixin WebGL2RenderingContextOverloads { undefined bufferData(GLenum target, BufferSource? srcData, GLenum usage); undefined bufferSubData(GLenum target, GLintptr dstByteOffset, BufferSource srcData); // WebGL2: - [FIXME] undefined bufferData(GLenum target, [AllowShared] ArrayBufferView srcData, GLenum usage, unsigned long long srcOffset, optional GLuint length = 0); + undefined bufferData(GLenum target, [AllowShared] ArrayBufferView srcData, GLenum usage, unsigned long long srcOffset, optional GLuint length = 0); [FIXME] undefined bufferSubData(GLenum target, GLintptr dstByteOffset, [AllowShared] ArrayBufferView srcData, unsigned long long srcOffset, optional GLuint length = 0); // WebGL1 legacy entrypoints: diff --git a/Libraries/LibWeb/WebIDL/Buffers.cpp b/Libraries/LibWeb/WebIDL/Buffers.cpp index 94477be5638..272b241c911 100644 --- a/Libraries/LibWeb/WebIDL/Buffers.cpp +++ b/Libraries/LibWeb/WebIDL/Buffers.cpp @@ -29,6 +29,21 @@ u32 BufferableObjectBase::byte_length() const [](GC::Ref array_buffer) { return static_cast(array_buffer->byte_length()); }); } +u32 BufferableObjectBase::element_size() const +{ + return m_bufferable_object.visit( + [](GC::Ref typed_array) -> u32 { + auto typed_array_record = JS::make_typed_array_with_buffer_witness_record(typed_array, JS::ArrayBuffer::Order::SeqCst); + return typed_array_record.object->element_size(); + }, + [](GC::Ref) -> u32 { + return 1; + }, + [](GC::Ref) -> u32 { + return 1; + }); +} + GC::Ref BufferableObjectBase::raw_object() { return m_bufferable_object.visit([](auto const& obj) -> GC::Ref { return obj; }); diff --git a/Libraries/LibWeb/WebIDL/Buffers.h b/Libraries/LibWeb/WebIDL/Buffers.h index 10df7ea44f1..f9018f2e33a 100644 --- a/Libraries/LibWeb/WebIDL/Buffers.h +++ b/Libraries/LibWeb/WebIDL/Buffers.h @@ -27,6 +27,7 @@ public: virtual ~BufferableObjectBase() override = default; u32 byte_length() const; + u32 element_size() const; GC::Ref raw_object(); GC::Ref raw_object() const { return const_cast(*this).raw_object(); } diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp index 9741df363ff..f68816d3912 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWebGLRenderingContext.cpp @@ -802,6 +802,34 @@ public: continue; } + if (webgl_version == 2 && function.name == "bufferData"sv && function.overload_index == 2) { + function_impl_generator.append(R"~~~( + VERIFY(src_data); + auto const& viewed_array_buffer = src_data->viewed_array_buffer(); + auto const& byte_buffer = viewed_array_buffer->buffer(); + auto src_data_length = src_data->byte_length(); + auto src_data_element_size = src_data->element_size(); + u8 const* buffer_ptr = byte_buffer.data(); + + u64 copy_length = length == 0 ? src_data_length - src_offset : length; + copy_length *= src_data_element_size; + + if (src_offset > src_data_length) { + set_error(GL_INVALID_VALUE); + return; + } + + if (src_offset + copy_length > src_data_length) { + set_error(GL_INVALID_VALUE); + return; + } + + buffer_ptr += src_offset * src_data_element_size; + glBufferData(target, copy_length, buffer_ptr, usage); +)~~~"); + continue; + } + if (function.name == "readPixels"sv) { function_impl_generator.append(R"~~~( if (!pixels) {