Store everything in a VBO, making things faster.
authorDavid Gow <david@ingeniumdigital.com>
Mon, 21 Apr 2014 05:46:46 +0000 (13:46 +0800)
committerDavid Gow <david@ingeniumdigital.com>
Mon, 21 Apr 2014 05:46:46 +0000 (13:46 +0800)
Also 1024*1024 grid of boxes, for extreme slowness. Yay!

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

index 10e25fe..7e9fdb3 100755 (executable)
Binary files a/bin/ipdf and b/bin/ipdf differ
index 90adae9..0b3be85 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 stb_truetype.o
+OBJ = log.o real.o document.o view.o screen.o vfpu.o graphicsbuffer.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/graphicsbuffer.cpp b/src/graphicsbuffer.cpp
new file mode 100644 (file)
index 0000000..906226e
--- /dev/null
@@ -0,0 +1,137 @@
+#include "graphicsbuffer.h"
+#define GL_GLEXT_PROTOTYPES
+#include <SDL_opengl.h>
+#include <GL/glext.h>
+
+using namespace IPDF;
+
+GraphicsBuffer::GraphicsBuffer()
+{
+       SetUsage(BufferUsageStaticDraw);
+}
+
+GraphicsBuffer::~GraphicsBuffer()
+{
+       if (m_map_pointer)
+       {
+               UnMap();
+       }
+       glDeleteBuffers(1, &m_buffer_handle);
+}
+
+void GraphicsBuffer::SetType(GraphicsBuffer::BufferType bufType)
+{
+       glGenBuffers(1, &m_buffer_handle);
+       m_buffer_type = bufType;
+}
+
+void GraphicsBuffer::SetUsage(GraphicsBuffer::BufferUsage bufUsage)
+{
+       m_buffer_usage = bufUsage;
+}
+
+void* GraphicsBuffer::Map(bool read, bool write, bool invalidate)
+{
+       GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_BUFFER_BIT:0);
+       GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER;
+       
+       Bind();
+       
+       return glMapBufferRange(target, 0, m_buffer_size, access);
+       
+       //TODO: Emulate DSA
+       //return glMapNamedBufferEXT(m_bufferHandle, access);
+}
+
+void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bool invalidate)
+{
+       GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_RANGE_BIT:0);
+       GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER;
+       
+       Bind();
+       
+       return glMapBufferRange(target, offset, length, access);
+
+       //TODO: Emulate DSA
+       //return glMapNamedBufferRangeEXT(m_bufferHandle, offset, length, access);
+}
+
+void GraphicsBuffer::UnMap()
+{
+       GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER;
+       
+       Bind();
+       glUnmapBuffer(target);
+       //glUnmapNamedBufferEXT(m_bufferHandle);
+}
+
+void GraphicsBuffer::Upload(size_t length, const void* data)
+{
+       GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER;
+       
+       GLenum usage;
+       switch (m_buffer_usage)
+       {
+       case BufferUsageStaticDraw:
+               usage = GL_STATIC_DRAW;
+               break;
+       case BufferUsageStaticRead:
+               usage = GL_STATIC_READ;
+               break;
+       case BufferUsageStaticCopy:
+               usage = GL_STATIC_COPY;
+               break;
+       case BufferUsageDynamicDraw:
+               usage = GL_DYNAMIC_DRAW;
+               break;
+       case BufferUsageDynamicRead:
+               usage = GL_DYNAMIC_READ;
+               break;
+       case BufferUsageDynamicCopy:
+               usage = GL_DYNAMIC_COPY;
+               break;
+       case BufferUsageStreamDraw:
+               usage = GL_STREAM_DRAW;
+               break;
+       case BufferUsageStreamRead:
+               usage = GL_STREAM_READ;
+               break;
+       case BufferUsageStreamCopy:
+               usage = GL_STREAM_COPY;
+               break;
+       default:
+               SDL_assert(false && "Unknown buffer usage type.");
+               usage = GL_DYNAMIC_DRAW;
+       }
+       
+       Bind();
+       glBufferData(target, length, data, usage);
+       m_buffer_size = length;
+       //glNamedBufferDataEXT(m_bufferHandle, length, data, usage);
+}
+
+void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* data)
+{
+       GLenum target = (m_buffer_type == GraphicsBuffer::BufferTypeVertex)?GL_ARRAY_BUFFER:GL_ELEMENT_ARRAY_BUFFER;
+       
+       Bind();
+       glBufferSubData(target, offset, length, data);
+       //glNamedBufferSubDataEXT(m_bufferHandle, offset, length, data);
+}
+
+void GraphicsBuffer::Bind()
+{
+       if (m_buffer_type == BufferTypeVertex)
+               glBindBuffer(GL_ARRAY_BUFFER, m_buffer_handle);
+       else if (m_buffer_type == BufferTypeIndex)
+               glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer_handle);
+       else if (m_buffer_type == BufferTypePixelPack)
+               glBindBuffer(GL_PIXEL_PACK_BUFFER, m_buffer_handle);
+       else if (m_buffer_type == BufferTypePixelUnpack)
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_buffer_handle);
+       else if (m_buffer_type == BufferTypeUniform)
+               glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer_handle);
+       else if (m_buffer_type == BufferTypeDrawIndirect)
+               glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_buffer_handle);
+}
+
diff --git a/src/graphicsbuffer.h b/src/graphicsbuffer.h
new file mode 100644 (file)
index 0000000..15e5b42
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef _GRAPHICSBUFFER_H
+#define _GRAPHICSBUFFER_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 GraphicsBuffer
+       {
+       public:
+               enum BufferType
+               {
+                       BufferTypeVertex,               // A Vertex Buffer
+                       BufferTypeIndex,                // An Index Buffer
+                       BufferTypePixelPack,            // Pixel Pack buffer
+                       BufferTypePixelUnpack,
+                       BufferTypeUniform,              // Uniform/Constant buffer
+                       BufferTypeDrawIndirect,
+               };
+               
+               enum BufferUsage
+               {
+                       BufferUsageStaticDraw,
+                       BufferUsageStaticRead,
+                       BufferUsageStaticCopy,
+                       BufferUsageDynamicDraw,
+                       BufferUsageDynamicRead,
+                       BufferUsageDynamicCopy,
+                       BufferUsageStreamDraw,
+                       BufferUsageStreamRead,
+                       BufferUsageStreamCopy
+               };
+               
+               GraphicsBuffer();
+               ~GraphicsBuffer();
+               
+               void SetType(BufferType bufType);
+               void SetUsage(BufferUsage bufUsage);
+               
+               void *Map(bool read, bool write, bool invalidate);
+               void *MapRange(int offset, int length, bool read, bool write, bool invalidate);
+               
+               void UnMap();
+               
+               void Upload(size_t length, const void *data);
+               void UploadRange(size_t length, intptr_t offset, const void *data);
+
+               void Resize(size_t length);
+               
+               void Bind();
+       private:
+               GLuint m_buffer_handle;
+               BufferType m_buffer_type;
+               BufferUsage m_buffer_usage;
+               void *m_map_pointer;
+               size_t m_buffer_size;
+               bool m_invalidated;
+       };
+
+}
+
+#endif // _SCREEN_H
index 9cf0c68..d9f2a7f 100644 (file)
@@ -76,7 +76,14 @@ int main(int argc, char ** argv)
        }
        else 
        {
-               doc.Add(RECT_OUTLINE, Rect(0.5,0.5,1,1));
+               for(int i = 0; i < 1024; ++i)
+               {
+                       for (int j = 0; j < 1024; ++j)
+                       {
+                               doc.Add(((i^j)&1)?RECT_OUTLINE:RECT_FILLED, Rect(0.2+i-512.0,0.2+j-512.0,0.6,0.6));
+                       }
+               }
+               
        }
        Rect bounds(b[0],b[1],b[2],b[3]);
 
