From 8900d99779d836cf4a016809277003518d0b2a7c Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Sat, 24 Nov 2012 15:19:08 +0100 Subject: [PATCH] Add OpenGL state cache to save some redundant state change. --- Android.mk | 1 + gfx_es2/CMakeLists.txt | 1 + gfx_es2/draw_buffer.cpp | 14 ++--- gfx_es2/gl_state.cpp | 23 +++++++++ gfx_es2/gl_state.h | 112 ++++++++++++++++++++++++++++++++++++++++ native.vcxproj | 2 + native.vcxproj.filters | 8 ++- ui/ui_context.cpp | 9 ++-- 8 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 gfx_es2/gl_state.cpp create mode 100644 gfx_es2/gl_state.h diff --git a/Android.mk b/Android.mk index 5038523435..5600a9952a 100644 --- a/Android.mk +++ b/Android.mk @@ -38,6 +38,7 @@ LOCAL_SRC_FILES :=\ net/resolve.cpp \ profiler/profiler.cpp \ gfx_es2/glsl_program.cpp \ + gfx_es2/gl_state.cpp \ gfx_es2/draw_buffer.cpp.arm \ gfx_es2/vertex_format.cpp \ gfx_es2/fbo.cpp \ diff --git a/gfx_es2/CMakeLists.txt b/gfx_es2/CMakeLists.txt index 43e11ef74d..e3a45b0a7f 100644 --- a/gfx_es2/CMakeLists.txt +++ b/gfx_es2/CMakeLists.txt @@ -2,6 +2,7 @@ set(SRCS draw_buffer.cpp fbo.cpp glsl_program.cpp + gl_state.cpp vertex_format.cpp) set(SRCS ${SRCS}) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 698ab346c5..f733ea13ac 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -18,6 +18,7 @@ #include "math/math_util.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/glsl_program.h" +#include "gfx_es2/gl_state.h" #include "gfx/texture_atlas.h" #include "gfx/gl_debug_log.h" @@ -50,8 +51,8 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); if (set_blend_state) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glUniform1i(program->sampler0, 0); glEnableVertexAttribArray(program->a_position); @@ -357,13 +358,8 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co } void DrawBuffer::EnableBlend(bool enable) { - if (enable) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - glDisable(GL_BLEND); + glstate.blend.set(enable); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } void DrawBuffer::SetClipRect(float x, float y, float w, float h) diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp new file mode 100644 index 0000000000..a95e9988bd --- /dev/null +++ b/gfx_es2/gl_state.cpp @@ -0,0 +1,23 @@ +#include "gl_state.h" + +OpenGLState glstate; + +void OpenGLState::Initialize() { + if(initialized) return; + + Restore(); + + initialized = true; +} + +void OpenGLState::Restore() { + blend.restore(); + blendEquation.restore(); + blendFunc.restore(); + + cullFace.restore(); + cullFaceMode.restore(); + + depthTest.restore(); + depthFunc.restore(); +} \ No newline at end of file diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h new file mode 100644 index 0000000000..a3cadded1c --- /dev/null +++ b/gfx_es2/gl_state.h @@ -0,0 +1,112 @@ +#pragma once + +#if defined(ANDROID) || defined(BLACKBERRY) +#include +#include +#else +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif +#include + +class OpenGLState +{ +private: + template + class BoolState { + bool _value; + public: + BoolState() : _value(init) {} + + inline void set(bool value) { + if(value && value != _value) { + _value = value; + glEnable(cap); + } + if(!value && value != _value) { + _value = value; + glDisable(cap); + } + } + inline void enable() { + set(true); + } + inline void disable() { + set(false); + } + operator bool() const { + return isset(); + } + inline bool isset() { + return _value; + } + void restore() { + if(_value) + glEnable(cap); + else + glDisable(cap); + } + }; + +#define STATE1(func, p1type, p1def) \ + class SavedState1_##func { \ + p1type p1; \ + public: \ + SavedState1_##func() : p1(p1def) {}; \ + void set(p1type newp1) { \ + if(newp1 != p1) { \ + p1 = newp1; \ + ##func(p1); \ + } \ + } \ + void restore() { \ + ##func(p1); \ + } \ + } + +#define STATE2(func, p1type, p2type, p1def, p2def) \ + class SavedState2_##func { \ + p1type p1; \ + p2type p2; \ + public: \ + SavedState2_##func() : p1(p1def), p2(p2def) {}; \ + inline void set(p1type newp1, p2type newp2) { \ + if(newp1 != p1 || newp2 != p2) { \ + p1 = newp1; \ + p2 = newp2; \ + ##func(p1, p2); \ + } \ + } \ + inline void restore() { \ + ##func(p1, p2); \ + } \ + } + + bool initialized; + + + +public: + OpenGLState() : initialized(false) {} + void Initialize(); + void Restore(); + + BoolState blend; + STATE2(glBlendFunc, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFunc; + STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; + + BoolState cullFace; + STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; + + BoolState depthTest; + STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; +}; + +#undef STATE1 +#undef STATE2 + +extern OpenGLState glstate; \ No newline at end of file diff --git a/native.vcxproj b/native.vcxproj index d488538e03..de6389110c 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -221,6 +221,7 @@ + @@ -310,6 +311,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index ddc4fc3429..6b3a7f67c9 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -229,6 +229,8 @@ ext + + gfx @@ -404,6 +406,10 @@ ext + + base + + gfx @@ -465,4 +471,4 @@ {4515306f-4664-46bf-a89b-abfec5520a15} - \ No newline at end of file + diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index f5fd58dd0a..f961713b5a 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -3,13 +3,14 @@ #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/glsl_program.h" +#include "gfx_es2/gl_state.h" void UIContext::Begin() { - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.cullFace.disable(); + glstate.depthTest.disable(); if (uishader_) glsl_bind(uishader_); if (uitexture_)