From 274a732e3c9af2569cbc53edf63daf3e176aaedb Mon Sep 17 00:00:00 2001
From: Sam Hocevar <sam@hocevar.net>
Date: Thu, 20 Jun 2013 16:55:23 +0000
Subject: [PATCH] gpu: move SetClearColor and SetClearDepth to the Renderer and
 RenderContext classes instead of Video.

---
 src/gpu/rendercontext.cpp   | 46 ++++++++++++++++++---------
 src/gpu/renderer.cpp        | 62 +++++++++++++++++++++++++++++++++----
 src/lol/gpu/rendercontext.h |  2 ++
 src/lol/gpu/renderer.h      |  6 ++++
 src/video.cpp               | 36 ++++-----------------
 src/video.h                 |  2 --
 test/meshviewer.cpp         |  2 +-
 tutorial/02_cube.cpp        |  2 +-
 tutorial/05_easymesh.cpp    |  4 +--
 tutorial/06_sprite.cpp      |  2 +-
 tutorial/08_fbo.cpp         | 11 +++++--
 tutorial/12_voronoi.cpp     | 45 ++++++++++++++++++---------
 12 files changed, 144 insertions(+), 76 deletions(-)

diff --git a/src/gpu/rendercontext.cpp b/src/gpu/rendercontext.cpp
index 197b5dc4..00399d6e 100644
--- a/src/gpu/rendercontext.cpp
+++ b/src/gpu/rendercontext.cpp
@@ -19,36 +19,32 @@
 namespace lol
 {
 
-class TrackedState
+template<typename T> class TrackedState
 {
 public:
     inline TrackedState()
-      : m_state(Unchanged)
+      : m_changed(false)
     {}
 
-    inline void TrackValue(bool set)
+    inline void TrackValue(T const &value)
     {
-        m_state = set ? MustSet : MustUnset;
+        m_value = value;
+        m_changed = true;
     }
 
     inline bool HasChanged()
     {
-        return m_state != Unchanged;
+        return m_changed;
     }
 
-    inline bool GetValue()
+    inline T GetValue()
     {
-        return m_state == MustSet;
+        return m_value;
     }
 
 private:
-    enum
-    {
-        Unchanged,
-        MustSet,
-        MustUnset,
-    }
-    m_state;
+    T m_value;
+    bool m_changed;
 };
 
 class RenderContextData
@@ -58,7 +54,11 @@ class RenderContextData
 private:
     Scene *m_scene;
 
-    TrackedState m_alpha_blend, m_depth_test, m_face_culling;
+    TrackedState<vec4> m_clear_color;
+    TrackedState<float> m_clear_depth;
+    TrackedState<bool> m_alpha_blend;
+    TrackedState<bool> m_depth_test;
+    TrackedState<bool> m_face_culling;
 };
 
 /*
@@ -85,6 +85,22 @@ RenderContext::~RenderContext()
     delete m_data;
 }
 
+void RenderContext::SetClearColor(vec4 color)
+{
+    if (!m_data->m_clear_color.HasChanged())
+        m_data->m_clear_color.TrackValue(g_renderer->GetClearColor());
+
+    g_renderer->SetClearColor(color);
+}
+
+void RenderContext::SetClearDepth(float depth)
+{
+    if (!m_data->m_clear_depth.HasChanged())
+        m_data->m_clear_depth.TrackValue(g_renderer->GetClearDepth());
+
+    g_renderer->SetClearDepth(depth);
+}
+
 void RenderContext::SetAlphaBlend(bool set)
 {
     if (!m_data->m_alpha_blend.HasChanged())
diff --git a/src/gpu/renderer.cpp b/src/gpu/renderer.cpp
index d4c1cdff..09350947 100644
--- a/src/gpu/renderer.cpp
+++ b/src/gpu/renderer.cpp
@@ -47,6 +47,8 @@ class RendererData
     friend class Renderer;
 
 private:
+    vec4 m_clear_color;
+    float m_clear_depth;
     bool m_blend, m_depth_test, m_face_culling;
 };
 
@@ -57,6 +59,12 @@ private:
 Renderer::Renderer()
   : m_data(new RendererData())
 {
+    m_data->m_clear_color = vec4(-1.f);
+    SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f));
+
+    m_data->m_clear_depth = -1.f;
+    SetClearDepth(1.f);
+
     m_data->m_blend = false;
     SetAlphaBlend(true);
 
@@ -72,6 +80,48 @@ Renderer::~Renderer()
     delete m_data;
 }
 
+/*
+ * Clear color
+ */
+
+void Renderer::SetClearColor(vec4 color)
+{
+#if defined USE_D3D9 || defined _XBOX
+    /* Nothing to do */
+#else
+    glClearColor(color.r, color.g, color.b, color.a);
+#endif
+
+    m_data->m_clear_color = color;
+}
+
+vec4 Renderer::GetClearColor() const
+{
+    return m_data->m_clear_color;
+}
+
+/*
+ * Clear depth
+ */
+
+void Renderer::SetClearDepth(float depth)
+{
+#if defined USE_D3D9 || defined _XBOX
+    /* Nothing to do */
+#elif defined HAVE_GLES_2X
+    glClearDepthf(depth);
+#else
+    glClearDepth(depth);
+#endif
+
+    m_data->m_clear_depth = depth;
+}
+
+float Renderer::GetClearDepth() const
+{
+    return m_data->m_clear_depth;
+}
+
 /*
  * Alpha blending
  */