index 07d3f94..5c3957c 100644 (file)
@@ -293,7 +293,7 @@ void Screen::DebugFontPrint(const char* str)
        glDisable(GL_BLEND);
        glDisable(GL_TEXTURE_2D);
        glPopMatrix();
-       glMatrixMode(GL_MODELVIEW);
+       glMatrixMode(GL_PROJECTION);
        glPopMatrix();
 }
 
index 26e9507..bda0faa 100644 (file)
@@ -12,6 +12,8 @@ void View::Translate(Real x, Real y)
        m_bounds.x += x;
        m_bounds.y += y;
        Debug("View Bounds => %s", m_bounds.Str().c_str());
+       if (!m_use_gpu_transform)
+               m_bounds_dirty = true;
 }
 
 void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt)
@@ -36,6 +38,8 @@ void View::ScaleAroundPoint(Real x, Real y, Real scaleAmt)
        m_bounds.w *= scaleAmt;
        m_bounds.h *= scaleAmt;
        Debug("View Bounds => %s", m_bounds.Str().c_str());
+       if (!m_use_gpu_transform)
+               m_bounds_dirty = true;
 }
 
 Rect View::TransformToViewCoords(const Rect& inp) const
@@ -74,18 +78,11 @@ void View::DrawGrid()
        }
 }
 
