mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-12 07:32:20 +00:00
gl_engine: support basic alpha composite
* introduce a new class GlRenderPass to hold off-screen rendering result * add basic alpha composite support with begin/end render-pass
This commit is contained in:
parent
81e3025ad9
commit
a46af19ccb
8 changed files with 452 additions and 26 deletions
|
@ -4,6 +4,7 @@ source_file = [
|
|||
'tvgGlGpuBuffer.h',
|
||||
'tvgGlProgram.h',
|
||||
'tvgGlRenderer.h',
|
||||
'tvgGlRenderPass.h',
|
||||
'tvgGlRenderTask.h',
|
||||
'tvgGlShader.h',
|
||||
'tvgGlShaderSrc.h',
|
||||
|
@ -11,6 +12,7 @@ source_file = [
|
|||
'tvgGlGpuBuffer.cpp',
|
||||
'tvgGlProgram.cpp',
|
||||
'tvgGlRenderer.cpp',
|
||||
'tvgGlRenderPass.cpp',
|
||||
'tvgGlRenderTask.cpp',
|
||||
'tvgGlShader.cpp',
|
||||
'tvgGlShaderSrc.cpp',
|
||||
|
|
|
@ -57,8 +57,8 @@ struct GlShape
|
|||
const RenderShape* rshape = nullptr;
|
||||
float viewWd;
|
||||
float viewHt;
|
||||
uint32_t opacity = 0;
|
||||
GLuint texId = 0;
|
||||
uint32_t texOpacity = 0;
|
||||
uint32_t texFlipY = 0;
|
||||
ColorSpace texColorSpace = ColorSpace::ABGR8888;
|
||||
RenderUpdateFlag updateFlag = None;
|
||||
|
|
74
src/renderer/gl_engine/tvgGlRenderPass.cpp
Normal file
74
src/renderer/gl_engine/tvgGlRenderPass.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 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 "tvgGlRenderPass.h"
|
||||
#include "tvgGlRenderTask.h"
|
||||
|
||||
GlRenderTarget::GlRenderTarget(uint32_t width, uint32_t height): mWidth(width), mHeight(height) {}
|
||||
|
||||
GlRenderTarget::~GlRenderTarget()
|
||||
{
|
||||
if (mFbo == 0) return;
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
|
||||
GL_CHECK(glDeleteFramebuffers(1, &mFbo));
|
||||
|
||||
if (mColorTex) GL_CHECK(glDeleteTextures(1, &mColorTex));
|
||||
}
|
||||
|
||||
void GlRenderTarget::init(GLint resolveId)
|
||||
{
|
||||
if (mFbo != 0 || mWidth == 0 || mHeight == 0) return;
|
||||
|
||||
GL_CHECK(glGenFramebuffers(1, &mFbo));
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mFbo));
|
||||
|
||||
GL_CHECK(glGenTextures(1, &mColorTex));
|
||||
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D, mColorTex));
|
||||
GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
|
||||
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
||||
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTex, 0));
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, resolveId));
|
||||
}
|
||||
|
||||
GlRenderPass::GlRenderPass(GlRenderTarget* fbo): mFbo(fbo), mTasks() {}
|
||||
|
||||
GlRenderPass::GlRenderPass(GlRenderPass&& other): mFbo(other.mFbo), mTasks(std::move(other.mTasks)) {}
|
||||
|
||||
GlRenderPass::~GlRenderPass() {}
|
||||
|
||||
void GlRenderPass::addRenderTask(unique_ptr<GlRenderTask> task)
|
||||
{
|
||||
mTasks.emplace_back(std::move(task));
|
||||
}
|
74
src/renderer/gl_engine/tvgGlRenderPass.h
Normal file
74
src/renderer/gl_engine/tvgGlRenderPass.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 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_PASS_H_
|
||||
#define _TVG_GL_RENDER_PASS_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "tvgGlCommon.h"
|
||||
|
||||
class GlRenderTask;
|
||||
class GlProgram;
|
||||
|
||||
class GlRenderTarget
|
||||
{
|
||||
public:
|
||||
GlRenderTarget(uint32_t width, uint32_t height);
|
||||
~GlRenderTarget();
|
||||
|
||||
void init(GLint resolveId);
|
||||
|
||||
GLuint getFboId() { return mFbo; }
|
||||
GLuint getColorTexture() { return mColorTex; }
|
||||
|
||||
private:
|
||||
uint32_t mWidth = 0;
|
||||
uint32_t mHeight = 0;
|
||||
GLuint mFbo = 0;
|
||||
GLuint mColorTex = 0;
|
||||
};
|
||||
|
||||
class GlRenderPass
|
||||
{
|
||||
public:
|
||||
GlRenderPass(GlRenderTarget* fbo);
|
||||
GlRenderPass(GlRenderPass&& other);
|
||||
|
||||
~GlRenderPass();
|
||||
|
||||
void addRenderTask(unique_ptr<GlRenderTask> task);
|
||||
|
||||
GLuint getFboId() { return mFbo->getFboId(); }
|
||||
|
||||
template <class T>
|
||||
unique_ptr<T> endRenderPass(GlProgram* program, GLuint targetFbo) {
|
||||
return make_unique<T>(program, targetFbo, mFbo->getFboId(), std::move(mTasks));
|
||||
}
|
||||
private:
|
||||
GlRenderTarget* mFbo;
|
||||
vector<unique_ptr<GlRenderTask>> mTasks = {};
|
||||
};
|
||||
|
||||
|
||||
#endif // _TVG_GL_RENDER_PASS_H_
|
|
@ -27,7 +27,7 @@
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
void GlRenderTask::run()
|
||||
void GlRenderTask::run()
|
||||
{
|
||||
// bind shader
|
||||
mProgram->load();
|
||||
|
@ -89,3 +89,59 @@ void GlRenderTask::setViewport(const RenderRegion &viewport)
|
|||
{
|
||||
mViewport = viewport;
|
||||
}
|
||||
|
||||
GlComposeTask::GlComposeTask(GlProgram* program, GLuint target, GLuint selfFbo, vector<unique_ptr<GlRenderTask>> tasks)
|
||||
:GlRenderTask(program) ,mTargetFbo(target), mSelfFbo(selfFbo), mTasks(std::move(tasks))
|
||||
{
|
||||
}
|
||||
|
||||
void GlComposeTask::run()
|
||||
{
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getSelfFbo()));
|
||||
|
||||
// clear this fbo
|
||||
GLenum color_buffer = GL_COLOR_ATTACHMENT0;
|
||||
const float transparent[] = {0.f, 0.f, 0.f, 0.f};
|
||||
|
||||
GL_CHECK(glDrawBuffers(1, &color_buffer));
|
||||
GL_CHECK(glClearBufferfv(GL_COLOR, 0, transparent));
|
||||
|
||||
for(auto& task : mTasks) {
|
||||
task->run();
|
||||
}
|
||||
}
|
||||
|
||||
GlBlitTask::GlBlitTask(GlProgram* program, GLuint target, GLuint compose, vector<unique_ptr<GlRenderTask>> tasks)
|
||||
: GlComposeTask(program, target, compose, std::move(tasks))
|
||||
{
|
||||
}
|
||||
|
||||
void GlBlitTask::setSize(uint32_t width, uint32_t height)
|
||||
{
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
}
|
||||
|
||||
void GlBlitTask::run()
|
||||
{
|
||||
GlComposeTask::run();
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo()));
|
||||
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, getSelfFbo()));
|
||||
|
||||
GL_CHECK(glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||
}
|
||||
|
||||
GlDrawBlitTask::GlDrawBlitTask(GlProgram* program, GLuint target, GLuint compose, vector<unique_ptr<GlRenderTask>> tasks)
|
||||
: GlComposeTask(program, target, compose, std::move(tasks))
|
||||
{
|
||||
}
|
||||
|
||||
void GlDrawBlitTask::run()
|
||||
{
|
||||
GlComposeTask::run();
|
||||
|
||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo()));
|
||||
|
||||
GlRenderTask::run();
|
||||
}
|
|
@ -23,6 +23,9 @@
|
|||
#ifndef _TVG_GL_RENDER_TASK_H_
|
||||
#define _TVG_GL_RENDER_TASK_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "tvgGlCommon.h"
|
||||
#include "tvgGlProgram.h"
|
||||
|
||||
|
@ -69,14 +72,13 @@ struct GlBindingResource
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class GlRenderTask
|
||||
{
|
||||
public:
|
||||
GlRenderTask(GlProgram* program): mProgram(program) {}
|
||||
~GlRenderTask() = default;
|
||||
virtual ~GlRenderTask() = default;
|
||||
|
||||
void run();
|
||||
virtual void run();
|
||||
|
||||
void addVertexLayout(const GlVertexLayout& layout);
|
||||
void addBindResource(const GlBindingResource& binding);
|
||||
|
@ -93,4 +95,48 @@ private:
|
|||
Array<GlBindingResource> mBindingResources = {};
|
||||
};
|
||||
|
||||
class GlComposeTask : public GlRenderTask
|
||||
{
|
||||
public:
|
||||
GlComposeTask(GlProgram* program, GLuint target, GLuint selfFbo, vector<unique_ptr<GlRenderTask>> tasks);
|
||||
~GlComposeTask() override = default;
|
||||
|
||||
void run() override;
|
||||
|
||||
protected:
|
||||
GLuint getTargetFbo() { return mTargetFbo; }
|
||||
|
||||
GLuint getSelfFbo() { return mSelfFbo; }
|
||||
|
||||
private:
|
||||
GLuint mTargetFbo;
|
||||
GLuint mSelfFbo;
|
||||
vector<unique_ptr<GlRenderTask>> mTasks;
|
||||
};
|
||||
|
||||
class GlBlitTask : public GlComposeTask
|
||||
{
|
||||
public:
|
||||
GlBlitTask(GlProgram*, GLuint target, GLuint compose, vector<unique_ptr<GlRenderTask>> tasks);
|
||||
~GlBlitTask() override = default;
|
||||
|
||||
void setSize(uint32_t width, uint32_t height);
|
||||
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
uint32_t mWidth = 0;
|
||||
uint32_t mHeight = 0;
|
||||
};
|
||||
|
||||
class GlDrawBlitTask : public GlComposeTask
|
||||
{
|
||||
public:
|
||||
GlDrawBlitTask(GlProgram*, GLuint target, GLuint compose, vector<unique_ptr<GlRenderTask>> tasks);
|
||||
~GlDrawBlitTask() override = default;
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _TVG_GL_RENDER_TASK_H_ */
|
||||
|
|
|
@ -68,6 +68,14 @@ bool GlRenderer::target(TVG_UNUSED uint32_t* buffer, uint32_t stride, uint32_t w
|
|||
mViewport.w = surface.w;
|
||||
mViewport.h = surface.h;
|
||||
|
||||
// get current binded framebuffer id
|
||||
// EFL seems has a seperate framebuffer for evagl view
|
||||
//TODO: introduce a new api to specify which fbo this canvas is binded
|
||||
GL_CHECK(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mTargetFboId));
|
||||
|
||||
mRootTarget = make_unique<GlRenderTarget>(surface.w, surface.h);
|
||||
mRootTarget->init(mTargetFboId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -83,16 +91,22 @@ bool GlRenderer::sync()
|
|||
|
||||
mGpuBuffer->bind();
|
||||
|
||||
for(auto& task: mRenderTasks) {
|
||||
task->run();
|
||||
}
|
||||
assert(mRenderPassStack.size() == 1);
|
||||
|
||||
auto task = mRenderPassStack.front().endRenderPass<GlBlitTask>(nullptr, mTargetFboId);
|
||||
|
||||
task->setSize(surface.w, surface.h);
|
||||
|
||||
task->run();
|
||||
|
||||
mGpuBuffer->unbind();
|
||||
|
||||
mRenderTasks.clear();
|
||||
|
||||
GL_CHECK(glDisable(GL_SCISSOR_TEST));
|
||||
|
||||
mRenderPassStack.clear();
|
||||
mPoolIndex = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -110,6 +124,8 @@ bool GlRenderer::preRender()
|
|||
initShaders();
|
||||
}
|
||||
|
||||
mRenderPassStack.emplace_back(GlRenderPass(mRootTarget.get()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -122,22 +138,46 @@ bool GlRenderer::postRender()
|
|||
|
||||
Compositor* GlRenderer::target(TVG_UNUSED const RenderRegion& region, TVG_UNUSED ColorSpace cs)
|
||||
{
|
||||
//TODO: Prepare frameBuffer & Setup render target for composition
|
||||
return nullptr;
|
||||
mComposeStack.emplace_back(make_unique<tvg::Compositor>());
|
||||
return mComposeStack.back().get();
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::beginComposite(TVG_UNUSED Compositor* cmp, CompositeMethod method, uint8_t opacity)
|
||||
bool GlRenderer::beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity)
|
||||
{
|
||||
//TODO: delete the given compositor and restore the context
|
||||
return false;
|
||||
if (!cmp) return false;
|
||||
|
||||
// TODO handle other composite method with recursive begin composite
|
||||
|
||||
cmp->method = method;
|
||||
cmp->opacity = opacity;
|
||||
|
||||
if (cmp->method == CompositeMethod::None) {
|
||||
if (mPoolIndex >= mComposePool.size()) {
|
||||
mComposePool.emplace_back(make_unique<GlRenderTarget>(surface.w, surface.h));
|
||||
mComposePool.back()->init(mTargetFboId);
|
||||
}
|
||||
mRenderPassStack.emplace_back(GlRenderPass(mComposePool[mPoolIndex++].get()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::endComposite(TVG_UNUSED Compositor* cmp)
|
||||
{
|
||||
//TODO: delete the given compositor and restore the context
|
||||
return false;
|
||||
if (mComposeStack.empty()) return false;
|
||||
if (mComposeStack.back().get() != cmp) return false;
|
||||
|
||||
// end current render pass;
|
||||
auto currCmp = std::move(mComposeStack.back());
|
||||
mComposeStack.pop_back();
|
||||
|
||||
assert(cmp == currCmp.get());
|
||||
|
||||
endRenderPass(currCmp.get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -181,7 +221,7 @@ bool GlRenderer::renderImage(void* data)
|
|||
}
|
||||
// image info
|
||||
{
|
||||
uint32_t info[4] = {sdata->texColorSpace, sdata->texFlipY, sdata->texOpacity, 0};
|
||||
uint32_t info[4] = {sdata->texColorSpace, sdata->texFlipY, sdata->opacity, 0};
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("ColorInfo");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
|
@ -198,7 +238,7 @@ bool GlRenderer::renderImage(void* data)
|
|||
task->addBindResource(GlBindingResource{0, sdata->texId, loc});
|
||||
}
|
||||
|
||||
mRenderTasks.emplace_back(std::move(task));
|
||||
currentPass()->addRenderTask(std::move(task));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -283,7 +323,7 @@ RenderData GlRenderer::prepare(Surface* image, const RenderMesh* mesh, RenderDat
|
|||
sdata->updateFlag = flags;
|
||||
|
||||
sdata->texId = _genTexture(image);
|
||||
sdata->texOpacity = opacity;
|
||||
sdata->opacity = opacity;
|
||||
sdata->texColorSpace = image->cs;
|
||||
sdata->texFlipY = (mesh && mesh->triangleCnt) ? 0 : 1;
|
||||
sdata->geometry = make_unique<GlGeometry>();
|
||||
|
@ -309,7 +349,7 @@ RenderData GlRenderer::prepare(TVG_UNUSED const Array<RenderData>& scene, TVG_UN
|
|||
}
|
||||
|
||||
|
||||
RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, TVG_UNUSED uint8_t opacity, RenderUpdateFlag flags, TVG_UNUSED bool clipper)
|
||||
RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, TVG_UNUSED bool clipper)
|
||||
{
|
||||
//prepare shape data
|
||||
GlShape* sdata = static_cast<GlShape*>(data);
|
||||
|
@ -325,6 +365,7 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
|
||||
|
||||
sdata->geometry = make_unique<GlGeometry>();
|
||||
sdata->opacity = opacity;
|
||||
|
||||
//invisible?
|
||||
uint8_t alphaF = 0, alphaS = 0;
|
||||
|
@ -400,14 +441,12 @@ GlRenderer* GlRenderer::gen()
|
|||
return new GlRenderer();
|
||||
}
|
||||
|
||||
GlRenderer::GlRenderer() :mViewport() ,mGpuBuffer(new GlStageBuffer), mPrograms(), mRenderTasks()
|
||||
GlRenderer::GlRenderer() :mViewport() ,mGpuBuffer(new GlStageBuffer), mPrograms()
|
||||
{
|
||||
}
|
||||
|
||||
GlRenderer::~GlRenderer()
|
||||
{
|
||||
mRenderTasks.clear();
|
||||
|
||||
--rendererCnt;
|
||||
|
||||
if (rendererCnt == 0 && initEngineCnt == 0) _termEngine();
|
||||
|
@ -435,6 +474,8 @@ void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b,
|
|||
auto task = make_unique<GlRenderTask>(mPrograms[RT_Color].get());
|
||||
|
||||
if (!sdata.geometry->draw(task.get(), mGpuBuffer.get(), flag)) return;
|
||||
|
||||
a = MULTIPLY(a, sdata.opacity);
|
||||
|
||||
// matrix buffer
|
||||
{
|
||||
|
@ -464,7 +505,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b,
|
|||
});
|
||||
}
|
||||
|
||||
mRenderTasks.emplace_back(std::move(task));
|
||||
currentPass()->addRenderTask(std::move(task));
|
||||
}
|
||||
|
||||
|
||||
|
@ -558,6 +599,128 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
task->addBindResource(gradientBinding);
|
||||
}
|
||||
|
||||
mRenderTasks.emplace_back(std::move(task));
|
||||
currentPass()->addRenderTask(std::move(task));
|
||||
}
|
||||
|
||||
GlRenderPass* GlRenderer::currentPass()
|
||||
{
|
||||
if (mRenderPassStack.empty()) return nullptr;
|
||||
|
||||
return &mRenderPassStack.back();
|
||||
}
|
||||
|
||||
void GlRenderer::prepareCmpTask(GlRenderTask* task)
|
||||
{
|
||||
// we use 1:1 blit mapping since compositor fbo is same size as root fbo
|
||||
Array<float> vertices;
|
||||
vertices.reserve(5 * 4);
|
||||
|
||||
float left = -1.f;
|
||||
float top = 1.f;
|
||||
float right = 1.f;
|
||||
float bottom = -1.f;
|
||||
|
||||
// left top point
|
||||
vertices.push(left);
|
||||
vertices.push(top);
|
||||
vertices.push(1.f);
|
||||
vertices.push(0.f);
|
||||
vertices.push(1.f);
|
||||
// left bottom point
|
||||
vertices.push(left);
|
||||
vertices.push(bottom);
|
||||
vertices.push(1.f);
|
||||
vertices.push(0.f);
|
||||
vertices.push(0.f);
|
||||
// right top point
|
||||
vertices.push(right);
|
||||
vertices.push(top);
|
||||
vertices.push(1.f);
|
||||
vertices.push(1.f);
|
||||
vertices.push(1.f);
|
||||
// right bottom point
|
||||
vertices.push(right);
|
||||
vertices.push(bottom);
|
||||
vertices.push(1.f);
|
||||
vertices.push(1.f);
|
||||
vertices.push(0.f);
|
||||
|
||||
Array<uint32_t> indices;
|
||||
indices.reserve(6);
|
||||
|
||||
indices.push(0);
|
||||
indices.push(1);
|
||||
indices.push(2);
|
||||
indices.push(2);
|
||||
indices.push(1);
|
||||
indices.push(3);
|
||||
|
||||
uint32_t vertexOffset = mGpuBuffer->push(vertices.data, vertices.count * sizeof(float));
|
||||
uint32_t indexOffset = mGpuBuffer->push(indices.data, vertices.count * sizeof(uint32_t));
|
||||
|
||||
task->addVertexLayout(GlVertexLayout{0, 3, 5 * sizeof(float), vertexOffset});
|
||||
task->addVertexLayout(GlVertexLayout{1, 2, 5 * sizeof(float), vertexOffset + 3 * sizeof(float)});
|
||||
|
||||
task->setDrawRange(indexOffset, indices.count);
|
||||
task->setViewport(RenderRegion{
|
||||
mViewport.x,
|
||||
static_cast<int32_t>((surface.h - mViewport.y - mViewport.h)),
|
||||
mViewport.w,
|
||||
mViewport.h,
|
||||
});
|
||||
}
|
||||
|
||||
void GlRenderer::endRenderPass(Compositor* cmp)
|
||||
{
|
||||
if (cmp->method != CompositeMethod::None) {
|
||||
//TODO support advance composite method with recursive compositor
|
||||
return;
|
||||
}
|
||||
|
||||
auto renderPass = std::move(mRenderPassStack.back());
|
||||
mRenderPassStack.pop_back();
|
||||
|
||||
auto task = renderPass.endRenderPass<GlDrawBlitTask>(
|
||||
mPrograms[RT_Image].get(), currentPass()->getFboId());
|
||||
|
||||
prepareCmpTask(task.get());
|
||||
|
||||
// matrix buffer
|
||||
{
|
||||
float matrix[16];
|
||||
memset(matrix, 0, 16 * sizeof(float));
|
||||
matrix[0] = 1.f;
|
||||
matrix[5] = 1.f;
|
||||
matrix[10] = 1.f;
|
||||
matrix[15] = 1.f;
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
0,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(matrix, 16 * sizeof(float), true),
|
||||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
// image info
|
||||
{
|
||||
uint32_t info[4] = {ABGR8888, 0, cmp->opacity, 0};
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("ColorInfo");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(info, 4 * sizeof(uint32_t), true),
|
||||
4 * sizeof(uint32_t),
|
||||
});
|
||||
}
|
||||
// texture id
|
||||
{
|
||||
uint32_t loc = task->getProgram()->getUniformLocation("uTexture");
|
||||
task->addBindResource(GlBindingResource{0, renderPass.getFboId(), loc});
|
||||
}
|
||||
|
||||
currentPass()->addRenderTask(std::move(task));
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "tvgGlRenderTask.h"
|
||||
#include "tvgGlGpuBuffer.h"
|
||||
#include "tvgGlRenderPass.h"
|
||||
|
||||
class GlRenderer : public RenderMethod
|
||||
{
|
||||
|
@ -78,10 +79,20 @@ private:
|
|||
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);
|
||||
|
||||
GlRenderPass* currentPass();
|
||||
|
||||
void prepareCmpTask(GlRenderTask* task);
|
||||
void endRenderPass(Compositor* cmp);
|
||||
|
||||
GLint mTargetFboId = 0;
|
||||
RenderRegion mViewport;
|
||||
std::unique_ptr<GlStageBuffer> mGpuBuffer;
|
||||
vector<std::unique_ptr<GlProgram>> mPrograms;
|
||||
vector<std::unique_ptr<GlRenderTask>> mRenderTasks;
|
||||
unique_ptr<GlRenderTarget> mRootTarget = {};
|
||||
vector<unique_ptr<GlRenderTarget>> mComposePool = {};
|
||||
size_t mPoolIndex = 0;
|
||||
vector<GlRenderPass> mRenderPassStack = {};
|
||||
vector<unique_ptr<Compositor>> mComposeStack = {};
|
||||
};
|
||||
|
||||
#endif /* _TVG_GL_RENDERER_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue