Serenity Operating System
1/*
2 * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
3 * Copyright (c) 2022, cflip <cflip@cflip.net>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include <LibGL/GLContext.h>
9
10namespace GL {
11
12void GLContext::gl_bind_buffer(GLenum target, GLuint buffer)
13{
14 RETURN_WITH_ERROR_IF(target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER, GL_INVALID_ENUM);
15 RETURN_WITH_ERROR_IF(!m_buffer_name_allocator.has_allocated_name(buffer), GL_INVALID_VALUE);
16
17 auto& target_buffer = target == GL_ELEMENT_ARRAY_BUFFER ? m_element_array_buffer : m_array_buffer;
18 target_buffer = nullptr;
19
20 if (buffer != 0) {
21 auto it = m_allocated_buffers.find(buffer);
22 if (it != m_allocated_buffers.end()) {
23 auto buffer_object = it->value;
24 if (!buffer_object.is_null()) {
25 target_buffer = buffer_object;
26 }
27 }
28
29 if (!target_buffer) {
30 target_buffer = adopt_ref(*new Buffer());
31 m_allocated_buffers.set(buffer, target_buffer);
32 }
33 }
34}
35
36void GLContext::gl_buffer_data(GLenum target, GLsizeiptr size, void const* data, GLenum usage)
37{
38 RETURN_WITH_ERROR_IF(usage != GL_STREAM_DRAW
39 && usage != GL_STREAM_READ
40 && usage != GL_STREAM_COPY
41 && usage != GL_STATIC_DRAW
42 && usage != GL_STATIC_READ
43 && usage != GL_STATIC_COPY
44 && usage != GL_DYNAMIC_DRAW
45 && usage != GL_DYNAMIC_READ
46 && usage != GL_DYNAMIC_COPY,
47 GL_INVALID_ENUM);
48 RETURN_WITH_ERROR_IF(target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER, GL_INVALID_ENUM);
49
50 auto& target_buffer = target == GL_ELEMENT_ARRAY_BUFFER ? m_element_array_buffer : m_array_buffer;
51 RETURN_WITH_ERROR_IF(!target_buffer, GL_INVALID_OPERATION);
52
53 RETURN_WITH_ERROR_IF(target_buffer->set_data(data, size).is_error(), GL_OUT_OF_MEMORY);
54}
55
56void GLContext::gl_buffer_sub_data(GLenum target, GLintptr offset, GLsizeiptr size, void const* data)
57{
58 RETURN_WITH_ERROR_IF(target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER, GL_INVALID_ENUM);
59 RETURN_WITH_ERROR_IF(offset < 0, GL_INVALID_VALUE);
60 // FIXME: Support buffer storage mutability flags.
61
62 auto& target_buffer = target == GL_ELEMENT_ARRAY_BUFFER ? m_element_array_buffer : m_array_buffer;
63 RETURN_WITH_ERROR_IF(!target_buffer, GL_INVALID_OPERATION);
64 RETURN_WITH_ERROR_IF(static_cast<size_t>(offset + size) > target_buffer->size(), GL_INVALID_VALUE);
65
66 target_buffer->replace_data(data, offset, size);
67}
68
69void GLContext::gl_delete_buffers(GLsizei n, GLuint const* buffers)
70{
71 RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
72
73 for (auto i = 0; i < n; i++) {
74 GLuint name = buffers[i];
75 if (name == 0)
76 continue;
77
78 auto buffer_object = m_allocated_buffers.find(name);
79 if (buffer_object == m_allocated_buffers.end() || buffer_object->value.is_null())
80 continue;
81
82 Buffer* buffer = buffer_object->value;
83
84 if (m_array_buffer == buffer)
85 m_array_buffer = nullptr;
86
87 if (m_element_array_buffer == buffer)
88 m_element_array_buffer = nullptr;
89
90 m_buffer_name_allocator.free(name);
91 m_allocated_buffers.remove(name);
92 }
93}
94
95void GLContext::gl_gen_buffers(GLsizei n, GLuint* buffers)
96{
97 RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
98
99 m_buffer_name_allocator.allocate(n, buffers);
100
101 // Initialize all buffer names with a nullptr
102 for (auto i = 0; i < n; ++i) {
103 GLuint name = buffers[i];
104 m_allocated_buffers.set(name, nullptr);
105 }
106}
107
108}