LibGL: Add simple implementation of buffer objects

For now, buffers are only implemented on the LibGL side, however in the
future buffer objects should be stored in LibGPU.
This commit is contained in:
cflip 2022-11-13 15:08:24 -07:00 committed by Andreas Kling
parent 892006218a
commit 59df2e62ee
Notes: sideshowbarker 2024-07-17 04:03:29 +09:00
6 changed files with 170 additions and 10 deletions

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
* Copyright (c) 2022, cflip <cflip@cflip.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -11,32 +12,99 @@ namespace GL {
void GLContext::gl_bind_buffer(GLenum target, GLuint buffer)
{
// FIXME: implement me
dbgln_if(GL_DEBUG, "{}({:#x}, {})): unimplemented", __FUNCTION__, target, buffer);
RETURN_WITH_ERROR_IF(target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER, GL_INVALID_ENUM);
RETURN_WITH_ERROR_IF(!m_buffer_name_allocator.has_allocated_name(buffer), GL_INVALID_VALUE);
auto& target_buffer = target == GL_ELEMENT_ARRAY_BUFFER ? m_element_array_buffer : m_array_buffer;
target_buffer = nullptr;
if (buffer != 0) {
auto it = m_allocated_buffers.find(buffer);
if (it != m_allocated_buffers.end()) {
auto buffer_object = it->value;
if (!buffer_object.is_null()) {
target_buffer = buffer_object;
}
}
if (!target_buffer) {
target_buffer = adopt_ref(*new Buffer());
m_allocated_buffers.set(buffer, target_buffer);
}
}
}
void GLContext::gl_buffer_data(GLenum target, GLsizeiptr size, void const* data, GLenum usage)
{
// FIXME: implement me
dbgln_if(GL_DEBUG, "{}({:#x}, {}, {:p}, {:#x}): unimplemented", __FUNCTION__, target, size, data, usage);
RETURN_WITH_ERROR_IF(usage != GL_STREAM_DRAW
&& usage != GL_STREAM_READ
&& usage != GL_STREAM_COPY
&& usage != GL_STATIC_DRAW
&& usage != GL_STATIC_READ
&& usage != GL_STATIC_COPY
&& usage != GL_DYNAMIC_DRAW
&& usage != GL_DYNAMIC_READ
&& usage != GL_DYNAMIC_COPY,
GL_INVALID_ENUM);
RETURN_WITH_ERROR_IF(target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER, GL_INVALID_ENUM);
auto& target_buffer = target == GL_ELEMENT_ARRAY_BUFFER ? m_element_array_buffer : m_array_buffer;
RETURN_WITH_ERROR_IF(!target_buffer, GL_INVALID_OPERATION);
// FIXME: Report GL_OUT_OF_MEMORY or other errors as needed here
MUST(target_buffer->set_data(data, size));
}
void GLContext::gl_buffer_sub_data(GLenum target, GLintptr offset, GLsizeiptr size, void const* data)
{
// FIXME: implement me
dbgln_if(GL_DEBUG, "{}({:#x}, {}, {}, {:p}): unimplemented", __FUNCTION__, target, offset, size, data);
RETURN_WITH_ERROR_IF(target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER, GL_INVALID_ENUM);
RETURN_WITH_ERROR_IF(offset < 0, GL_INVALID_VALUE);
// FIXME: Support buffer storage mutability flags.
auto& target_buffer = target == GL_ELEMENT_ARRAY_BUFFER ? m_element_array_buffer : m_array_buffer;
RETURN_WITH_ERROR_IF(!target_buffer, GL_INVALID_OPERATION);
RETURN_WITH_ERROR_IF((offset + size) > target_buffer->size(), GL_INVALID_VALUE);
target_buffer->replace_data(data, offset, size);
}
void GLContext::gl_delete_buffers(GLsizei n, GLuint const* buffers)
{
// FIXME: implement me
dbgln_if(GL_DEBUG, "{}({}, {:p}): unimplemented", __FUNCTION__, n, buffers);
RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
for (auto i = 0; i < n; i++) {
GLuint name = buffers[i];
if (name == 0)
continue;
auto buffer_object = m_allocated_buffers.find(name);
if (buffer_object == m_allocated_buffers.end() || buffer_object->value.is_null())
continue;
Buffer* buffer = buffer_object->value;
if (m_array_buffer == buffer)
m_array_buffer = nullptr;
if (m_element_array_buffer == buffer)
m_element_array_buffer = nullptr;
m_buffer_name_allocator.free(name);
m_allocated_buffers.remove(name);
}
}
void GLContext::gl_gen_buffers(GLsizei n, GLuint* buffers)
{
// FIXME: implement me
dbgln_if(GL_DEBUG, "{}({}, {:p}): unimplemented", __FUNCTION__, n, buffers);
RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
m_buffer_name_allocator.allocate(n, buffers);
// Initialize all buffer names with a nullptr
for (auto i = 0; i < n; ++i) {
GLuint name = buffers[i];
m_allocated_buffers.set(name, nullptr);
}
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2022, cflip <cflip@cflip.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "Buffer.h"
namespace GL {
ErrorOr<void> Buffer::set_data(void const* data, size_t size)
{
if (!data) {
m_data = TRY(ByteBuffer::create_uninitialized(size));
return {};
}
m_data = TRY(ByteBuffer::copy(data, size));
return {};
}
void Buffer::replace_data(void const* data, size_t offset, size_t size)
{
m_data.overwrite(offset, data, size);
}
size_t Buffer::size()
{
return m_data.size();
}
void* Buffer::data()
{
return m_data.data();
}
void* Buffer::offset_data(size_t offset)
{
return m_data.offset_pointer(offset);
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2022, cflip <cflip@cflip.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/ByteBuffer.h>
#include <AK/RefCounted.h>
namespace GL {
// FIXME: For now, this is basically just a wrapper around ByteBuffer, but in
// the future buffer data should be stored in LibGPU.
class Buffer : public RefCounted<Buffer> {
public:
ErrorOr<void> set_data(void const*, size_t);
void replace_data(void const*, size_t offset, size_t size);
size_t size();
void* data();
void* offset_data(size_t);
private:
ByteBuffer m_data;
};
}

View File

@ -1,4 +1,5 @@
set(SOURCES
Buffer/Buffer.cpp
Buffer.cpp
ClipPlane.cpp
ContextParameter.cpp

View File

@ -587,6 +587,20 @@ extern "C" {
#define GL_CLIP_PLANE4 0x3004
#define GL_CLIP_PLANE5 0x3005
// Buffer objects
#define GL_ARRAY_BUFFER 0x8892
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_STREAM_DRAW 0x88e0
#define GL_STREAM_READ 0x88e1
#define GL_STREAM_COPY 0x88e2
#define GL_STATIC_DRAW 0x88e4
#define GL_STATIC_READ 0x88e5
#define GL_STATIC_COPY 0x88e6
#define GL_DYNAMIC_DRAW 0x88e8
#define GL_DYNAMIC_READ 0x88e9
#define GL_DYNAMIC_COPY 0x88ea
GLAPI void glBegin(GLenum mode);
GLAPI void glClear(GLbitfield mask);
GLAPI void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);

View File

@ -15,6 +15,7 @@
#include <AK/Tuple.h>
#include <AK/Variant.h>
#include <AK/Vector.h>
#include <LibGL/Buffer/Buffer.h>
#include <LibGL/NameAllocator.h>
#include <LibGL/Tex/Texture.h>
#include <LibGL/Tex/TextureUnit.h>
@ -543,6 +544,12 @@ private:
// GL Extension string
String m_extensions;
// Buffer objects
NameAllocator m_buffer_name_allocator;
HashMap<GLuint, RefPtr<Buffer>> m_allocated_buffers;
RefPtr<Buffer> m_array_buffer;
RefPtr<Buffer> m_element_array_buffer;
};
ErrorOr<NonnullOwnPtr<GLContext>> create_context(Gfx::Bitmap&);