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
--- /dev/null
+#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);
+}
+
--- /dev/null
+#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
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())
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)
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
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();
glOrtho(0,1,1,0,-1,1);
}
- if (m_bounds_dirty)
+ if (m_buffer_dirty)
ReRender();
glMatrixMode(GL_MODELVIEW);
{
glDisable(GL_BLEND);
}
-
+ m_cached_display.UnBind();
+ m_cached_display.Blit();
}
#include "ipdf.h"
#include "document.h"
#include "graphicsbuffer.h"
+#include "framebuffer.h"
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);
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;