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:
RuiwenTang 2024-06-05 19:55:31 +08:00 committed by Hermet Park
parent d9294471a6
commit f8626d13d1
9 changed files with 166 additions and 65 deletions

View file

@ -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;

View file

@ -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()

View file

@ -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;
}; };

View file

@ -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));
} }

View file

@ -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_ */

View file

@ -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
{ {

View file

@ -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();

View file

@ -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(

View file

@ -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 &center) void Stroker::strokeBevel(const GlPoint &prev, const GlPoint &curr, const GlPoint &center)
@ -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))),
}; };
} }