Don't re-render the display if nothing has changed
authorDavid Gow <[email protected]>
Tue, 22 Apr 2014 03:29:25 +0000 (11:29 +0800)
committerDavid Gow <[email protected]>
Tue, 22 Apr 2014 03:29:25 +0000 (11:29 +0800)
We now render to an offscreen buffer, and blit that
to the screen. This probably breaks the bitmap stuff, and I'll
fix that soon.

bin/ipdf
src/Makefile
src/framebuffer.cpp [new file with mode: 0644]
src/framebuffer.h [new file with mode: 0644]
src/main.h
src/view.cpp
src/view.h

index 1428b87..0c11d65 100755 (executable)
Binary files a/bin/ipdf and b/bin/ipdf differ
index 0b3be85..008a613 100644 (file)
@@ -4,7 +4,7 @@ ARCH := $(shell uname -m)
 CXX = g++ -std=gnu++0x -g
 # -Wall -Werror -Wshadow -pedantic
 MAIN = main.o
-OBJ = log.o real.o document.o view.o screen.o vfpu.o graphicsbuffer.o stb_truetype.o
+OBJ = log.o real.o document.o view.o screen.o vfpu.o graphicsbuffer.o framebuffer.o stb_truetype.o
 LIB_x86_64 = ../contrib/lib/libSDL2-2.0.so.0 -lGL
 LIB_i386 = ../contrib/lib32/libSDL2-2.0.so.0 -lGL
 
diff --git a/src/framebuffer.cpp b/src/framebuffer.cpp
new file mode 100644 (file)
index 0000000..88d2cd4
--- /dev/null
@@ -0,0 +1,59 @@
+#include "framebuffer.h"
+#define GL_GLEXT_PROTOTYPES
+#include <SDL_opengl.h>
+#include <GL/glext.h>
+
+using namespace IPDF;
+
+void FrameBuffer::Create(int w, int h)
+{
+       if (m_render_texture)
+       {
+               Destroy();
+       }
+       m_width = w;
+       m_height = h;
+       glGenTextures(1, &m_render_texture);
+       glGenFramebuffers(1, &m_render_fbo);
+
+       glBindTexture(GL_TEXTURE_2D, m_render_texture);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+       glBindFramebuffer(GL_FRAMEBUFFER, m_render_fbo);
+
+       glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_render_texture, 0);
+
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+       glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void FrameBuffer::Destroy()
+{
+       if (!m_render_texture) return;
+       glDeleteFramebuffers(1, &m_render_fbo);
+       glDeleteTextures(1, &m_render_texture);
+}
+
+void FrameBuffer::Bind()
+{
+       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_render_fbo);
+}
+
+void FrameBuffer::UnBind()
+{
+       glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void FrameBuffer::Blit()
+{
+       glBindFramebuffer(GL_READ_FRAMEBUFFER, m_render_fbo);
+       glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+}
+
+void FrameBuffer::Clear(float r, float g, float b, float a)
+{
+       Bind();
+       glClearColor(r,g,b,a);
+       glClear(GL_COLOR_BUFFER_BIT);
+}
+
diff --git a/src/framebuffer.h b/src/framebuffer.h
new file mode 100644 (file)
index 0000000..e3ec6fa
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _FRAMEBUFFER_H
+#define _FRAMEBUFFER_H
+
+#include <SDL.h>
+#define GL_GLEXT_PROTOTYPES
+#include <SDL_opengl.h>
+
+
+namespace IPDF
+{
+       /*
+        * The "Screen" class handles managing the OS window (using SDL2).
+        */
+       class FrameBuffer
+       {
+       public:
+               FrameBuffer() : m_render_texture(0), m_render_fbo(0), m_width(0), m_height(0) {}
+               ~FrameBuffer() { Destroy(); }
+               void Create(int w, int h);
+               void Destroy();
+               void Bind();
+               void UnBind();
+               void Blit();
+               void Clear(float r=1.0, float g=1.0, float b=1.0, float a=1.0);
+               int GetWidth() { return m_width; }
+               int GetHeight() { return m_height; }
+       private:
+               GLuint m_render_texture;
+               GLuint m_render_fbo;
+               int m_width;
+               int m_height;
+       };
+
+}
+
+#endif // _SCREEN_H
index 7d586ce..e6100ed 100644 (file)
@@ -69,7 +69,7 @@ inline void MainLoop(Document & doc, const Rect & bounds = Rect(0,0,1,1), const
        while (scr.PumpEvents())
        {
                scr.Clear();
-               view.Render();
+               view.Render(scr.ViewportWidth(), scr.ViewportHeight());
                scr.DebugFontPrintF("[CPU] Render took %lf ms (%lf FPS)\n", (SDL_GetPerformanceCounter() - init_time)* 1000.0/SDL_GetPerformanceFrequency(), SDL_GetPerformanceFrequency()/(SDL_GetPerformanceCounter() - init_time));
                scr.DebugFontPrintF("View bounds: %s\n", view.GetBounds().Str().c_str());
                if (view.UsingGPUTransform())
index c5a1841..d9227b4 100644 (file)
@@ -13,7 +13,10 @@ void View::Translate(Real x, Real y)
        m_bounds.y += y;
        Debug("View Bounds => %s", m_bounds.Str().c_str());
        if (!m_use_gpu_transform)
-               m_bounds_dirty = true;
+       {
+               m_buffer_dirty = true;
+       }
+       m_bounds_dirty = true;
 }
 
 void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt)
@@ -39,7 +42,8 @@ void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt)
        m_bounds.h *= scaleAmt;
        Debug("View Bounds => %s", m_bounds.Str().c_str());
        if (!m_use_gpu_transform)
