diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.cpp b/Userland/Libraries/LibGL/SoftwareGLContext.cpp index 0ffb999170..9ee041f490 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.cpp +++ b/Userland/Libraries/LibGL/SoftwareGLContext.cpp @@ -129,17 +129,28 @@ static void clip_triangle_against_frustum(Vector& in_vec) void SoftwareGLContext::gl_begin(GLenum mode) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + if (mode < GL_TRIANGLES || mode > GL_POLYGON) { m_error = GL_INVALID_ENUM; return; } m_current_draw_mode = mode; + m_in_draw_state = true; // Certain commands will now generate an error m_error = GL_NO_ERROR; } void SoftwareGLContext::gl_clear(GLbitfield mask) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + if (mask & GL_COLOR_BUFFER_BIT) { uint8_t r = static_cast(floor(m_clear_color.x() * 255.0f)); uint8_t g = static_cast(floor(m_clear_color.y() * 255.0f)); @@ -155,6 +166,11 @@ void SoftwareGLContext::gl_clear(GLbitfield mask) void SoftwareGLContext::gl_clear_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + m_clear_color = { red, green, blue, alpha }; m_error = GL_NO_ERROR; } @@ -181,6 +197,12 @@ void SoftwareGLContext::gl_end() float scr_width = 640.0f; float scr_height = 480.0f; + // Make sure we had a `glBegin` before this call... + if (!m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + // Let's construct some triangles if (m_current_draw_mode == GL_TRIANGLES) { GLTriangle triangle; @@ -385,11 +407,17 @@ void SoftwareGLContext::gl_end() processed_triangles.clear(); vertex_list.clear(); + m_in_draw_state = false; m_error = GL_NO_ERROR; } void SoftwareGLContext::gl_frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + // Let's do some math! // FIXME: Are we losing too much precision by doing this? float a = static_cast((right + left) / (right - left)); @@ -416,11 +444,20 @@ void SoftwareGLContext::gl_frustum(GLdouble left, GLdouble right, GLdouble botto GLenum SoftwareGLContext::gl_get_error() { + if (m_in_draw_state) { + return GL_INVALID_OPERATION; + } + return m_error; } GLubyte* SoftwareGLContext::gl_get_string(GLenum name) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return nullptr; + } + switch (name) { case GL_VENDOR: return reinterpret_cast(const_cast("The SerenityOS Developers")); @@ -439,6 +476,11 @@ GLubyte* SoftwareGLContext::gl_get_string(GLenum name) void SoftwareGLContext::gl_load_identity() { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + if (m_current_matrix_mode == GL_PROJECTION) m_projection_matrix = FloatMatrix4x4::identity(); else if (m_current_matrix_mode == GL_MODELVIEW) @@ -451,6 +493,11 @@ void SoftwareGLContext::gl_load_identity() void SoftwareGLContext::gl_matrix_mode(GLenum mode) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + if (mode < GL_MODELVIEW || mode > GL_PROJECTION) { m_error = GL_INVALID_ENUM; return; @@ -462,6 +509,11 @@ void SoftwareGLContext::gl_matrix_mode(GLenum mode) void SoftwareGLContext::gl_push_matrix() { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + dbgln_if(GL_DEBUG, "glPushMatrix(): Pushing matrix to the matrix stack (matrix_mode {})", m_current_matrix_mode); switch (m_current_matrix_mode) { @@ -481,6 +533,11 @@ void SoftwareGLContext::gl_push_matrix() void SoftwareGLContext::gl_pop_matrix() { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + 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) @@ -501,6 +558,11 @@ void SoftwareGLContext::gl_pop_matrix() void SoftwareGLContext::gl_rotate(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + FloatVector3 axis = { (float)x, (float)y, (float)z }; axis.normalize(); auto rotation_mat = FloatMatrix4x4::rotate(axis, angle); @@ -515,6 +577,11 @@ void SoftwareGLContext::gl_rotate(GLdouble angle, GLdouble x, GLdouble y, GLdoub void SoftwareGLContext::gl_translate(GLdouble x, GLdouble y, GLdouble z) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + if (m_current_matrix_mode == GL_MODELVIEW) { m_model_view_matrix = m_model_view_matrix * FloatMatrix4x4::translate({ (float)x, (float)y, (float)z }); } else if (m_current_matrix_mode == GL_PROJECTION) { @@ -548,6 +615,11 @@ void SoftwareGLContext::gl_vertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w void SoftwareGLContext::gl_viewport(GLint x, GLint y, GLsizei width, GLsizei height) { + if (m_in_draw_state) { + m_error = GL_INVALID_OPERATION; + return; + } + (void)(x); (void)(y); (void)(width); diff --git a/Userland/Libraries/LibGL/SoftwareGLContext.h b/Userland/Libraries/LibGL/SoftwareGLContext.h index 7ae19b9a42..58bb859867 100644 --- a/Userland/Libraries/LibGL/SoftwareGLContext.h +++ b/Userland/Libraries/LibGL/SoftwareGLContext.h @@ -52,6 +52,7 @@ private: Vector processed_triangles; GLenum m_error = GL_NO_ERROR; + bool m_in_draw_state = false; }; }