+void glPrimitiveRestartIndex(GLuint index);
+
 void View::Render()
 {
-       static bool debug_output_done = false;
-       if (!debug_output_done)
-       {
-               m_document.DebugDumpObjects();
-               debug_output_done = true;
-       }
-
-
-       //DrawGrid(); // Draw the gridlines
-
+       
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        if (m_use_gpu_transform)
@@ -96,16 +93,70 @@ void View::Render()
        {
                glOrtho(0,1,1,0,-1,1);
        }
+
+       if (m_bounds_dirty)
+               ReRender();
+
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
-
        if (m_colour.a < 1.0f)
        {
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        }
        glColor4f(m_colour.r, m_colour.g, m_colour.b, m_colour.a);
-       glBegin(GL_QUADS);
+       m_vertex_buffer.Bind();
+       m_index_buffer.Bind();
+       glEnable(GL_PRIMITIVE_RESTART);
+       glPrimitiveRestartIndex(0xFFFFFFFF);
+       glVertexPointer(2, GL_FLOAT, 0, 0);
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glDrawElements(GL_TRIANGLE_STRIP, m_rendered_filled * 5, GL_UNSIGNED_INT, 0);
+       glDrawElements(GL_LINE_LOOP, m_rendered_outline*5, GL_UNSIGNED_INT,(void*)(sizeof(uint32_t)*m_rendered_filled*5));
+       glDisable(GL_PRIMITIVE_RESTART);
+       if (m_colour.a < 1.0f)
+       {
+               glDisable(GL_BLEND);
+       }
+
+
+}
+
+void View::ReRender()
+{
+       static bool debug_output_done = false;
+       if (!debug_output_done)
+       {
+               m_document.DebugDumpObjects();
+               debug_output_done = true;
+
+               m_vertex_buffer.SetType(GraphicsBuffer::BufferTypeVertex);
+               m_index_buffer.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
+               m_index_buffer.SetType(GraphicsBuffer::BufferTypeIndex);
+
+               m_vertex_buffer.Upload(m_document.ObjectCount() * 8 * sizeof(float), NULL);
+               m_index_buffer.Upload(m_document.ObjectCount() * 5 * sizeof(uint32_t), NULL);
+       }
+       m_rendered_filled = m_rendered_outline = 0;
+       
+       if (m_use_gpu_transform)
+       {
+               m_vertex_buffer.SetUsage(GraphicsBuffer::BufferUsageStaticDraw);
+       }
+       else
+       {
+               m_vertex_buffer.SetUsage(GraphicsBuffer::BufferUsageDynamicDraw);
+       }
+
+
+       //DrawGrid(); // Draw the gridlines
+
+
+
+       float *vertexData = (float*)m_vertex_buffer.Map(false, true, true);
+       uint32_t *indexData = (uint32_t*)m_index_buffer.Map(false, true, true);
+
+       uint32_t currentIndex = 0;
        for (unsigned id = 0; id < m_document.ObjectCount(); ++id)
        {
                if (m_document.m_objects.types[id] != RECT_FILLED)
@@ -119,13 +170,25 @@ void View::Render()
                {
                        obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]);
                }
