Przeglądaj źródła

Make sure existing OpenGL state is respected. (#449)

Co-authored-by: Michael Ragazzon <[email protected]>
reworks 2 lat temu
rodzic
commit
bb9f6a45d4
2 zmienionych plików z 125 dodań i 6 usunięć
  1. 92 6
      Backends/RmlUi_Renderer_GL3.cpp
  2. 33 0
      Backends/RmlUi_Renderer_GL3.h

+ 92 - 6
Backends/RmlUi_Renderer_GL3.cpp

@@ -338,6 +338,43 @@ void RenderInterface_GL3::SetViewport(int width, int height)
 void RenderInterface_GL3::BeginFrame()
 {
 	RMLUI_ASSERT(viewport_width >= 0 && viewport_height >= 0);
+
+	// Backup GL state.
+	glstate_backup.enable_cull_face = glIsEnabled(GL_CULL_FACE);
+	glstate_backup.enable_blend = glIsEnabled(GL_BLEND);
+	glstate_backup.enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
+	glstate_backup.enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+
+	glGetIntegerv(GL_VIEWPORT, glstate_backup.viewport);
+	glGetIntegerv(GL_SCISSOR_BOX, glstate_backup.scissor);
+
+	glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &glstate_backup.stencil_clear_value);
+	glGetFloatv(GL_COLOR_CLEAR_VALUE, glstate_backup.color_clear_value);
+
+	glGetIntegerv(GL_BLEND_EQUATION_RGB, &glstate_backup.blend_equation_rgb);
+	glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &glstate_backup.blend_equation_alpha);
+	glGetIntegerv(GL_BLEND_SRC_RGB, &glstate_backup.blend_src_rgb);
+	glGetIntegerv(GL_BLEND_DST_RGB, &glstate_backup.blend_dst_rgb);
+	glGetIntegerv(GL_BLEND_SRC_ALPHA, &glstate_backup.blend_src_alpha);
+	glGetIntegerv(GL_BLEND_DST_ALPHA, &glstate_backup.blend_dst_alpha);
+
+	glGetIntegerv(GL_STENCIL_FUNC, &glstate_backup.stencil_front.func);
+	glGetIntegerv(GL_STENCIL_REF, &glstate_backup.stencil_front.ref);
+	glGetIntegerv(GL_STENCIL_VALUE_MASK, &glstate_backup.stencil_front.value_mask);
+	glGetIntegerv(GL_STENCIL_WRITEMASK, &glstate_backup.stencil_front.writemask);
+	glGetIntegerv(GL_STENCIL_FAIL, &glstate_backup.stencil_front.fail);
+	glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &glstate_backup.stencil_front.pass_depth_fail);
+	glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &glstate_backup.stencil_front.pass_depth_pass);
+
+	glGetIntegerv(GL_STENCIL_BACK_FUNC, &glstate_backup.stencil_back.func);
+	glGetIntegerv(GL_STENCIL_BACK_REF, &glstate_backup.stencil_back.ref);
+	glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &glstate_backup.stencil_back.value_mask);
+	glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &glstate_backup.stencil_back.writemask);
+	glGetIntegerv(GL_STENCIL_BACK_FAIL, &glstate_backup.stencil_back.fail);
+	glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &glstate_backup.stencil_back.pass_depth_fail);
+	glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &glstate_backup.stencil_back.pass_depth_pass);
+
+	// Setup expected GL state.
 	glViewport(0, 0, viewport_width, viewport_height);
 
 	glClearStencil(0);
@@ -345,20 +382,62 @@ void RenderInterface_GL3::BeginFrame()
 
 	glDisable(GL_CULL_FACE);
 
-	glEnable(GL_STENCIL_TEST);
-	glStencilFunc(GL_ALWAYS, 1, GLuint(-1));
-	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
 	glEnable(GL_BLEND);
 	glBlendEquation(GL_FUNC_ADD);
 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-	projection = Rml::Matrix4f::ProjectOrtho(0, (float)viewport_width, (float)viewport_height, 0, -10000, 10000);
+	glEnable(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 1, GLuint(-1));
+	glStencilMask(GLuint(-1));
+	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 
+	projection = Rml::Matrix4f::ProjectOrtho(0, (float)viewport_width, (float)viewport_height, 0, -10000, 10000);
 	SetTransform(nullptr);
 }
 
