diff --git a/src/renderer/gl_engine/tvgGlGeometry.cpp b/src/renderer/gl_engine/tvgGlGeometry.cpp index 1be3c709..4b112dbe 100644 --- a/src/renderer/gl_engine/tvgGlGeometry.cpp +++ b/src/renderer/gl_engine/tvgGlGeometry.cpp @@ -32,12 +32,9 @@ GlGeometry::~GlGeometry() { - if (mVao) { - glDeleteVertexArrays(1, &mVao); - } } -bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) +bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer) { mFillVertexOffset = 0; mStrokeVertexOffset = 0; @@ -46,13 +43,7 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) mFillCount = 0; mStrokeCount = 0; - mStaveVertex.clear(); - mStageIndex.clear(); - if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { - mFillVertexOffset = mStaveVertex.count * sizeof(float); - mFillIndexOffset = mStageIndex.count * sizeof(uint32_t); - Array vertex; Array index; @@ -61,14 +52,11 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) mFillCount = index.count; - mStaveVertex.push(vertex); - mStageIndex.push(index); + mFillVertexOffset = gpuBuffer->push(vertex.data, vertex.count * sizeof(float)); + mFillIndexOffset = gpuBuffer->push(index.data, index.count * sizeof(uint32_t)); } if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { - mStrokeVertexOffset = mStaveVertex.count * sizeof(float); - mStrokeIndexOffset = mStageIndex.count * sizeof(uint32_t); - Array vertex; Array index; @@ -77,8 +65,8 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) mStrokeCount = index.count; - mStaveVertex.push(vertex); - mStageIndex.push(index); + mStrokeVertexOffset = gpuBuffer->push(vertex.data, vertex.count * sizeof(float)); + mStrokeIndexOffset = gpuBuffer->push(index.data, index.count * sizeof(uint32_t)); } return true; @@ -88,8 +76,6 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) void GlGeometry::disableVertex(uint32_t location) { GL_CHECK(glDisableVertexAttribArray(location)); - mVertexBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER); - mIndexBuffer->unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER); } @@ -100,10 +86,6 @@ void GlGeometry::draw(const uint32_t location, RenderUpdateFlag flag) return; } - if (mVao == 0) glGenVertexArrays(1, &mVao); - glBindVertexArray(mVao); - - updateBuffer(location); uint32_t vertexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeVertexOffset : mFillVertexOffset; uint32_t indexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeIndexOffset : mFillIndexOffset; @@ -116,16 +98,6 @@ void GlGeometry::draw(const uint32_t location, RenderUpdateFlag flag) } -void GlGeometry::updateBuffer(uint32_t location) -{ - if (mVertexBuffer == nullptr) mVertexBuffer = std::make_unique(); - if (mIndexBuffer == nullptr) mIndexBuffer = std::make_unique(); - - mVertexBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStaveVertex.count * sizeof(float), mStaveVertex.data); - mIndexBuffer->updateBufferData(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER, mStageIndex.count * sizeof(uint32_t), mStageIndex.data); -} - - void GlGeometry::updateTransform(const RenderTransform* transform, float w, float h) { float modelMatrix[16]; diff --git a/src/renderer/gl_engine/tvgGlGeometry.h b/src/renderer/gl_engine/tvgGlGeometry.h index 71e15977..3dcf0ddb 100644 --- a/src/renderer/gl_engine/tvgGlGeometry.h +++ b/src/renderer/gl_engine/tvgGlGeometry.h @@ -181,7 +181,7 @@ public: } }; -class GlGpuBuffer; +class GlStageBuffer; class GlGeometry { @@ -189,26 +189,19 @@ public: ~GlGeometry(); - bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag); + bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer); void disableVertex(uint32_t location); void draw(const uint32_t location, RenderUpdateFlag flag); void updateTransform(const RenderTransform* transform, float w, float h); float* getTransforMatrix(); private: - void updateBuffer(const uint32_t location); - - Array mStaveVertex; - Array mStageIndex; uint32_t mFillVertexOffset; uint32_t mFillIndexOffset; uint32_t mFillCount; uint32_t mStrokeVertexOffset; uint32_t mStrokeIndexOffset; uint32_t mStrokeCount; - GLuint mVao = 0; - std::unique_ptr mVertexBuffer; - std::unique_ptr mIndexBuffer; float mTransform[16]; }; diff --git a/src/renderer/gl_engine/tvgGlGpuBuffer.cpp b/src/renderer/gl_engine/tvgGlGpuBuffer.cpp index c0b7ed81..3220acbc 100644 --- a/src/renderer/gl_engine/tvgGlGpuBuffer.cpp +++ b/src/renderer/gl_engine/tvgGlGpuBuffer.cpp @@ -22,6 +22,9 @@ #include "tvgGlGpuBuffer.h" +#include +#include + /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ @@ -44,12 +47,66 @@ GlGpuBuffer::~GlGpuBuffer() void GlGpuBuffer::updateBufferData(Target target, uint32_t size, const void* data) { - GL_CHECK(glBindBuffer(static_cast(target), mGlBufferId)); GL_CHECK(glBufferData(static_cast(target), size, data, GL_STATIC_DRAW)); } +void GlGpuBuffer::bind(Target target) +{ + GL_CHECK(glBindBuffer(static_cast(target), mGlBufferId)); +} void GlGpuBuffer::unbind(Target target) { GL_CHECK(glBindBuffer(static_cast(target), 0)); } + +GlStageBuffer::~GlStageBuffer() +{ + if (mVao) { + glDeleteVertexArrays(1, &mVao); + mVao = 0; + } +} + +uint32_t GlStageBuffer::push(void *data, uint32_t size) +{ + uint32_t offset = mStageBuffer.count; + + if (this->mStageBuffer.reserved - this->mStageBuffer.count < size) { + this->mStageBuffer.grow(max(size, this->mStageBuffer.reserved)); + } + + memcpy(this->mStageBuffer.data + offset, data, size); + + this->mStageBuffer.count += size; + + return offset; +} + +void GlStageBuffer::flushToGPU() +{ + if (mStageBuffer.empty()) return; + + if (!mGpuBuffer) { + mGpuBuffer.reset(new GlGpuBuffer); + GL_CHECK(glGenVertexArrays(1, &mVao)); + } + + mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER); + mGpuBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStageBuffer.count, mStageBuffer.data); + mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER); +} + +void GlStageBuffer::bind() +{ + glBindVertexArray(mVao); + mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER); + mGpuBuffer->bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER); +} + +void GlStageBuffer::unbind() +{ + glBindVertexArray(0); + mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER); + mGpuBuffer->unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER); +} diff --git a/src/renderer/gl_engine/tvgGlGpuBuffer.h b/src/renderer/gl_engine/tvgGlGpuBuffer.h index 0587466f..e86b4200 100644 --- a/src/renderer/gl_engine/tvgGlGpuBuffer.h +++ b/src/renderer/gl_engine/tvgGlGpuBuffer.h @@ -23,6 +23,9 @@ #ifndef _TVG_GL_GPU_BUFFER_H_ #define _TVG_GL_GPU_BUFFER_H_ +#include + +#include "tvgArray.h" #include "tvgGlCommon.h" class GlGpuBuffer @@ -37,11 +40,31 @@ public: GlGpuBuffer(); ~GlGpuBuffer(); void updateBufferData(Target target, uint32_t size, const void* data); + void bind(Target target); void unbind(Target target); private: uint32_t mGlBufferId = 0; }; +class GlStageBuffer { +public: + GlStageBuffer() = default; + ~GlStageBuffer(); + + uint32_t push(void* data, uint32_t size); + + void flushToGPU(); + + void bind(); + + void unbind(); + +private: + GLuint mVao = 0; + unique_ptr mGpuBuffer = {}; + Array mStageBuffer = {}; +}; + #endif /* _TVG_GL_GPU_BUFFER_H_ */ diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 49c462df..5826e87a 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -87,16 +87,21 @@ bool GlRenderer::preRender() } GlRenderTask::unload(); + mGpuBuffer->flushToGPU(); + // Blend function for straight alpha GL_CHECK(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GL_CHECK(glEnable(GL_BLEND)); + + mGpuBuffer->bind(); + return true; } bool GlRenderer::postRender() { - //TODO: called just after render() + mGpuBuffer->unbind(); return true; } @@ -238,7 +243,7 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform) ) { - if (!sdata->geometry->tesselate(rshape, sdata->updateFlag)) return sdata; + if (!sdata->geometry->tesselate(rshape, sdata->updateFlag, mGpuBuffer.get())) return sdata; } return sdata; } diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index 277799b2..5f9f9294 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -24,6 +24,7 @@ #define _TVG_GL_RENDERER_H_ #include "tvgGlRenderTask.h" +#include "tvgGlGpuBuffer.h" class GlRenderer : public RenderMethod { @@ -58,7 +59,7 @@ public: static int term(); private: - GlRenderer(){}; + GlRenderer(): mGpuBuffer(new GlStageBuffer) {}; ~GlRenderer(); void initShaders(); @@ -66,6 +67,7 @@ private: void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag); vector> mRenderTasks; + std::unique_ptr mGpuBuffer; }; #endif /* _TVG_GL_RENDERER_H_ */