From: David Gow Date: Tue, 22 Apr 2014 03:29:25 +0000 (+0800) Subject: Don't re-render the display if nothing has changed X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=commitdiff_plain;h=45806117a53330b9f0c9c60310d79c56e960fd1f Don't re-render the display if nothing has changed 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. --- diff --git a/bin/ipdf b/bin/ipdf index 1428b87..0c11d65 100755 Binary files a/bin/ipdf and b/bin/ipdf differ diff --git a/src/Makefile b/src/Makefile index 0b3be85..008a613 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 index 0000000..88d2cd4 --- /dev/null +++ b/src/framebuffer.cpp @@ -0,0 +1,59 @@ +#include "framebuffer.h" +#define GL_GLEXT_PROTOTYPES +#include +#include + +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 index 0000000..e3ec6fa --- /dev/null +++ b/src/framebuffer.h @@ -0,0 +1,36 @@ +#ifndef _FRAMEBUFFER_H +#define _FRAMEBUFFER_H + +#include +#define GL_GLEXT_PROTOTYPES +#include + + +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 diff --git a/src/main.h b/src/main.h index 7d586ce..e6100ed 100644 --- a/src/main.h +++ b/src/main.h @@ -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()) diff --git a/src/view.cpp b/src/view.cpp index c5a1841..d9227b4 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -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(); } diff --git a/src/view.h b/src/view.h index 172b5e7..d5fe522 100644 --- a/src/view.h +++ b/src/view.h @@ -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;