-               glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y));
-               glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y));
-               glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y) + Float(obj_bounds.h));
-               glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y) + Float(obj_bounds.h));
-       }
-       glEnd();
+               *vertexData = Float(obj_bounds.x); vertexData++;
+               *vertexData = Float(obj_bounds.y); vertexData++;
+               *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++;
+               *vertexData = Float(obj_bounds.y); vertexData++;
+               *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++;
+               *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++;
+               *vertexData = Float(obj_bounds.x); vertexData++;
+               *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++;
+
+               *indexData = currentIndex; indexData++;
+               *indexData = currentIndex+1; indexData++;
+               *indexData = currentIndex+3; indexData++;
+               *indexData = currentIndex+2; indexData++;
+               *indexData = 0xFFFFFFFF; // Primitive restart.
+               indexData++;
+               currentIndex += 4;
+               m_rendered_filled++;
 
+       }
        
        for (unsigned id = 0; id < m_document.ObjectCount(); ++id)
        {
@@ -140,17 +203,27 @@ void View::Render()
                {
                        obj_bounds = TransformToViewCoords(m_document.m_objects.bounds[id]);
                }
-               glBegin(GL_LINE_LOOP);
-               glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y));
-               glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y));
-               glVertex2f(Float(obj_bounds.x) + Float(obj_bounds.w), Float(obj_bounds.y) + Float(obj_bounds.h));
-               glVertex2f(Float(obj_bounds.x), Float(obj_bounds.y) + Float(obj_bounds.h));
-               glEnd();
+               *vertexData = Float(obj_bounds.x); vertexData++;
+               *vertexData = Float(obj_bounds.y); vertexData++;
+               *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++;
+               *vertexData = Float(obj_bounds.y); vertexData++;
+               *vertexData = Float(obj_bounds.x) + Float(obj_bounds.w); vertexData++;
+               *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++;
+               *vertexData = Float(obj_bounds.x); vertexData++;
+               *vertexData = Float(obj_bounds.y) + Float(obj_bounds.h); vertexData++;
+
+               *indexData = currentIndex; indexData++;
+               *indexData = currentIndex+1; indexData++;
+               *indexData = currentIndex+2; indexData++;
+               *indexData = currentIndex+3; indexData++;
+               *indexData = 0xFFFFFFFF; // Primitive restart.
+               indexData++;
+               currentIndex += 4;
+               m_rendered_outline++;
        }
+       m_vertex_buffer.UnMap();
+       m_index_buffer.UnMap();
 
-       if (m_colour.a < 1.0f)
-       {
-               glDisable(GL_BLEND);
-       }
+       m_bounds_dirty = false;
 
 }
index c6c230d..172b5e7 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "ipdf.h"
 #include "document.h"
+#include "graphicsbuffer.h"
 
 namespace IPDF
 {
@@ -10,7 +11,7 @@ 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_document(document), m_bounds(bounds), m_colour(colour), m_use_gpu_transform(false), m_bounds_dirty(true)
                        {
                                Debug("View Created - Bounds => {%s}", m_bounds.Str().c_str());
                        }
@@ -26,14 +27,20 @@ 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); }
+                       void ToggleGPUTransform() { m_use_gpu_transform = (!m_use_gpu_transform); m_bounds_dirty = true; }
                
                private:
+                       void ReRender();
                        void DrawGrid();
                        bool m_use_gpu_transform;
+                       bool m_bounds_dirty;
+                       GraphicsBuffer m_vertex_buffer;
+                       GraphicsBuffer m_index_buffer;
                        Document & m_document;
                        Rect m_bounds;
                        Colour m_colour;
+                       uint32_t m_rendered_filled;
+                       uint32_t m_rendered_outline;
        };
 }
 

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