@@ -81,8 +131,6 @@ void Renderer::SetAlphaBlend(bool set)
     if (m_data->m_blend == set)
         return;
 
-    m_data->m_blend = set;
-
 #if defined USE_D3D9 || defined _XBOX
 #   define STR0(x) #x
 #   define STR(x) STR0(x)
@@ -93,6 +141,8 @@ void Renderer::SetAlphaBlend(bool set)
     else
         glDisable(GL_BLEND);
 #endif
+
+    m_data->m_blend = set;
 }
 
 bool Renderer::GetAlphaBlend() const
@@ -109,8 +159,6 @@ void Renderer::SetDepthTest(bool set)
     if (m_data->m_depth_test == set)
         return;
 
-    m_data->m_depth_test = set;
-
 #if defined USE_D3D9 || defined _XBOX
 #   define STR0(x) #x
 #   define STR(x) STR0(x)
@@ -121,6 +169,8 @@ void Renderer::SetDepthTest(bool set)
     else
         glDisable(GL_DEPTH_TEST);
 #endif
+
+    m_data->m_depth_test = set;
 }
 
 bool Renderer::GetDepthTest() const
@@ -137,8 +187,6 @@ void Renderer::SetFaceCulling(bool set)
     if (m_data->m_face_culling == set)
         return;
 
-    m_data->m_face_culling = set;
-
 #if defined USE_D3D9 || defined _XBOX
 #   define STR0(x) #x
 #   define STR(x) STR0(x)
@@ -149,6 +197,8 @@ void Renderer::SetFaceCulling(bool set)
     else
         glDisable(GL_CULL_FACE);
 #endif
+
+    m_data->m_face_culling = set;
 }
 
 bool Renderer::GetFaceCulling() const
diff --git a/src/lol/gpu/rendercontext.h b/src/lol/gpu/rendercontext.h
index 3377b74b..6f4acda1 100644
--- a/src/lol/gpu/rendercontext.h
+++ b/src/lol/gpu/rendercontext.h
@@ -27,6 +27,8 @@ public:
     RenderContext();
     ~RenderContext();
 
+    void SetClearColor(vec4 color);
+    void SetClearDepth(float depth);
     void SetAlphaBlend(bool set);
     void SetDepthTest(bool set);
     void SetFaceCulling(bool set);
diff --git a/src/lol/gpu/renderer.h b/src/lol/gpu/renderer.h
index 32da1870..d9853a66 100644
--- a/src/lol/gpu/renderer.h
+++ b/src/lol/gpu/renderer.h
@@ -27,6 +27,12 @@ public:
     Renderer();
     ~Renderer();
 
+    void SetClearColor(vec4 color);
+    vec4 GetClearColor() const;
+
+    void SetClearDepth(float depth);
+    float GetClearDepth() const;
+
     void SetAlphaBlend(bool set);
     bool GetAlphaBlend() const;
 
diff --git a/src/video.cpp b/src/video.cpp
index f1a5ab08..83255330 100644
--- a/src/video.cpp
+++ b/src/video.cpp
@@ -60,8 +60,6 @@ private:
     static Direct3D *d3d_ctx;
     static D3DDevice *d3d_dev;
 #   endif