-void RenderInterface_GL3::EndFrame() {}
+void RenderInterface_GL3::EndFrame()
+{
+	// Restore GL state.
+	if (glstate_backup.enable_cull_face)
+		glEnable(GL_CULL_FACE);
+	else
+		glDisable(GL_CULL_FACE);
+
+	if (glstate_backup.enable_blend)
+		glEnable(GL_BLEND);
+	else
+		glDisable(GL_BLEND);
+
+	if (glstate_backup.enable_stencil_test)
+		glEnable(GL_STENCIL_TEST);
+	else
+		glDisable(GL_STENCIL_TEST);
+
+	if (glstate_backup.enable_scissor_test)
+		glEnable(GL_SCISSOR_TEST);
+	else
+		glDisable(GL_SCISSOR_TEST);
+
+	glViewport(glstate_backup.viewport[0], glstate_backup.viewport[1], glstate_backup.viewport[2], glstate_backup.viewport[3]);
+	glScissor(glstate_backup.scissor[0], glstate_backup.scissor[1], glstate_backup.scissor[2], glstate_backup.scissor[3]);
+
+	glClearStencil(glstate_backup.stencil_clear_value);
+	glClearColor(glstate_backup.color_clear_value[0], glstate_backup.color_clear_value[1], glstate_backup.color_clear_value[2],
+		glstate_backup.color_clear_value[3]);
+
+	glBlendEquationSeparate(glstate_backup.blend_equation_rgb, glstate_backup.blend_equation_alpha);
+	glBlendFuncSeparate(glstate_backup.blend_src_rgb, glstate_backup.blend_dst_rgb, glstate_backup.blend_src_alpha, glstate_backup.blend_dst_alpha);
+
+	glStencilFuncSeparate(GL_FRONT, glstate_backup.stencil_front.func, glstate_backup.stencil_front.ref, glstate_backup.stencil_front.value_mask);
+	glStencilMaskSeparate(GL_FRONT, glstate_backup.stencil_front.writemask);
+	glStencilOpSeparate(GL_FRONT, glstate_backup.stencil_front.fail, glstate_backup.stencil_front.pass_depth_fail,
+		glstate_backup.stencil_front.pass_depth_pass);
+
+	glStencilFuncSeparate(GL_BACK, glstate_backup.stencil_back.func, glstate_backup.stencil_back.ref, glstate_backup.stencil_back.value_mask);
+	glStencilMaskSeparate(GL_BACK, glstate_backup.stencil_back.writemask);
+	glStencilOpSeparate(GL_BACK, glstate_backup.stencil_back.fail, glstate_backup.stencil_back.pass_depth_fail,
+		glstate_backup.stencil_back.pass_depth_pass);
+}
 
 void RenderInterface_GL3::Clear()
 {
@@ -410,7 +489,9 @@ Rml::CompiledGeometryHandle RenderInterface_GL3::CompileGeometry(Rml::Vertex* ve
 
 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * num_indices, (const void*)indices, draw_usage);
+
 	glBindVertexArray(0);
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
 
 	Gfx::CheckGLError("CompileGeometry");
 
@@ -446,7 +527,10 @@ void RenderInterface_GL3::RenderCompiledGeometry(Rml::CompiledGeometryHandle han
 
 	glBindVertexArray(geometry->vao);
 	glDrawElements(GL_TRIANGLES, geometry->draw_count, GL_UNSIGNED_INT, (const GLvoid*)0);
+
 	glBindVertexArray(0);
+	glUseProgram(0);
+	glBindTexture(GL_TEXTURE_2D, 0);
 
 	Gfx::CheckGLError("RenderCompiledGeometry");
 }
@@ -652,6 +736,8 @@ bool RenderInterface_GL3::GenerateTexture(Rml::TextureHandle& texture_handle, co
 
 	texture_handle = (Rml::TextureHandle)texture_id;
 
+	glBindTexture(GL_TEXTURE_2D, 0);
+
 	return true;
 }
 

+ 33 - 0
Backends/RmlUi_Renderer_GL3.h

@@ -91,6 +91,39 @@ private:
 	int viewport_height = 0;
 
 	Rml::UniquePtr<Gfx::ShadersData> shaders;
+
+	struct GLStateBackup {
+		bool enable_cull_face;
+		bool enable_blend;
+		bool enable_stencil_test;
+		bool enable_scissor_test;
+
+		int viewport[4];
+		int scissor[4];
+
+		int stencil_clear_value;
+		float color_clear_value[4];
+
+		int blend_equation_rgb;
+		int blend_equation_alpha;
+		int blend_src_rgb;
+		int blend_dst_rgb;
+		int blend_src_alpha;
+		int blend_dst_alpha;
+
+		struct Stencil {
+			int func;
+			int ref;
+			int value_mask;
+			int writemask;
+			int fail;
+			int pass_depth_fail;
+			int pass_depth_pass;
+		};
+		Stencil stencil_front;
+		Stencil stencil_back;
+	};
+	GLStateBackup glstate_backup = {};
 };
 
 /**