mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
gl_engine: fix clip path and bounds not correct
* Optimize clip logical, change to use GL_GRATER and keep incrace depth value, so no need to do depth clear after every clip draw. * Correct geometry bounding box calculation, and make sure the bounds is larger than all vertices * Limit drawing area for off-screen RenderPass with correct scissor box
This commit is contained in:
parent
d9294471a6
commit
f8626d13d1
9 changed files with 166 additions and 65 deletions
|
@ -279,10 +279,10 @@ RenderRegion GlGeometry::getBounds() const
|
||||||
float bottom = max(max(lt.y, lb.y), max(rt.y, rb.y));
|
float bottom = max(max(lt.y, lb.y), max(rt.y, rb.y));
|
||||||
|
|
||||||
auto bounds = RenderRegion {
|
auto bounds = RenderRegion {
|
||||||
static_cast<int32_t>(left),
|
static_cast<int32_t>(floor(left)),
|
||||||
static_cast<int32_t>(top),
|
static_cast<int32_t>(floor(top)),
|
||||||
static_cast<int32_t>(right - left),
|
static_cast<int32_t>(ceil(right - floor(left))),
|
||||||
static_cast<int32_t>(bottom - top),
|
static_cast<int32_t>(ceil(bottom - floor(top))),
|
||||||
};
|
};
|
||||||
if (bounds.x < 0 || bounds.y < 0 || bounds.w < 0 || bounds.h < 0) {
|
if (bounds.x < 0 || bounds.y < 0 || bounds.w < 0 || bounds.h < 0) {
|
||||||
return mBounds;
|
return mBounds;
|
||||||
|
|
|
@ -83,13 +83,15 @@ void GlRenderTarget::init(GLint resolveId)
|
||||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, resolveId));
|
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, resolveId));
|
||||||
}
|
}
|
||||||
|
|
||||||
GlRenderPass::GlRenderPass(GlRenderTarget* fbo): mFbo(fbo), mTasks() {}
|
GlRenderPass::GlRenderPass(GlRenderTarget* fbo): mFbo(fbo), mTasks(), mDrawDepth(0) {}
|
||||||
|
|
||||||
GlRenderPass::GlRenderPass(GlRenderPass&& other): mFbo(other.mFbo), mTasks()
|
GlRenderPass::GlRenderPass(GlRenderPass&& other): mFbo(other.mFbo), mTasks(), mDrawDepth(0)
|
||||||
{
|
{
|
||||||
mTasks.push(other.mTasks);
|
mTasks.push(other.mTasks);
|
||||||
|
|
||||||
other.mTasks.clear();
|
other.mTasks.clear();
|
||||||
|
|
||||||
|
mDrawDepth = other.mDrawDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlRenderPass::~GlRenderPass()
|
GlRenderPass::~GlRenderPass()
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "tvgGlCommon.h"
|
#include "tvgGlCommon.h"
|
||||||
|
#include "tvgGlRenderTask.h"
|
||||||
|
|
||||||
class GlRenderTask;
|
|
||||||
class GlProgram;
|
class GlProgram;
|
||||||
|
|
||||||
class GlRenderTarget
|
class GlRenderTarget
|
||||||
|
@ -72,11 +72,20 @@ public:
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T* endRenderPass(GlProgram* program, GLuint targetFbo) {
|
T* endRenderPass(GlProgram* program, GLuint targetFbo) {
|
||||||
|
int32_t maxDepth = mDrawDepth + 1;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mTasks.count; i++) {
|
||||||
|
mTasks[i]->normalizeDrawDepth(maxDepth);
|
||||||
|
}
|
||||||
|
|
||||||
return new T(program, targetFbo, mFbo, std::move(mTasks));
|
return new T(program, targetFbo, mFbo, std::move(mTasks));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nextDrawDepth() { return ++mDrawDepth; }
|
||||||
private:
|
private:
|
||||||
GlRenderTarget* mFbo;
|
GlRenderTarget* mFbo;
|
||||||
Array<GlRenderTask*> mTasks = {};
|
Array<GlRenderTask*> mTasks = {};
|
||||||
|
int32_t mDrawDepth = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,12 @@ void GlRenderTask::run()
|
||||||
// bind shader
|
// bind shader
|
||||||
mProgram->load();
|
mProgram->load();
|
||||||
|
|
||||||
|
int32_t dLoc = mProgram->getUniformLocation("uDepth");
|
||||||
|
if (dLoc >= 0) {
|
||||||
|
// fixme: prevent compiler warning: macro expands to multiple statements [-Wmultistatement-macros]
|
||||||
|
GL_CHECK(glUniform1f(dLoc, mDrawDepth));
|
||||||
|
}
|
||||||
|
|
||||||
// setup scissor rect
|
// setup scissor rect
|
||||||
GL_CHECK(glScissor(mViewport.x, mViewport.y, mViewport.w, mViewport.h));
|
GL_CHECK(glScissor(mViewport.x, mViewport.y, mViewport.w, mViewport.h));
|
||||||
|
|
||||||
|
@ -141,6 +147,12 @@ void GlStencilCoverTask::run()
|
||||||
GL_CHECK(glDisable(GL_STENCIL_TEST));
|
GL_CHECK(glDisable(GL_STENCIL_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlStencilCoverTask::normalizeDrawDepth(int32_t maxDepth)
|
||||||
|
{
|
||||||
|
mCoverTask->normalizeDrawDepth(maxDepth);
|
||||||
|
mStencilTask->normalizeDrawDepth(maxDepth);
|
||||||
|
}
|
||||||
|
|
||||||
GlComposeTask::GlComposeTask(GlProgram* program, GLuint target, GlRenderTarget* fbo, Array<GlRenderTask*>&& tasks)
|
GlComposeTask::GlComposeTask(GlProgram* program, GLuint target, GlRenderTarget* fbo, Array<GlRenderTask*>&& tasks)
|
||||||
:GlRenderTask(program) ,mTargetFbo(target), mFbo(fbo), mTasks()
|
:GlRenderTask(program) ,mTargetFbo(target), mFbo(fbo), mTasks()
|
||||||
{
|
{
|
||||||
|
@ -162,11 +174,15 @@ void GlComposeTask::run()
|
||||||
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getSelfFbo()));
|
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getSelfFbo()));
|
||||||
GL_CHECK(glViewport(0, 0, mFbo->getWidth(), mFbo->getHeight()));
|
GL_CHECK(glViewport(0, 0, mFbo->getWidth(), mFbo->getHeight()));
|
||||||
|
|
||||||
|
const auto& vp = getViewport();
|
||||||
|
|
||||||
|
GL_CHECK(glScissor(vp.x, vp.y, vp.w, vp.h));
|
||||||
|
|
||||||
// clear this fbo
|
// clear this fbo
|
||||||
if (mClearBuffer) {
|
if (mClearBuffer) {
|
||||||
GL_CHECK(glClearColor(0, 0, 0, 0));
|
GL_CHECK(glClearColor(0, 0, 0, 0));
|
||||||
GL_CHECK(glClearStencil(0));
|
GL_CHECK(glClearStencil(0));
|
||||||
GL_CHECK(glClearDepthf(1.0));
|
GL_CHECK(glClearDepthf(0.0));
|
||||||
GL_CHECK(glDepthMask(1));
|
GL_CHECK(glDepthMask(1));
|
||||||
|
|
||||||
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||||
|
@ -193,7 +209,14 @@ void GlComposeTask::onResolve() {
|
||||||
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, getSelfFbo()));
|
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, getSelfFbo()));
|
||||||
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getResolveFboId()));
|
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getResolveFboId()));
|
||||||
|
|
||||||
GL_CHECK(glBlitFramebuffer(0, 0, mFbo->getWidth(), mFbo->getHeight(), 0, 0, mFbo->getWidth(), mFbo->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
const auto& vp = getViewport();
|
||||||
|
|
||||||
|
auto x1 = vp.x;
|
||||||
|
auto y1 = vp.y;
|
||||||
|
auto x2 = x1 + vp.w;
|
||||||
|
auto y2 = y1 + vp.h;
|
||||||
|
|
||||||
|
GL_CHECK(glBlitFramebuffer(x1, y1, x2, y2, x1, y1, x2, y2, GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||||
}
|
}
|
||||||
|
|
||||||
GlBlitTask::GlBlitTask(GlProgram* program, GLuint target, GlRenderTarget* fbo, Array<GlRenderTask*>&& tasks)
|
GlBlitTask::GlBlitTask(GlProgram* program, GLuint target, GlRenderTarget* fbo, Array<GlRenderTask*>&& tasks)
|
||||||
|
@ -241,7 +264,6 @@ GlClipTask::GlClipTask(GlRenderTask* clip, GlRenderTask* mask)
|
||||||
void GlClipTask::run()
|
void GlClipTask::run()
|
||||||
{
|
{
|
||||||
GL_CHECK(glEnable(GL_STENCIL_TEST));
|
GL_CHECK(glEnable(GL_STENCIL_TEST));
|
||||||
GL_CHECK(glDepthFunc(GL_ALWAYS));
|
|
||||||
GL_CHECK(glColorMask(0, 0, 0, 0));
|
GL_CHECK(glColorMask(0, 0, 0, 0));
|
||||||
// draw clip path as normal stencil mask
|
// draw clip path as normal stencil mask
|
||||||
GL_CHECK(glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x1, 0xFF));
|
GL_CHECK(glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x1, 0xFF));
|
||||||
|
@ -262,15 +284,11 @@ void GlClipTask::run()
|
||||||
|
|
||||||
GL_CHECK(glColorMask(1, 1, 1, 1));
|
GL_CHECK(glColorMask(1, 1, 1, 1));
|
||||||
GL_CHECK(glDepthMask(0));
|
GL_CHECK(glDepthMask(0));
|
||||||
GL_CHECK(glDepthFunc(GL_LESS));
|
|
||||||
GL_CHECK(glDisable(GL_STENCIL_TEST));
|
GL_CHECK(glDisable(GL_STENCIL_TEST));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlClipClearTask::run()
|
void GlClipTask::normalizeDrawDepth(int32_t maxDepth)
|
||||||
{
|
{
|
||||||
GL_CHECK(glDisable(GL_SCISSOR_TEST));
|
mClipTask->normalizeDrawDepth(maxDepth);
|
||||||
GL_CHECK(glDepthMask(1));
|
mMaskTask->normalizeDrawDepth(maxDepth);
|
||||||
GL_CHECK(glClear(GL_DEPTH_BUFFER_BIT));
|
|
||||||
GL_CHECK(glDepthMask(0));
|
|
||||||
GL_CHECK(glEnable(GL_SCISSOR_TEST));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,8 +86,11 @@ public:
|
||||||
void addBindResource(const GlBindingResource& binding);
|
void addBindResource(const GlBindingResource& binding);
|
||||||
void setDrawRange(uint32_t offset, uint32_t count);
|
void setDrawRange(uint32_t offset, uint32_t count);
|
||||||
void setViewport(const RenderRegion& viewport);
|
void setViewport(const RenderRegion& viewport);
|
||||||
|
void setDrawDepth(int32_t depth) { mDrawDepth = static_cast<float>(depth); }
|
||||||
|
virtual void normalizeDrawDepth(int32_t maxDepth) { mDrawDepth /= static_cast<float>(maxDepth); }
|
||||||
|
|
||||||
GlProgram* getProgram() { return mProgram; }
|
GlProgram* getProgram() { return mProgram; }
|
||||||
|
const RenderRegion& getViewport() const { return mViewport; }
|
||||||
private:
|
private:
|
||||||
GlProgram* mProgram;
|
GlProgram* mProgram;
|
||||||
RenderRegion mViewport = {};
|
RenderRegion mViewport = {};
|
||||||
|
@ -95,6 +98,7 @@ private:
|
||||||
uint32_t mIndexCount = {};
|
uint32_t mIndexCount = {};
|
||||||
Array<GlVertexLayout> mVertexLayout = {};
|
Array<GlVertexLayout> mVertexLayout = {};
|
||||||
Array<GlBindingResource> mBindingResources = {};
|
Array<GlBindingResource> mBindingResources = {};
|
||||||
|
float mDrawDepth = 0.f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlStencilCoverTask : public GlRenderTask
|
class GlStencilCoverTask : public GlRenderTask
|
||||||
|
@ -105,6 +109,7 @@ public:
|
||||||
|
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
|
void normalizeDrawDepth(int32_t maxDepth) override;
|
||||||
private:
|
private:
|
||||||
GlRenderTask* mStencilTask;
|
GlRenderTask* mStencilTask;
|
||||||
GlRenderTask* mCoverTask;
|
GlRenderTask* mCoverTask;
|
||||||
|
@ -170,19 +175,10 @@ public:
|
||||||
|
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
|
void normalizeDrawDepth(int32_t maxDepth) override;
|
||||||
private:
|
private:
|
||||||
GlRenderTask* mClipTask;
|
GlRenderTask* mClipTask;
|
||||||
GlRenderTask* mMaskTask;
|
GlRenderTask* mMaskTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlClipClearTask : public GlRenderTask
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GlClipClearTask(): GlRenderTask(nullptr) {}
|
|
||||||
~GlClipClearTask() override = default;
|
|
||||||
|
|
||||||
void run() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _TVG_GL_RENDER_TASK_H_ */
|
#endif /* _TVG_GL_RENDER_TASK_H_ */
|
||||||
|
|
|
@ -102,7 +102,7 @@ bool GlRenderer::sync()
|
||||||
GL_CHECK(glCullFace(GL_FRONT_AND_BACK));
|
GL_CHECK(glCullFace(GL_FRONT_AND_BACK));
|
||||||
GL_CHECK(glFrontFace(GL_CCW));
|
GL_CHECK(glFrontFace(GL_CCW));
|
||||||
GL_CHECK(glEnable(GL_DEPTH_TEST));
|
GL_CHECK(glEnable(GL_DEPTH_TEST));
|
||||||
GL_CHECK(glDepthFunc(GL_LESS));
|
GL_CHECK(glDepthFunc(GL_GREATER));
|
||||||
|
|
||||||
auto task = mRenderPassStack.front().endRenderPass<GlBlitTask>(mPrograms[RT_Blit].get(), mTargetFboId);
|
auto task = mRenderPassStack.front().endRenderPass<GlBlitTask>(mPrograms[RT_Blit].get(), mTargetFboId);
|
||||||
|
|
||||||
|
@ -227,9 +227,12 @@ bool GlRenderer::renderImage(void* data)
|
||||||
|
|
||||||
if ((sdata->updateFlag & RenderUpdateFlag::Image) == 0) return false;
|
if ((sdata->updateFlag & RenderUpdateFlag::Image) == 0) return false;
|
||||||
|
|
||||||
|
int32_t drawDepth = currentPass()->nextDrawDepth();
|
||||||
|
|
||||||
if (!sdata->clips.empty()) drawClip(sdata->clips);
|
if (!sdata->clips.empty()) drawClip(sdata->clips);
|
||||||
|
|
||||||
auto task = new GlRenderTask(mPrograms[RT_Image].get());
|
auto task = new GlRenderTask(mPrograms[RT_Image].get());
|
||||||
|
task->setDrawDepth(drawDepth);
|
||||||
|
|
||||||
if (!sdata->geometry->draw(task, mGpuBuffer.get(), RenderUpdateFlag::Image)) return false;
|
if (!sdata->geometry->draw(task, mGpuBuffer.get(), RenderUpdateFlag::Image)) return false;
|
||||||
|
|
||||||
|
@ -267,8 +270,6 @@ bool GlRenderer::renderImage(void* data)
|
||||||
|
|
||||||
currentPass()->addRenderTask(task);
|
currentPass()->addRenderTask(task);
|
||||||
|
|
||||||
if (!sdata->clips.empty()) currentPass()->addRenderTask(new GlClipClearTask);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,15 +281,32 @@ bool GlRenderer::renderShape(RenderData data)
|
||||||
|
|
||||||
if (sdata->updateFlag == RenderUpdateFlag::None) return false;
|
if (sdata->updateFlag == RenderUpdateFlag::None) return false;
|
||||||
|
|
||||||
if (!sdata->clips.empty()) drawClip(sdata->clips);
|
|
||||||
|
|
||||||
uint8_t r = 0, g = 0, b = 0, a = 0;
|
uint8_t r = 0, g = 0, b = 0, a = 0;
|
||||||
|
int32_t drawDepth1 = 0, drawDepth2 = 0, drawDepth3 = 0;
|
||||||
|
|
||||||
size_t flags = static_cast<size_t>(sdata->updateFlag);
|
size_t flags = static_cast<size_t>(sdata->updateFlag);
|
||||||
|
|
||||||
|
if (flags == 0) return false;
|
||||||
|
|
||||||
|
if ((flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) && sdata->rshape->fill) drawDepth1 = currentPass()->nextDrawDepth();
|
||||||
|
if(flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Transform))
|
||||||
|
{
|
||||||
|
sdata->rshape->fillColor(&r, &g, &b, &a);
|
||||||
|
if (a > 0) drawDepth2 = currentPass()->nextDrawDepth();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform))
|
||||||
|
{
|
||||||
|
sdata->rshape->strokeFill(&r, &g, &b, &a);
|
||||||
|
if (sdata->rshape->strokeFill() || a > 0) drawDepth3 = currentPass()->nextDrawDepth();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sdata->clips.empty()) drawClip(sdata->clips);
|
||||||
|
|
||||||
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform))
|
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform))
|
||||||
{
|
{
|
||||||
auto gradient = sdata->rshape->fill;
|
auto gradient = sdata->rshape->fill;
|
||||||
if (gradient) drawPrimitive(*sdata, gradient, RenderUpdateFlag::Gradient);
|
if (gradient) drawPrimitive(*sdata, gradient, RenderUpdateFlag::Gradient, drawDepth1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Transform))
|
if(flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Transform))
|
||||||
|
@ -296,7 +314,7 @@ bool GlRenderer::renderShape(RenderData data)
|
||||||
sdata->rshape->fillColor(&r, &g, &b, &a);
|
sdata->rshape->fillColor(&r, &g, &b, &a);
|
||||||
if (a > 0)
|
if (a > 0)
|
||||||
{
|
{
|
||||||
drawPrimitive(*sdata, r, g, b, a, RenderUpdateFlag::Color);
|
drawPrimitive(*sdata, r, g, b, a, RenderUpdateFlag::Color, drawDepth2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,17 +322,15 @@ bool GlRenderer::renderShape(RenderData data)
|
||||||
{
|
{
|
||||||
auto gradient = sdata->rshape->strokeFill();
|
auto gradient = sdata->rshape->strokeFill();
|
||||||
if (gradient) {
|
if (gradient) {
|
||||||
drawPrimitive(*sdata, gradient, RenderUpdateFlag::GradientStroke);
|
drawPrimitive(*sdata, gradient, RenderUpdateFlag::GradientStroke, drawDepth3);
|
||||||
} else {
|
} else {
|
||||||
if (sdata->rshape->strokeFill(&r, &g, &b, &a) && a > 0)
|
if (sdata->rshape->strokeFill(&r, &g, &b, &a) && a > 0)
|
||||||
{
|
{
|
||||||
drawPrimitive(*sdata, r, g, b, a, RenderUpdateFlag::Stroke);
|
drawPrimitive(*sdata, r, g, b, a, RenderUpdateFlag::Stroke, drawDepth3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sdata->clips.empty()) currentPass()->addRenderTask(new GlClipClearTask);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,16 +560,20 @@ void GlRenderer::initShaders()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag)
|
void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag, int32_t depth)
|
||||||
{
|
{
|
||||||
auto task = new GlRenderTask(mPrograms[RT_Color].get());
|
auto task = new GlRenderTask(mPrograms[RT_Color].get());
|
||||||
|
task->setDrawDepth(depth);
|
||||||
|
|
||||||
if (!sdata.geometry->draw(task, mGpuBuffer.get(), flag)) return;
|
if (!sdata.geometry->draw(task, mGpuBuffer.get(), flag)) return;
|
||||||
|
|
||||||
GlRenderTask* stencilTask = nullptr;
|
GlRenderTask* stencilTask = nullptr;
|
||||||
|
|
||||||
GlStencilMode stencilMode = sdata.geometry->getStencilMode(flag);
|
GlStencilMode stencilMode = sdata.geometry->getStencilMode(flag);
|
||||||
if (stencilMode != GlStencilMode::None) stencilTask = new GlRenderTask(mPrograms[RT_Stencil].get(), task);
|
if (stencilMode != GlStencilMode::None) {
|
||||||
|
stencilTask = new GlRenderTask(mPrograms[RT_Stencil].get(), task);
|
||||||
|
stencilTask->setDrawDepth(depth);
|
||||||
|
}
|
||||||
|
|
||||||
a = MULTIPLY(a, sdata.opacity);
|
a = MULTIPLY(a, sdata.opacity);
|
||||||
|
|
||||||
|
@ -605,7 +625,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag)
|
void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag, int32_t depth)
|
||||||
{
|
{
|
||||||
const Fill::ColorStop* stops = nullptr;
|
const Fill::ColorStop* stops = nullptr;
|
||||||
auto stopCnt = min(fill->colorStops(&stops),
|
auto stopCnt = min(fill->colorStops(&stops),
|
||||||
|
@ -622,11 +642,16 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task->setDrawDepth(depth);
|
||||||
|
|
||||||
if (!sdata.geometry->draw(task, mGpuBuffer.get(), flag)) return;
|
if (!sdata.geometry->draw(task, mGpuBuffer.get(), flag)) return;
|
||||||
|
|
||||||
GlRenderTask* stencilTask = nullptr;
|
GlRenderTask* stencilTask = nullptr;
|
||||||
GlStencilMode stencilMode = sdata.geometry->getStencilMode(flag);
|
GlStencilMode stencilMode = sdata.geometry->getStencilMode(flag);
|
||||||
if (stencilMode != GlStencilMode::None) stencilTask = new GlRenderTask(mPrograms[RT_Stencil].get(), task);
|
if (stencilMode != GlStencilMode::None) {
|
||||||
|
stencilTask = new GlRenderTask(mPrograms[RT_Stencil].get(), task);
|
||||||
|
stencilTask->setDrawDepth(depth);
|
||||||
|
}
|
||||||
|
|
||||||
// matrix buffer
|
// matrix buffer
|
||||||
{
|
{
|
||||||
|
@ -804,11 +829,20 @@ void GlRenderer::drawClip(Array<RenderData>& clips)
|
||||||
auto identityIndexOffset = mGpuBuffer->push(indentityIndex.data, 6 * sizeof(uint32_t));
|
auto identityIndexOffset = mGpuBuffer->push(indentityIndex.data, 6 * sizeof(uint32_t));
|
||||||
auto mat4Offset = mGpuBuffer->push(mat4, 16 * sizeof(float), true);
|
auto mat4Offset = mGpuBuffer->push(mat4, 16 * sizeof(float), true);
|
||||||
|
|
||||||
|
Array<int32_t> clipDepths(clips.count);
|
||||||
|
clipDepths.count = clips.count;
|
||||||
|
|
||||||
|
for (int32_t i = clips.count - 1; i >= 0; i--) {
|
||||||
|
clipDepths[i] = currentPass()->nextDrawDepth();
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < clips.count; ++i) {
|
for (uint32_t i = 0; i < clips.count; ++i) {
|
||||||
auto sdata = static_cast<GlShape*>(clips[i]);
|
auto sdata = static_cast<GlShape*>(clips[i]);
|
||||||
|
|
||||||
auto clipTask = new GlRenderTask(mPrograms[RT_Stencil].get());
|
auto clipTask = new GlRenderTask(mPrograms[RT_Stencil].get());
|
||||||
|
|
||||||
|
clipTask->setDrawDepth(clipDepths[i]);
|
||||||
|
|
||||||
sdata->geometry->draw(clipTask, mGpuBuffer.get(), RenderUpdateFlag::Path);
|
sdata->geometry->draw(clipTask, mGpuBuffer.get(), RenderUpdateFlag::Path);
|
||||||
|
|
||||||
auto matrix = sdata->geometry->getTransforMatrix();
|
auto matrix = sdata->geometry->getTransforMatrix();
|
||||||
|
@ -827,6 +861,8 @@ void GlRenderer::drawClip(Array<RenderData>& clips)
|
||||||
|
|
||||||
auto maskTask = new GlRenderTask(mPrograms[RT_Stencil].get());
|
auto maskTask = new GlRenderTask(mPrograms[RT_Stencil].get());
|
||||||
|
|
||||||
|
maskTask->setDrawDepth(clipDepths[i]);
|
||||||
|
|
||||||
maskTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), identityVertexOffset});
|
maskTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), identityVertexOffset});
|
||||||
maskTask->addBindResource(GlBindingResource{
|
maskTask->addBindResource(GlBindingResource{
|
||||||
0,
|
0,
|
||||||
|
@ -961,7 +997,13 @@ void GlRenderer::endRenderPass(Compositor* cmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto prev_task = mask_pass.endRenderPass<GlComposeTask>(nullptr, currentPass()->getFboId());
|
auto prev_task = mask_pass.endRenderPass<GlComposeTask>(nullptr, currentPass()->getFboId());
|
||||||
|
prev_task->setDrawDepth(currentPass()->nextDrawDepth());
|
||||||
|
prev_task->setViewport(RenderRegion{
|
||||||
|
gl_cmp->bbox.x,
|
||||||
|
static_cast<int32_t>((surface.h - gl_cmp->bbox.y - gl_cmp->bbox.h)),
|
||||||
|
gl_cmp->bbox.w,
|
||||||
|
gl_cmp->bbox.h,
|
||||||
|
});
|
||||||
currentPass()->addRenderTask(prev_task);
|
currentPass()->addRenderTask(prev_task);
|
||||||
|
|
||||||
auto compose_task = self_pass.endRenderPass<GlDrawBlitTask>(program, currentPass()->getFboId());
|
auto compose_task = self_pass.endRenderPass<GlDrawBlitTask>(program, currentPass()->getFboId());
|
||||||
|
@ -978,7 +1020,7 @@ void GlRenderer::endRenderPass(Compositor* cmp)
|
||||||
compose_task->addBindResource(GlBindingResource{1, mask_pass.getTextureId(), loc});
|
compose_task->addBindResource(GlBindingResource{1, mask_pass.getTextureId(), loc});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compose_task->setDrawDepth(currentPass()->nextDrawDepth());
|
||||||
currentPass()->addRenderTask(compose_task);
|
currentPass()->addRenderTask(compose_task);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -989,6 +1031,7 @@ void GlRenderer::endRenderPass(Compositor* cmp)
|
||||||
mPrograms[RT_Image].get(), currentPass()->getFboId());
|
mPrograms[RT_Image].get(), currentPass()->getFboId());
|
||||||
|
|
||||||
prepareCmpTask(task, gl_cmp->bbox);
|
prepareCmpTask(task, gl_cmp->bbox);
|
||||||
|
task->setDrawDepth(currentPass()->nextDrawDepth());
|
||||||
|
|
||||||
// matrix buffer
|
// matrix buffer
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,8 +85,8 @@ private:
|
||||||
~GlRenderer();
|
~GlRenderer();
|
||||||
|
|
||||||
void initShaders();
|
void initShaders();
|
||||||
void drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag);
|
void drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag, int32_t depth);
|
||||||
void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag);
|
void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag, int32_t depth);
|
||||||
void drawClip(Array<RenderData>& clips);
|
void drawClip(Array<RenderData>& clips);
|
||||||
|
|
||||||
GlRenderPass* currentPass();
|
GlRenderPass* currentPass();
|
||||||
|
|
|
@ -26,13 +26,16 @@
|
||||||
#define TVG_COMPOSE_SHADER(shader) #shader
|
#define TVG_COMPOSE_SHADER(shader) #shader
|
||||||
|
|
||||||
const char* COLOR_VERT_SHADER = TVG_COMPOSE_SHADER(
|
const char* COLOR_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform float uDepth; \n
|
||||||
layout(location = 0) in vec2 aLocation; \n
|
layout(location = 0) in vec2 aLocation; \n
|
||||||
layout(std140) uniform Matrix { \n
|
layout(std140) uniform Matrix { \n
|
||||||
mat4 transform; \n
|
mat4 transform; \n
|
||||||
} uMatrix; \n
|
} uMatrix; \n
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \n
|
{ \n
|
||||||
gl_Position = uMatrix.transform * vec4(aLocation, 0.0, 1.0);\n
|
vec4 pos = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
||||||
|
pos.z = uDepth; \n
|
||||||
|
gl_Position = pos; \n
|
||||||
});
|
});
|
||||||
|
|
||||||
const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
@ -47,6 +50,7 @@ const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
});
|
});
|
||||||
|
|
||||||
const char* GRADIENT_VERT_SHADER = TVG_COMPOSE_SHADER(
|
const char* GRADIENT_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform float uDepth; \n
|
||||||
layout(location = 0) in vec2 aLocation; \n
|
layout(location = 0) in vec2 aLocation; \n
|
||||||
out vec2 vPos; \n
|
out vec2 vPos; \n
|
||||||
layout(std140) uniform Matrix { \n
|
layout(std140) uniform Matrix { \n
|
||||||
|
@ -58,7 +62,9 @@ layout(std140) uniform InvMatrix {
|
||||||
\n
|
\n
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \n
|
{ \n
|
||||||
gl_Position = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
vec4 glPos = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
||||||
|
glPos.z = uDepth; \n
|
||||||
|
gl_Position = glPos; \n
|
||||||
vec4 pos = uInvMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
vec4 pos = uInvMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
||||||
vPos = pos.xy / pos.w; \n
|
vPos = pos.xy / pos.w; \n
|
||||||
});
|
});
|
||||||
|
@ -224,6 +230,7 @@ const char* RADIAL_GRADIENT_FRAG_SHADER = STR_RADIAL_GRADIENT_FRAG_SHADER.c_str(
|
||||||
|
|
||||||
|
|
||||||
const char* IMAGE_VERT_SHADER = TVG_COMPOSE_SHADER(
|
const char* IMAGE_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform float uDepth; \n
|
||||||
layout (location = 0) in vec2 aLocation; \n
|
layout (location = 0) in vec2 aLocation; \n
|
||||||
layout (location = 1) in vec2 aUV; \n
|
layout (location = 1) in vec2 aUV; \n
|
||||||
layout (std140) uniform Matrix { \n
|
layout (std140) uniform Matrix { \n
|
||||||
|
@ -234,7 +241,9 @@ const char* IMAGE_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
\n
|
\n
|
||||||
void main() { \n
|
void main() { \n
|
||||||
vUV = aUV; \n
|
vUV = aUV; \n
|
||||||
gl_Position = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
vec4 pos = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
||||||
|
pos.z = uDepth; \n
|
||||||
|
gl_Position = pos; \n
|
||||||
} \n
|
} \n
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -276,6 +285,7 @@ const char* IMAGE_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
);
|
);
|
||||||
|
|
||||||
const char* MASK_VERT_SHADER = TVG_COMPOSE_SHADER(
|
const char* MASK_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform float uDepth; \n
|
||||||
layout(location = 0) in vec2 aLocation; \n
|
layout(location = 0) in vec2 aLocation; \n
|
||||||
layout(location = 1) in vec2 aUV; \n
|
layout(location = 1) in vec2 aUV; \n
|
||||||
\n
|
\n
|
||||||
|
@ -284,7 +294,7 @@ out vec2 vUV; \n
|
||||||
void main() { \n
|
void main() { \n
|
||||||
vUV = aUV; \n
|
vUV = aUV; \n
|
||||||
\n
|
\n
|
||||||
gl_Position = vec4(aLocation, 0.0, 1.0); \n
|
gl_Position = vec4(aLocation, uDepth, 1.0); \n
|
||||||
} \n
|
} \n
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -442,14 +452,16 @@ void main() { \n
|
||||||
);
|
);
|
||||||
|
|
||||||
const char* STENCIL_VERT_SHADER = TVG_COMPOSE_SHADER(
|
const char* STENCIL_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
uniform float uDepth; \n
|
||||||
layout(location = 0) in vec2 aLocation; \n
|
layout(location = 0) in vec2 aLocation; \n
|
||||||
layout(std140) uniform Matrix { \n
|
layout(std140) uniform Matrix { \n
|
||||||
mat4 transform; \n
|
mat4 transform; \n
|
||||||
} uMatrix; \n
|
} uMatrix; \n
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \n
|
{ \n
|
||||||
gl_Position = \n
|
vec4 pos = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
||||||
uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
pos.z = uDepth; \n
|
||||||
|
gl_Position = pos; \n
|
||||||
});
|
});
|
||||||
|
|
||||||
const char* STENCIL_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
const char* STENCIL_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||||
|
|
|
@ -1668,10 +1668,10 @@ void Stroker::stroke(const RenderShape *rshape)
|
||||||
RenderRegion Stroker::bounds() const
|
RenderRegion Stroker::bounds() const
|
||||||
{
|
{
|
||||||
return RenderRegion {
|
return RenderRegion {
|
||||||
static_cast<int32_t>(mLeftTop.x),
|
static_cast<int32_t>(floor(mLeftTop.x)),
|
||||||
static_cast<int32_t>(mLeftTop.y),
|
static_cast<int32_t>(floor(mLeftTop.y)),
|
||||||
static_cast<int32_t>(mRightBottom.x - mLeftTop.x),
|
static_cast<int32_t>(ceil(mRightBottom.x - floor(mLeftTop.x))),
|
||||||
static_cast<int32_t>(mRightBottom.y - mLeftTop.y),
|
static_cast<int32_t>(ceil(mRightBottom.y - floor(mLeftTop.y))),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1802,12 +1802,12 @@ void Stroker::strokeLineTo(const GlPoint &curr)
|
||||||
if (ia == 0) {
|
if (ia == 0) {
|
||||||
mRightBottom.x = mLeftTop.x = curr.x;
|
mRightBottom.x = mLeftTop.x = curr.x;
|
||||||
mRightBottom.y = mLeftTop.y = curr.y;
|
mRightBottom.y = mLeftTop.y = curr.y;
|
||||||
} else {
|
|
||||||
mLeftTop.x = min(mLeftTop.x, curr.x);
|
|
||||||
mLeftTop.y = min(mLeftTop.y, curr.y);
|
|
||||||
mRightBottom.x = max(mRightBottom.x, curr.x);
|
|
||||||
mRightBottom.y = max(mRightBottom.y , curr.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLeftTop.x = std::min(mLeftTop.x, min(min(a.x, b.x), min(c.x, d.x)));
|
||||||
|
mLeftTop.y = std::min(mLeftTop.y, min(min(a.y, b.y), min(c.y, d.y)));
|
||||||
|
mRightBottom.x = std::max(mRightBottom.x, max(max(a.x, b.x), max(c.x, d.x)));
|
||||||
|
mRightBottom.y = std::max(mRightBottom.y, max(max(a.y, b.y), max(c.y, d.y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stroker::strokeCubicTo(const GlPoint &cnt1, const GlPoint &cnt2, const GlPoint &end)
|
void Stroker::strokeCubicTo(const GlPoint &cnt1, const GlPoint &cnt2, const GlPoint &end)
|
||||||
|
@ -1903,6 +1903,11 @@ void Stroker::strokeRound(const GlPoint &prev, const GlPoint &curr, const GlPoin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLeftTop.x = std::min(mLeftTop.x, min(center.x, min(prev.x, curr.x)));
|
||||||
|
mLeftTop.y = std::min(mLeftTop.y, min(center.y, min(prev.y, curr.y)));
|
||||||
|
mRightBottom.x = std::max(mRightBottom.x, max(center.x, max(prev.x, curr.x)));
|
||||||
|
mRightBottom.y = std::max(mRightBottom.y, max(center.y, max(prev.y, curr.y)));
|
||||||
|
|
||||||
// Fixme: just use bezier curve to calculate step count
|
// Fixme: just use bezier curve to calculate step count
|
||||||
auto count = detail::_bezierCurveCount(detail::_bezFromArc(prev, curr, strokeRadius()));
|
auto count = detail::_bezierCurveCount(detail::_bezFromArc(prev, curr, strokeRadius()));
|
||||||
|
|
||||||
|
@ -1930,6 +1935,11 @@ void Stroker::strokeRound(const GlPoint &prev, const GlPoint &curr, const GlPoin
|
||||||
this->mResIndices->push(oi);
|
this->mResIndices->push(oi);
|
||||||
|
|
||||||
pi = oi;
|
pi = oi;
|
||||||
|
|
||||||
|
mLeftTop.x = std::min(mLeftTop.x, out.x);
|
||||||
|
mLeftTop.y = std::min(mLeftTop.y, out.y);
|
||||||
|
mRightBottom.x = std::max(mRightBottom.x, out.x);
|
||||||
|
mRightBottom.y = std::max(mRightBottom.y, out.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1965,6 +1975,12 @@ void Stroker::strokeMiter(const GlPoint &prev, const GlPoint &curr, const GlPoin
|
||||||
this->mResIndices->push(e);
|
this->mResIndices->push(e);
|
||||||
this->mResIndices->push(cp2);
|
this->mResIndices->push(cp2);
|
||||||
this->mResIndices->push(c);
|
this->mResIndices->push(c);
|
||||||
|
|
||||||
|
mLeftTop.x = std::min(mLeftTop.x, join.x);
|
||||||
|
mLeftTop.y = std::min(mLeftTop.y, join.y);
|
||||||
|
|
||||||
|
mRightBottom.x = std::max(mRightBottom.x, join.x);
|
||||||
|
mRightBottom.y = std::max(mRightBottom.y, join.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stroker::strokeBevel(const GlPoint &prev, const GlPoint &curr, const GlPoint ¢er)
|
void Stroker::strokeBevel(const GlPoint &prev, const GlPoint &curr, const GlPoint ¢er)
|
||||||
|
@ -2000,6 +2016,11 @@ void Stroker::strokeSquare(const GlPoint& p, const GlPoint& outDir)
|
||||||
mResIndices->push(ci);
|
mResIndices->push(ci);
|
||||||
mResIndices->push(bi);
|
mResIndices->push(bi);
|
||||||
mResIndices->push(di);
|
mResIndices->push(di);
|
||||||
|
|
||||||
|
mLeftTop.x = std::min(mLeftTop.x, min(min(a.x, b.x), min(c.x, d.x)));
|
||||||
|
mLeftTop.y = std::min(mLeftTop.y, min(min(a.y, b.y), min(c.y, d.y)));
|
||||||
|
mRightBottom.x = std::max(mRightBottom.x, max(max(a.x, b.x), max(c.x, d.x)));
|
||||||
|
mRightBottom.y = std::max(mRightBottom.y, max(max(a.y, b.y), max(c.y, d.y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stroker::strokeRound(const GlPoint& p, const GlPoint& outDir)
|
void Stroker::strokeRound(const GlPoint& p, const GlPoint& outDir)
|
||||||
|
@ -2262,10 +2283,10 @@ void BWTessellator::tessellate(const RenderShape *rshape, const Matrix& matrix)
|
||||||
RenderRegion BWTessellator::bounds() const
|
RenderRegion BWTessellator::bounds() const
|
||||||
{
|
{
|
||||||
return RenderRegion {
|
return RenderRegion {
|
||||||
static_cast<int32_t>(mLeftTop.x),
|
static_cast<int32_t>(floor(mLeftTop.x)),
|
||||||
static_cast<int32_t>(mLeftTop.y),
|
static_cast<int32_t>(floor(mLeftTop.y)),
|
||||||
static_cast<int32_t>(mRightBottom.x - mLeftTop.x),
|
static_cast<int32_t>(ceil(mRightBottom.x - floor(mLeftTop.x))),
|
||||||
static_cast<int32_t>(mRightBottom.y - mLeftTop.y),
|
static_cast<int32_t>(ceil(mRightBottom.y - floor(mLeftTop.y))),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue