1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 04:07:44 +00:00

LibGL: Set GL error on some calls during begin/end

According to the OpenGL 2.x spec, some calls will set the current
global error to `GL_INVALID_OPERATION` if they are used during
a `glBegin`/`glEnd` block.
This commit is contained in:
Jesse Buhagiar 2021-04-24 01:45:09 +10:00 committed by Andreas Kling
parent e537e2690a
commit 1959efe063
2 changed files with 73 additions and 0 deletions

View file

@ -129,17 +129,28 @@ static void clip_triangle_against_frustum(Vector<FloatVector4>& 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<uint8_t>(floor(m_clear_color.x() * 255.0f));
uint8_t g = static_cast<uint8_t>(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<float>((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<GLubyte*>(const_cast<char*>("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);