-    static D3DCOLOR clear_color;
-    static float clear_depth;
 #endif
 };
 
@@ -77,8 +75,6 @@ IDirect3DDevice9 *VideoData::d3d_dev;
 Direct3D *VideoData::d3d_ctx;
 D3DDevice *VideoData::d3d_dev;
 #   endif
-D3DCOLOR VideoData::clear_color;
-float VideoData::clear_depth;
 #endif
 
 /*
@@ -155,8 +151,6 @@ void Video::Setup(ivec2 size)
     g_renderer = new Renderer();
 
     /* Initialise reasonable scene default properties */
-    SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f));
-    SetClearDepth(1.f);
     SetDebugRenderMode(DebugRenderMode::Default);
 }
 
@@ -233,28 +227,6 @@ void Video::SetFov(float theta)
     }
 }
 
-void Video::SetClearColor(vec4 color)
-{
-#if defined USE_D3D9 || defined _XBOX
-    VideoData::clear_color = D3DCOLOR_XRGB((int)(color.r * 255.999f),
-                                           (int)(color.g * 255.999f),
-                                           (int)(color.b * 255.999f));
-#else
-    glClearColor(color.r, color.g, color.b, color.a);
-#endif
-}
-
-void Video::SetClearDepth(float f)
-{
-#if defined USE_D3D9 || defined _XBOX
-    VideoData::clear_depth = f;
-#elif defined HAVE_GLES_2X
-    glClearDepthf(f);
-#else
-    glClearDepth(f);
-#endif
-}
-
 void Video::SetDebugRenderMode(DebugRenderMode d)
 {
     switch(d)
@@ -321,9 +293,13 @@ void Video::Clear(ClearMask m)
         mask |= D3DCLEAR_ZBUFFER;
     if (m & ClearMask::Stencil)
         mask |= D3DCLEAR_STENCIL;
+
+    vec4 tmp = 255.999f * g_renderer->GetClearColor();
+    D3DCOLOR clear_color = D3DCOLOR_XRGB((int)tmp.r, (int)tmp.g, (int)tmp.b);
+
     if (FAILED(VideoData::d3d_dev->Clear(0, nullptr, mask,
-                                         VideoData::clear_color,
-                                         VideoData::clear_depth, 0)))
+                                         clear_color,
+                                         g_renderer->GetClearDepth(), 0)))
         Abort();
 #else
     /* FIXME: is this necessary here? */
diff --git a/src/video.h b/src/video.h
index eba9c2d2..fa11f33c 100644
--- a/src/video.h
+++ b/src/video.h
@@ -71,8 +71,6 @@ public:
     static void SetCustomSize(ivec2 size);
     static void RestoreSize();
     static void SetFov(float theta);
-    static void SetClearColor(vec4 color);
-    static void SetClearDepth(float f);
     static void SetDebugRenderMode(DebugRenderMode d);
     static DebugRenderMode GetDebugRenderMode();
     static void Clear(ClearMask m);
diff --git a/test/meshviewer.cpp b/test/meshviewer.cpp
index 46c1415a..8390d68f 100644
--- a/test/meshviewer.cpp
+++ b/test/meshviewer.cpp
@@ -440,7 +440,7 @@ public:
             }
         }
 
-        Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
+        g_renderer->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
 
         mat4 default_proj = Scene::GetDefault()->GetCamera()->GetProjection();
         int max_drawn = m_meshes.Count() - m_mesh_shown;
diff --git a/tutorial/02_cube.cpp b/tutorial/02_cube.cpp
index 50564be8..ebe746da 100644
--- a/tutorial/02_cube.cpp
+++ b/tutorial/02_cube.cpp
@@ -103,7 +103,7 @@ public:
             m_ready = true;
         }
 
-        Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
+        g_renderer->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
 
         m_shader->Bind();
         m_vdecl->SetStream(m_vbo, m_coord, m_color);
diff --git a/tutorial/05_easymesh.cpp b/tutorial/05_easymesh.cpp
index 2e3a09e1..b1672833 100644
--- a/tutorial/05_easymesh.cpp
+++ b/tutorial/05_easymesh.cpp
@@ -111,13 +111,13 @@ public:
 
         if (!m_ready)
         {
+            g_renderer->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
+
             for (int i = 0; i < m_gears.Count(); i++)
                 m_gears[i].m1.MeshConvert();
             m_ready = true;
         }
 
