LibWeb: Bind WebGL uniform locations to their respective program

The spec mandates that each uniform location object only gets used with
the program it was created with.
This commit is contained in:
Undefine 2025-11-07 18:36:12 +01:00 committed by Jelle Raaijmakers
parent 7d6212ae71
commit f373ab7011
Notes: github-actions[bot] 2025-11-27 18:21:14 +00:00
6 changed files with 209 additions and 51 deletions

View file

@ -229,25 +229,45 @@ void WebGL2RenderingContextImpl::tex_sub_image3d(WebIDL::UnsignedLong target, We
void WebGL2RenderingContextImpl::uniform1ui(GC::Root<WebGLUniformLocation> location, WebIDL::UnsignedLong v0)
{
m_context->make_current();
glUniform1ui(location ? location->handle() : 0, v0);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform1ui(location_handle, v0);
}
void WebGL2RenderingContextImpl::uniform2ui(GC::Root<WebGLUniformLocation> location, WebIDL::UnsignedLong v0, WebIDL::UnsignedLong v1)
{
m_context->make_current();
glUniform2ui(location ? location->handle() : 0, v0, v1);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform2ui(location_handle, v0, v1);
}
void WebGL2RenderingContextImpl::uniform3ui(GC::Root<WebGLUniformLocation> location, WebIDL::UnsignedLong v0, WebIDL::UnsignedLong v1, WebIDL::UnsignedLong v2)
{
m_context->make_current();
glUniform3ui(location ? location->handle() : 0, v0, v1, v2);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform3ui(location_handle, v0, v1, v2);
}
void WebGL2RenderingContextImpl::uniform4ui(GC::Root<WebGLUniformLocation> location, WebIDL::UnsignedLong v0, WebIDL::UnsignedLong v1, WebIDL::UnsignedLong v2, WebIDL::UnsignedLong v3)
{
m_context->make_current();
glUniform4ui(location ? location->handle() : 0, v0, v1, v2, v3);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform4ui(location_handle, v0, v1, v2, v3);
}
void WebGL2RenderingContextImpl::uniform1uiv(GC::Root<WebGLUniformLocation> location, Uint32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -257,8 +277,10 @@ void WebGL2RenderingContextImpl::uniform1uiv(GC::Root<WebGLUniformLocation> loca
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_uint32_list(values, src_offset, src_length), GL_INVALID_VALUE);
glUniform1uiv(location->handle(), span.size(), span.data());
glUniform1uiv(location_handle, span.size(), span.data());
}
void WebGL2RenderingContextImpl::uniform2uiv(GC::Root<WebGLUniformLocation> location, Uint32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -268,12 +290,14 @@ void WebGL2RenderingContextImpl::uniform2uiv(GC::Root<WebGLUniformLocation> loca
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_uint32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 2 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform2uiv(location->handle(), span.size() / 2, span.data());
glUniform2uiv(location_handle, span.size() / 2, span.data());
}
void WebGL2RenderingContextImpl::uniform3uiv(GC::Root<WebGLUniformLocation> location, Uint32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -283,12 +307,14 @@ void WebGL2RenderingContextImpl::uniform3uiv(GC::Root<WebGLUniformLocation> loca
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_uint32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 3 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform3uiv(location->handle(), span.size() / 3, span.data());
glUniform3uiv(location_handle, span.size() / 3, span.data());
}
void WebGL2RenderingContextImpl::uniform4uiv(GC::Root<WebGLUniformLocation> location, Uint32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -298,12 +324,14 @@ void WebGL2RenderingContextImpl::uniform4uiv(GC::Root<WebGLUniformLocation> loca
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_uint32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 4 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform4uiv(location->handle(), span.size() / 4, span.data());
glUniform4uiv(location_handle, span.size() / 4, span.data());
}
void WebGL2RenderingContextImpl::uniform_matrix3x2fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -313,13 +341,15 @@ void WebGL2RenderingContextImpl::uniform_matrix3x2fv(GC::Root<WebGLUniformLocati
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 3 * 2;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix3x2fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix3x2fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextImpl::uniform_matrix4x2fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -329,13 +359,15 @@ void WebGL2RenderingContextImpl::uniform_matrix4x2fv(GC::Root<WebGLUniformLocati
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 4 * 2;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix4x2fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix4x2fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextImpl::uniform_matrix2x3fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -345,13 +377,15 @@ void WebGL2RenderingContextImpl::uniform_matrix2x3fv(GC::Root<WebGLUniformLocati
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 2 * 3;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix2x3fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix2x3fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextImpl::uniform_matrix4x3fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -361,13 +395,15 @@ void WebGL2RenderingContextImpl::uniform_matrix4x3fv(GC::Root<WebGLUniformLocati
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 4 * 3;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix4x3fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix4x3fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextImpl::uniform_matrix2x4fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -377,13 +413,15 @@ void WebGL2RenderingContextImpl::uniform_matrix2x4fv(GC::Root<WebGLUniformLocati
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 2 * 4;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix2x4fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix2x4fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextImpl::uniform_matrix3x4fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -393,13 +431,15 @@ void WebGL2RenderingContextImpl::uniform_matrix3x4fv(GC::Root<WebGLUniformLocati
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 3 * 4;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix3x4fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix3x4fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextImpl::vertex_attrib_i4i(WebIDL::UnsignedLong index, WebIDL::Long x, WebIDL::Long y, WebIDL::Long z, WebIDL::Long w)

View file

@ -2,6 +2,7 @@
* Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2024-2025, Luke Wilde <luke@ladybird.org>
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
* Copyright (c) 2025, Undefine <undefine@undefine.pl>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -195,8 +196,10 @@ void WebGL2RenderingContextOverloads::uniform1fv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE);
glUniform1fv(location->handle(), span.size(), span.data());
glUniform1fv(location_handle, span.size(), span.data());
}
void WebGL2RenderingContextOverloads::uniform2fv(GC::Root<WebGLUniformLocation> location, Float32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -206,12 +209,14 @@ void WebGL2RenderingContextOverloads::uniform2fv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 2 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform2fv(location->handle(), span.size() / 2, span.data());
glUniform2fv(location_handle, span.size() / 2, span.data());
}
void WebGL2RenderingContextOverloads::uniform3fv(GC::Root<WebGLUniformLocation> location, Float32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -221,12 +226,14 @@ void WebGL2RenderingContextOverloads::uniform3fv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 3 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform3fv(location->handle(), span.size() / 3, span.data());
glUniform3fv(location_handle, span.size() / 3, span.data());
}
void WebGL2RenderingContextOverloads::uniform4fv(GC::Root<WebGLUniformLocation> location, Float32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -236,12 +243,14 @@ void WebGL2RenderingContextOverloads::uniform4fv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 4 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform4fv(location->handle(), span.size() / 4, span.data());
glUniform4fv(location_handle, span.size() / 4, span.data());
}
void WebGL2RenderingContextOverloads::uniform1iv(GC::Root<WebGLUniformLocation> location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -251,8 +260,10 @@ void WebGL2RenderingContextOverloads::uniform1iv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE);
glUniform1iv(location->handle(), span.size(), span.data());
glUniform1iv(location_handle, span.size(), span.data());
}
void WebGL2RenderingContextOverloads::uniform2iv(GC::Root<WebGLUniformLocation> location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -262,12 +273,14 @@ void WebGL2RenderingContextOverloads::uniform2iv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 2 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform2iv(location->handle(), span.size() / 2, span.data());
glUniform2iv(location_handle, span.size() / 2, span.data());
}
void WebGL2RenderingContextOverloads::uniform3iv(GC::Root<WebGLUniformLocation> location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -277,12 +290,14 @@ void WebGL2RenderingContextOverloads::uniform3iv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 3 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform3iv(location->handle(), span.size() / 3, span.data());
glUniform3iv(location_handle, span.size() / 3, span.data());
}
void WebGL2RenderingContextOverloads::uniform4iv(GC::Root<WebGLUniformLocation> location, Int32List values, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -292,12 +307,14 @@ void WebGL2RenderingContextOverloads::uniform4iv(GC::Root<WebGLUniformLocation>
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_int32_list(values, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % 4 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform4iv(location->handle(), span.size() / 4, span.data());
glUniform4iv(location_handle, span.size() / 4, span.data());
}
void WebGL2RenderingContextOverloads::uniform_matrix2fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -307,13 +324,15 @@ void WebGL2RenderingContextOverloads::uniform_matrix2fv(GC::Root<WebGLUniformLoc
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 2 * 2;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix2fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix2fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextOverloads::uniform_matrix3fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -323,13 +342,15 @@ void WebGL2RenderingContextOverloads::uniform_matrix3fv(GC::Root<WebGLUniformLoc
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 3 * 3;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix3fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix3fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextOverloads::uniform_matrix4fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List data, WebIDL::UnsignedLongLong src_offset, WebIDL::UnsignedLong src_length)
@ -339,13 +360,15 @@ void WebGL2RenderingContextOverloads::uniform_matrix4fv(GC::Root<WebGLUniformLoc
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 4 * 4;
auto span = SET_ERROR_VALUE_IF_ERROR(span_from_float32_list(data, src_offset, src_length), GL_INVALID_VALUE);
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix4fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix4fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGL2RenderingContextOverloads::read_pixels(WebIDL::Long x, WebIDL::Long y, WebIDL::Long width, WebIDL::Long height, WebIDL::UnsignedLong format, WebIDL::UnsignedLong type, GC::Root<WebIDL::ArrayBufferView> pixels)

View file

@ -1751,7 +1751,7 @@ GC::Root<WebGLUniformLocation> WebGLRenderingContextImpl::get_uniform_location(G
if (location == -1)
return nullptr;
return WebGLUniformLocation::create(m_realm, location);
return WebGLUniformLocation::create(m_realm, location, program.ptr());
}
JS::Value WebGLRenderingContextImpl::get_vertex_attrib(WebIDL::UnsignedLong index, WebIDL::UnsignedLong pname)
@ -2082,49 +2082,89 @@ void WebGLRenderingContextImpl::tex_parameteri(WebIDL::UnsignedLong target, WebI
void WebGLRenderingContextImpl::uniform1f(GC::Root<WebGLUniformLocation> location, float x)
{
m_context->make_current();
glUniform1f(location ? location->handle() : 0, x);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform1f(location_handle, x);
}
void WebGLRenderingContextImpl::uniform2f(GC::Root<WebGLUniformLocation> location, float x, float y)
{
m_context->make_current();
glUniform2f(location ? location->handle() : 0, x, y);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform2f(location_handle, x, y);
}
void WebGLRenderingContextImpl::uniform3f(GC::Root<WebGLUniformLocation> location, float x, float y, float z)
{
m_context->make_current();
glUniform3f(location ? location->handle() : 0, x, y, z);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform3f(location_handle, x, y, z);
}
void WebGLRenderingContextImpl::uniform4f(GC::Root<WebGLUniformLocation> location, float x, float y, float z, float w)
{
m_context->make_current();
glUniform4f(location ? location->handle() : 0, x, y, z, w);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform4f(location_handle, x, y, z, w);
}
void WebGLRenderingContextImpl::uniform1i(GC::Root<WebGLUniformLocation> location, WebIDL::Long x)
{
m_context->make_current();
glUniform1i(location ? location->handle() : 0, x);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform1i(location_handle, x);
}
void WebGLRenderingContextImpl::uniform2i(GC::Root<WebGLUniformLocation> location, WebIDL::Long x, WebIDL::Long y)
{
m_context->make_current();
glUniform2i(location ? location->handle() : 0, x, y);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform2i(location_handle, x, y);
}
void WebGLRenderingContextImpl::uniform3i(GC::Root<WebGLUniformLocation> location, WebIDL::Long x, WebIDL::Long y, WebIDL::Long z)
{
m_context->make_current();
glUniform3i(location ? location->handle() : 0, x, y, z);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform3i(location_handle, x, y, z);
}
void WebGLRenderingContextImpl::uniform4i(GC::Root<WebGLUniformLocation> location, WebIDL::Long x, WebIDL::Long y, WebIDL::Long z, WebIDL::Long w)
{
m_context->make_current();
glUniform4i(location ? location->handle() : 0, x, y, z, w);
GLuint location_handle = 0;
if (location)
location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
glUniform4i(location_handle, x, y, z, w);
}
void WebGLRenderingContextImpl::use_program(GC::Root<WebGLProgram> program)

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2024-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2024-2025, Luke Wilde <luke@ladybird.org>
* Copyright (c) 2025, Undefine <undefine@undefine.pl>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -192,8 +193,11 @@ void WebGLRenderingContextOverloads::uniform1fv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0));
glUniform1fv(location->handle(), span.size(), span.data());
glUniform1fv(location_handle, span.size(), span.data());
}
void WebGLRenderingContextOverloads::uniform2fv(GC::Root<WebGLUniformLocation> location, Float32List v)
@ -202,12 +206,15 @@ void WebGLRenderingContextOverloads::uniform2fv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0));
if (span.size() % 2 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform2fv(location->handle(), span.size() / 2, span.data());
glUniform2fv(location_handle, span.size() / 2, span.data());
}
void WebGLRenderingContextOverloads::uniform3fv(GC::Root<WebGLUniformLocation> location, Float32List v)
@ -216,12 +223,15 @@ void WebGLRenderingContextOverloads::uniform3fv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0));
if (span.size() % 3 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform3fv(location->handle(), span.size() / 3, span.data());
glUniform3fv(location_handle, span.size() / 3, span.data());
}
void WebGLRenderingContextOverloads::uniform4fv(GC::Root<WebGLUniformLocation> location, Float32List v)
@ -230,12 +240,15 @@ void WebGLRenderingContextOverloads::uniform4fv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_float32_list(v, /* src_offset= */ 0));
if (span.size() % 4 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform4fv(location->handle(), span.size() / 4, span.data());
glUniform4fv(location_handle, span.size() / 4, span.data());
}
void WebGLRenderingContextOverloads::uniform1iv(GC::Root<WebGLUniformLocation> location, Int32List v)
@ -244,8 +257,11 @@ void WebGLRenderingContextOverloads::uniform1iv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0));
glUniform1iv(location->handle(), span.size(), span.data());
glUniform1iv(location_handle, span.size(), span.data());
}
void WebGLRenderingContextOverloads::uniform2iv(GC::Root<WebGLUniformLocation> location, Int32List v)
@ -254,12 +270,15 @@ void WebGLRenderingContextOverloads::uniform2iv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0));
if (span.size() % 2 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform2iv(location->handle(), span.size() / 2, span.data());
glUniform2iv(location_handle, span.size() / 2, span.data());
}
void WebGLRenderingContextOverloads::uniform3iv(GC::Root<WebGLUniformLocation> location, Int32List v)
@ -268,12 +287,15 @@ void WebGLRenderingContextOverloads::uniform3iv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0));
if (span.size() % 3 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform3iv(location->handle(), span.size() / 3, span.data());
glUniform3iv(location_handle, span.size() / 3, span.data());
}
void WebGLRenderingContextOverloads::uniform4iv(GC::Root<WebGLUniformLocation> location, Int32List v)
@ -282,12 +304,15 @@ void WebGLRenderingContextOverloads::uniform4iv(GC::Root<WebGLUniformLocation> l
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
auto span = MUST(span_from_int32_list(v, /* src_offset= */ 0));
if (span.size() % 4 != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniform4iv(location->handle(), span.size() / 4, span.data());
glUniform4iv(location_handle, span.size() / 4, span.data());
}
void WebGLRenderingContextOverloads::uniform_matrix2fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List value)
@ -296,13 +321,16 @@ void WebGLRenderingContextOverloads::uniform_matrix2fv(GC::Root<WebGLUniformLoca
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 2 * 2;
auto span = MUST(span_from_float32_list(value, /* src_offset= */ 0));
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix2fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix2fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGLRenderingContextOverloads::uniform_matrix3fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List value)
@ -311,13 +339,16 @@ void WebGLRenderingContextOverloads::uniform_matrix3fv(GC::Root<WebGLUniformLoca
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 3 * 3;
auto span = MUST(span_from_float32_list(value, /* src_offset= */ 0));
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix3fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix3fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
void WebGLRenderingContextOverloads::uniform_matrix4fv(GC::Root<WebGLUniformLocation> location, bool transpose, Float32List value)
@ -326,13 +357,16 @@ void WebGLRenderingContextOverloads::uniform_matrix4fv(GC::Root<WebGLUniformLoca
if (!location)
return;
GLuint location_handle = SET_ERROR_VALUE_IF_ERROR(location->handle(m_current_program), GL_INVALID_OPERATION);
constexpr auto matrix_size = 4 * 4;
auto span = MUST(span_from_float32_list(value, /* src_offset= */ 0));
if (span.size() % matrix_size != 0) [[unlikely]] {
set_error(GL_INVALID_VALUE);
return;
}
glUniformMatrix4fv(location->handle(), span.size() / matrix_size, transpose, span.data());
glUniformMatrix4fv(location_handle, span.size() / matrix_size, transpose, span.data());
}
}

