Deal with groups in SVG parsing
[ipdf/code.git] / src / graphicsbuffer.cpp
index 6f9ea9a..d3911db 100644 (file)
@@ -1,8 +1,5 @@
 #include "graphicsbuffer.h"
 #include "log.h"
-#define GL_GLEXT_PROTOTYPES
-#include <SDL_opengl.h>
-#include <GL/glext.h>
 
 using namespace IPDF;
 
@@ -39,7 +36,7 @@ static GLenum BufferUsageToGLUsage(GraphicsBuffer::BufferUsage buffer_usage)
                usage = GL_STREAM_COPY;
                break;
        default:
-               SDL_assert(false && "Unknown buffer usage type.");
+               SDL_assert(false && "Unknown buffer usage type."); //WTF?
                usage = GL_DYNAMIC_DRAW;
        }
        return usage;
@@ -59,6 +56,8 @@ static GLenum BufferTypeToGLType(GraphicsBuffer::BufferType buffer_type)
                return GL_PIXEL_UNPACK_BUFFER;
        case GraphicsBuffer::BufferTypeUniform:
                return GL_UNIFORM_BUFFER;
+       case GraphicsBuffer::BufferTypeTexture:
+               return GL_TEXTURE_BUFFER;
        case GraphicsBuffer::BufferTypeDrawIndirect:
                return GL_DRAW_INDIRECT_BUFFER;
        default:
@@ -69,7 +68,12 @@ static GLenum BufferTypeToGLType(GraphicsBuffer::BufferType buffer_type)
 GraphicsBuffer::GraphicsBuffer()
 {
        m_invalidated = true;
+       m_map_pointer = NULL;
        m_buffer_size = 0;
+       m_buffer_shape_dirty = true;
+       m_buffer_handle = 0;
+       m_buffer_usage = BufferUsageDynamicDraw;
+       m_faking_map = false;
        SetUsage(BufferUsageStaticDraw);
 }
 
@@ -84,13 +88,47 @@ GraphicsBuffer::~GraphicsBuffer()
 
 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;
+       if (bufUsage != m_buffer_usage)
+       {
+               m_buffer_usage = bufUsage;
+               m_buffer_shape_dirty = true;
+       }
+}
+
+void GraphicsBuffer::Invalidate()
+{
+       m_invalidated = true;
+       if (!m_buffer_shape_dirty)
+       {
+               // Orphan the block of memory we're pointing to.
+               Upload(m_buffer_size, NULL);
+       }
+       // Apparently not supported.
+       //glInvalidateBufferData(m_buffer_handle);
+}
+
+bool GraphicsBuffer::RecreateBuffer(const void *data)
+{
+       // If the buffer is not dirty, don't recreate it.
+       if (!m_buffer_shape_dirty) return false;
+       // If the buffer is mapped, don't recreate it.
+       if (!m_faking_map && m_map_pointer) return false;
+       // If the buffer has data in it we need, don't recreate it.
+       if (!m_invalidated) return false;
+       if (m_buffer_handle)
+       {
+               glDeleteBuffers(1, &m_buffer_handle);
+       }
+       glGenBuffers(1, &m_buffer_handle);
+       m_buffer_shape_dirty = false;
+       if (m_buffer_size)
+               Upload(m_buffer_size, data);
+       return true;
 }
 
 void* GraphicsBuffer::Map(bool read, bool write, bool invalidate)
@@ -98,12 +136,34 @@ 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 = BufferTypeToGLType(m_buffer_type);
 
+       if (invalidate)
+       {
+               m_invalidated = true;
+
+               // Intel's Mesa driver does not rename the buffer when we map with GL_MAP_INVALIDATE_BUFFER_BIT,
+               // resulting in the CPU stalling waiting for rendering from the buffer to complete on the GPU.
+               // We manually force the buffer to be renamed here to avoid this.
+               m_buffer_shape_dirty = true;
+       }
+
+       if (m_map_pointer)
+               Warn("Tried to map already mapped buffer!");    
+
+
+       if (!read && m_buffer_usage == BufferUsage::BufferUsageStaticDraw)
+       {
+               m_map_pointer = malloc(m_buffer_size);
+               m_faking_map = true;
+               return m_map_pointer;
+       }
+
+       RecreateBuffer();
+
        Bind();
        
