diff --git a/src/renderer/gl_engine/tvgGlGeometry.cpp b/src/renderer/gl_engine/tvgGlGeometry.cpp index c266c12b..97cf2ce8 100644 --- a/src/renderer/gl_engine/tvgGlGeometry.cpp +++ b/src/renderer/gl_engine/tvgGlGeometry.cpp @@ -57,55 +57,52 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) bool GlGeometry::tesselate(const RenderSurface* image, RenderUpdateFlag flag) { - if (flag & RenderUpdateFlag::Image) { - fill.clear(); + if (!(flag & RenderUpdateFlag::Image)) return true; - fill.vertex.reserve(5 * 4); - fill.index.reserve(6); + fill.clear(); - float left = 0.f; - float top = 0.f; - float right = image->w; - float bottom = image->h; + fill.vertex.reserve(5 * 4); + fill.index.reserve(6); - // left top point - fill.vertex.push(left); - fill.vertex.push(top); + auto left = 0.f; + auto top = 0.f; + auto right = float(image->w); + auto bottom = float(image->h); - fill.vertex.push(0.f); - fill.vertex.push(1.f); - // left bottom point - fill.vertex.push(left); - fill.vertex.push(bottom); + // left top point + fill.vertex.push(left); + fill.vertex.push(top); - fill.vertex.push(0.f); - fill.vertex.push(0.f); - // right top point - fill.vertex.push(right); - fill.vertex.push(top); + fill.vertex.push(0.f); + fill.vertex.push(1.f); + // left bottom point + fill.vertex.push(left); + fill.vertex.push(bottom); - fill.vertex.push(1.f); - fill.vertex.push(1.f); - // right bottom point - fill.vertex.push(right); - fill.vertex.push(bottom); + fill.vertex.push(0.f); + fill.vertex.push(0.f); + // right top point + fill.vertex.push(right); + fill.vertex.push(top); - fill.vertex.push(1.f); - fill.vertex.push(0.f); + fill.vertex.push(1.f); + fill.vertex.push(1.f); + // right bottom point + fill.vertex.push(right); + fill.vertex.push(bottom); - fill.index.push(0); - fill.index.push(1); - fill.index.push(2); + fill.vertex.push(1.f); + fill.vertex.push(0.f); - fill.index.push(2); - fill.index.push(1); - fill.index.push(3); + fill.index.push(0); + fill.index.push(1); + fill.index.push(2); - bounds.x = 0; - bounds.y = 0; - bounds.w = image->w; - bounds.h = image->h; - } + fill.index.push(2); + fill.index.push(1); + fill.index.push(3); + + bounds = {{0, 0}, {int32_t(image->w), int32_t(image->h)}}; return true; } @@ -155,31 +152,20 @@ GlStencilMode GlGeometry::getStencilMode(RenderUpdateFlag flag) RenderRegion GlGeometry::getBounds() const { - if (tvg::identity(&matrix)) { - return bounds; - } else { - Point lt{static_cast(bounds.x), static_cast(bounds.y)}; - Point lb{static_cast(bounds.x), static_cast(bounds.y + bounds.h)}; - Point rt{static_cast(bounds.x + bounds.w), static_cast(bounds.y)}; - Point rb{static_cast(bounds.x + bounds.w), static_cast(bounds.y + bounds.h)}; + if (tvg::identity(&matrix)) return bounds; - lt *= matrix; - lb *= matrix; - rt *= matrix; - rb *= matrix; + auto lt = Point{float(bounds.min.x), float(bounds.min.y)} * matrix; + auto lb = Point{float(bounds.min.x), float(bounds.max.y)} * matrix; + auto rt = Point{float(bounds.max.x), float(bounds.min.y)} * matrix; + auto rb = Point{float(bounds.max.x), float(bounds.max.y)} * matrix; - float left = min(min(lt.x, lb.x), min(rt.x, rb.x)); - float top = min(min(lt.y, lb.y), min(rt.y, rb.y)); - float right = max(max(lt.x, lb.x), max(rt.x, rb.x)); - float bottom = max(max(lt.y, lb.y), max(rt.y, rb.y)); + auto left = min(min(lt.x, lb.x), min(rt.x, rb.x)); + auto top = min(min(lt.y, lb.y), min(rt.y, rb.y)); + auto right = max(max(lt.x, lb.x), max(rt.x, rb.x)); + auto bottom = max(max(lt.y, lb.y), max(rt.y, rb.y)); + + auto bounds = RenderRegion {{int32_t(floor(left)), int32_t(floor(top))}, {int32_t(ceil(right)), int32_t(ceil(bottom))}}; + if (bounds.valid()) return bounds; + return this->bounds; - auto bounds = RenderRegion { - static_cast(floor(left)), - static_cast(floor(top)), - static_cast(ceil(right - floor(left))), - static_cast(ceil(bottom - floor(top))), - }; - if (bounds.w < 0 || bounds.h < 0) return this->bounds; - else return bounds; - } } \ No newline at end of file diff --git a/src/renderer/gl_engine/tvgGlRenderPass.cpp b/src/renderer/gl_engine/tvgGlRenderPass.cpp index 743b5abd..e20ffe10 100644 --- a/src/renderer/gl_engine/tvgGlRenderPass.cpp +++ b/src/renderer/gl_engine/tvgGlRenderPass.cpp @@ -52,17 +52,17 @@ void GlRenderPass::addRenderTask(GlRenderTask* task) void GlRenderPass::getMatrix(float *dst, const Matrix &matrix) const { - const auto& vp = getViewport(); - Matrix postMatrix{}; tvg::identity(&postMatrix); - translate(&postMatrix, {(float)-vp.x, (float)-vp.y}); + + const auto& vp = getViewport(); + translate(&postMatrix, {(float)-vp.sx(), (float)-vp.sy()}); auto m = postMatrix * matrix; float modelMatrix[16]; GET_MATRIX44(m, modelMatrix); - MVP_MATRIX(vp.w, vp.h); + MVP_MATRIX(vp.w(), vp.h()); MULTIPLY_MATRIX(mvp, modelMatrix, dst); } diff --git a/src/renderer/gl_engine/tvgGlRenderPass.h b/src/renderer/gl_engine/tvgGlRenderPass.h index 96890f06..b9c4f89e 100644 --- a/src/renderer/gl_engine/tvgGlRenderPass.h +++ b/src/renderer/gl_engine/tvgGlRenderPass.h @@ -62,10 +62,7 @@ public: } auto task = new T(program, targetFbo, mFbo, std::move(mTasks)); - - const auto& vp = mFbo->getViewport(); - - task->setRenderSize(static_cast(vp.w), static_cast(vp.h)); + task->setRenderSize(mFbo->getViewport().w(), mFbo->getViewport().h()); return task; } diff --git a/src/renderer/gl_engine/tvgGlRenderTarget.cpp b/src/renderer/gl_engine/tvgGlRenderTarget.cpp index 9c2ae4a6..d4dbf5de 100644 --- a/src/renderer/gl_engine/tvgGlRenderTarget.cpp +++ b/src/renderer/gl_engine/tvgGlRenderTarget.cpp @@ -107,23 +107,20 @@ uint32_t alignPow2(uint32_t value) GlRenderTarget* GlRenderTargetPool::getRenderTarget(const RenderRegion& vp, GLuint resolveId) { - uint32_t width = static_cast(vp.w); - uint32_t height = static_cast(vp.h); + auto width = vp.w(); + auto height = vp.h(); // pow2 align width and height if (width >= mMaxWidth) width = mMaxWidth; else width = alignPow2(width); - if (width >= mMaxWidth) width = mMaxWidth; if (height >= mMaxHeight) height = mMaxHeight; else height = alignPow2(height); - if (height >= mMaxHeight) height = mMaxHeight; for (uint32_t i = 0; i < mPool.count; i++) { auto rt = mPool[i]; - if (rt->getWidth() == width && rt->getHeight() == height) { rt->setViewport(vp); return rt; diff --git a/src/renderer/gl_engine/tvgGlRenderTask.cpp b/src/renderer/gl_engine/tvgGlRenderTask.cpp index 0464b35f..c978febf 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.cpp +++ b/src/renderer/gl_engine/tvgGlRenderTask.cpp @@ -24,6 +24,9 @@ #include "tvgGlProgram.h" #include "tvgGlRenderPass.h" +/************************************************************************/ +/* GlRenderTask Class Implementation */ +/************************************************************************/ GlRenderTask::GlRenderTask(GlProgram* program, GlRenderTask* other): mProgram(program) { @@ -33,6 +36,7 @@ GlRenderTask::GlRenderTask(GlProgram* program, GlRenderTask* other): mProgram(pr mIndexCount = other->mIndexCount; } + void GlRenderTask::run() { // bind shader @@ -45,7 +49,7 @@ void GlRenderTask::run() } // setup scissor rect - GL_CHECK(glScissor(mViewport.x, mViewport.y, mViewport.w, mViewport.h)); + GL_CHECK(glScissor(mViewport.sx(), mViewport.sy(), mViewport.sw(), mViewport.sh())); // setup attribute layout for (uint32_t i = 0; i < mVertexLayout.count; i++) { @@ -81,36 +85,44 @@ void GlRenderTask::run() } } + void GlRenderTask::addVertexLayout(const GlVertexLayout &layout) { mVertexLayout.push(layout); } + void GlRenderTask::addBindResource(const GlBindingResource &binding) { mBindingResources.push(binding); } + void GlRenderTask::setDrawRange(uint32_t offset, uint32_t count) { mIndexOffset = offset; mIndexCount = count; } + void GlRenderTask::setViewport(const RenderRegion &viewport) { mViewport = viewport; - if (mViewport.w < 0) { - mViewport.w = 0; - } - - if (mViewport.h < 0) { - mViewport.h = 0; - } + if (mViewport.max.x < mViewport.min.x) mViewport.max.x = mViewport.min.x; + if (mViewport.max.y < mViewport.min.y) mViewport.max.y = mViewport.min.y; } + +/************************************************************************/ +/* GlStencilCoverTask Class Implementation */ +/************************************************************************/ + GlStencilCoverTask::GlStencilCoverTask(GlRenderTask* stencil, GlRenderTask* cover, GlStencilMode mode) - :GlRenderTask(nullptr), mStencilTask(stencil), mCoverTask(cover), mStencilMode(mode) {} + :GlRenderTask(nullptr), mStencilTask(stencil), mCoverTask(cover), mStencilMode(mode) + { + + } + GlStencilCoverTask::~GlStencilCoverTask() { @@ -118,6 +130,7 @@ GlStencilCoverTask::~GlStencilCoverTask() delete mCoverTask; } + void GlStencilCoverTask::run() { GL_CHECK(glEnable(GL_STENCIL_TEST)); @@ -151,12 +164,18 @@ void GlStencilCoverTask::run() GL_CHECK(glDisable(GL_STENCIL_TEST)); } + void GlStencilCoverTask::normalizeDrawDepth(int32_t maxDepth) { mCoverTask->normalizeDrawDepth(maxDepth); mStencilTask->normalizeDrawDepth(maxDepth); } + +/************************************************************************/ +/* GlComposeTask Class Implementation */ +/************************************************************************/ + GlComposeTask::GlComposeTask(GlProgram* program, GLuint target, GlRenderTarget* fbo, Array&& tasks) :GlRenderTask(program) ,mTargetFbo(target), mFbo(fbo), mTasks() { @@ -164,12 +183,14 @@ GlComposeTask::GlComposeTask(GlProgram* program, GLuint target, GlRenderTarget* tasks.clear(); } + GlComposeTask::~GlComposeTask() { ARRAY_FOREACH(p, mTasks) delete(*p); mTasks.clear(); } + void GlComposeTask::run() { GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getSelfFbo())); @@ -209,29 +230,43 @@ void GlComposeTask::run() onResolve(); } -GLuint GlComposeTask::getSelfFbo() { return mFbo->getFboId(); } -GLuint GlComposeTask::getResolveFboId() { return mFbo->getResolveFboId(); } +GLuint GlComposeTask::getSelfFbo() +{ + return mFbo->getFboId(); +} -void GlComposeTask::onResolve() { + +GLuint GlComposeTask::getResolveFboId() +{ + return mFbo->getResolveFboId(); +} + + +void GlComposeTask::onResolve() +{ GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, getSelfFbo())); GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getResolveFboId())); - - GL_CHECK(glBlitFramebuffer(0, 0, mRenderWidth, mRenderHeight, 0, 0, mRenderWidth, mRenderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST)); } + +/************************************************************************/ +/* GlBlitTask Class Implementation */ +/************************************************************************/ + GlBlitTask::GlBlitTask(GlProgram* program, GLuint target, GlRenderTarget* fbo, Array&& tasks) : GlComposeTask(program, target, fbo, std::move(tasks)), mColorTex(fbo->getColorTexture()) { } + void GlBlitTask::run() { GlComposeTask::run(); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo())); - GL_CHECK(glViewport(mTargetViewport.x, mTargetViewport.y, mTargetViewport.w, mTargetViewport.h)); + GL_CHECK(glViewport(mTargetViewport.x(), mTargetViewport.y(), mTargetViewport.w(), mTargetViewport.h())); if (mClearBuffer) { GL_CHECK(glClearColor(0, 0, 0, 0)); @@ -246,16 +281,24 @@ void GlBlitTask::run() GlRenderTask::run(); } + +/************************************************************************/ +/* GlDrawBlitTask Class Implementation */ +/************************************************************************/ + + GlDrawBlitTask::GlDrawBlitTask(GlProgram* program, GLuint target, GlRenderTarget* fbo, Array&& tasks) : GlComposeTask(program, target, fbo, std::move(tasks)) { } + GlDrawBlitTask::~GlDrawBlitTask() { if (mPrevTask) delete mPrevTask; } + void GlDrawBlitTask::run() { if (mPrevTask) mPrevTask->run(); @@ -269,15 +312,22 @@ void GlDrawBlitTask::run() GlRenderTask::run(); } + +/************************************************************************/ +/* GlClipTask Class Implementation */ +/************************************************************************/ + GlClipTask::GlClipTask(GlRenderTask* clip, GlRenderTask* mask) :GlRenderTask(nullptr), mClipTask(clip), mMaskTask(mask) {} + GlClipTask::~GlClipTask() { delete mClipTask; delete mMaskTask; } + void GlClipTask::run() { GL_CHECK(glEnable(GL_STENCIL_TEST)); @@ -304,14 +354,22 @@ void GlClipTask::run() GL_CHECK(glDisable(GL_STENCIL_TEST)); } + void GlClipTask::normalizeDrawDepth(int32_t maxDepth) { mClipTask->normalizeDrawDepth(maxDepth); mMaskTask->normalizeDrawDepth(maxDepth); } +/************************************************************************/ +/* GlSimpleBlendTask Class Implementation */ +/************************************************************************/ + GlSimpleBlendTask::GlSimpleBlendTask(BlendMethod method, GlProgram* program) - : GlRenderTask(program), mBlendMethod(method) {} + : GlRenderTask(program), mBlendMethod(method) + { + } + void GlSimpleBlendTask::run() { @@ -332,8 +390,17 @@ void GlSimpleBlendTask::run() glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } + +/************************************************************************/ +/* GlComplexBlendTask Class Implementation */ +/************************************************************************/ + + GlComplexBlendTask::GlComplexBlendTask(GlProgram* program, GlRenderTarget* dstFbo, GlRenderTarget* dstCopyFbo, GlRenderTask* stencilTask, GlComposeTask* composeTask) - : GlRenderTask(program), mDstFbo(dstFbo), mDstCopyFbo(dstCopyFbo), mStencilTask(stencilTask), mComposeTask(composeTask) {} + : GlRenderTask(program), mDstFbo(dstFbo), mDstCopyFbo(dstCopyFbo), mStencilTask(stencilTask), mComposeTask(composeTask) + { + } + GlComplexBlendTask::~GlComplexBlendTask() { @@ -341,6 +408,7 @@ GlComplexBlendTask::~GlComplexBlendTask() delete mComposeTask; } + void GlComplexBlendTask::run() { mComposeTask->run(); @@ -349,12 +417,11 @@ void GlComplexBlendTask::run() GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, mDstFbo->getFboId())); GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mDstCopyFbo->getResolveFboId())); - GL_CHECK(glViewport(0, 0, mDstFbo->getViewport().w, mDstFbo->getViewport().h)); - GL_CHECK(glScissor(0, 0, mDstFbo->getViewport().w, mDstFbo->getViewport().h)); + GL_CHECK(glViewport(0, 0, mDstFbo->getViewport().w(), mDstFbo->getViewport().h())); + GL_CHECK(glScissor(0, 0, mDstFbo->getViewport().w(), mDstFbo->getViewport().h())); const auto& vp = getViewport(); - - GL_CHECK(glBlitFramebuffer(vp.x, vp.y, vp.x + vp.w, vp.y + vp.h, 0, 0, vp.w, vp.h, GL_COLOR_BUFFER_BIT, GL_LINEAR)); + GL_CHECK(glBlitFramebuffer(vp.min.x, vp.min.y, vp.max.x, vp.max.y, 0, 0, vp.w(), vp.h(), GL_COLOR_BUFFER_BIT, GL_LINEAR)); GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mDstFbo->getFboId())); @@ -381,12 +448,17 @@ void GlComplexBlendTask::run() GL_CHECK(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); } + void GlComplexBlendTask::normalizeDrawDepth(int32_t maxDepth) { mStencilTask->normalizeDrawDepth(maxDepth); GlRenderTask::normalizeDrawDepth(maxDepth); } +/************************************************************************/ +/* GlGaussianBlurTask Class Implementation */ +/************************************************************************/ + void GlGaussianBlurTask::run() { const auto vp = getViewport(); @@ -439,6 +511,9 @@ void GlGaussianBlurTask::run() GL_CHECK(glEnable(GL_BLEND)); } +/************************************************************************/ +/* GlEffectDropShadowTask Class Implementation */ +/************************************************************************/ void GlEffectDropShadowTask::run() { @@ -492,6 +567,9 @@ void GlEffectDropShadowTask::run() GL_CHECK(glEnable(GL_BLEND)); } +/************************************************************************/ +/* GlEffectColorTransformTask Class Implementation */ +/************************************************************************/ void GlEffectColorTransformTask::run() { diff --git a/src/renderer/gl_engine/tvgGlRenderTask.h b/src/renderer/gl_engine/tvgGlRenderTask.h index d6fa93f2..6254292a 100644 --- a/src/renderer/gl_engine/tvgGlRenderTask.h +++ b/src/renderer/gl_engine/tvgGlRenderTask.h @@ -130,12 +130,10 @@ public: protected: GLuint getTargetFbo() { return mTargetFbo; } - GLuint getSelfFbo(); - GLuint getResolveFboId(); - void onResolve(); + private: GLuint mTargetFbo; GlRenderTarget* mFbo; diff --git a/src/renderer/gl_engine/tvgGlRenderer.cpp b/src/renderer/gl_engine/tvgGlRenderer.cpp index 67bc60cb..19a64da0 100644 --- a/src/renderer/gl_engine/tvgGlRenderer.cpp +++ b/src/renderer/gl_engine/tvgGlRenderer.cpp @@ -183,10 +183,10 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat bbox.intersect(vp); } - auto x = bbox.x - vp.x; - auto y = bbox.y - vp.y; - auto w = bbox.w; - auto h = bbox.h; + auto x = bbox.sx() - vp.sx(); + auto y = bbox.sy() - vp.sy(); + auto w = bbox.sw(); + auto h = bbox.sh(); GlRenderTask* task = nullptr; if (mBlendMethod != BlendMethod::Normal && !complexBlend) task = new GlSimpleBlendTask(mBlendMethod, mPrograms[RT_Color]); @@ -199,7 +199,8 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat return; } - task->setViewport({x, vp.h - y - h, w, h}); + y = vp.sh() - y - h; + task->setViewport({{x, y}, {x + w, y + h}}); GlRenderTask* stencilTask = nullptr; @@ -268,7 +269,6 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla { auto vp = currentPass()->getViewport(); auto bbox = sdata.geometry.viewport; - bbox.intersect(vp); const Fill::ColorStop* stops = nullptr; @@ -277,13 +277,9 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla GlRenderTask* task = nullptr; - if (fill->type() == Type::LinearGradient) { - task = new GlRenderTask(mPrograms[RT_LinGradient]); - } else if (fill->type() == Type::RadialGradient) { - task = new GlRenderTask(mPrograms[RT_RadGradient]); - } else { - return; - } + if (fill->type() == Type::LinearGradient) task = new GlRenderTask(mPrograms[RT_LinGradient]); + else if (fill->type() == Type::RadialGradient) task = new GlRenderTask(mPrograms[RT_RadGradient]); + else return; task->setDrawDepth(depth); @@ -293,13 +289,11 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla } auto complexBlend = beginComplexBlending(bbox, sdata.geometry.getBounds()); - if (complexBlend) vp = currentPass()->getViewport(); - auto x = bbox.x - vp.x; - auto y = bbox.y - vp.y; - - task->setViewport({x, vp.h - y - bbox.h, bbox.w, bbox.h}); + auto x = bbox.sx() - vp.sx(); + auto y = vp.sh() - (bbox.sy() - vp.sy()) - bbox.sh(); + task->setViewport({{x, y}, {x + bbox.sw(), y + bbox.sh()}}); GlRenderTask* stencilTask = nullptr; GlStencilMode stencilMode = sdata.geometry.getStencilMode(flag); @@ -498,22 +492,18 @@ void GlRenderer::drawClip(Array& clips) for (uint32_t i = 0; i < clips.count; ++i) { auto sdata = static_cast(clips[i]); - auto clipTask = new GlRenderTask(mPrograms[RT_Stencil]); - clipTask->setDrawDepth(clipDepths[i]); auto flag = (sdata->geometry.stroke.vertex.count > 0) ? RenderUpdateFlag::Stroke : RenderUpdateFlag::Path; sdata->geometry.draw(clipTask, &mGpuBuffer, flag); auto bbox = sdata->geometry.viewport; - bbox.intersect(vp); - auto x = bbox.x - vp.x; - auto y = bbox.y - vp.y; - - clipTask->setViewport({x, vp.h - y - bbox.h, bbox.w, bbox.h}); + auto x = bbox.sx() - vp.sx(); + auto y = vp.sh() - (bbox.sy() - vp.sy()) - bbox.sh(); + clipTask->setViewport({{x, y}, {x + bbox.sw(), y + bbox.sh()}}); float matrix44[16]; currentPass()->getMatrix(matrix44, sdata->geometry.matrix); @@ -529,7 +519,7 @@ void GlRenderer::drawClip(Array& clips) maskTask->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), identityVertexOffset}); maskTask->addBindResource(GlBindingResource{0, loc, mGpuBuffer.getBufferId(), mat4Offset, 16 * sizeof(float), }); maskTask->setDrawRange(identityIndexOffset, 6); - maskTask->setViewport({0, 0, static_cast(vp.w), static_cast(vp.h)}); + maskTask->setViewport({{0, 0}, {vp.sw(), vp.sh()}}); currentPass()->addRenderTask(new GlClipTask(clipTask, maskTask)); } @@ -543,11 +533,10 @@ GlRenderPass* GlRenderer::currentPass() bool GlRenderer::beginComplexBlending(const RenderRegion& vp, RenderRegion bounds) { - if (vp.w == 0 || vp.h == 0) return false; + if (vp.invalid()) return false; bounds.intersect(vp); - - if (bounds.w == 0 || bounds.h == 0) return false; + if (bounds.invalid()) return false; if (mBlendMethod == BlendMethod::Normal || mBlendMethod == BlendMethod::Add || mBlendMethod == BlendMethod::Darken || mBlendMethod == BlendMethod::Lighten) return false; @@ -573,37 +562,26 @@ void GlRenderer::endBlendingCompose(GlRenderTask* stencilTask, const Matrix& mat if (mBlendPool.count < 2) mBlendPool.push(new GlRenderTargetPool(surface.w, surface.h)); auto dstCopyFbo = mBlendPool[1]->getRenderTarget(vp); - { - const auto& passVp = currentPass()->getViewport(); - - auto x = vp.x; - auto y = vp.y; - auto w = vp.w; - auto h = vp.h; - - stencilTask->setViewport({x, passVp.h - y - h, w, h}); - } + auto x = vp.sx(); + auto y = currentPass()->getViewport().sh() - vp.sy() - vp.sh(); + stencilTask->setViewport({{x, y}, {x + vp.sw(), y + vp.sh()}}); stencilTask->setDrawDepth(currentPass()->nextDrawDepth()); - { - // set view matrix - float matrix44[16]; - currentPass()->getMatrix(matrix44, matrix); - uint32_t viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true); - stencilTask->addBindResource(GlBindingResource{ - 0, - stencilTask->getProgram()->getUniformBlockIndex("Matrix"), - mGpuBuffer.getBufferId(), - viewOffset, - 16 * sizeof(float), - }); - } + // set view matrix + float matrix44[16]; + currentPass()->getMatrix(matrix44, matrix); + uint32_t viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true); + stencilTask->addBindResource(GlBindingResource{ + 0, + stencilTask->getProgram()->getUniformBlockIndex("Matrix"), + mGpuBuffer.getBufferId(), + viewOffset, + 16 * sizeof(float), + }); auto task = new GlComplexBlendTask(getBlendProgram(), currentPass()->getFbo(), dstCopyFbo, stencilTask, composeTask); - prepareCmpTask(task, vp, blendPass->getFboWidth(), blendPass->getFboHeight()); - task->setDrawDepth(currentPass()->nextDrawDepth()); // src and dst texture @@ -634,8 +612,7 @@ GlProgram* GlRenderer::getBlendProgram() void GlRenderer::prepareBlitTask(GlBlitTask* task) { - RenderRegion region{0, 0, static_cast(surface.w), static_cast(surface.h)}; - prepareCmpTask(task, region, surface.w, surface.h); + prepareCmpTask(task, {{0, 0}, {int32_t(surface.w), int32_t(surface.h)}}, surface.w, surface.h); task->addBindResource(GlBindingResource{0, task->getColorTexture(), task->getProgram()->getUniformLocation("uSrcTexture")}); } @@ -650,13 +627,13 @@ void GlRenderer::prepareCmpTask(GlRenderTask* task, const RenderRegion& vp, uint auto taskVp = vp; taskVp.intersect(passVp); - auto x = taskVp.x - passVp.x; - auto y = taskVp.y - passVp.y; - auto w = taskVp.w; - auto h = taskVp.h; + auto x = taskVp.sx() - passVp.sx(); + auto y = taskVp.sy() - passVp.sy(); + auto w = taskVp.sw(); + auto h = taskVp.sh(); - float rw = static_cast(passVp.w); - float rh = static_cast(passVp.h); + float rw = static_cast(passVp.w()); + float rh = static_cast(passVp.h()); float l = static_cast(x); float t = static_cast(rh - y); @@ -707,10 +684,9 @@ void GlRenderer::prepareCmpTask(GlRenderTask* task, const RenderRegion& vp, uint task->addVertexLayout(GlVertexLayout{0, 2, 4 * sizeof(float), vertexOffset}); task->addVertexLayout(GlVertexLayout{1, 2, 4 * sizeof(float), vertexOffset + 2 * sizeof(float)}); - task->setDrawRange(indexOffset, indices.count); - - task->setViewport({x, static_cast((passVp.h - y - h)), w, h}); + y = (passVp.sh() - y - h); + task->setViewport({{x, y}, {x + w, y + h}}); } @@ -743,11 +719,11 @@ void GlRenderer::endRenderPass(RenderCompositor* cmp) if (program && !selfPass->isEmpty() && !maskPass->isEmpty()) { auto prev_task = maskPass->endRenderPass(nullptr, currentPass()->getFboId()); prev_task->setDrawDepth(currentPass()->nextDrawDepth()); - prev_task->setRenderSize(static_cast(glCmp->bbox.w), static_cast(glCmp->bbox.h)); + prev_task->setRenderSize(glCmp->bbox.w(), glCmp->bbox.h()); prev_task->setViewport(glCmp->bbox); auto compose_task = selfPass->endRenderPass(program, currentPass()->getFboId()); - compose_task->setRenderSize(static_cast(glCmp->bbox.w), static_cast(glCmp->bbox.h)); + compose_task->setRenderSize(glCmp->bbox.w(), glCmp->bbox.h()); compose_task->setPrevTask(prev_task); prepareCmpTask(compose_task, glCmp->bbox, selfPass->getFboWidth(), selfPass->getFboHeight()); @@ -756,7 +732,7 @@ void GlRenderer::endRenderPass(RenderCompositor* cmp) compose_task->addBindResource(GlBindingResource{1, maskPass->getTextureId(), program->getUniformLocation("uMaskTexture")}); compose_task->setDrawDepth(currentPass()->nextDrawDepth()); - compose_task->setParentSize(static_cast(currentPass()->getViewport().w), static_cast(currentPass()->getViewport().h)); + compose_task->setParentSize(currentPass()->getViewport().w(), currentPass()->getViewport().h()); currentPass()->addRenderTask(compose_task); } @@ -769,7 +745,7 @@ void GlRenderer::endRenderPass(RenderCompositor* cmp) if (!renderPass->isEmpty()) { auto task = renderPass->endRenderPass(mPrograms[RT_Image], currentPass()->getFboId()); - task->setRenderSize(static_cast(glCmp->bbox.w), static_cast(glCmp->bbox.h)); + task->setRenderSize(glCmp->bbox.w(), glCmp->bbox.h()); prepareCmpTask(task, glCmp->bbox, renderPass->getFboWidth(), renderPass->getFboHeight()); task->setDrawDepth(currentPass()->nextDrawDepth()); @@ -797,7 +773,7 @@ void GlRenderer::endRenderPass(RenderCompositor* cmp) // texture id task->addBindResource(GlBindingResource{0, renderPass->getTextureId(), task->getProgram()->getUniformLocation("uTexture")}); - task->setParentSize(static_cast(currentPass()->getViewport().w), static_cast(currentPass()->getViewport().h)); + task->setParentSize(currentPass()->getViewport().w(), currentPass()->getViewport().h()); currentPass()->addRenderTask(std::move(task)); } delete(renderPass); @@ -836,7 +812,7 @@ bool GlRenderer::target(void* context, int32_t id, uint32_t w, uint32_t h) currentContext(); - mRootTarget.setViewport({0, 0, static_cast(surface.w), static_cast(surface.h)}); + mRootTarget.setViewport({{0, 0}, {int32_t(surface.w), int32_t(surface.h)}}); mRootTarget.init(surface.w, surface.h, mTargetFboId); return true; @@ -864,7 +840,7 @@ bool GlRenderer::sync() prepareBlitTask(task); task->mClearBuffer = mClearBuffer; - task->setTargetViewport({0, 0, static_cast(surface.w), static_cast(surface.h)}); + task->setTargetViewport({{0, 0}, {int32_t(surface.w), int32_t(surface.h)}}); if (mGpuBuffer.flushToGPU()) { mGpuBuffer.bind(); @@ -935,20 +911,11 @@ bool GlRenderer::beginComposite(RenderCompositor* cmp, MaskMethod method, uint8_ cmp->opacity = opacity; uint32_t index = mRenderPassStack.count - 1; - - if (index >= mComposePool.count) { - mComposePool.push( new GlRenderTargetPool(surface.w, surface.h)); - } + if (index >= mComposePool.count) mComposePool.push( new GlRenderTargetPool(surface.w, surface.h)); auto glCmp = static_cast(cmp); - - if (glCmp->bbox.w > 0 && glCmp->bbox.h > 0) { - auto renderTarget = mComposePool[index]->getRenderTarget(glCmp->bbox); - mRenderPassStack.push(new GlRenderPass(renderTarget)); - } else { - // empty render pass - mRenderPassStack.push(new GlRenderPass(nullptr)); - } + if (glCmp->bbox.valid()) mRenderPassStack.push(new GlRenderPass(mComposePool[index]->getRenderTarget(glCmp->bbox))); + else mRenderPassStack.push(new GlRenderPass(nullptr)); return true; } @@ -1069,12 +1036,12 @@ bool GlRenderer::effectGaussianBlurRegion(RenderEffectGaussianBlur* effect) { auto gaussianBlur = (GlGaussianBlur*)effect->rd; if (effect->direction != 2) { - effect->extend.x = -gaussianBlur->extend; - effect->extend.w = +gaussianBlur->extend * 2; + effect->extend.min.x = -gaussianBlur->extend; + effect->extend.max.x = +gaussianBlur->extend; } if (effect->direction != 1) { - effect->extend.y = -gaussianBlur->extend; - effect->extend.h = +gaussianBlur->extend * 2; + effect->extend.min.y = -gaussianBlur->extend; + effect->extend.max.y = +gaussianBlur->extend; } return true; }; @@ -1083,10 +1050,10 @@ bool GlRenderer::effectGaussianBlurRegion(RenderEffectGaussianBlur* effect) bool GlRenderer::effectDropShadowRegion(RenderEffectDropShadow* effect) { auto gaussianBlur = (GlDropShadow*)effect->rd; - effect->extend.x = -gaussianBlur->extend; - effect->extend.w = +gaussianBlur->extend * 2; - effect->extend.y = -gaussianBlur->extend; - effect->extend.h = +gaussianBlur->extend * 2; + effect->extend.min.x = -gaussianBlur->extend; + effect->extend.max.x = +gaussianBlur->extend; + effect->extend.min.y = -gaussianBlur->extend; + effect->extend.max.y = +gaussianBlur->extend; return true; }; @@ -1136,7 +1103,6 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef auto voffset = mGpuBuffer.push((void*)vdata, sizeof(vdata)); auto ioffset = mGpuBuffer.pushIndex((void*)idata, sizeof(idata)); - // effect gaussian blur if (effect->type == SceneEffect::GaussianBlur) { // get gaussian programs GlProgram* programHorz = mPrograms[RT_GaussianHorz]; @@ -1152,7 +1118,7 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef // create gaussian blur tasks auto gaussianTask = new GlGaussianBlurTask(dstFbo, dstCopyFbo0, dstCopyFbo1); gaussianTask->effect = (RenderEffectGaussianBlur*)effect; - gaussianTask->setViewport({0, 0, vp.w, vp.h}); + gaussianTask->setViewport({{0, 0}, {vp.sw(), vp.sh()}}); // horizontal blur task and geometry gaussianTask->horzTask = new GlRenderTask(programHorz); gaussianTask->horzTask->addBindResource(GlBindingResource{0, programHorz->getUniformBlockIndex("Gaussian"), mGpuBuffer.getBufferId(), blurOffset, sizeof(GlGaussianBlur)}); @@ -1165,8 +1131,7 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef gaussianTask->vertTask->setDrawRange(ioffset, 6); // add task to render pipeline pass->addRenderTask(gaussianTask); - } // effect drop shadow - else if (effect->type == SceneEffect::DropShadow) { + } else if (effect->type == SceneEffect::DropShadow) { // get programs GlProgram* program = mPrograms[RT_DropShadow]; GlProgram* programHorz = mPrograms[RT_GaussianHorz]; @@ -1182,7 +1147,7 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef // create gaussian blur tasks auto task = new GlEffectDropShadowTask(program, dstFbo, dstCopyFbo0, dstCopyFbo1); task->effect = (RenderEffectDropShadow*)effect; - task->setViewport({0, 0, vp.w, vp.h}); + task->setViewport({{0, 0}, {vp.sw(), vp.sh()}}); task->addBindResource(GlBindingResource{0, program->getUniformBlockIndex("DropShadow"), mGpuBuffer.getBufferId(), paramsOffset, sizeof(GlDropShadow)}); task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset}); task->setDrawRange(ioffset, 6); @@ -1198,8 +1163,7 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef task->vertTask->setDrawRange(ioffset, 6); // add task to render pipeline pass->addRenderTask(task); - } // effect fill, tint, tritone - else if ((effect->type == SceneEffect::Fill) || (effect->type == SceneEffect::Tint) || (effect->type == SceneEffect::Tritone)) { + } else if ((effect->type == SceneEffect::Fill) || (effect->type == SceneEffect::Tint) || (effect->type == SceneEffect::Tritone)) { GlProgram* program{}; if (effect->type == SceneEffect::Fill) program = mPrograms[RT_EffectFill]; else if (effect->type == SceneEffect::Tint) program = mPrograms[RT_EffectTint]; @@ -1213,7 +1177,7 @@ bool GlRenderer::render(TVG_UNUSED RenderCompositor* cmp, const RenderEffect* ef auto paramsOffset = mGpuBuffer.push(params, sizeof(GlEffectParams), true); // create and setup task auto task = new GlEffectColorTransformTask(program, dstFbo, dstCopyFbo); - task->setViewport({0, 0, vp.w, vp.h}); + task->setViewport({{0, 0}, {vp.sw(), vp.sh()}}); task->addBindResource(GlBindingResource{0, program->getUniformBlockIndex("Params"), mGpuBuffer.getBufferId(), paramsOffset, sizeof(GlEffectParams)}); task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), voffset}); task->setDrawRange(ioffset, 6); @@ -1256,25 +1220,18 @@ bool GlRenderer::blend(BlendMethod method) bool GlRenderer::renderImage(void* data) { auto sdata = static_cast(data); - if (!sdata) return false; - if (currentPass()->isEmpty()) return true; + if (currentPass()->isEmpty() || !(sdata->updateFlag & RenderUpdateFlag::Image)) return true; - if ((sdata->updateFlag & RenderUpdateFlag::Image) == 0) return true; auto vp = currentPass()->getViewport(); - auto bbox = sdata->geometry.viewport; - bbox.intersect(vp); + if (bbox.invalid()) return true; - if (bbox.w <= 0 || bbox.h <= 0) return true; - - auto x = bbox.x - vp.x; - auto y = bbox.y - vp.y; - - - int32_t drawDepth = currentPass()->nextDrawDepth(); + auto x = bbox.sx() - vp.sx(); + auto y = bbox.sy() - vp.sy(); + auto drawDepth = currentPass()->nextDrawDepth(); if (!sdata->clips.empty()) drawClip(sdata->clips); @@ -1287,7 +1244,6 @@ bool GlRenderer::renderImage(void* data) } bool complexBlend = beginComplexBlending(bbox, sdata->geometry.getBounds()); - if (complexBlend) vp = currentPass()->getViewport(); // matrix buffer @@ -1316,7 +1272,11 @@ bool GlRenderer::renderImage(void* data) // texture id task->addBindResource(GlBindingResource{0, sdata->texId, task->getProgram()->getUniformLocation("uTexture")}); - task->setViewport({x, vp.h - y - bbox.h, bbox.w, bbox.h}); + y = vp.sh() - y - bbox.sh(); + auto x2 = x + bbox.sw(); + auto y2 = y + bbox.sh(); + + task->setViewport({{x, y}, {x2, y2}}); currentPass()->addRenderTask(task); @@ -1332,33 +1292,25 @@ bool GlRenderer::renderImage(void* data) bool GlRenderer::renderShape(RenderData data) { - auto sdata = static_cast(data); - if (currentPass()->isEmpty()) return true; + auto sdata = static_cast(data); if (sdata->updateFlag == RenderUpdateFlag::None) return true; - const auto& vp = currentPass()->getViewport(); - auto bbox = sdata->geometry.viewport; - bbox.intersect(vp); - - if (bbox.w <= 0 || bbox.h <= 0) return true; + bbox.intersect(currentPass()->getViewport()); + if (bbox.invalid()) return true; int32_t drawDepth1 = 0, drawDepth2 = 0; - size_t flags = static_cast(sdata->updateFlag); - - if (flags == 0) return false; - - if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Color)) drawDepth1 = currentPass()->nextDrawDepth(); - - if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke)) drawDepth2 = currentPass()->nextDrawDepth(); + if (sdata->updateFlag == RenderUpdateFlag::None) return false; + if (sdata->updateFlag & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Color)) drawDepth1 = currentPass()->nextDrawDepth(); + if (sdata->updateFlag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke)) drawDepth2 = currentPass()->nextDrawDepth(); if (!sdata->clips.empty()) drawClip(sdata->clips); auto processFill = [&]() { - if (flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient)) { + if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient)) { if (const auto& gradient = sdata->rshape->fill) { drawPrimitive(*sdata, gradient, RenderUpdateFlag::Gradient, drawDepth1); } else if (sdata->rshape->color.a > 0) { @@ -1369,7 +1321,7 @@ bool GlRenderer::renderShape(RenderData data) auto processStroke = [&]() { if (!sdata->rshape->stroke) return; - if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke)) { + if (sdata->updateFlag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke)) { if (const auto& gradient = sdata->rshape->strokeFill()) { drawPrimitive(*sdata, gradient, RenderUpdateFlag::GradientStroke, drawDepth2); } else if (sdata->rshape->stroke->color.a > 0) { diff --git a/src/renderer/gl_engine/tvgGlTessellator.cpp b/src/renderer/gl_engine/tvgGlTessellator.cpp index dc583261..d263e64e 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.cpp +++ b/src/renderer/gl_engine/tvgGlTessellator.cpp @@ -1516,12 +1516,7 @@ void Stroker::stroke(const RenderShape *rshape, const RenderPath& path) RenderRegion Stroker::bounds() const { - return RenderRegion { - static_cast(floor(mLeftTop.x)), - static_cast(floor(mLeftTop.y)), - static_cast(ceil(mRightBottom.x - floor(mLeftTop.x))), - static_cast(ceil(mRightBottom.y - floor(mLeftTop.y))), - }; + return {{int32_t(floor(mLeftTop.x)), int32_t(floor(mLeftTop.y))}, {int32_t(ceil(mRightBottom.x)), int32_t(ceil(mRightBottom.y))}}; } @@ -2197,26 +2192,15 @@ void BWTessellator::tessellate(const RenderPath& path, const Matrix& matrix) RenderRegion BWTessellator::bounds() const { - return RenderRegion { - static_cast(floor(bbox.min.x)), - static_cast(floor(bbox.min.y)), - static_cast(ceil(bbox.max.x - floor(bbox.min.x))), - static_cast(ceil(bbox.max.y - floor(bbox.min.y))), - }; + return {{int32_t(floor(bbox.min.x)), int32_t(floor(bbox.min.y))}, {int32_t(ceil(bbox.max.x)), int32_t(ceil(bbox.max.y))}}; } uint32_t BWTessellator::pushVertex(float x, float y) { auto index = _pushVertex(mBuffer->vertex, x, y); - - if (index == 0) { - bbox.max = bbox.min = {x, y}; - } else { - bbox.min = {std::min(bbox.min.x, x), std::min(bbox.min.y, y)}; - bbox.max = {std::max(bbox.max.x, x), std::max(bbox.max.y, y)}; - } - + if (index == 0) bbox.max = bbox.min = {x, y}; + else bbox = {{std::min(bbox.min.x, x), std::min(bbox.min.y, y)}, {std::max(bbox.max.x, x), std::max(bbox.max.y, y)}}; return index; } diff --git a/src/renderer/gl_engine/tvgGlTessellator.h b/src/renderer/gl_engine/tvgGlTessellator.h index 44fbab41..a4ad1f36 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.h +++ b/src/renderer/gl_engine/tvgGlTessellator.h @@ -156,7 +156,7 @@ private: void pushTriangle(uint32_t a, uint32_t b, uint32_t c); GlGeometryBuffer* mBuffer; - BBox bbox = {{}, {}}; + BBox bbox = {}; }; } // namespace tvg diff --git a/src/renderer/sw_engine/tvgSwPostEffect.cpp b/src/renderer/sw_engine/tvgSwPostEffect.cpp index 32debffb..410b3f5a 100644 --- a/src/renderer/sw_engine/tvgSwPostEffect.cpp +++ b/src/renderer/sw_engine/tvgSwPostEffect.cpp @@ -141,12 +141,12 @@ bool effectGaussianBlurRegion(RenderEffectGaussianBlur* params) auto extra = static_cast(params->rd)->extends; if (params->direction != 2) { - region.x = -extra; - region.w = extra * 2; + region.min.x = -extra; + region.max.x = extra; } if (params->direction != 1) { - region.y = -extra; - region.h = extra * 2; + region.min.y = -extra; + region.max.y = extra; } return true; @@ -299,15 +299,14 @@ bool effectDropShadowRegion(RenderEffectDropShadow* params) auto& offset = static_cast(params->rd)->offset; auto extra = static_cast(params->rd)->extends; - region.x = -extra; - region.w = extra * 2; - region.y = -extra; - region.h = extra * 2; + region.min = {-extra, -extra}; + region.max = {extra, extra}; - region.x = std::min(region.x + (int32_t)offset.x, region.x); - region.y = std::min(region.y + (int32_t)offset.y, region.y); - region.w += abs(offset.x); - region.h += abs(offset.y); + if (offset.x < 0) region.min.x += (int32_t) offset.x; + else region.max.x += offset.x; + + if (offset.y < 0) region.min.y += (int32_t) offset.y; + else region.max.y += offset.y; return true; } diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index e097e1a5..b7cc684b 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -54,14 +54,10 @@ struct SwTask : Task done(); RenderRegion region; - - //Range over? - region.x = bbox.min.x > 0 ? bbox.min.x : 0; - region.y = bbox.min.y > 0 ? bbox.min.y : 0; - region.w = bbox.max.x - region.x; - region.h = bbox.max.y - region.y; - if (region.w < 0) region.w = 0; - if (region.h < 0) region.h = 0; + region.min.x = bbox.min.x > 0 ? bbox.min.x : 0; + region.min.y = bbox.min.y > 0 ? bbox.min.y : 0; + region.max.x = bbox.max.x > bbox.min.x ? bbox.max.x : bbox.min.x; + region.max.y = bbox.max.y > bbox.min.y ? bbox.max.y : bbox.min.y; return region; } @@ -570,38 +566,40 @@ SwSurface* SwRenderer::request(int channelSize, bool square) RenderCompositor* SwRenderer::target(const RenderRegion& region, ColorSpace cs, CompositionFlag flags) { - auto x = region.x; - auto y = region.y; - auto w = region.w; - auto h = region.h; + auto min = region.min; + auto max = region.max; + auto sw = static_cast(surface->w); auto sh = static_cast(surface->h); //Out of boundary - if (x >= sw || y >= sh || x + w < 0 || y + h < 0) return nullptr; + if (min.x >= sw || min.y >= sh || max.x < 0 || max.y < 0) return nullptr; auto cmp = request(CHANNEL_SIZE(cs), (flags & CompositionFlag::PostProcessing)); //Boundary Check - if (x < 0) x = 0; - if (y < 0) y = 0; - if (x + w > sw) w = (sw - x); - if (y + h > sh) h = (sh - y); + if (min.x < 0) min.x = 0; + if (min.y < 0) min.y = 0; + if (max.x > sw) max.x = (sw - min.x); + if (max.y > sh) max.y = (sh - min.y); + + auto w = max.x - min.x; + auto h = max.y - min.y; if (w == 0 || h == 0) return nullptr; cmp->compositor->recoverSfc = surface; cmp->compositor->recoverCmp = surface->compositor; cmp->compositor->valid = false; - cmp->compositor->bbox.min.x = x; - cmp->compositor->bbox.min.y = y; - cmp->compositor->bbox.max.x = x + w; - cmp->compositor->bbox.max.y = y + h; + cmp->compositor->bbox.min.x = min.x; + cmp->compositor->bbox.min.y = min.y; + cmp->compositor->bbox.max.x = max.x; + cmp->compositor->bbox.max.y = max.y; /* TODO: Currently, only blending might work. Blending and composition must be handled together. */ auto color = (surface->blender && !surface->compositor) ? 0x00ffffff : 0x00000000; - rasterClear(cmp, x, y, w, h, color); + rasterClear(cmp, min.x, min.y, w, h, color); //Switch render target surface = cmp; @@ -737,10 +735,10 @@ void* SwRenderer::prepareCommon(SwTask* task, const Matrix& transform, const Arr task->surface = surface; task->mpool = mpool; task->flags = flags; - task->bbox.min.x = std::max(static_cast(0), static_cast(vport.x)); - task->bbox.min.y = std::max(static_cast(0), static_cast(vport.y)); - task->bbox.max.x = std::min(static_cast(surface->w), static_cast(vport.x + vport.w)); - task->bbox.max.y = std::min(static_cast(surface->h), static_cast(vport.y + vport.h)); + task->bbox.min.x = std::max(static_cast(0), static_cast(vport.min.x)); + task->bbox.min.y = std::max(static_cast(0), static_cast(vport.min.y)); + task->bbox.max.x = std::min(static_cast(surface->w), static_cast(vport.max.x)); + task->bbox.max.y = std::min(static_cast(surface->h), static_cast(vport.max.y)); if (!task->pushed) { task->pushed = true; diff --git a/src/renderer/tvgCanvas.h b/src/renderer/tvgCanvas.h index 5c794bab..ba5cc5ed 100644 --- a/src/renderer/tvgCanvas.h +++ b/src/renderer/tvgCanvas.h @@ -31,7 +31,7 @@ struct Canvas::Impl { Scene* scene; RenderMethod* renderer; - RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX}; + RenderRegion vport = {{0, 0}, {INT32_MAX, INT32_MAX}}; Status status = Status::Synced; Impl() : scene(Scene::gen()) @@ -119,11 +119,11 @@ struct Canvas::Impl { if (status != Status::Damaged && status != Status::Synced) return Result::InsufficientCondition; - RenderRegion val = {x, y, w, h}; + RenderRegion val = {{x, y}, {x + w, y + h}}; //intersect if the target buffer is already set. auto surface = renderer->mainSurface(); if (surface && surface->w > 0 && surface->h > 0) { - val.intersect({0, 0, (int32_t)surface->w, (int32_t)surface->h}); + val.intersect({{0, 0}, {(int32_t)surface->w, (int32_t)surface->h}}); } if (vport == val) return Result::Success; renderer->viewport(val); diff --git a/src/renderer/tvgGlCanvas.cpp b/src/renderer/tvgGlCanvas.cpp index d66af6ad..39d26ffe 100644 --- a/src/renderer/tvgGlCanvas.cpp +++ b/src/renderer/tvgGlCanvas.cpp @@ -51,7 +51,7 @@ Result GlCanvas::target(void* context, int32_t id, uint32_t w, uint32_t h, Color if (!renderer) return Result::MemoryCorruption; if (!renderer->target(context, id, w, h)) return Result::Unknown; - pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; + pImpl->vport = {{0, 0}, {(int32_t)w, (int32_t)h}}; renderer->viewport(pImpl->vport); //Paints must be updated again with this new target. diff --git a/src/renderer/tvgPaint.cpp b/src/renderer/tvgPaint.cpp index e4d9d26e..497bf983 100644 --- a/src/renderer/tvgPaint.cpp +++ b/src/renderer/tvgPaint.cpp @@ -58,7 +58,7 @@ static Result _clipRect(RenderMethod* renderer, const Point* pts, const Matrix& if (tmp[i].y > max.y) max.y = tmp[i].y; } - float region[4] = {float(before.x), float(before.x + before.w), float(before.y), float(before.y + before.h)}; + float region[4] = {float(before.min.x), float(before.max.x), float(before.min.y), float(before.max.y)}; //figure out if the clipper is a superset of the current viewport(before) region if (min.x <= region[0] && max.x >= region[1] && min.y <= region[2] && max.y >= region[3]) { @@ -66,7 +66,7 @@ static Result _clipRect(RenderMethod* renderer, const Point* pts, const Matrix& return Result::Success; //figure out if the clipper is totally outside of the viewport } else if (max.x <= region[0] || min.x >= region[1] || max.y <= region[2] || min.y >= region[3]) { - renderer->viewport({0, 0, 0, 0}); + renderer->viewport({}); return Result::Success; } return Result::InsufficientCondition; @@ -122,13 +122,13 @@ static Result _compFastTrack(RenderMethod* renderer, Paint* cmpTarget, const Mat if (v1.x > v2.x) std::swap(v1.x, v2.x); if (v1.y > v2.y) std::swap(v1.y, v2.y); - after.x = static_cast(nearbyint(v1.x)); - after.y = static_cast(nearbyint(v1.y)); - after.w = static_cast(nearbyint(v2.x)) - after.x; - after.h = static_cast(nearbyint(v2.y)) - after.y; + after.min.x = static_cast(nearbyint(v1.x)); + after.min.y = static_cast(nearbyint(v1.y)); + after.max.x = static_cast(nearbyint(v2.x)); + after.max.y = static_cast(nearbyint(v2.y)); - if (after.w < 0) after.w = 0; - if (after.h < 0) after.h = 0; + if (after.max.x < after.min.x) after.max.x = after.min.x; + if (after.max.y < after.min.y) after.max.y = after.min.y; after.intersect(before); renderer->viewport(after); @@ -185,7 +185,7 @@ bool Paint::Impl::render(RenderMethod* renderer) PAINT_METHOD(region, bounds(renderer)); if (MASK_REGION_MERGING(maskData->method)) region.add(PAINT(maskData->target)->bounds(renderer)); - if (region.w == 0 || region.h == 0) return true; + if (region.invalid()) return true; cmp = renderer->target(region, MASK_TO_COLORSPACE(renderer, maskData->method), CompositionFlag::Masking); if (renderer->beginComposite(cmp, MaskMethod::None, 255)) { maskData->target->pImpl->render(renderer); diff --git a/src/renderer/tvgPicture.h b/src/renderer/tvgPicture.h index 5a032c5a..b52a1418 100644 --- a/src/renderer/tvgPicture.h +++ b/src/renderer/tvgPicture.h @@ -273,7 +273,7 @@ struct PictureImpl : Picture { if (impl.rd) return renderer->region(impl.rd); if (vector) return vector->pImpl->bounds(renderer); - return {0, 0, 0, 0}; + return {}; } Result load(ImageLoader* loader) diff --git a/src/renderer/tvgRender.cpp b/src/renderer/tvgRender.cpp index 2a4ee4cc..78d7b41a 100644 --- a/src/renderer/tvgRender.cpp +++ b/src/renderer/tvgRender.cpp @@ -106,33 +106,14 @@ bool RenderPath::bounds(Matrix* m, float* x, float* y, float* w, float* h) void RenderRegion::intersect(const RenderRegion& rhs) { - auto x1 = x + w; - auto y1 = y + h; - auto x2 = rhs.x + rhs.w; - auto y2 = rhs.y + rhs.h; + if (min.x < rhs.min.x) min.x = rhs.min.x; + if (min.y < rhs.min.y) min.y = rhs.min.y; + if (max.x > rhs.max.x) max.x = rhs.max.x; + if (max.y > rhs.max.y) max.y = rhs.max.y; - x = (x > rhs.x) ? x : rhs.x; - y = (y > rhs.y) ? y : rhs.y; - w = ((x1 < x2) ? x1 : x2) - x; - h = ((y1 < y2) ? y1 : y2) - y; - - if (w < 0) w = 0; - if (h < 0) h = 0; -} - - -void RenderRegion::add(const RenderRegion& rhs) -{ - if (rhs.x < x) { - w += (x - rhs.x); - x = rhs.x; - } - if (rhs.y < y) { - h += (y - rhs.y); - y = rhs.y; - } - if (rhs.x + rhs.w > x + w) w = (rhs.x + rhs.w) - x; - if (rhs.y + rhs.h > y + h) h = (rhs.y + rhs.h) - y; + // Not intersected: collapse to zero-area region + if (max.x < min.x) max.x = min.x; + if (max.y < min.y) max.y = min.y; } /************************************************************************/ diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index 5491f746..46bd0e82 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -94,16 +94,47 @@ struct RenderCompositor struct RenderRegion { - int32_t x, y, w, h; + struct { + int32_t x, y; + } min; + + struct { + int32_t x, y; + } max; + + static constexpr RenderRegion intersect(const RenderRegion& lhs, const RenderRegion& rhs) + { + return {{std::max(lhs.min.x, rhs.min.x), std::max(lhs.min.y, rhs.min.y)}, {std::min(lhs.max.x, rhs.max.x), std::min(lhs.max.y, rhs.max.y)}}; + } void intersect(const RenderRegion& rhs); - void add(const RenderRegion& rhs); + + void add(const RenderRegion& rhs) + { + if (rhs.min.x < min.x) min.x = rhs.min.x; + if (rhs.min.y < min.y) min.y = rhs.min.y; + if (rhs.max.x > max.x) max.x = rhs.max.x; + if (rhs.max.y > max.y) max.y = rhs.max.y; + } bool operator==(const RenderRegion& rhs) const { - if (x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h) return true; - return false; + return (min.x == rhs.min.x && min.y == rhs.min.y && max.x == rhs.max.x && max.y == rhs.max.y); } + + void reset() { min.x = min.y = max.x = max.y = 0; } + bool valid() const { return (max.x > min.x && max.y > min.y); } + bool invalid() const { return !valid(); } + + int32_t sx() const { return min.x; } + int32_t sy() const { return min.y; } + int32_t sw() const { return max.x - min.x; } + int32_t sh() const { return max.y - min.y; } + + uint32_t x() const { return (uint32_t) sx(); } + uint32_t y() const { return (uint32_t) sy(); } + uint32_t w() const { return (uint32_t) sw(); } + uint32_t h() const { return (uint32_t) sh(); } }; struct RenderPath @@ -272,7 +303,7 @@ struct RenderShape struct RenderEffect { RenderData rd = nullptr; - RenderRegion extend = {0, 0, 0, 0}; + RenderRegion extend{}; SceneEffect type; bool valid = false; diff --git a/src/renderer/tvgScene.h b/src/renderer/tvgScene.h index 8f4395b0..506bb876 100644 --- a/src/renderer/tvgScene.h +++ b/src/renderer/tvgScene.h @@ -64,7 +64,7 @@ struct SceneImpl : Scene { Paint::Impl impl; list paints; //children list - RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX}; + RenderRegion vport = {}; Array* effects = nullptr; uint8_t compFlag = CompositionFlag::Invalid; uint8_t opacity; //for composition @@ -159,40 +159,34 @@ struct SceneImpl : Scene RenderRegion bounds(RenderMethod* renderer) const { - if (paints.empty()) return {0, 0, 0, 0}; - - int32_t x1 = INT32_MAX; - int32_t y1 = INT32_MAX; - int32_t x2 = 0; - int32_t y2 = 0; + if (paints.empty()) return {}; + //Merge regions + RenderRegion pRegion = {{INT32_MAX, INT32_MAX}, {0, 0}}; for (auto paint : paints) { auto region = paint->pImpl->bounds(renderer); - - //Merge regions - if (region.x < x1) x1 = region.x; - if (x2 < region.x + region.w) x2 = (region.x + region.w); - if (region.y < y1) y1 = region.y; - if (y2 < region.y + region.h) y2 = (region.y + region.h); + if (region.min.x < pRegion.min.x) pRegion.min.x = region.min.x; + if (pRegion.max.x < region.max.x) pRegion.max.x = region.max.x; + if (region.min.y < pRegion.min.y) pRegion.min.y = region.min.y; + if (pRegion.max.y < region.max.y) pRegion.max.y = region.max.y; } //Extends the render region if post effects require - int32_t ex = 0, ey = 0, ew = 0, eh = 0; + RenderRegion eRegion{}; if (effects) { ARRAY_FOREACH(p, *effects) { auto effect = *p; - if (effect->valid && renderer->region(effect)) { - ex = std::min(ex, effect->extend.x); - ey = std::min(ey, effect->extend.y); - ew = std::max(ew, effect->extend.w); - eh = std::max(eh, effect->extend.h); - } + if (effect->valid && renderer->region(effect)) eRegion.add(effect->extend); } } - auto ret = RenderRegion{x1 + ex, y1 + ey, (x2 - x1) + ew, (y2 - y1) + eh}; - ret.intersect(this->vport); - return ret; + pRegion.min.x += eRegion.min.x; + pRegion.min.y += eRegion.min.y; + pRegion.max.x += eRegion.max.x; + pRegion.max.y += eRegion.max.y; + + pRegion.intersect(this->vport); + return pRegion; } Result bounds(Point* pt4, Matrix& m, bool obb, bool stroking) diff --git a/src/renderer/tvgShape.h b/src/renderer/tvgShape.h index 72d81454..0adb92aa 100644 --- a/src/renderer/tvgShape.h +++ b/src/renderer/tvgShape.h @@ -114,7 +114,7 @@ struct ShapeImpl : Shape RenderRegion bounds(RenderMethod* renderer) { - if (!impl.rd) return {0, 0, 0, 0}; + if (!impl.rd) return {}; return renderer->region(impl.rd); } diff --git a/src/renderer/tvgSwCanvas.cpp b/src/renderer/tvgSwCanvas.cpp index 9e64bfce..44f3a491 100644 --- a/src/renderer/tvgSwCanvas.cpp +++ b/src/renderer/tvgSwCanvas.cpp @@ -54,7 +54,7 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t if (!renderer) return Result::MemoryCorruption; if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments; - pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; + pImpl->vport = {{0, 0}, {(int32_t)w, (int32_t)h}}; renderer->viewport(pImpl->vport); //FIXME: The value must be associated with an individual canvas instance. diff --git a/src/renderer/tvgWgCanvas.cpp b/src/renderer/tvgWgCanvas.cpp index 5d074199..39928239 100644 --- a/src/renderer/tvgWgCanvas.cpp +++ b/src/renderer/tvgWgCanvas.cpp @@ -55,7 +55,7 @@ Result WgCanvas::target(void* device, void* instance, void* target, uint32_t w, if (!renderer) return Result::MemoryCorruption; if (!renderer->target((WGPUDevice)device, (WGPUInstance)instance, target, w, h, type)) return Result::Unknown; - pImpl->vport = {0, 0, (int32_t)w, (int32_t)h}; + pImpl->vport = {{0, 0}, {(int32_t)w, (int32_t)h}}; renderer->viewport(pImpl->vport); //Paints must be updated again with this new target. diff --git a/src/renderer/wg_engine/tvgWgCompositor.cpp b/src/renderer/wg_engine/tvgWgCompositor.cpp index bc61b3eb..4211a65b 100644 --- a/src/renderer/wg_engine/tvgWgCompositor.cpp +++ b/src/renderer/wg_engine/tvgWgCompositor.cpp @@ -117,18 +117,13 @@ void WgCompositor::resize(WgContext& context, uint32_t width, uint32_t height) { RenderRegion WgCompositor::shrinkRenderRegion(RenderRegion& rect) { - // cut viewport to screen dimensions - int32_t xmin = std::max(0, std::min((int32_t)width, rect.x)); - int32_t ymin = std::max(0, std::min((int32_t)height, rect.y)); - int32_t xmax = std::max(xmin, std::min((int32_t)width, rect.x + rect.w)); - int32_t ymax = std::max(ymin, std::min((int32_t)height, rect.y + rect.h)); - return { xmin, ymin, xmax - xmin, ymax - ymin }; + return RenderRegion::intersect(rect, {{0, 0}, {(int32_t)width, (int32_t)height}}); } void WgCompositor::copyTexture(const WgRenderStorage* dst, const WgRenderStorage* src) { - const RenderRegion region = { 0, 0, (int32_t)src->width, (int32_t)src->height }; + const RenderRegion region = {{0, 0}, {(int32_t)src->width, (int32_t)src->height}}; copyTexture(dst, src, region); } @@ -138,9 +133,9 @@ void WgCompositor::copyTexture(const WgRenderStorage* dst, const WgRenderStorage assert(dst); assert(src); assert(commandEncoder); - const WGPUImageCopyTexture texSrc { .texture = src->texture, .origin = { .x = (uint32_t)region.x, .y = (uint32_t)region.y } }; - const WGPUImageCopyTexture texDst { .texture = dst->texture, .origin = { .x = (uint32_t)region.x, .y = (uint32_t)region.y } }; - const WGPUExtent3D copySize { .width = (uint32_t)region.w, .height = (uint32_t)region.h, .depthOrArrayLayers = 1 }; + const WGPUImageCopyTexture texSrc { .texture = src->texture, .origin = { .x = region.x(), .y = region.y() } }; + const WGPUImageCopyTexture texDst { .texture = dst->texture, .origin = { .x = region.x(), .y = region.y() } }; + const WGPUExtent3D copySize { .width = region.w(), .height = region.h(), .depthOrArrayLayers = 1 }; wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &texSrc, &texDst, ©Size); } @@ -257,7 +252,7 @@ void WgCompositor::composeScene(WgContext& context, WgRenderStorage* src, WgRend assert(mask); assert(renderPassEncoder); RenderRegion rect = shrinkRenderRegion(cmp->aabb); - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x, rect.y, rect.w, rect.h); + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x(), rect.y(), rect.w(), rect.h()); wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, src->bindGroupTexure, 0, nullptr); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, mask->bindGroupTexure, 0, nullptr); @@ -293,10 +288,8 @@ void WgCompositor::drawShape(WgContext& context, WgRenderDataShape* renderData) assert(renderData); assert(renderPassEncoder); assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count); - if (renderData->renderSettingsShape.skip) return; - if (renderData->meshGroupShapes.meshes.count == 0) return; - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // setup stencil rules WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd; wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); @@ -331,16 +324,14 @@ void WgCompositor::blendShape(WgContext& context, WgRenderDataShape* renderData, assert(renderData); assert(renderPassEncoder); assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count); - if (renderData->renderSettingsShape.skip) return; - if (renderData->meshGroupShapes.meshes.count == 0) return; - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; + if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return; // copy current render target data to dst storage WgRenderStorage *target = currentTarget; endRenderPass(); copyTexture(&storageTemp0, target); beginRenderPass(commandEncoder, target, false); // render shape with blend settings - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // setup stencil rules WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd; wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); @@ -377,10 +368,9 @@ void WgCompositor::clipShape(WgContext& context, WgRenderDataShape* renderData) assert(renderData); assert(renderPassEncoder); assert(renderData->meshGroupShapes.meshes.count == renderData->meshGroupShapesBBox.meshes.count); - if (renderData->renderSettingsShape.skip) return; - if (renderData->meshGroupShapes.meshes.count == 0) return; - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + if (renderData->renderSettingsShape.skip || renderData->meshGroupShapes.meshes.count == 0 || renderData->viewport.invalid()) return; + + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // setup stencil rules WGPURenderPipeline stencilPipeline = (renderData->fillRule == FillRule::NonZero) ? pipelines.nonzero : pipelines.evenodd; wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); @@ -420,10 +410,9 @@ void WgCompositor::drawStrokes(WgContext& context, WgRenderDataShape* renderData assert(renderData); assert(renderPassEncoder); assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count); - if (renderData->renderSettingsStroke.skip) return; - if (renderData->meshGroupStrokes.meshes.count == 0) return; - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + if (renderData->renderSettingsStroke.skip || renderData->meshGroupStrokes.meshes.count == 0 || renderData->viewport.invalid()) return; + + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // draw strokes to stencil (first pass) for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) { // setup stencil rules @@ -459,15 +448,14 @@ void WgCompositor::blendStrokes(WgContext& context, WgRenderDataShape* renderDat assert(renderData); assert(renderPassEncoder); assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count); - if (renderData->renderSettingsStroke.skip) return; - if (renderData->meshGroupStrokes.meshes.count == 0) return; - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; + if (renderData->renderSettingsStroke.skip || renderData->meshGroupStrokes.meshes.count == 0 || renderData->viewport.invalid()) return; + // copy current render target data to dst storage WgRenderStorage *target = currentTarget; endRenderPass(); copyTexture(&storageTemp0, target); beginRenderPass(commandEncoder, target, false); - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // draw strokes to stencil (first pass) for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) { // setup stencil rules @@ -507,8 +495,8 @@ void WgCompositor::clipStrokes(WgContext& context, WgRenderDataShape* renderData assert(renderData->meshGroupStrokes.meshes.count == renderData->meshGroupStrokesBBox.meshes.count); if (renderData->renderSettingsStroke.skip) return; if (renderData->meshGroupStrokes.meshes.count == 0) return; - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + if (renderData->viewport.invalid()) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // draw strokes to stencil (first pass) for (uint32_t i = 0; i < renderData->meshGroupStrokes.meshes.count; i++) { // setup stencil rules @@ -548,8 +536,8 @@ void WgCompositor::drawImage(WgContext& context, WgRenderDataPicture* renderData { assert(renderData); assert(renderPassEncoder); - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + if (renderData->viewport.invalid()) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // draw stencil wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); @@ -570,8 +558,8 @@ void WgCompositor::blendImage(WgContext& context, WgRenderDataPicture* renderDat { assert(renderData); assert(renderPassEncoder); - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + if (renderData->viewport.invalid()) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // copy current render target data to dst storage WgRenderStorage *target = currentTarget; endRenderPass(); @@ -599,8 +587,8 @@ void WgCompositor::clipImage(WgContext& context, WgRenderDataPicture* renderData { assert(renderData); assert(renderPassEncoder); - if ((renderData->viewport.w <= 0) || (renderData->viewport.h <= 0)) return; - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x, renderData->viewport.y, renderData->viewport.w, renderData->viewport.h); + if (renderData->viewport.invalid()) return; + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, renderData->viewport.x(), renderData->viewport.y(), renderData->viewport.w(), renderData->viewport.h()); // setup stencil rules wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 255); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, bindGroupViewMat, 0, nullptr); @@ -629,7 +617,7 @@ void WgCompositor::drawScene(WgContext& context, WgRenderStorage* scene, WgCompo assert(currentTarget); // draw scene RenderRegion rect = shrinkRenderRegion(compose->aabb); - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x, rect.y, rect.w, rect.h); + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x(), rect.y(), rect.w(), rect.h()); wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, scene->bindGroupTexure, 0, nullptr); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, bindGroupOpacities[compose->opacity], 0, nullptr); @@ -651,7 +639,7 @@ void WgCompositor::blendScene(WgContext& context, WgRenderStorage* scene, WgComp // blend scene uint32_t blendMethodInd = (uint32_t)compose->blend; RenderRegion rect = shrinkRenderRegion(compose->aabb); - wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x, rect.y, rect.w, rect.h); + wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, rect.x(), rect.y(), rect.w(), rect.h()); wgpuRenderPassEncoderSetStencilReference(renderPassEncoder, 0); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 0, scene->bindGroupTexure, 0, nullptr); wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, 1, storageTemp0.bindGroupTexure, 0, nullptr); @@ -784,7 +772,7 @@ bool WgCompositor::gaussianBlur(WgContext& context, WgRenderStorage* dst, const wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, renderData->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, viewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.gaussian_horz); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (aabb.w - 1) / 128 + 1, aabb.h, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (aabb.sw() - 1) / 128 + 1, aabb.sh(), 1); std::swap(sbuff, dbuff); } // vertical blur @@ -794,7 +782,7 @@ bool WgCompositor::gaussianBlur(WgContext& context, WgRenderStorage* dst, const wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, renderData->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, viewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.gaussian_vert); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, aabb.w, (aabb.h - 1) / 128 + 1, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, aabb.sw(), (aabb.sh() - 1) / 128 + 1, 1); std::swap(sbuff, dbuff); } } @@ -834,7 +822,7 @@ bool WgCompositor::dropShadow(WgContext& context, WgRenderStorage* dst, const Re wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, renderDataParams->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, viewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.gaussian_horz); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (aabb.w - 1) / 128 + 1, aabb.h, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (aabb.sw() - 1) / 128 + 1, aabb.h(), 1); std::swap(sbuff, dbuff); // vertical blur wgpuComputePassEncoderSetBindGroup(computePassEncoder, 0, sbuff->bindGroupRead, 0, nullptr); @@ -842,7 +830,7 @@ bool WgCompositor::dropShadow(WgContext& context, WgRenderStorage* dst, const Re wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, renderDataParams->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, viewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.gaussian_vert); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, aabb.w, (aabb.h - 1) / 128 + 1, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, aabb.sw(), (aabb.sh() - 1) / 128 + 1, 1); std::swap(sbuff, dbuff); wgpuComputePassEncoderEnd(computePassEncoder); wgpuComputePassEncoderRelease(computePassEncoder); @@ -857,7 +845,7 @@ bool WgCompositor::dropShadow(WgContext& context, WgRenderStorage* dst, const Re wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, renderDataParams->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, viewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.dropshadow); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (aabb.w - 1) / 128 + 1, aabb.h, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (aabb.sw() - 1) / 128 + 1, aabb.h(), 1); wgpuComputePassEncoderEnd(computePassEncoder); wgpuComputePassEncoderRelease(computePassEncoder); } @@ -882,7 +870,7 @@ bool WgCompositor::fillEffect(WgContext& context, WgRenderStorage* dst, const Re wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, static_cast(params->rd)->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, compose->rdViewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.fill_effect); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (compose->aabb.w - 1) / 128 + 1, compose->aabb.h, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (compose->aabb.sw() - 1) / 128 + 1, compose->aabb.sh(), 1); wgpuComputePassEncoderEnd(computePassEncoder); wgpuComputePassEncoderRelease(computePassEncoder); @@ -906,7 +894,7 @@ bool WgCompositor::tintEffect(WgContext& context, WgRenderStorage* dst, const Re wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, static_cast(params->rd)->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, compose->rdViewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.tint_effect); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (compose->aabb.w - 1) / 128 + 1, compose->aabb.h, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (compose->aabb.sw() - 1) / 128 + 1, compose->aabb.sh(), 1); wgpuComputePassEncoderEnd(computePassEncoder); wgpuComputePassEncoderRelease(computePassEncoder); @@ -929,7 +917,7 @@ bool WgCompositor::tritoneEffect(WgContext& context, WgRenderStorage* dst, const wgpuComputePassEncoderSetBindGroup(computePassEncoder, 2, static_cast(params->rd)->bindGroupParams, 0, nullptr); wgpuComputePassEncoderSetBindGroup(computePassEncoder, 3, compose->rdViewport->bindGroupViewport, 0, nullptr); wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelines.tritone_effect); - wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (compose->aabb.w - 1) / 128 + 1, compose->aabb.h, 1); + wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, (compose->aabb.sw() - 1) / 128 + 1, compose->aabb.sh(), 1); wgpuComputePassEncoderEnd(computePassEncoder); wgpuComputePassEncoderRelease(computePassEncoder); diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 74d71c48..f4f9374a 100644 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -259,14 +259,9 @@ RenderRegion WgRenderer::region(RenderData data) if (renderData->type() == Type::Shape) { auto& v1 = renderData->aabb.min; auto& v2 = renderData->aabb.max; - RenderRegion renderRegion; - renderRegion.x = static_cast(nearbyint(v1.x)); - renderRegion.y = static_cast(nearbyint(v1.y)); - renderRegion.w = static_cast(nearbyint(v2.x)) - renderRegion.x; - renderRegion.h = static_cast(nearbyint(v2.y)) - renderRegion.y; - return renderRegion; + return {{int32_t(nearbyint(v1.x)), int32_t(nearbyint(v1.y))}, {int32_t(nearbyint(v2.x)), int32_t(nearbyint(v2.y))}}; } - return { 0, 0, (int32_t)mTargetSurface.w, (int32_t)mTargetSurface.h }; + return {{0, 0}, {(int32_t)mTargetSurface.w, (int32_t)mTargetSurface.h}}; } @@ -586,12 +581,12 @@ bool WgRenderer::region(RenderEffect* effect) auto gaussian = (RenderEffectGaussianBlur*)effect; auto renderData = (WgRenderDataEffectParams*)gaussian->rd; if (gaussian->direction != 2) { - gaussian->extend.x = -renderData->extend; - gaussian->extend.w = +renderData->extend * 2; + gaussian->extend.min.x = -renderData->extend; + gaussian->extend.max.x = +renderData->extend; } if (gaussian->direction != 1) { - gaussian->extend.y = -renderData->extend; - gaussian->extend.h = +renderData->extend * 2; + gaussian->extend.min.y = -renderData->extend; + gaussian->extend.max.y = +renderData->extend; } return true; } else @@ -599,10 +594,10 @@ bool WgRenderer::region(RenderEffect* effect) if (effect->type == SceneEffect::DropShadow) { auto dropShadow = (RenderEffectDropShadow*)effect; auto renderData = (WgRenderDataEffectParams*)dropShadow->rd; - dropShadow->extend.x = -(renderData->extend + std::abs(renderData->offset.x)); - dropShadow->extend.w = +(renderData->extend + std::abs(renderData->offset.x)) * 2; - dropShadow->extend.y = -(renderData->extend + std::abs(renderData->offset.y)); - dropShadow->extend.h = +(renderData->extend + std::abs(renderData->offset.y)) * 2; + dropShadow->extend.min.x = -(renderData->extend + std::abs(renderData->offset.x)); + dropShadow->extend.max.x = +(renderData->extend + std::abs(renderData->offset.x)); + dropShadow->extend.min.y = -(renderData->extend + std::abs(renderData->offset.y)); + dropShadow->extend.max.y = +(renderData->extend + std::abs(renderData->offset.y)); return true; } return false; diff --git a/src/renderer/wg_engine/tvgWgShaderTypes.cpp b/src/renderer/wg_engine/tvgWgShaderTypes.cpp index a6e8e19a..7f99c189 100644 --- a/src/renderer/wg_engine/tvgWgShaderTypes.cpp +++ b/src/renderer/wg_engine/tvgWgShaderTypes.cpp @@ -118,10 +118,10 @@ void WgShaderTypeVec4f::update(const RenderColor& c) void WgShaderTypeVec4f::update(const RenderRegion& r) { - vec[0] = r.x; // left - vec[1] = r.y; // top - vec[2] = r.x + r.w - 1; // right - vec[3] = r.y + r.h - 1; // bottom + vec[0] = r.min.x; + vec[1] = r.min.y; + vec[2] = r.max.x - 1; + vec[3] = r.max.y - 1; } //************************************************************************