LibWeb/WebGL2: Implement bufferData with offset and length

This commit is contained in:
Luke Wilde 2024-12-16 19:22:41 +00:00 committed by Alexander Kalenik
commit 18ea91715b
Notes: github-actions[bot] 2025-01-08 15:01:00 +00:00
4 changed files with 45 additions and 1 deletions

View file

@ -10,7 +10,7 @@ interface mixin WebGL2RenderingContextOverloads {
undefined bufferData(GLenum target, BufferSource? srcData, GLenum usage); undefined bufferData(GLenum target, BufferSource? srcData, GLenum usage);
undefined bufferSubData(GLenum target, GLintptr dstByteOffset, BufferSource srcData); undefined bufferSubData(GLenum target, GLintptr dstByteOffset, BufferSource srcData);
// WebGL2: // 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); [FIXME] undefined bufferSubData(GLenum target, GLintptr dstByteOffset, [AllowShared] ArrayBufferView srcData, unsigned long long srcOffset, optional GLuint length = 0);
// WebGL1 legacy entrypoints: // WebGL1 legacy entrypoints:

View file

@ -29,6 +29,21 @@ u32 BufferableObjectBase::byte_length() const
[](GC::Ref<JS::ArrayBuffer> array_buffer) { return static_cast<u32>(array_buffer->byte_length()); }); [](GC::Ref<JS::ArrayBuffer> array_buffer) { return static_cast<u32>(array_buffer->byte_length()); });
} }
u32 BufferableObjectBase::element_size() const
{
return m_bufferable_object.visit(
[](GC::Ref<JS::TypedArrayBase> 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<JS::DataView>) -> u32 {
return 1;
},
[](GC::Ref<JS::ArrayBuffer>) -> u32 {
return 1;
});
}
GC::Ref<JS::Object> BufferableObjectBase::raw_object() GC::Ref<JS::Object> BufferableObjectBase::raw_object()
{ {
return m_bufferable_object.visit([](auto const& obj) -> GC::Ref<JS::Object> { return obj; }); return m_bufferable_object.visit([](auto const& obj) -> GC::Ref<JS::Object> { return obj; });

View file

@ -27,6 +27,7 @@ public:
virtual ~BufferableObjectBase() override = default; virtual ~BufferableObjectBase() override = default;
u32 byte_length() const; u32 byte_length() const;
u32 element_size() const;
GC::Ref<JS::Object> raw_object(); GC::Ref<JS::Object> raw_object();
GC::Ref<JS::Object const> raw_object() const { return const_cast<BufferableObjectBase&>(*this).raw_object(); } GC::Ref<JS::Object const> raw_object() const { return const_cast<BufferableObjectBase&>(*this).raw_object(); }

View file

@ -802,6 +802,34 @@ public:
continue; 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) { if (function.name == "readPixels"sv) {
function_impl_generator.append(R"~~~( function_impl_generator.append(R"~~~(
if (!pixels) { if (!pixels) {