-       return glMapBufferRange(target, 0, m_buffer_size, access);
+       m_map_pointer = glMapBufferRange(target, 0, m_buffer_size, access);
        
-       //TODO: Emulate DSA
-       //return glMapNamedBufferEXT(m_bufferHandle, access);
+       return m_map_pointer;
 }
 
 void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bool invalidate)
@@ -111,21 +171,39 @@ void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bo
        GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_RANGE_BIT:0);
        GLenum target = BufferTypeToGLType(m_buffer_type);
 
+       if (m_map_pointer)
+               Warn("Tried to map already mapped buffer!");    
+
+       RecreateBuffer();
+
        Bind();
        
-       return glMapBufferRange(target, offset, length, access);
-
-       //TODO: Emulate DSA
-       //return glMapNamedBufferRangeEXT(m_bufferHandle, offset, length, access);
+       m_map_pointer = glMapBufferRange(target, offset, length, access);
+       return m_map_pointer;
 }
 
 void GraphicsBuffer::UnMap()
 {
        GLenum target = BufferTypeToGLType(m_buffer_type);
        
+       // If we're not mapped, unmapping is a no-op.
+       if (!m_map_pointer)
+               return;
+
+       if (m_faking_map)
+       {
+               Upload(m_buffer_size, m_map_pointer);
+               free(m_map_pointer);
+               m_map_pointer = NULL;
+               m_invalidated = false;
+               m_faking_map = false;
+               return;
+       }
+       
        Bind();
        glUnmapBuffer(target);
-       //glUnmapNamedBufferEXT(m_bufferHandle);
+       m_map_pointer = NULL;
+       m_invalidated = false;
 }
 
 void GraphicsBuffer::Upload(size_t length, const void* data)
@@ -133,27 +211,34 @@ void GraphicsBuffer::Upload(size_t length, const void* data)
        GLenum target = BufferTypeToGLType(m_buffer_type);
        
        GLenum usage = BufferUsageToGLUsage(m_buffer_usage);
-       
-       Bind();
-       glBufferData(target, length, data, usage);
+
+       m_invalidated = true;
        m_buffer_size = length;
-       //glNamedBufferDataEXT(m_bufferHandle, length, data, usage);
+       if (!RecreateBuffer(data))
+       {
+               Bind();
+               glBufferData(target, length, data, usage);
+       }
+       if (data != NULL)
+               m_invalidated = false;
 }
 
 void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* data)
 {
        GLenum target = BufferTypeToGLType(m_buffer_type);
+
+       RecreateBuffer();
        
        Bind();
        glBufferSubData(target, offset, length, data);
-       //glNamedBufferSubDataEXT(m_bufferHandle, offset, length, data);
+       m_invalidated = false;
 }
 
 void GraphicsBuffer::Resize(size_t length)
 {
        if (m_invalidated)
        {
-               Upload(length, nullptr);
+               m_buffer_size = length;
        }
        else
        {
@@ -161,17 +246,16 @@ void GraphicsBuffer::Resize(size_t length)
                UnMap();
                GLuint old_buffer = m_buffer_handle;    
                glGenBuffers(1, &m_buffer_handle);
-               Upload(length, nullptr);
+               Upload(length, NULL);
                glBindBuffer(GL_COPY_READ_BUFFER, old_buffer);
                glBindBuffer(GL_COPY_WRITE_BUFFER, m_buffer_handle);
                glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, m_buffer_size);
                glDeleteBuffers(1, &old_buffer);
+               m_buffer_size = length;
        }
-       m_buffer_size = length;
-
 }
 
-void GraphicsBuffer::Bind()
+void GraphicsBuffer::Bind() const
 {
        if (m_buffer_type == BufferTypeUniform)
                glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer_handle);

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