diff --git a/src/renderer/gl_engine/meson.build b/src/renderer/gl_engine/meson.build index fc21c450..fee510d3 100644 --- a/src/renderer/gl_engine/meson.build +++ b/src/renderer/gl_engine/meson.build @@ -3,16 +3,13 @@ source_file = [ 'tvgGlGeometry.h', 'tvgGlGpuBuffer.h', 'tvgGlProgram.h', - 'tvgGlPropertyInterface.h', 'tvgGlRenderer.h', - 'tvgGlRendererProperties.h', 'tvgGlRenderTask.h', 'tvgGlShader.h', 'tvgGlShaderSrc.h', 'tvgGlGeometry.cpp', 'tvgGlGpuBuffer.cpp', 'tvgGlProgram.cpp', - 'tvgGlPropertyInterface.cpp', 'tvgGlRenderer.cpp', 'tvgGlRenderTask.cpp', 'tvgGlShader.cpp', diff --git a/src/renderer/gl_engine/tvgGlCommon.h b/src/renderer/gl_engine/tvgGlCommon.h index ca10480f..420c6795 100644 --- a/src/renderer/gl_engine/tvgGlCommon.h +++ b/src/renderer/gl_engine/tvgGlCommon.h @@ -61,5 +61,25 @@ struct GlShape unique_ptr geometry; }; +#define MAX_GRADIENT_STOPS 4 + +struct GlLinearGradientBlock +{ + alignas(16) float nStops[4] = {}; + alignas(16) float startPos[2] = {}; + alignas(8) float stopPos[2] = {}; + alignas(8) float stopPoints[MAX_GRADIENT_STOPS] = {}; + alignas(16) float stopColors[4 * MAX_GRADIENT_STOPS] = {}; +}; + +struct GlRadialGradientBlock +{ + alignas(16) float nStops[4] = {}; + alignas(16) float centerPos[2] = {}; + alignas(8) float radius[2] = {}; + alignas(8) float stopPoints[MAX_GRADIENT_STOPS] = {}; + alignas(16) float stopColors[4 * MAX_GRADIENT_STOPS] = {}; +}; + #endif /* _TVG_GL_COMMON_H_ */ diff --git a/src/renderer/gl_engine/tvgGlGeometry.cpp b/src/renderer/gl_engine/tvgGlGeometry.cpp index 4b112dbe..1a9cfa5d 100644 --- a/src/renderer/gl_engine/tvgGlGeometry.cpp +++ b/src/renderer/gl_engine/tvgGlGeometry.cpp @@ -24,6 +24,7 @@ #include "tvgGlGpuBuffer.h" #include "tvgGlGeometry.h" #include "tvgGlTessellator.h" +#include "tvgGlRenderTask.h" #define NORMALIZED_TOP_3D 1.0f #define NORMALIZED_BOTTOM_3D -1.0f @@ -34,39 +35,22 @@ GlGeometry::~GlGeometry() { } -bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer) +bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) { - mFillVertexOffset = 0; - mStrokeVertexOffset = 0; - mFillIndexOffset = 0; - mStrokeIndexOffset = 0; - mFillCount = 0; - mStrokeCount = 0; - if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) { - Array vertex; - Array index; + fillVertex.clear(); + fillIndex.clear(); - tvg::Tessellator tess{&vertex, &index}; + Tessellator tess{&fillVertex, &fillIndex}; tess.tessellate(&rshape, true); - - mFillCount = index.count; - - 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)) { - Array vertex; - Array index; + strokeVertex.clear(); + strokeIndex.clear(); - tvg::Stroker stroke{&vertex, &index}; + Stroker stroke{&strokeVertex, &strokeIndex}; stroke.stroke(&rshape); - - mStrokeCount = index.count; - - mStrokeVertexOffset = gpuBuffer->push(vertex.data, vertex.count * sizeof(float)); - mStrokeIndexOffset = gpuBuffer->push(index.data, index.count * sizeof(uint32_t)); } return true; @@ -79,22 +63,34 @@ void GlGeometry::disableVertex(uint32_t location) } -void GlGeometry::draw(const uint32_t location, RenderUpdateFlag flag) +bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag) { if (flag == RenderUpdateFlag::None) { - return; + return false; } + Array* vertexBuffer = nullptr; + Array* indexBuffer = nullptr; - uint32_t vertexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeVertexOffset : mFillVertexOffset; - uint32_t indexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeIndexOffset : mFillIndexOffset; - uint32_t count = (flag == RenderUpdateFlag::Stroke) ? mStrokeCount : mFillCount; + if (flag & RenderUpdateFlag::Stroke) { + vertexBuffer = &strokeVertex; + indexBuffer = &strokeIndex; + } else { + vertexBuffer = &fillVertex; + indexBuffer = &fillIndex; + } - GL_CHECK(glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), reinterpret_cast(vertexOffset))); - GL_CHECK(glEnableVertexAttribArray(location)); + if (indexBuffer->count == 0) return false; - GL_CHECK(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, reinterpret_cast(indexOffset))); + uint32_t vertexOffset = gpuBuffer->push(vertexBuffer->data, vertexBuffer->count * sizeof(float)); + uint32_t indexOffset = gpuBuffer->push(indexBuffer->data, indexBuffer->count * sizeof(uint32_t)); + + // vertex layout + task->addVertexLayout(GlVertexLayout{0, 3, 3 * sizeof(float), vertexOffset}); + task->setDrawRange(indexOffset, indexBuffer->count); + + return true; } diff --git a/src/renderer/gl_engine/tvgGlGeometry.h b/src/renderer/gl_engine/tvgGlGeometry.h index 04e4ef88..ce8f7d08 100644 --- a/src/renderer/gl_engine/tvgGlGeometry.h +++ b/src/renderer/gl_engine/tvgGlGeometry.h @@ -180,26 +180,25 @@ public: }; class GlStageBuffer; +class GlRenderTask; class GlGeometry { public: - + GlGeometry() = default; ~GlGeometry(); - bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer); + bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag); void disableVertex(uint32_t location); - void draw(const uint32_t location, RenderUpdateFlag flag); + bool draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag); void updateTransform(const RenderTransform* transform, float w, float h); float* getTransforMatrix(); private: - uint32_t mFillVertexOffset; - uint32_t mFillIndexOffset; - uint32_t mFillCount; - uint32_t mStrokeVertexOffset; - uint32_t mStrokeIndexOffset; - uint32_t mStrokeCount; + Array fillVertex = {}; + Array strokeVertex = {}; + Array fillIndex = {}; + Array strokeIndex = {}; float mTransform[16]; }; diff --git a/src/renderer/gl_engine/tvgGlGpuBuffer.cpp b/src/renderer/gl_engine/tvgGlGpuBuffer.cpp index 3220acbc..eb17f2f9 100644 --- a/src/renderer/gl_engine/tvgGlGpuBuffer.cpp +++ b/src/renderer/gl_engine/tvgGlGpuBuffer.cpp @@ -29,6 +29,18 @@ /* Internal Class Implementation */ /************************************************************************/ +static GLint _getGpuBufferAlign() +{ + static GLint offset = 0; + + if (!offset) + { + GL_CHECK(glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offset)); + } + + return offset; +} + GlGpuBuffer::GlGpuBuffer() { GL_CHECK(glGenBuffers(1, &mGlBufferId)); @@ -60,6 +72,11 @@ void GlGpuBuffer::unbind(Target target) GL_CHECK(glBindBuffer(static_cast(target), 0)); } +GlStageBuffer::GlStageBuffer() : mVao(0), mGpuBuffer(new GlGpuBuffer) +{ + GL_CHECK(glGenVertexArrays(1, &mVao)); +} + GlStageBuffer::~GlStageBuffer() { if (mVao) { @@ -68,8 +85,10 @@ GlStageBuffer::~GlStageBuffer() } } -uint32_t GlStageBuffer::push(void *data, uint32_t size) +uint32_t GlStageBuffer::push(void *data, uint32_t size, bool alignGpuOffset) { + if (alignGpuOffset) alignOffset(); + uint32_t offset = mStageBuffer.count; if (this->mStageBuffer.reserved - this->mStageBuffer.count < size) { @@ -87,14 +106,12 @@ 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); + + mStageBuffer.clear(); } void GlStageBuffer::bind() @@ -102,6 +119,7 @@ void GlStageBuffer::bind() glBindVertexArray(mVao); mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER); mGpuBuffer->bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER); + mGpuBuffer->bind(GlGpuBuffer::Target::UNIFORM_BUFFER); } void GlStageBuffer::unbind() @@ -109,4 +127,27 @@ void GlStageBuffer::unbind() glBindVertexArray(0); mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER); mGpuBuffer->unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER); + mGpuBuffer->unbind(GlGpuBuffer::Target::UNIFORM_BUFFER); +} + +GLuint GlStageBuffer::getBufferId() +{ + return mGpuBuffer->getBufferId(); +} + +void GlStageBuffer::alignOffset() +{ + + uint32_t alignment = _getGpuBufferAlign(); + + if (mStageBuffer.count % alignment == 0) return; + + + uint32_t offset = alignment - mStageBuffer.count % alignment; + + if (mStageBuffer.count + offset > mStageBuffer.reserved) { + mStageBuffer.grow(max(alignment, mStageBuffer.reserved)); + } + + mStageBuffer.count += offset; } diff --git a/src/renderer/gl_engine/tvgGlGpuBuffer.h b/src/renderer/gl_engine/tvgGlGpuBuffer.h index e08f643a..88f812fc 100644 --- a/src/renderer/gl_engine/tvgGlGpuBuffer.h +++ b/src/renderer/gl_engine/tvgGlGpuBuffer.h @@ -34,6 +34,7 @@ public: { ARRAY_BUFFER = GL_ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER, + UNIFORM_BUFFER = GL_UNIFORM_BUFFER, }; GlGpuBuffer(); @@ -41,6 +42,8 @@ public: void updateBufferData(Target target, uint32_t size, const void* data); void bind(Target target); void unbind(Target target); + + uint32_t getBufferId() { return mGlBufferId; } private: uint32_t mGlBufferId = 0; @@ -48,10 +51,10 @@ private: class GlStageBuffer { public: - GlStageBuffer() = default; + GlStageBuffer(); ~GlStageBuffer(); - uint32_t push(void* data, uint32_t size); + uint32_t push(void* data, uint32_t size, bool alignGpuOffset = false); void flushToGPU(); @@ -59,6 +62,9 @@ public: void unbind(); + GLuint getBufferId(); +private: + void alignOffset(); private: GLuint mVao = 0; unique_ptr mGpuBuffer = {}; diff --git a/src/renderer/gl_engine/tvgGlProgram.cpp b/src/renderer/gl_engine/tvgGlProgram.cpp index 6a48b60f..fdaaa910 100644 --- a/src/renderer/gl_engine/tvgGlProgram.cpp +++ b/src/renderer/gl_engine/tvgGlProgram.cpp @@ -87,6 +87,16 @@ int32_t GlProgram::getUniformLocation(const char* name) return location; } +int32_t GlProgram::getUniformBlockIndex(const char* name) +{ + GL_CHECK(int32_t index = glGetUniformBlockIndex(mProgramObj, name)); + return index; +} + +uint32_t GlProgram::getProgramId() +{ + return mProgramObj; +} void GlProgram::setUniform1Value(int32_t location, int count, const int* values) { diff --git a/src/renderer/gl_engine/tvgGlProgram.h b/src/renderer/gl_engine/tvgGlProgram.h index 807b985b..4d3e9cc8 100644 --- a/src/renderer/gl_engine/tvgGlProgram.h +++ b/src/renderer/gl_engine/tvgGlProgram.h @@ -23,7 +23,6 @@ #ifndef _TVG_GL_PROGRAM_H_ #define _TVG_GL_PROGRAM_H_ -#include #include "tvgGlShader.h" class GlProgram @@ -37,6 +36,8 @@ public: static void unload(); int32_t getAttributeLocation(const char* name); int32_t getUniformLocation(const char* name); + int32_t getUniformBlockIndex(const char* name); + uint32_t getProgramId(); void setUniform1Value(int32_t location, int count, const int* values); void setUniform2Value(int32_t location, int count, const int* values); void setUniform3Value(int32_t location, int count, const int* values); diff --git a/src/renderer/gl_engine/tvgGlPropertyInterface.cpp b/src/renderer/gl_engine/tvgGlPropertyInterface.cpp deleted file mode 100644 index ef0f9c56..00000000 --- a/src/renderer/gl_engine/tvgGlPropertyInterface.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgGlPropertyInterface.h" - -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ - -VertexProperty PropertyInterface::mEmptyProperty; - - -/************************************************************************/ -/* External Class Implementation */ -/************************************************************************/ - -VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_ptr prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType, VertexProperty::DataType dataType) -{ - std::map* vertexProperty = nullptr; - int32_t id; - switch (propType) { - case VertexProperty::PropertyType::ATTRIBUTE: { - id = prog->getAttributeLocation(name.c_str()); - vertexProperty = &rTask->getAttributeVertexProperty(); - break; - } - case VertexProperty::PropertyType::UNIFORM: { - id = prog->getUniformLocation(name.c_str()); - vertexProperty = &rTask->getUniformVertexProperty(); - break; - } - default: break; - } - if (id != -1) - { - VertexProperty property = { id, name, propType, dataType }; - property.propertyValues.setStride(propFormatSize); - if (vertexProperty) - { - (*vertexProperty)[id] = property; - return (*vertexProperty)[id]; - } - } - return mEmptyProperty; -} - - -void PropertyInterface::setProperty(GlRenderTask* rTask, int32_t propId, int32_t count, float* data) -{ - std::map::iterator itr = rTask->getUniformVertexProperty().find(propId); - if (itr->second.propertyId == -1) return; - - VertexProperty& prop = itr->second; - - for (int i = 0; i < count; ++i) { - prop.propertyValues.set(data[i]); - } -} - -int32_t PropertyInterface::getPropertyId(GlRenderTask* rTask, std::string name) -{ - std::map& vertexProperty = rTask->getUniformVertexProperty(); - for (auto& property : vertexProperty) { - if (property.second.propertyName == name) return property.second.propertyId; - } - return -1; -} - - -VertexProperty& PropertyInterface::getProperty(GlRenderTask* rTask, std::string name) -{ - std::map& vertexProperty = rTask->getUniformVertexProperty(); - for (auto& property : vertexProperty) { - if (property.second.propertyName == name) return property.second; - } - return mEmptyProperty; -} - - -VertexProperty& PropertyInterface::getProperty(GlRenderTask* rTask, int32_t propId) -{ - std::map& vertexProperty = rTask->getUniformVertexProperty(); - if (vertexProperty.find(propId) != vertexProperty.end()) return vertexProperty[propId]; - return mEmptyProperty; -} - - -void PropertyInterface::clearData(GlRenderTask* rTask) -{ - std::map& vertexProperty = rTask->getUniformVertexProperty(); - for (auto& prop : vertexProperty) { - prop.second.propertyValues.clear(); - } -} diff --git a/src/renderer/gl_engine/tvgGlPropertyInterface.h b/src/renderer/gl_engine/tvgGlPropertyInterface.h deleted file mode 100644 index 823571a9..00000000 --- a/src/renderer/gl_engine/tvgGlPropertyInterface.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_GL_PROPERTY_INTERFACE_H_ -#define _TVG_GL_PROPERTY_INTERFACE_H_ - -#include "tvgGlRenderTask.h" - - -#define ADD_ATTRIBUTE_PROPERTY(var, rtask, prog, varName, formatSize, location) \ - var = &PropertyInterface::addProperty(rtask, prog, varName, formatSize, VertexProperty::PropertyType::ATTRIBUTE); \ - if (var->propertyId != -1) \ - location = var->propertyId - -#define ADD_UNIFORM_PROPERTY(var, rtask, prog, varName, formatSize, location) \ - var = &PropertyInterface::addProperty(rtask, prog, varName, formatSize, VertexProperty::PropertyType::UNIFORM); \ - if (var->propertyId != -1) \ - location = var->propertyId - -#define ADD_UNIFORM_PROPERTY_2(var, rtask, prog, varName, formatSize, location, datatype) \ - var = &PropertyInterface::addProperty(rtask, prog, varName, formatSize, VertexProperty::PropertyType::UNIFORM, datatype); \ - if (var->propertyId != -1) \ - location = var->propertyId - -#define FORMAT_SIZE_FLOAT 1 -#define FORMAT_SIZE_VEC_2 2 -#define FORMAT_SIZE_VEC_3 3 -#define FORMAT_SIZE_VEC_4 4 -#define FORMAT_SIZE_MAT_4x4 16 - -class PropertyInterface -{ -public: - static VertexProperty& addProperty(GlRenderTask* rTask, std::shared_ptr prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType, VertexProperty::DataType dataType = VertexProperty::DataType::FLOAT); - template - static void setProperty(GlRenderTask* rTask, std::string name, float first, Args... args) - { - VertexProperty& prop = getProperty(rTask, name); - if (prop.propertyId == -1) - { - return; - } - setProperty(prop.propertyId, first, args...); - } - template - static void setProperty(GlRenderTask* rTask, int32_t propId, float first, Args... args) - { - std::map::iterator itr = rTask->getUniformVertexProperty().find(propId); - if (itr->second.propertyId == -1) - { - return; - } - VertexProperty& prop = itr->second; - - prop.propertyValues.set(first, args...); - } - - static void setProperty(GlRenderTask* rTask, int32_t propId, int32_t count, float* data); - static int32_t getPropertyId(GlRenderTask* rTask, std::string name); - static VertexProperty& getProperty(GlRenderTask* rTask, std::string name); - static VertexProperty& getProperty(GlRenderTask* rTask, int32_t propId); - static void clearData(GlRenderTask* rTask); - -private: - PropertyInterface() {} - static VertexProperty mEmptyProperty; -}; - - -#endif /* _TVG_GL_PROPERTY_INTERFACE_H_ */ diff --git a/src/renderer/gl_engine/tvgGlRenderTask.cpp b/src/renderer/gl_engine/tvgGlRenderTask.cpp index 1dd05146..62190187 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.cpp +++ b/src/renderer/gl_engine/tvgGlRenderTask.cpp @@ -21,268 +21,62 @@ */ #include "tvgGlRenderTask.h" -#include "tvgGlShaderSrc.h" -#include "tvgGlPropertyInterface.h" - +#include "tvgGlProgram.h" /************************************************************************/ /* External Class Implementation */ /************************************************************************/ -GlRenderTask::GlRenderTask(RenderTypes renderType, shared_ptr shader) -{ - mRenderType = renderType; - mProgram = GlProgram::gen(shader); - load(); - - VertexProperty* prop = nullptr; - // now location is specified directly in shader - mLocVertexAttribute = 0; - ADD_UNIFORM_PROPERTY_2(prop, this, mProgram, "uTransform", FORMAT_SIZE_MAT_4x4, mLocTransform, VertexProperty::DataType::MATRIX); -} - - -GlRenderTask::RenderTypes GlRenderTask::getRenderType() -{ - return mRenderType; -} - - -void GlRenderTask::load() +void GlRenderTask::run() { + // bind shader mProgram->load(); -} - - -void GlRenderTask::unload() -{ - GlProgram::unload(); -} - - -std::shared_ptr GlRenderTask::getProgram() -{ - return mProgram; -} - - -std::map& GlRenderTask::getAttributeVertexProperty() -{ - return mAttributePropertyBuffer; -} - - -std::map& GlRenderTask::getUniformVertexProperty() -{ - return mUniformPropertyBuffer; -} - - -int32_t GlRenderTask::getLocationPropertyId() const -{ - return mLocVertexAttribute; -} - - -int32_t GlRenderTask::getTransformLocationPropertyId() const -{ - return mLocTransform; -} - - -void GlRenderTask::setTransform(int count, float* transform) -{ - if (mLocTransform != -1) - { - PropertyInterface::setProperty(this, mLocTransform, count, transform); + // setup attribute layout + for (uint32_t i = 0; i < mVertexLayout.count; i++) { + const auto &layout = mVertexLayout[i]; + GL_CHECK(glEnableVertexAttribArray(layout.index)); + GL_CHECK(glVertexAttribPointer(layout.index, layout.size, GL_FLOAT, + GL_FALSE, layout.stride, + reinterpret_cast(layout.offset))); } -} -void GlRenderTask::uploadValues() -{ - for (auto& property : mUniformPropertyBuffer) - { - PropertyValue& propertyVal = property.second.propertyValues; - switch (property.second.dataType) { - case VertexProperty::DataType::INT: { - switch (propertyVal.getStride()) { - case 1: - mProgram->setUniform1Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData()); - break; - case 2: - mProgram->setUniform2Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData()); - break; - case 3: - mProgram->setUniform3Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData()); - break; - case 4: - mProgram->setUniform4Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData()); - default: break; - } - break; - } - case VertexProperty::DataType::FLOAT: { - switch (propertyVal.getStride()) { - case 1: - mProgram->setUniform1Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData()); - break; - case 2: - mProgram->setUniform2Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData()); - break; - case 3: - mProgram->setUniform3Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData()); - break; - case 4: - mProgram->setUniform4Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData()); - default: break; - } - break; - } - case VertexProperty::DataType::MATRIX: { - mProgram->setUniform4x4Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData()); - break; - } + // binding uniforms + for (uint32_t i = 0; i < mBindingResources.count; i++) { + const auto& binding = mBindingResources[i]; + if (binding.type == GlBindingType::kTexture) { + GL_CHECK(glActiveTexture(GL_TEXTURE0 + binding.bindPoint)); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, binding.gBufferId)); + + mProgram->setUniform1Value(binding.location, 1, (int32_t*)&binding.bindPoint); + } else if (binding.type == GlBindingType::kUniformBuffer) { + + GL_CHECK(glUniformBlockBinding(mProgram->getProgramId(), binding.location, binding.bindPoint)); + GL_CHECK(glBindBufferRange(GL_UNIFORM_BUFFER, binding.bindPoint, binding.gBufferId, + binding.bufferOffset, binding.bufferRange)); } } -} + GL_CHECK(glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_INT, reinterpret_cast(mIndexOffset))); -std::shared_ptr GlColorRenderTask::gen() -{ - return std::make_shared(); -} - - -GlColorRenderTask::GlColorRenderTask() - :GlRenderTask(GlRenderTask::RenderTypes::RT_Color, GlShader::gen(COLOR_VERT_SHADER, COLOR_FRAG_SHADER)) -{ - VertexProperty* prop = nullptr; - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "uColor", FORMAT_SIZE_VEC_4, mLocColor); -} - - -void GlColorRenderTask::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) -{ - if (mLocColor != -1) - { - PropertyInterface::setProperty(this, mLocColor, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); + // setup attribute layout + for (uint32_t i = 0; i < mVertexLayout.count; i++) { + const auto &layout = mVertexLayout[i]; + GL_CHECK(glDisableVertexAttribArray(layout.index)); } } - -GlGradientRenderTask::GlGradientRenderTask(GlRenderTask::RenderTypes renderType, std::shared_ptr shader) - :GlRenderTask(renderType, shader) +void GlRenderTask::addVertexLayout(const GlVertexLayout &layout) { - VertexProperty* prop = nullptr; - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "noise_level", FORMAT_SIZE_FLOAT, mLocNoise); - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "nStops", FORMAT_SIZE_FLOAT, mLocStopCnt); - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "stopPoints", FORMAT_SIZE_FLOAT, mLocStops); - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "stopColors", FORMAT_SIZE_VEC_4, mLocStopColors); + mVertexLayout.push(layout); } - -void GlGradientRenderTask::setNoise(float noise) +void GlRenderTask::addBindResource(const GlBindingResource &binding) { - if (mLocNoise != -1) - { - PropertyInterface::setProperty(this, mLocNoise, noise); - } + mBindingResources.push(binding); } - -void GlGradientRenderTask::setStopCount(int32_t count) +void GlRenderTask::setDrawRange(uint32_t offset, uint32_t count) { - if (mLocStopCnt != -1) - { - PropertyInterface::setProperty(this, mLocStopCnt, (float)count); - } -} - -void GlGradientRenderTask::setStopColor(int index, float stopVal, uint8_t r, uint8_t g, uint8_t b, uint8_t a) -{ - if (index < MAX_GRADIENT_STOPS && mLocStops != -1 && mLocStopColors != -1) - { - PropertyInterface::setProperty(this, mLocStops, stopVal); - PropertyInterface::setProperty(this, mLocStopColors, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); - } -} - - -std::shared_ptr GlLinearGradientRenderTask::gen() -{ - return std::make_shared(); -} - - -GlLinearGradientRenderTask::GlLinearGradientRenderTask() - :GlGradientRenderTask(GlRenderTask::RenderTypes::RT_LinGradient, GlShader::gen(GRADIENT_VERT_SHADER, LINEAR_GRADIENT_FRAG_SHADER)) -{ - VertexProperty* prop = nullptr; - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "gradStartPos", FORMAT_SIZE_VEC_2, mLocStartPos); - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "gradEndPos", FORMAT_SIZE_VEC_2, mLocEndPos); -} - - -void GlLinearGradientRenderTask::setStartPosition(float posX, float posY) -{ - if (mLocStartPos != -1) - { - PropertyInterface::setProperty(this, mLocStartPos, posX, posY); - } -} - - -void GlLinearGradientRenderTask::setEndPosition(float posX, float posY) -{ - if (mLocEndPos != -1) - { - PropertyInterface::setProperty(this, mLocEndPos, posX, posY); - } -} - - -std::shared_ptr GlRadialGradientRenderTask::gen() -{ - return std::make_shared(); -} - - -GlRadialGradientRenderTask::GlRadialGradientRenderTask() - :GlGradientRenderTask(GlRenderTask::RenderTypes::RT_RadGradient, GlShader::gen(GRADIENT_VERT_SHADER, RADIAL_GRADIENT_FRAG_SHADER)) -{ - VertexProperty* prop = nullptr; - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "gradStartPos", FORMAT_SIZE_VEC_2, mLocStartPos); - ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "stRadius", FORMAT_SIZE_FLOAT, mLocStRadius); -} - - -GlRadialGradientRenderTask::~GlRadialGradientRenderTask() -{ -} - - -void GlRadialGradientRenderTask::setStartPosition(float posX, float posY) -{ - if (mLocStartPos != -1) - { - PropertyInterface::setProperty(this, mLocStartPos, posX, posY); - } -} - - -void GlRadialGradientRenderTask::setStartRadius(float radius) -{ - if (mLocStRadius != -1) - { - PropertyInterface::setProperty(this, mLocStRadius, radius); - } -} - - -void GlRadialGradientRenderTask::setEndRadius(float radius) -{ - if (mLocEdRadius != -1) - { - PropertyInterface::setProperty(this, mLocEdRadius, radius); - } -} + mIndexOffset = offset; + mIndexCount = count; +} \ No newline at end of file diff --git a/src/renderer/gl_engine/tvgGlRenderTask.h b/src/renderer/gl_engine/tvgGlRenderTask.h index 49442fec..f69156e3 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.h +++ b/src/renderer/gl_engine/tvgGlRenderTask.h @@ -23,102 +23,72 @@ #ifndef _TVG_GL_RENDER_TASK_H_ #define _TVG_GL_RENDER_TASK_H_ -#include "tvgGlRendererProperties.h" +#include "tvgGlCommon.h" +#include "tvgGlProgram.h" + + +struct GlVertexLayout +{ + uint32_t index; + uint32_t size; + uint32_t stride; + size_t offset; +}; + +enum class GlBindingType +{ + kUniformBuffer, + kTexture, +}; + + +struct GlBindingResource +{ + GlBindingType type; + /** + * Binding point index. + * Can be a uniform location for a texture + * Can be a uniform buffer binding index for a uniform block + */ + uint32_t bindPoint = {}; + uint32_t location = {}; + GLuint gBufferId = {}; + uint32_t bufferOffset = {}; + uint32_t bufferRange = {}; + + GlBindingResource() = default; + + GlBindingResource(uint32_t index, uint32_t location, uint32_t bufferId, uint32_t offset, uint32_t range) + : type(GlBindingType::kUniformBuffer), bindPoint(index), location(location), gBufferId(bufferId), bufferOffset(offset), bufferRange(range) + { + } + + GlBindingResource(uint32_t bindPoint, uint32_t texId, uint32_t location) + : type(GlBindingType::kTexture), bindPoint(bindPoint), location(location), gBufferId(texId) + { + } +}; -#define MAX_GRADIENT_STOPS 4 class GlRenderTask { public: - enum RenderTypes - { - RT_Color = 0, - RT_LinGradient, - RT_RadGradient, + GlRenderTask(GlProgram* program): mProgram(program) {} + ~GlRenderTask() = default; - RT_None, - }; + void run(); - GlRenderTask(RenderTypes renderType, std::shared_ptr shader); - RenderTypes getRenderType(); - - void load(); - static void unload(); - std::shared_ptr getProgram(); - std::map& getAttributeVertexProperty(); - std::map& getUniformVertexProperty(); - int32_t getLocationPropertyId() const; - int32_t getTransformLocationPropertyId() const; - void setTransform(int count, float* transform_matrix); - void uploadValues(); + void addVertexLayout(const GlVertexLayout& layout); + void addBindResource(const GlBindingResource& binding); + void setDrawRange(uint32_t offset, uint32_t count); + GlProgram* getProgram() { return mProgram; } private: - RenderTypes mRenderType; - - std::shared_ptr mProgram; - std::map mAttributePropertyBuffer; - std::map mUniformPropertyBuffer; - - int32_t mLocVertexAttribute = -1; - int32_t mLocTransform = -1; + GlProgram* mProgram; + uint32_t mIndexOffset = {}; + uint32_t mIndexCount = {}; + Array mVertexLayout = {}; + Array mBindingResources = {}; }; -class GlColorRenderTask : public GlRenderTask -{ -public: - static std::shared_ptr gen(); - GlColorRenderTask(); - void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a); - -private: - int32_t mLocColor = -1; -}; - -class GlGradientRenderTask : public GlRenderTask -{ -public: - GlGradientRenderTask(GlRenderTask::RenderTypes renderType, std::shared_ptr shader); - void setPrimitveSize(float width, float height); - void setCanvasSize(float width, float height); - void setNoise(float noise); - void setStopCount(int32_t count); - void setStopColor(int index, float stopVal, uint8_t r, uint8_t g, uint8_t b, uint8_t a); - int32_t getTransformLocationPropertyId() const; -private: - int32_t mLocNoise = -1; - int32_t mLocStopCnt = -1; - int32_t mLocStops = -1; - int32_t mLocStopColors = -1; -}; - -class GlLinearGradientRenderTask : public GlGradientRenderTask -{ -public: - static std::shared_ptr gen(); - GlLinearGradientRenderTask(); - void setStartPosition(float posX, float posY); - void setEndPosition(float posX, float posY); - -private: - int32_t mLocStartPos = -1; - int32_t mLocEndPos = -1; -}; - -class GlRadialGradientRenderTask : public GlGradientRenderTask -{ -public: - static std::shared_ptr gen(); - GlRadialGradientRenderTask(); - ~GlRadialGradientRenderTask(); - void setStartPosition(float posX, float posY); - void setStartRadius(float radius); - void setEndRadius(float radius); - -private: - int32_t mLocStartPos = -1; - int32_t mLocStRadius = -1; - int32_t mLocEdRadius = -1; -}; - - #endif /* _TVG_GL_RENDER_TASK_H_ */ diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 5826e87a..9f4e16ef 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -23,7 +23,9 @@ #include "tvgGlRenderer.h" #include "tvgGlGpuBuffer.h" #include "tvgGlGeometry.h" -#include "tvgGlPropertyInterface.h" +#include "tvgGlRenderTask.h" +#include "tvgGlProgram.h" +#include "tvgGlShaderSrc.h" /************************************************************************/ /* Internal Class Implementation */ @@ -67,8 +69,22 @@ bool GlRenderer::target(TVG_UNUSED uint32_t* buffer, uint32_t stride, uint32_t w bool GlRenderer::sync() { - GL_CHECK(glFinish()); - 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(); + + for(auto& task: mRenderTasks) { + task->run(); + } + + mGpuBuffer->unbind(); + + mRenderTasks.clear(); + return true; } @@ -81,19 +97,10 @@ RenderRegion GlRenderer::region(TVG_UNUSED RenderData data) bool GlRenderer::preRender() { - if (mRenderTasks.size() == 0) + if (mPrograms.size() == 0) { initShaders(); } - 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; } @@ -101,8 +108,6 @@ bool GlRenderer::preRender() bool GlRenderer::postRender() { - mGpuBuffer->unbind(); - return true; } @@ -243,7 +248,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, mGpuBuffer.get())) return sdata; + if (!sdata->geometry->tesselate(rshape, sdata->updateFlag)) return sdata; } return sdata; } @@ -295,6 +300,9 @@ GlRenderer* GlRenderer::gen() return new GlRenderer(); } +GlRenderer::GlRenderer() :mGpuBuffer(new GlStageBuffer), mPrograms(), mRenderTasks() +{ +} GlRenderer::~GlRenderer() { @@ -309,30 +317,51 @@ GlRenderer::~GlRenderer() void GlRenderer::initShaders() { // Solid Color Renderer - mRenderTasks.push_back(GlColorRenderTask::gen()); + mPrograms.push_back(make_unique(GlShader::gen(COLOR_VERT_SHADER, COLOR_FRAG_SHADER))); // Linear Gradient Renderer - mRenderTasks.push_back(GlLinearGradientRenderTask::gen()); + mPrograms.push_back(make_unique(GlShader::gen(GRADIENT_VERT_SHADER, LINEAR_GRADIENT_FRAG_SHADER))); // Radial Gradient Renderer - mRenderTasks.push_back(GlRadialGradientRenderTask::gen()); + mPrograms.push_back(make_unique(GlShader::gen(GRADIENT_VERT_SHADER, RADIAL_GRADIENT_FRAG_SHADER))); } void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag) { - GlColorRenderTask* renderTask = static_cast(mRenderTasks[GlRenderTask::RenderTypes::RT_Color].get()); - assert(renderTask); - renderTask->load(); - float* matrix = sdata.geometry->getTransforMatrix(); - PropertyInterface::clearData(renderTask); - renderTask->setColor(r, g, b, a); - renderTask->setTransform(FORMAT_SIZE_MAT_4x4, matrix); - int32_t vertexLoc = renderTask->getLocationPropertyId(); - renderTask->uploadValues(); - sdata.geometry->draw(vertexLoc, flag); - sdata.geometry->disableVertex(vertexLoc); + auto task = make_unique(mPrograms[RT_Color].get()); + if (!sdata.geometry->draw(task.get(), mGpuBuffer.get(), flag)) return; + + // matrix buffer + { + auto matrix = sdata.geometry->getTransforMatrix(); + uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix"); + + task->addBindResource(GlBindingResource{ + 0, + loc, + mGpuBuffer->getBufferId(), + mGpuBuffer->push(matrix, 16 * sizeof(float), true), + 16 * sizeof(float), + }); + } + // color + { + float color[4] = {r / 255.f, g / 255.f, b / 255.f, a / 255.f}; + + uint32_t loc = task->getProgram()->getUniformBlockIndex("ColorInfo"); + + task->addBindResource(GlBindingResource{ + 1, + loc, + mGpuBuffer->getBufferId(), + mGpuBuffer->push(color, 4 * sizeof(float), true), + 4 * sizeof(float), + }); + } + + mRenderTasks.emplace_back(std::move(task)); } @@ -342,50 +371,90 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla auto stopCnt = fill->colorStops(&stops); if (stopCnt < 2) return; - GlGradientRenderTask* rTask = nullptr; - auto matrix = sdata.geometry->getTransforMatrix(); + unique_ptr task; - switch (fill->identifier()) { - case TVG_CLASS_ID_LINEAR: { - float x1, y1, x2, y2; - GlLinearGradientRenderTask *renderTask = static_cast(mRenderTasks[GlRenderTask::RenderTypes::RT_LinGradient].get()); - assert(renderTask); - rTask = renderTask; - renderTask->load(); - PropertyInterface::clearData(renderTask); - const LinearGradient* grad = static_cast(fill); - grad->linear(&x1, &y1, &x2, &y2); - renderTask->setStartPosition(x1, y1); - renderTask->setEndPosition(x2, y2); - break; - } - case TVG_CLASS_ID_RADIAL: { - float x1, y1, r1; - GlRadialGradientRenderTask *renderTask = static_cast(mRenderTasks[GlRenderTask::RenderTypes::RT_RadGradient].get()); - assert(renderTask); - rTask = renderTask; - renderTask->load(); - PropertyInterface::clearData(renderTask); - const RadialGradient* grad = static_cast(fill); - grad->radial(&x1, &y1, &r1); - renderTask->setStartPosition(x1, y1); - renderTask->setStartRadius(r1); - break; - } + if (fill->identifier() == TVG_CLASS_ID_LINEAR) { + task = make_unique(mPrograms[RT_LinGradient].get()); + } else if (fill->identifier() == TVG_CLASS_ID_RADIAL) { + task = make_unique(mPrograms[RT_RadGradient].get()); + } else { + return; } - if (rTask) { - auto vertexLoc = rTask->getLocationPropertyId(); - rTask->setNoise(NOISE_LEVEL); - rTask->setStopCount((int)stopCnt); - rTask->setTransform(FORMAT_SIZE_MAT_4x4, matrix); - for (uint32_t i = 0; i < stopCnt; ++i) { - rTask->setStopColor(i, stops[i].offset, stops[i].r, stops[i].g, stops[i].b, stops[i].a); + if (!sdata.geometry->draw(task.get(), mGpuBuffer.get(), flag)) return; + + // matrix buffer + { + auto matrix = sdata.geometry->getTransforMatrix(); + uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix"); + + task->addBindResource(GlBindingResource{ + 0, + loc, + mGpuBuffer->getBufferId(), + mGpuBuffer->push(matrix, 16 * sizeof(float), true), + 16 * sizeof(float), + }); + } + + // gradient block + { + GlBindingResource gradientBinding{}; + uint32_t loc = task->getProgram()->getUniformBlockIndex("GradientInfo"); + + if (fill->identifier() == TVG_CLASS_ID_LINEAR) { + auto linearFill = static_cast(fill); + + GlLinearGradientBlock gradientBlock; + + gradientBlock.nStops[0] = stopCnt * 1.f; + gradientBlock.nStops[1] = NOISE_LEVEL; + for (uint32_t i = 0; i < stopCnt; ++i) { + gradientBlock.stopPoints[i] = stops[i].offset; + gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f; + gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 255.f; + gradientBlock.stopColors[i * 4 + 2] = stops[i].b / 255.f; + gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f; + } + + linearFill->linear(&gradientBlock.startPos[0], &gradientBlock.startPos[1], &gradientBlock.stopPos[0], &gradientBlock.stopPos[1]); + + gradientBinding = GlBindingResource{ + 1, + loc, + mGpuBuffer->getBufferId(), + mGpuBuffer->push(&gradientBlock, sizeof(GlLinearGradientBlock), true), + sizeof(GlLinearGradientBlock), + }; + } else { + auto radialFill = static_cast(fill); + + GlRadialGradientBlock gradientBlock; + + gradientBlock.nStops[0] = stopCnt * 1.f; + gradientBlock.nStops[1] = NOISE_LEVEL; + for (uint32_t i = 0; i < stopCnt; ++i) { + gradientBlock.stopPoints[i] = stops[i].offset; + gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f; + gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 255.f; + gradientBlock.stopColors[i * 4 + 2] = stops[i].b / 255.f; + gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f; + } + + radialFill->radial(&gradientBlock.centerPos[0], &gradientBlock.centerPos[1], &gradientBlock.radius[0]); + + gradientBinding = GlBindingResource{ + 1, + loc, + mGpuBuffer->getBufferId(), + mGpuBuffer->push(&gradientBlock, sizeof(GlRadialGradientBlock), true), + sizeof(GlRadialGradientBlock), + }; } - rTask->uploadValues(); - sdata.geometry->draw(vertexLoc, flag); - sdata.geometry->disableVertex(vertexLoc); + task->addBindResource(gradientBinding); } + + mRenderTasks.emplace_back(std::move(task)); } diff --git a/src/renderer/gl_engine/tvgGlRenderer.h b/src/renderer/gl_engine/tvgGlRenderer.h index 5f9f9294..88462f9c 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.h +++ b/src/renderer/gl_engine/tvgGlRenderer.h @@ -23,12 +23,23 @@ #ifndef _TVG_GL_RENDERER_H_ #define _TVG_GL_RENDERER_H_ +#include + #include "tvgGlRenderTask.h" #include "tvgGlGpuBuffer.h" class GlRenderer : public RenderMethod { public: + enum RenderTypes + { + RT_Color = 0, + RT_LinGradient, + RT_RadGradient, + + RT_None, + }; + Surface surface = {nullptr, 0, 0, 0, ColorSpace::Unsupported, true}; RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) override; @@ -59,15 +70,16 @@ public: static int term(); private: - GlRenderer(): mGpuBuffer(new GlStageBuffer) {}; + GlRenderer(); ~GlRenderer(); void initShaders(); void drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag); void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag); - vector> mRenderTasks; std::unique_ptr mGpuBuffer; + vector> mPrograms; + vector> mRenderTasks; }; #endif /* _TVG_GL_RENDERER_H_ */ diff --git a/src/renderer/gl_engine/tvgGlRendererProperties.h b/src/renderer/gl_engine/tvgGlRendererProperties.h deleted file mode 100644 index 3bd97e33..00000000 --- a/src/renderer/gl_engine/tvgGlRendererProperties.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_GL_RENDER_PROPERTIES_H_ -#define _TVG_GL_RENDER_PROPERTIES_H_ - -#include -#include "tvgGlCommon.h" -#include "tvgGlProgram.h" - -class PropertyValue -{ -public: - void setStride(uint32_t s) - { - stride = s; - if (values.capacity() == values.size()) - { - values.reserve(values.size() + stride); - } - } - - uint32_t getStride() const - { - return stride; - } - - uint32_t getSize() const - { - return values.size(); - } - - uint32_t getCount() const - { - return (values.size() / stride); - } - - void clear() - { - values.clear(); - } - - const float* getData() - { - return values.data(); - } - - void set(float v) - { - values.push_back(v); - } - - template - void set(float first, Args... args) - { - if (values.capacity() == values.size()) - { - values.reserve(values.size() + stride); - } - set(first); - set(args...); - } - -private: - std::vector values; - uint32_t stride = 0; -}; - -struct VertexProperty -{ -public: - enum class DataType - { - INT = 0, - FLOAT, - MATRIX - }; - enum class PropertyType - { - ATTRIBUTE = 0, - UNIFORM - }; - - int32_t propertyId = -1; - std::string propertyName = ""; - PropertyType propType = PropertyType::UNIFORM; - DataType dataType = DataType::FLOAT; - PropertyValue propertyValues; -}; - - -#endif /* _TVG_GL_RENDER_PROPERTIES_H_ */ diff --git a/src/renderer/gl_engine/tvgGlShaderSrc.cpp b/src/renderer/gl_engine/tvgGlShaderSrc.cpp index 32a90d19..72048a0d 100644 --- a/src/renderer/gl_engine/tvgGlShaderSrc.cpp +++ b/src/renderer/gl_engine/tvgGlShaderSrc.cpp @@ -27,20 +27,26 @@ const char* COLOR_VERT_SHADER = TVG_COMPOSE_SHADER( layout(location = 0) in vec3 aLocation; \n - uniform mat4 uTransform; \n + layout(std140) uniform Matrix { \n + mat4 transform; \n + } uMatrix; \n out float vOpacity; \n void main() \n { \n - gl_Position = uTransform * vec4(aLocation.xy, 0.0, 1.0); \n + gl_Position = \n + uMatrix.transform * vec4(aLocation.xy, 0.0, 1.0); \n vOpacity = aLocation.z; \n }); const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER( - uniform vec4 uColor; \n + layout(std140) uniform ColorInfo { \n + vec4 solidColor; \n + } uColorInfo; \n in float vOpacity; \n out vec4 FragColor; \n void main() \n { \n + vec4 uColor = uColorInfo.solidColor; \n FragColor = vec4(uColor.xyz, uColor.w*vOpacity); \n }); @@ -48,22 +54,20 @@ const char* GRADIENT_VERT_SHADER = TVG_COMPOSE_SHADER( layout(location = 0) in vec3 aLocation; \n out float vOpacity; \n out vec2 vPos; \n -uniform mat4 uTransform; \n +layout(std140) uniform Matrix { \n + mat4 transform; \n +} uMatrix; \n \n void main() \n { \n - gl_Position = uTransform * vec4(aLocation.xy, 0.0, 1.0); \n + gl_Position = uMatrix.transform * vec4(aLocation.xy, 0.0, 1.0); \n vOpacity = aLocation.z; \n vPos = aLocation.xy; \n }); -std::string STR_GRADIENT_FRAG_COMMON_VARIABLES = TVG_COMPOSE_SHADER( \n +std::string STR_GRADIENT_FRAG_COMMON_VARIABLES = TVG_COMPOSE_SHADER( const int MAX_STOP_COUNT = 4; \n -uniform float nStops; \n -uniform float noise_level; \n -uniform float stopPoints[MAX_STOP_COUNT]; \n -uniform vec4 stopColors[MAX_STOP_COUNT]; \n in vec2 vPos; \n in float vOpacity; \n ); @@ -80,23 +84,26 @@ vec4 gradient(float t) { \n vec4 col = vec4(0.0); \n int i = 0; \n - int count = int(nStops); \n - if (t <= stopPoints[0]) \n + int count = int(uGradientInfo.nStops[0]); \n + if (t <= uGradientInfo.stopPoints[0]) \n { \n - col += stopColors[0]; \n + col += uGradientInfo.stopColors[0]; \n } \n - else if (t >= stopPoints[count - 1]) \n + else if (t >= uGradientInfo.stopPoints[count - 1]) \n { \n - col += stopColors[count - 1]; \n + col += uGradientInfo.stopColors[count - 1]; \n } \n else \n { \n for (i = 0; i < count - 1; ++i) \n { \n - if (t > stopPoints[i] && t < stopPoints[i + 1]) \n + if (t > uGradientInfo.stopPoints[i] && t < uGradientInfo.stopPoints[i + 1]) \n { \n - col += (stopColors[i] * (1. - gradientStep(stopPoints[i], stopPoints[i + 1], t))); \n - col += (stopColors[i + 1] * gradientStep(stopPoints[i], stopPoints[i + 1], t)); \n + col += (uGradientInfo.stopColors[i] * \n + (1. - gradientStep(uGradientInfo.stopPoints[i], \n + uGradientInfo.stopPoints[i + 1], t))); \n + col += (uGradientInfo.stopColors[i + 1] * \n + gradientStep(uGradientInfo.stopPoints[i], uGradientInfo.stopPoints[i + 1], t)); \n break; \n } \n } \n @@ -113,8 +120,13 @@ vec3 ScreenSpaceDither(vec2 vScreenPos) }); std::string STR_LINEAR_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER( -uniform vec2 gradStartPos; \n -uniform vec2 gradEndPos; \n +layout(std140) uniform GradientInfo { \n + vec4 nStops; \n + vec2 gradStartPos; \n + vec2 gradEndPos; \n + vec4 stopPoints; \n + vec4 stopColors[MAX_STOP_COUNT]; \n +} uGradientInfo ; \n ); std::string STR_LINEAR_GRADIENT_MAIN = TVG_COMPOSE_SHADER( @@ -122,8 +134,8 @@ out vec4 FragColor; void main() \n { \n vec2 pos = vPos; \n - vec2 st = gradStartPos; \n - vec2 ed = gradEndPos; \n + vec2 st = uGradientInfo.gradStartPos; \n + vec2 ed = uGradientInfo.gradEndPos; \n \n vec2 ba = ed - st; \n \n @@ -134,14 +146,19 @@ void main() \n vec4 color = gradient(t); \n \n - vec3 noise = 8.0 * noise_level * ScreenSpaceDither(pos); \n + vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n vec4 finalCol = vec4(color.xyz + noise, color.w); \n FragColor = vec4(finalCol.xyz, finalCol.w* vOpacity); \n }); std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER( - uniform vec2 gradStartPos; \n - uniform float stRadius; \n +layout(std140) uniform GradientInfo { \n + vec4 nStops; \n + vec2 centerPos; \n + vec2 radius; \n + vec4 stopPoints; \n + vec4 stopColors[MAX_STOP_COUNT]; \n +} uGradientInfo ; \n ); std::string STR_RADIAL_GRADIENT_MAIN = TVG_COMPOSE_SHADER( @@ -150,8 +167,8 @@ void main() { \n vec2 pos = vPos; \n \n - float ba = stRadius; \n - float d = distance(gradStartPos, pos); \n + float ba = uGradientInfo.radius.x; \n + float d = distance(uGradientInfo.centerPos, pos); \n d = (d / ba); \n \n //float t = smoothstep(0.0, 1.0, clamp(d, 0.0, 1.0)); \n @@ -159,7 +176,7 @@ void main() \n vec4 color = gradient(t); \n \n - vec3 noise = 8.0 * noise_level * ScreenSpaceDither(pos); \n + vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n vec4 finalCol = vec4(color.xyz + noise, color.w); \n FragColor = vec4(finalCol.xyz, finalCol.w * vOpacity); \n });