-               m_bounds_dirty = true;
+               m_buffer_dirty = true;
+       m_bounds_dirty = true;
 }
 
 Rect View::TransformToViewCoords(const Rect& inp) const
@@ -80,8 +84,22 @@ void View::DrawGrid()
 
 void glPrimitiveRestartIndex(GLuint index);
 
-void View::Render()
+void View::Render(int width, int height)
 {
+       if (width != m_cached_display.GetWidth() || height != m_cached_display.GetHeight())
+       {
+               m_cached_display.Create(width, height);
+               m_bounds_dirty = true;
+       }
+
+       if (!m_bounds_dirty)
+       {
+               m_cached_display.UnBind();
+               m_cached_display.Blit();
+               return;
+       }
+       m_cached_display.Bind();
+       m_cached_display.Clear();
        
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
@@ -94,7 +112,7 @@ void View::Render()
                glOrtho(0,1,1,0,-1,1);
        }
 
-       if (m_bounds_dirty)
+       if (m_buffer_dirty)
                ReRender();
 
        glMatrixMode(GL_MODELVIEW);
@@ -118,7 +136,8 @@ void View::Render()
        {
                glDisable(GL_BLEND);
        }
-
+       m_cached_display.UnBind();
+       m_cached_display.Blit();
 
 }
 
index 172b5e7..d5fe522 100644 (file)
@@ -4,6 +4,7 @@
 #include "ipdf.h"
 #include "document.h"
 #include "graphicsbuffer.h"
+#include "framebuffer.h"
 
 namespace IPDF
 {
@@ -11,13 +12,13 @@ namespace IPDF
        {
                public:
                        View(Document & document, const Rect & bounds = Rect(0,0,1,1), const Colour & colour = Colour(0.f,0.f,0.f,1.f)) 
-                               : m_document(document), m_bounds(bounds), m_colour(colour), m_use_gpu_transform(false), m_bounds_dirty(true)
+                               : m_document(document), m_bounds(bounds), m_colour(colour), m_use_gpu_transform(false), m_bounds_dirty(true), m_buffer_dirty(true)
                        {
                                Debug("View Created - Bounds => {%s}", m_bounds.Str().c_str());
                        }
                        virtual ~View() {}
 
-                       void Render();
+                       void Render(int width = 0, int height = 0);
                        
                        void Translate(Real x, Real y);
                        void ScaleAroundPoint(Real x, Real y, Real scaleAmt);
@@ -27,15 +28,17 @@ namespace IPDF
                        const Rect& GetBounds() const { return m_bounds; }
                        
                        const bool UsingGPUTransform() const { return m_use_gpu_transform; }
-                       void ToggleGPUTransform() { m_use_gpu_transform = (!m_use_gpu_transform); m_bounds_dirty = true; }
+                       void ToggleGPUTransform() { m_use_gpu_transform = (!m_use_gpu_transform); m_bounds_dirty = true; m_buffer_dirty = true; }
                
                private:
                        void ReRender();
                        void DrawGrid();
                        bool m_use_gpu_transform;
                        bool m_bounds_dirty;
+                       bool m_buffer_dirty;
                        GraphicsBuffer m_vertex_buffer;
                        GraphicsBuffer m_index_buffer;
+                       FrameBuffer m_cached_display;
                        Document & m_document;
                        Rect m_bounds;
                        Colour m_colour;

UCC git Repository :: git.ucc.asn.au