View file

@ -2,6 +2,7 @@
* Copyright (c) 2024, Jelle Raaijmakers <jelle@ladybird.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2024, Luke Wilde <luke@ladybird.org>
* Copyright (c) 2025, Undefine <undefine@undefine.pl>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -11,18 +12,21 @@
#include <LibWeb/Bindings/WebGLUniformLocationPrototype.h>
#include <LibWeb/WebGL/WebGLUniformLocation.h>
#include <GLES2/gl2.h>
namespace Web::WebGL {
GC_DEFINE_ALLOCATOR(WebGLUniformLocation);
GC::Ref<WebGLUniformLocation> WebGLUniformLocation::create(JS::Realm& realm, GLuint handle)
GC::Ref<WebGLUniformLocation> WebGLUniformLocation::create(JS::Realm& realm, GLuint handle, GC::Ptr<WebGLProgram> parent_shader)
{
return realm.create<WebGLUniformLocation>(realm, handle);
return realm.create<WebGLUniformLocation>(realm, handle, parent_shader);
}
WebGLUniformLocation::WebGLUniformLocation(JS::Realm& realm, GLuint handle)
WebGLUniformLocation::WebGLUniformLocation(JS::Realm& realm, GLuint handle, GC::Ptr<WebGLProgram> parent_shader)
: Bindings::PlatformObject(realm)
, m_handle(handle)
, m_parent_shader(parent_shader)
{
}
@ -34,4 +38,17 @@ void WebGLUniformLocation::initialize(JS::Realm& realm)
Base::initialize(realm);
}
void WebGLUniformLocation::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_parent_shader);
}
ErrorOr<GLuint> WebGLUniformLocation::handle(GC::Ptr<WebGLProgram> current_shader) const
{
if (current_shader == m_parent_shader)
return m_handle;
return Error::from_errno(GL_INVALID_OPERATION);
}
}

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2024, Jelle Raaijmakers <jelle@ladybird.org>
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
* Copyright (c) 2025, Undefine <undefine@undefine.pl>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -9,6 +10,7 @@
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/WebGL/Types.h>
#include <LibWeb/WebGL/WebGLProgram.h>
namespace Web::WebGL {
@ -17,18 +19,20 @@ class WebGLUniformLocation final : public Bindings::PlatformObject {
GC_DECLARE_ALLOCATOR(WebGLUniformLocation);
public:
static GC::Ref<WebGLUniformLocation> create(JS::Realm& realm, GLuint handle);
static GC::Ref<WebGLUniformLocation> create(JS::Realm& realm, GLuint handle, GC::Ptr<WebGLProgram> parent_shader);
virtual ~WebGLUniformLocation();
GLuint handle() const { return m_handle; }
ErrorOr<GLuint> handle(GC::Ptr<WebGLProgram> current_shader) const;
protected:
explicit WebGLUniformLocation(JS::Realm&, GLuint handle);
explicit WebGLUniformLocation(JS::Realm&, GLuint handle, GC::Ptr<WebGLProgram> parent_shader);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(JS::Cell::Visitor&) override;
GLuint m_handle { 0 };
GC::Ptr<WebGLProgram> m_parent_shader;
};
}