@@ -68,6 +68,58 @@ void WebGL2RenderingContextImpl::copy_buffer_sub_data(WebIDL::UnsignedLong read_
6868 glCopyBufferSubData (read_target, write_target, read_offset, write_offset, size);
6969}
7070
71+ // https://registry.khronos.org/webgl/specs/latest/2.0/#3.7.3
72+ void WebGL2RenderingContextImpl::get_buffer_sub_data (WebIDL::UnsignedLong target, WebIDL::LongLong src_byte_offset,
73+ GC::Root<WebIDL::ArrayBufferView> dst_buffer, WebIDL::UnsignedLongLong dst_offset, WebIDL::UnsignedLong length)
74+ {
75+ // If dstBuffer is a DataView, let elementSize be 1; otherwise, let elementSize be dstBuffer.BYTES_PER_ELEMENT.
76+ size_t element_size = dst_buffer->element_size ();
77+
78+ // If length is 0:
79+ size_t copy_length;
80+ if (length == 0 ) {
81+ // If dstBuffer is a DataView, let copyLength be dstBuffer.byteLength - dstOffset; the typed elements in the
82+ // text below are bytes. Otherwise, let copyLength be dstBuffer.length - dstOffset.
83+ copy_length = dst_buffer->byte_length () / element_size - dst_offset;
84+ }
85+
86+ // Otherwise, let copyLength be length.
87+ else {
88+ copy_length = length;
89+ }
90+
91+ // If copyLength is 0, no data is written to dstBuffer, but this does not cause a GL error to be generated.
92+ if (copy_length == 0 )
93+ return ;
94+
95+ // If dstOffset is greater than dstBuffer.length (or dstBuffer.byteLength in the case of DataView), generates an
96+ // INVALID_VALUE error.
97+ size_t dst_offset_in_bytes = dst_offset * element_size;
98+ if (dst_offset_in_bytes > dst_buffer->byte_length ()) {
99+ set_error (GL_INVALID_VALUE);
100+ return ;
101+ }
102+
103+ // If dstOffset + copyLength is greater than dstBuffer.length (or dstBuffer.byteLength in the case of DataView),
104+ // generates an INVALID_VALUE error.
105+ size_t copy_bytes = copy_length * element_size;
106+ if (dst_offset_in_bytes + copy_bytes > dst_buffer->byte_length ()) {
107+ set_error (GL_INVALID_VALUE);
108+ return ;
109+ }
110+
111+ // If copyLength is greater than zero, copy copyLength typed elements (each of size elementSize) from buf into
112+ // dstBuffer, reading buf starting at byte index srcByteOffset and writing into dstBuffer starting at element
113+ // index dstOffset.
114+ auto * buffer_data = glMapBufferRange (target, src_byte_offset, copy_bytes, GL_MAP_READ_BIT);
115+ if (!buffer_data)
116+ return ;
117+
118+ dst_buffer->write ({ buffer_data, copy_bytes }, dst_offset_in_bytes);
119+
120+ glUnmapBuffer (target);
121+ }
122+
71123void WebGL2RenderingContextImpl::blit_framebuffer (WebIDL::Long src_x0, WebIDL::Long src_y0, WebIDL::Long src_x1, WebIDL::Long src_y1, WebIDL::Long dst_x0, WebIDL::Long dst_y0, WebIDL::Long dst_x1, WebIDL::Long dst_y1, WebIDL::UnsignedLong mask, WebIDL::UnsignedLong filter)
72124{
73125 m_context->make_current ();
0 commit comments