diff --git a/Userland/Libraries/LibGL/CMakeLists.txt b/Userland/Libraries/LibGL/CMakeLists.txt index 3455679f728..04806d8b539 100644 --- a/Userland/Libraries/LibGL/CMakeLists.txt +++ b/Userland/Libraries/LibGL/CMakeLists.txt @@ -1,4 +1,5 @@ set(SOURCES + Tex/NameAllocator.cpp Clipper.cpp GLBlend.cpp GLColor.cpp @@ -6,6 +7,7 @@ set(SOURCES GLLights.cpp GLLists.cpp GLMat.cpp + GLTexture.cpp GLUtils.cpp GLVert.cpp SoftwareGLContext.cpp diff --git a/Userland/Libraries/LibGL/GL/gl.h b/Userland/Libraries/LibGL/GL/gl.h index 03637e41c3f..adbd47e4497 100644 --- a/Userland/Libraries/LibGL/GL/gl.h +++ b/Userland/Libraries/LibGL/GL/gl.h @@ -180,8 +180,10 @@ GLAPI void glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a); GLAPI void glColor4fv(const GLfloat* v); GLAPI void glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a); GLAPI void glColor4ubv(const GLubyte* v); +GLAPI void glDeleteTextures(GLsizei n, const GLuint* textures); GLAPI void glEnd(); GLAPI void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal); +GLAPI void glGenTextures(GLsizei n, GLuint* textures); GLAPI GLenum glGetError(); GLAPI GLubyte* glGetString(GLenum name); GLAPI void glLoadIdentity(); diff --git a/Userland/Libraries/LibGL/GLContext.h b/Userland/Libraries/LibGL/GLContext.h index 191ea58e2c8..fb819ac5c83 100644 --- a/Userland/Libraries/LibGL/GLContext.h +++ b/Userland/Libraries/LibGL/GLContext.h @@ -23,8 +23,10 @@ public: virtual void gl_clear_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) = 0; virtual void gl_clear_depth(GLdouble depth) = 0; virtual void gl_color(GLdouble r, GLdouble g, GLdouble b, GLdouble a) = 0; + virtual void gl_delete_textures(GLsizei n, const GLuint* textures) = 0; virtual void gl_end() = 0; virtual void gl_frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) = 0; + virtual void gl_gen_textures(GLsizei n, GLuint* textures) = 0; virtual GLenum gl_get_error() = 0; virtual GLubyte* gl_get_string(GLenum name) = 0; virtual void gl_load_identity() = 0; diff --git a/Userland/Libraries/LibGL/GLTexture.cpp b/Userland/Libraries/LibGL/GLTexture.cpp new file mode 100644 index 00000000000..9c974a1f49f --- /dev/null +++ b/Userland/Libraries/LibGL/GLTexture.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Jesse Buhagiar + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "GLContext.h" +#include + +extern GL::GLContext* g_gl_context; + +void glGenTextures(GLsizei n, GLuint* textures) +{ + g_gl_context->gl_gen_textures(n, textures); +} + +void glDeleteTextures(GLsizei n, const GLuint* textures) +{ + g_gl_context->gl_delete_textures(n, textures); +} diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index 950c948f896..6ab57d973d7 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -742,6 +742,36 @@ void SoftwareGLContext::gl_disable(GLenum capability) m_rasterizer.set_options(rasterizer_options); } +void SoftwareGLContext::gl_gen_textures(GLsizei n, GLuint* textures) +{ + if (n < 0) { + m_error = GL_INVALID_VALUE; + return; + } + + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + + m_name_allocator.allocate(n, textures); +} + +void SoftwareGLContext::gl_delete_textures(GLsizei n, const GLuint* textures) +{ + if (n < 0) { + m_error = GL_INVALID_VALUE; + return; + } + + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + + m_name_allocator.free(n, textures); +} + void SoftwareGLContext::gl_front_face(GLenum face) { APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_front_face, face); diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.h b/Userland/Libraries/LibGL/SoftwareGLContext.h index 4fd041919fc..cf942ad7523 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.h +++ b/Userland/Libraries/LibGL/SoftwareGLContext.h @@ -29,8 +29,10 @@ public: virtual void gl_clear_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) override; virtual void gl_clear_depth(GLdouble depth) override; virtual void gl_color(GLdouble r, GLdouble g, GLdouble b, GLdouble a) override; + virtual void gl_delete_textures(GLsizei n, const GLuint* textures) override; virtual void gl_end() override; virtual void gl_frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) override; + virtual void gl_gen_textures(GLsizei n, GLuint* textures) override; virtual GLenum gl_get_error() override; virtual GLubyte* gl_get_string(GLenum name) override; virtual void gl_load_identity() override; @@ -124,6 +126,7 @@ private: NonnullRefPtr m_frontbuffer; Clipper m_clipper; + TextureNameAllocator m_name_allocator; SoftwareRasterizer m_rasterizer; diff --git a/Userland/Libraries/LibGL/Tex/NameAllocator.cpp b/Userland/Libraries/LibGL/Tex/NameAllocator.cpp new file mode 100644 index 00000000000..cd1baea73b2 --- /dev/null +++ b/Userland/Libraries/LibGL/Tex/NameAllocator.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Jesse Buhagiar + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace GL { + +void TextureNameAllocator::allocate(GLsizei count, GLuint* textures) +{ + for (auto i = 0; i < count; ++i) { + if (!m_free_texture_names.is_empty()) { + textures[i] = m_free_texture_names.top(); + m_free_texture_names.pop(); + } else { + // We're out of free previously allocated names. Let's allocate a new contiguous amount from the + // last known texture name + textures[i] = m_last_texture_id++; + } + } +} + +void TextureNameAllocator::free(GLsizei count, const GLuint* textures) +{ + size_t tex_array_index = 0; + + while (count-- > 0) + m_free_texture_names.push(textures[tex_array_index++]); +} + +} diff --git a/Userland/Libraries/LibGL/Tex/NameAllocator.h b/Userland/Libraries/LibGL/Tex/NameAllocator.h new file mode 100644 index 00000000000..6f596474f06 --- /dev/null +++ b/Userland/Libraries/LibGL/Tex/NameAllocator.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Jesse Buhagiar + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace GL { + +class TextureNameAllocator { +public: + TextureNameAllocator() = default; + + void allocate(GLsizei count, GLuint* textures); + void free(GLsizei count, const GLuint* textures); + +private: + Stack m_free_texture_names; + GLuint m_last_texture_id { 1 }; +}; + +}