diff options
author | Stephan Unverwerth <s.unverwerth@serenityos.org> | 2021-05-30 00:15:51 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-05-30 00:32:37 +0100 |
commit | 755393e684268b8ee1c1f72b6a705e99827836b5 (patch) | |
tree | 6e2f552d4908db497931ef855ffc31a0f5fffe7a | |
parent | fde0045ebe7ac5aa1698870002ae58edac3c4f85 (diff) | |
download | serenity-755393e684268b8ee1c1f72b6a705e99827836b5.zip |
LibGL: Implement glBindTexture()
Textures are now initialized with a nullptr upon generation.
They are only actually created once they are bound to a target.
Currently only the GL_TEXTURE_2D target is supported.
The software rasterizer now allows rendering with or without
a bound TEXTURE_2D.
-rw-r--r-- | Userland/Applications/3DFileViewer/main.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/GL/gl.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/GLContext.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/GLTexture.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareGLContext.cpp | 68 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareGLContext.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareRasterizer.cpp | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibGL/SoftwareRasterizer.h | 1 |
8 files changed, 85 insertions, 4 deletions
diff --git a/Userland/Applications/3DFileViewer/main.cpp b/Userland/Applications/3DFileViewer/main.cpp index 177e181637..1a98418403 100644 --- a/Userland/Applications/3DFileViewer/main.cpp +++ b/Userland/Applications/3DFileViewer/main.cpp @@ -153,6 +153,7 @@ bool GLContextWidget::load(const String& filename) glGenTextures(1, &tex); if (texture_image) { // Upload texture data to the GL + glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_image->width(), texture_image->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_image->scanline(0)); } else { dbgln("3DFileViewer: Couldn't load texture for {}", filename); diff --git a/Userland/Libraries/LibGL/GL/gl.h b/Userland/Libraries/LibGL/GL/gl.h index c7fd7856c9..3cb027d44a 100644 --- a/Userland/Libraries/LibGL/GL/gl.h +++ b/Userland/Libraries/LibGL/GL/gl.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> + * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -257,6 +258,7 @@ GLAPI void glReadBuffer(GLenum mode); GLAPI void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); GLAPI void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data); GLAPI void glTexCoord2f(GLfloat s, GLfloat t); +GLAPI void glBindTexture(GLenum target, GLuint texture); #ifdef __cplusplus } diff --git a/Userland/Libraries/LibGL/GLContext.h b/Userland/Libraries/LibGL/GLContext.h index bb669537ab..f4c00ec43a 100644 --- a/Userland/Libraries/LibGL/GLContext.h +++ b/Userland/Libraries/LibGL/GLContext.h @@ -59,6 +59,7 @@ public: virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = 0; virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) = 0; virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) = 0; + virtual void gl_bind_texture(GLenum target, GLuint texture) = 0; virtual void present() = 0; }; diff --git a/Userland/Libraries/LibGL/GLTexture.cpp b/Userland/Libraries/LibGL/GLTexture.cpp index 31c96d97ab..fbc295ad48 100644 --- a/Userland/Libraries/LibGL/GLTexture.cpp +++ b/Userland/Libraries/LibGL/GLTexture.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> + * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -23,3 +24,8 @@ void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei widt { g_gl_context->gl_tex_image_2d(target, level, internalFormat, width, height, border, format, type, data); } + +void glBindTexture(GLenum target, GLuint texture) +{ + g_gl_context->gl_bind_texture(target, texture); +} diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index 96a54ee4b1..92b415abfd 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -313,7 +313,12 @@ void SoftwareGLContext::gl_end() } // FIXME: Change this when we have texture units/multi-texturing - m_rasterizer.submit_triangle(triangle, *static_ptr_cast<Texture2D>(m_allocated_textures.find(1)->value)); + if (m_bound_texture_2d == 0) { + m_rasterizer.submit_triangle(triangle); + } else { + auto it = m_allocated_textures.find(m_bound_texture_2d); + m_rasterizer.submit_triangle(triangle, *static_ptr_cast<Texture2D>(it->value)); + } } triangle_list.clear(); @@ -663,11 +668,11 @@ void SoftwareGLContext::gl_gen_textures(GLsizei n, GLuint* textures) m_name_allocator.allocate(n, textures); - // Let's allocate a new texture for each texture name + // Initialize all texture names with a nullptr for (auto i = 0; i < n; i++) { GLuint name = textures[i]; - m_allocated_textures.set(name, adopt_ref(*new Texture2D())); + m_allocated_textures.set(name, nullptr); } } @@ -678,10 +683,13 @@ void SoftwareGLContext::gl_delete_textures(GLsizei n, const GLuint* textures) m_name_allocator.free(n, textures); - // Let's allocate a new texture for each texture name for (auto i = 0; i < n; i++) { GLuint name = textures[i]; + // unbind texture if it is currently bound + if (m_bound_texture_2d == name) + m_bound_texture_2d = 0; + m_allocated_textures.remove(name); } } @@ -693,6 +701,9 @@ void SoftwareGLContext::gl_tex_image_2d(GLenum target, GLint level, GLint intern // We only support GL_TEXTURE_2D for now RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM); + // Check if there is actually a texture bound + RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && m_bound_texture_2d == 0, GL_INVALID_OPERATION); + // We only support symbolic constants for now RETURN_WITH_ERROR_IF(!(internal_format == GL_RGB || internal_format == GL_RGBA), GL_INVALID_ENUM); RETURN_WITH_ERROR_IF(type != GL_UNSIGNED_BYTE, GL_INVALID_VALUE); @@ -1226,6 +1237,55 @@ void SoftwareGLContext::gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei } } +void SoftwareGLContext::gl_bind_texture(GLenum target, GLuint texture) +{ + RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); + // FIXME: We only support GL_TEXTURE_2D for now + RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM); + + if (texture == 0) { + switch (target) { + case GL_TEXTURE_2D: + m_bound_texture_2d = 0; + return; + default: + VERIFY_NOT_REACHED(); + return; + } + } + + auto it = m_allocated_textures.find(texture); + + // The texture name does not exist + RETURN_WITH_ERROR_IF(it == m_allocated_textures.end(), GL_INVALID_VALUE); + + auto texture_object = it->value; + + // Binding a texture to a different target than it was first bound is an invalid operation + // FIXME: We only support GL_TEXTURE_2D for now + RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && !texture_object.is_null() && !texture_object->is_texture_2d(), GL_INVALID_OPERATION); + + if (!texture_object) { + // This is the first time the texture is bound. Allocate an actual texture object + switch (target) { + case GL_TEXTURE_2D: + texture_object = adopt_ref(*new Texture2D()); + break; + default: + VERIFY_NOT_REACHED(); + break; + } + + m_allocated_textures.set(texture, texture_object); + } + + switch (target) { + case GL_TEXTURE_2D: + m_bound_texture_2d = texture; + break; + } +} + void SoftwareGLContext::present() { m_rasterizer.blit_to(*m_frontbuffer); diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.h b/Userland/Libraries/LibGL/SoftwareGLContext.h index 17fe9f2fef..5e04504c03 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.h +++ b/Userland/Libraries/LibGL/SoftwareGLContext.h @@ -68,6 +68,7 @@ public: virtual void gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) override; virtual void gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data) override; virtual void gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q) override; + virtual void gl_bind_texture(GLenum target, GLuint texture) override; virtual void present() override; @@ -128,6 +129,8 @@ private: GLenum m_current_read_buffer = GL_BACK; + GLuint m_bound_texture_2d = 0; + NonnullRefPtr<Gfx::Bitmap> m_frontbuffer; Clipper m_clipper; diff --git a/Userland/Libraries/LibGL/SoftwareRasterizer.cpp b/Userland/Libraries/LibGL/SoftwareRasterizer.cpp index 3f13938288..d9b57f4da4 100644 --- a/Userland/Libraries/LibGL/SoftwareRasterizer.cpp +++ b/Userland/Libraries/LibGL/SoftwareRasterizer.cpp @@ -414,6 +414,13 @@ SoftwareRasterizer::SoftwareRasterizer(const Gfx::IntSize& min_size) { } +void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle) +{ + rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [](const FloatVector2&, const FloatVector4& color) -> FloatVector4 { + return color; + }); +} + void SoftwareRasterizer::submit_triangle(const GLTriangle& triangle, const Texture2D& texture) { rasterize_triangle(m_options, *m_render_target, *m_depth_buffer, triangle, [&texture](const FloatVector2& uv, const FloatVector4& color) -> FloatVector4 { diff --git a/Userland/Libraries/LibGL/SoftwareRasterizer.h b/Userland/Libraries/LibGL/SoftwareRasterizer.h index 717fefdc41..c7bd803276 100644 --- a/Userland/Libraries/LibGL/SoftwareRasterizer.h +++ b/Userland/Libraries/LibGL/SoftwareRasterizer.h @@ -32,6 +32,7 @@ public: SoftwareRasterizer(const Gfx::IntSize& min_size); void submit_triangle(const GLTriangle& triangle, const Texture2D& texture); + void submit_triangle(const GLTriangle& triangle); void resize(const Gfx::IntSize& min_size); void clear_color(const FloatVector4&); void clear_depth(float); |