summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Unverwerth <s.unverwerth@serenityos.org>2021-05-30 00:15:51 +0200
committerLinus Groh <mail@linusgroh.de>2021-05-30 00:32:37 +0100
commit755393e684268b8ee1c1f72b6a705e99827836b5 (patch)
tree6e2f552d4908db497931ef855ffc31a0f5fffe7a
parentfde0045ebe7ac5aa1698870002ae58edac3c4f85 (diff)
downloadserenity-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.cpp1
-rw-r--r--Userland/Libraries/LibGL/GL/gl.h2
-rw-r--r--Userland/Libraries/LibGL/GLContext.h1
-rw-r--r--Userland/Libraries/LibGL/GLTexture.cpp6
-rw-r--r--Userland/Libraries/LibGL/SoftwareGLContext.cpp68
-rw-r--r--Userland/Libraries/LibGL/SoftwareGLContext.h3
-rw-r--r--Userland/Libraries/LibGL/SoftwareRasterizer.cpp7
-rw-r--r--Userland/Libraries/LibGL/SoftwareRasterizer.h1
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);