From 18399d00fa3af03fdf58d78c1f42102dc2924fed Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Tue, 21 Dec 2021 00:52:14 +0100 Subject: [PATCH] LibGL: Implement matrix mode `GL_TEXTURE` Implement support for the `GL_TEXTURE` matrix mode, the texture matrix stack and texture coordinate matrix transformation. Also, an unused `m_current_matrix` was removed to make room for `m_texture_matrix`. --- Userland/Libraries/LibGL/GL/gl.h | 1 + .../Libraries/LibGL/SoftwareGLContext.cpp | 105 ++++++++++++------ Userland/Libraries/LibGL/SoftwareGLContext.h | 4 +- 3 files changed, 73 insertions(+), 37 deletions(-) diff --git a/Userland/Libraries/LibGL/GL/gl.h b/Userland/Libraries/LibGL/GL/gl.h index a50616f309..a64a3ba689 100644 --- a/Userland/Libraries/LibGL/GL/gl.h +++ b/Userland/Libraries/LibGL/GL/gl.h @@ -31,6 +31,7 @@ extern "C" { // Matrix Modes #define GL_MODELVIEW 0x1700 #define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 // glBegin/glEnd primitive types #define GL_TRIANGLES 0x0004 diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index e382bff19d..6affec55ba 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -23,8 +23,9 @@ using AK::dbgln; namespace GL { -// FIXME: We should set this up when we create the context! -static constexpr size_t MATRIX_STACK_LIMIT = 1024; +static constexpr size_t MODELVIEW_MATRIX_STACK_LIMIT = 64; +static constexpr size_t PROJECTION_MATRIX_STACK_LIMIT = 8; +static constexpr size_t TEXTURE_MATRIX_STACK_LIMIT = 8; #define APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(name, ...) \ if (should_append_to_listing()) { \ @@ -286,6 +287,12 @@ void SoftwareGLContext::gl_end() triangle.vertices[1].position = mvp * triangle.vertices[1].position; triangle.vertices[2].position = mvp * triangle.vertices[2].position; + // Apply texture transformation + // FIXME: implement multi-texturing: texcoords should be stored per texture unit + triangle.vertices[0].tex_coord = m_texture_matrix * triangle.vertices[0].tex_coord; + triangle.vertices[1].tex_coord = m_texture_matrix * triangle.vertices[1].tex_coord; + triangle.vertices[2].tex_coord = m_texture_matrix * triangle.vertices[2].tex_coord; + // At this point, we're in clip space // Here's where we do the clipping. This is a really crude implementation of the // https://learnopengl.com/Getting-started/Coordinate-Systems @@ -386,12 +393,14 @@ void SoftwareGLContext::gl_frustum(GLdouble left, GLdouble right, GLdouble botto 0, 0, -1, 0 }; - if (m_current_matrix_mode == GL_PROJECTION) { + if (m_current_matrix_mode == GL_PROJECTION) m_projection_matrix = m_projection_matrix * frustum; - } else if (m_current_matrix_mode == GL_MODELVIEW) { - dbgln_if(GL_DEBUG, "glFrustum(): frustum created with curr_matrix_mode == GL_MODELVIEW!!!"); + else if (m_current_matrix_mode == GL_MODELVIEW) m_projection_matrix = m_model_view_matrix * frustum; - } + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = m_texture_matrix * frustum; + else + VERIFY_NOT_REACHED(); } void SoftwareGLContext::gl_ortho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) @@ -415,11 +424,14 @@ void SoftwareGLContext::gl_ortho(GLdouble left, GLdouble right, GLdouble bottom, 0, 0, 0, 1 }; - if (m_current_matrix_mode == GL_PROJECTION) { + if (m_current_matrix_mode == GL_PROJECTION) m_projection_matrix = m_projection_matrix * projection; - } else if (m_current_matrix_mode == GL_MODELVIEW) { + else if (m_current_matrix_mode == GL_MODELVIEW) m_projection_matrix = m_model_view_matrix * projection; - } + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = m_texture_matrix * projection; + else + VERIFY_NOT_REACHED(); } GLenum SoftwareGLContext::gl_get_error() @@ -465,6 +477,8 @@ void SoftwareGLContext::gl_load_identity() m_projection_matrix = FloatMatrix4x4::identity(); else if (m_current_matrix_mode == GL_MODELVIEW) m_model_view_matrix = FloatMatrix4x4::identity(); + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = FloatMatrix4x4::identity(); else VERIFY_NOT_REACHED(); } @@ -479,6 +493,8 @@ void SoftwareGLContext::gl_load_matrix(const FloatMatrix4x4& matrix) m_projection_matrix = matrix; else if (m_current_matrix_mode == GL_MODELVIEW) m_model_view_matrix = matrix; + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = matrix; else VERIFY_NOT_REACHED(); } @@ -488,7 +504,7 @@ void SoftwareGLContext::gl_matrix_mode(GLenum mode) APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_matrix_mode, mode); RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); - RETURN_WITH_ERROR_IF(mode < GL_MODELVIEW || mode > GL_PROJECTION, GL_INVALID_ENUM); + RETURN_WITH_ERROR_IF(mode < GL_MODELVIEW || mode > GL_TEXTURE, GL_INVALID_ENUM); m_current_matrix_mode = mode; } @@ -503,16 +519,19 @@ void SoftwareGLContext::gl_push_matrix() switch (m_current_matrix_mode) { case GL_PROJECTION: - RETURN_WITH_ERROR_IF(m_projection_matrix_stack.size() >= MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW); + RETURN_WITH_ERROR_IF(m_projection_matrix_stack.size() >= PROJECTION_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW); m_projection_matrix_stack.append(m_projection_matrix); break; case GL_MODELVIEW: - RETURN_WITH_ERROR_IF(m_model_view_matrix_stack.size() >= MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW); + RETURN_WITH_ERROR_IF(m_model_view_matrix_stack.size() >= MODELVIEW_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW); m_model_view_matrix_stack.append(m_model_view_matrix); break; + case GL_TEXTURE: + RETURN_WITH_ERROR_IF(m_texture_matrix_stack.size() >= TEXTURE_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW); + m_texture_matrix_stack.append(m_texture_matrix); + break; default: - dbgln_if(GL_DEBUG, "glPushMatrix(): Attempt to push matrix with invalid matrix mode {})", m_current_matrix_mode); - return; + VERIFY_NOT_REACHED(); } } @@ -524,7 +543,6 @@ void SoftwareGLContext::gl_pop_matrix() dbgln_if(GL_DEBUG, "glPopMatrix(): Popping matrix from matrix stack (matrix_mode = {})", m_current_matrix_mode); - // FIXME: Make sure stack::top() doesn't cause any nasty issues if it's empty (that could result in a lockup/hang) switch (m_current_matrix_mode) { case GL_PROJECTION: RETURN_WITH_ERROR_IF(m_projection_matrix_stack.size() == 0, GL_STACK_UNDERFLOW); @@ -534,9 +552,12 @@ void SoftwareGLContext::gl_pop_matrix() RETURN_WITH_ERROR_IF(m_model_view_matrix_stack.size() == 0, GL_STACK_UNDERFLOW); m_model_view_matrix = m_model_view_matrix_stack.take_last(); break; + case GL_TEXTURE: + RETURN_WITH_ERROR_IF(m_texture_matrix_stack.size() == 0, GL_STACK_UNDERFLOW); + m_texture_matrix = m_texture_matrix_stack.take_last(); + break; default: - dbgln_if(GL_DEBUG, "glPopMatrix(): Attempt to pop matrix with invalid matrix mode, {}", m_current_matrix_mode); - return; + VERIFY_NOT_REACHED(); } } @@ -546,16 +567,14 @@ void SoftwareGLContext::gl_mult_matrix(FloatMatrix4x4 const& matrix) RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); - switch (m_current_matrix_mode) { - case GL_PROJECTION: - m_projection_matrix = m_projection_matrix * matrix; - break; - case GL_MODELVIEW: + if (m_current_matrix_mode == GL_MODELVIEW) m_model_view_matrix = m_model_view_matrix * matrix; - break; - default: - dbgln_if(GL_DEBUG, "glMultMatrix(): Attempt to mult matrix with unsupported matrix mode {}", m_current_matrix_mode); - } + else if (m_current_matrix_mode == GL_PROJECTION) + m_projection_matrix = m_projection_matrix * matrix; + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = m_texture_matrix * matrix; + else + VERIFY_NOT_REACHED(); } void SoftwareGLContext::gl_rotate(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) @@ -572,6 +591,10 @@ void SoftwareGLContext::gl_rotate(GLdouble angle, GLdouble x, GLdouble y, GLdoub m_model_view_matrix = m_model_view_matrix * rotation_mat; else if (m_current_matrix_mode == GL_PROJECTION) m_projection_matrix = m_projection_matrix * rotation_mat; + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = m_texture_matrix * rotation_mat; + else + VERIFY_NOT_REACHED(); } void SoftwareGLContext::gl_scale(GLdouble x, GLdouble y, GLdouble z) @@ -580,11 +603,16 @@ void SoftwareGLContext::gl_scale(GLdouble x, GLdouble y, GLdouble z) RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); - if (m_current_matrix_mode == GL_MODELVIEW) { - m_model_view_matrix = m_model_view_matrix * Gfx::scale_matrix(FloatVector3 { static_cast(x), static_cast(y), static_cast(z) }); - } else if (m_current_matrix_mode == GL_PROJECTION) { - m_projection_matrix = m_projection_matrix * Gfx::scale_matrix(FloatVector3 { static_cast(x), static_cast(y), static_cast(z) }); - } + auto scale_matrix = Gfx::scale_matrix(FloatVector3 { static_cast(x), static_cast(y), static_cast(z) }); + + if (m_current_matrix_mode == GL_MODELVIEW) + m_model_view_matrix = m_model_view_matrix * scale_matrix; + else if (m_current_matrix_mode == GL_PROJECTION) + m_projection_matrix = m_projection_matrix * scale_matrix; + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = m_texture_matrix * scale_matrix; + else + VERIFY_NOT_REACHED(); } void SoftwareGLContext::gl_translate(GLdouble x, GLdouble y, GLdouble z) @@ -593,11 +621,16 @@ void SoftwareGLContext::gl_translate(GLdouble x, GLdouble y, GLdouble z) RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); - if (m_current_matrix_mode == GL_MODELVIEW) { - m_model_view_matrix = m_model_view_matrix * Gfx::translation_matrix(FloatVector3 { (float)x, (float)y, (float)z }); - } else if (m_current_matrix_mode == GL_PROJECTION) { - m_projection_matrix = m_projection_matrix * Gfx::translation_matrix(FloatVector3 { (float)x, (float)y, (float)z }); - } + auto translation_matrix = Gfx::translation_matrix(FloatVector3 { static_cast(x), static_cast(y), static_cast(z) }); + + if (m_current_matrix_mode == GL_MODELVIEW) + m_model_view_matrix = m_model_view_matrix * translation_matrix; + else if (m_current_matrix_mode == GL_PROJECTION) + m_projection_matrix = m_projection_matrix * translation_matrix; + else if (m_current_matrix_mode == GL_TEXTURE) + m_texture_matrix = m_texture_matrix * translation_matrix; + else + VERIFY_NOT_REACHED(); } void SoftwareGLContext::gl_vertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.h b/Userland/Libraries/LibGL/SoftwareGLContext.h index 7a4d9806da..ab34b61d4c 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.h +++ b/Userland/Libraries/LibGL/SoftwareGLContext.h @@ -161,10 +161,12 @@ private: GLenum m_current_matrix_mode; FloatMatrix4x4 m_projection_matrix = FloatMatrix4x4::identity(); FloatMatrix4x4 m_model_view_matrix = FloatMatrix4x4::identity(); - FloatMatrix4x4 m_current_matrix = FloatMatrix4x4::identity(); + FloatMatrix4x4 m_texture_matrix = FloatMatrix4x4::identity(); Vector m_projection_matrix_stack; Vector m_model_view_matrix_stack; + // FIXME: implement multi-texturing: the texture matrix stack should live inside a texture unit + Vector m_texture_matrix_stack; FloatVector4 m_clear_color { 0.0f, 0.0f, 0.0f, 0.0f }; double m_clear_depth { 1.0 };