-        Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
-
         for (int i = 0; i < m_gears.Count(); i++)
             m_gears[i].m1.Render(m_mat * m_gears[i].m2);
     }
diff --git a/tutorial/06_sprite.cpp b/tutorial/06_sprite.cpp
index f57887cc..0e47bf48 100644
--- a/tutorial/06_sprite.cpp
+++ b/tutorial/06_sprite.cpp
@@ -69,7 +69,7 @@ public:
 
         if (!m_ready)
         {
-            Video::SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
+            g_renderer->SetClearColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));
             m_ready = true;
         }
 
diff --git a/tutorial/08_fbo.cpp b/tutorial/08_fbo.cpp
index b315b80c..40b4cbe9 100644
--- a/tutorial/08_fbo.cpp
+++ b/tutorial/08_fbo.cpp
@@ -73,9 +73,14 @@ public:
 
             m_fbo = new Framebuffer(Video::GetSize());
             m_fbo->Bind();
-            Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
-            Video::SetClearDepth(1.f);
-            Video::Clear(ClearMask::Color | ClearMask::Depth);
+
+            {
+                RenderContext rc;
+                rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
+                rc.SetClearDepth(1.f);
+                Video::Clear(ClearMask::Color | ClearMask::Depth);
+            }
+
             m_fbo->Unbind();
 
             m_ready = true;
diff --git a/tutorial/12_voronoi.cpp b/tutorial/12_voronoi.cpp
index ce6fc05c..f4db8326 100644
--- a/tutorial/12_voronoi.cpp
+++ b/tutorial/12_voronoi.cpp
@@ -122,17 +122,23 @@ public:
                 }
 
                 m_fbos.Last().m1->Bind();
-                Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
-                Video::SetClearDepth(1.f);
-                Video::Clear(ClearMask::Color | ClearMask::Depth);
+                {
+                    RenderContext rc;
+                    rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
+                    rc.SetClearDepth(1.f);
+                    Video::Clear(ClearMask::Color | ClearMask::Depth);
+                }
                 m_fbos.Last().m1->Unbind();
             }
 
             temp_buffer = new Framebuffer(Video::GetSize());
             temp_buffer->Bind();
-            Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
-            Video::SetClearDepth(1.f);
-            Video::Clear(ClearMask::Color | ClearMask::Depth);
+            {
+                RenderContext rc;
+                rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
+                rc.SetClearDepth(1.f);
+                Video::Clear(ClearMask::Color | ClearMask::Depth);
+            }
             temp_buffer->Unbind();
 
             m_ready = true;
@@ -188,9 +194,12 @@ public:
         }
 
         temp_buffer->Bind();
-        Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
-        Video::SetClearDepth(1.f);
-        Video::Clear(ClearMask::Color | ClearMask::Depth);
+        {
+            RenderContext rc;
+            rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
+            rc.SetClearDepth(1.f);
+            Video::Clear(ClearMask::Color | ClearMask::Depth);
+        }
         temp_buffer->Unbind();
 
         {
@@ -215,9 +224,12 @@ public:
             int f = SrcVoronoiFbo;
 
             m_fbos[f].m1->Bind();
-            Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
-            Video::SetClearDepth(1.f);
-            Video::Clear(ClearMask::Color | ClearMask::Depth);
+            {
+                RenderContext rc;
+                rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
+                rc.SetClearDepth(1.f);
+                Video::Clear(ClearMask::Color | ClearMask::Depth);
+            }
             m_fbos[f].m1->Unbind();
 
             int buf = voronoi_points.Count() % 2;
@@ -266,9 +278,12 @@ public:
         {
             //m_timer = 1.0f;
             m_fbos[m_cur_fbo].m1->Bind();
-            Video::SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
-            Video::SetClearDepth(1.f);
-            Video::Clear(ClearMask::Color | ClearMask::Depth);
+            {
+                RenderContext rc;
+                rc.SetClearColor(vec4(0.f, 0.f, 0.f, 1.f));
+                rc.SetClearDepth(1.f);
+                Video::Clear(ClearMask::Color | ClearMask::Depth);
+            }
             m_fbos[m_cur_fbo].m1->Unbind();
 
             ivec2 curres = ivec2(512, 512) / 2;