From 7f062e35a4c34454be180fd2e53e02e229cba91d Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Sun, 28 Aug 2022 11:47:58 +0200 Subject: [PATCH] LibGL: Implement glAttachShader --- Userland/Libraries/LibGL/Shader.cpp | 12 ++++++-- Userland/Libraries/LibGL/Shaders/Program.cpp | 32 ++++++++++++++++++-- Userland/Libraries/LibGL/Shaders/Program.h | 2 ++ Userland/Libraries/LibGL/Shaders/Shader.h | 1 + 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibGL/Shader.cpp b/Userland/Libraries/LibGL/Shader.cpp index 5e9c8f39de..01b1bbfd78 100644 --- a/Userland/Libraries/LibGL/Shader.cpp +++ b/Userland/Libraries/LibGL/Shader.cpp @@ -95,8 +95,16 @@ void GLContext::gl_delete_program(GLuint program) void GLContext::gl_attach_shader(GLuint program, GLuint shader) { - dbgln("gl_attach_shader({}, {}) unimplemented ", program, shader); - TODO(); + auto program_it = m_allocated_programs.find(program); + auto shader_it = m_allocated_shaders.find(shader); + // FIXME: implement check "GL_INVALID_VALUE is generated if either program or shader is not a value generated by OpenGL." + RETURN_WITH_ERROR_IF(program_it == m_allocated_programs.end(), GL_INVALID_OPERATION); + RETURN_WITH_ERROR_IF(shader_it == m_allocated_shaders.end(), GL_INVALID_OPERATION); + + // NOTE: attach_result is Error if the shader is already attached to this program + auto attach_result = program_it->value->attach_shader(*shader_it->value); + RETURN_WITH_ERROR_IF(attach_result.is_error() && attach_result.error().is_errno() && attach_result.error().code() == ENOMEM, GL_OUT_OF_MEMORY); + RETURN_WITH_ERROR_IF(attach_result.is_error(), GL_INVALID_OPERATION); } void GLContext::gl_link_program(GLuint program) diff --git a/Userland/Libraries/LibGL/Shaders/Program.cpp b/Userland/Libraries/LibGL/Shaders/Program.cpp index e432b24680..e6ad8fc6ef 100644 --- a/Userland/Libraries/LibGL/Shaders/Program.cpp +++ b/Userland/Libraries/LibGL/Shaders/Program.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include namespace GL { @@ -13,9 +14,36 @@ NonnullRefPtr Program::create() return adopt_ref(*new Program()); } -ErrorOr Program::attach_shader(Shader&) +bool Program::is_shader_attached(Shader const& shader) const { - TODO(); + switch (shader.type()) { + case GL_VERTEX_SHADER: + return m_vertex_shaders.contains_slow(shader); + case GL_FRAGMENT_SHADER: + return m_fragment_shaders.contains_slow(shader); + default: + VERIFY_NOT_REACHED(); + } +} + +ErrorOr Program::attach_shader(Shader& shader) +{ + if (is_shader_attached(shader)) + return Error::from_string_literal("Trying to attach a shader that is already attached"); + + switch (shader.type()) { + case GL_VERTEX_SHADER: + TRY(m_vertex_shaders.try_append(shader)); + break; + + case GL_FRAGMENT_SHADER: + TRY(m_fragment_shaders.try_append(shader)); + break; + + default: + VERIFY_NOT_REACHED(); + } + return {}; } diff --git a/Userland/Libraries/LibGL/Shaders/Program.h b/Userland/Libraries/LibGL/Shaders/Program.h index 3e619c3b2f..338149b9ca 100644 --- a/Userland/Libraries/LibGL/Shaders/Program.h +++ b/Userland/Libraries/LibGL/Shaders/Program.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -17,6 +18,7 @@ class Program final : public RefCounted { public: static NonnullRefPtr create(); + bool is_shader_attached(Shader const&) const; ErrorOr attach_shader(Shader&); ErrorOr link(); diff --git a/Userland/Libraries/LibGL/Shaders/Shader.h b/Userland/Libraries/LibGL/Shaders/Shader.h index 9b5c30c8ef..af1575b6e8 100644 --- a/Userland/Libraries/LibGL/Shaders/Shader.h +++ b/Userland/Libraries/LibGL/Shaders/Shader.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include