renderer: ++engines safety

Added drawing exceptions when target is not properly ready.

Now, Canvas::update() Canvas::draw() will return InsufficientCondition
if the target has not been set beforehand.
This commit is contained in:
Hermet Park 2025-05-12 11:50:52 +09:00 committed by Hermet Park
parent 2524cdfee5
commit 3fbb55440a
9 changed files with 32 additions and 5 deletions

View file

@ -40,8 +40,9 @@ GlRenderTarget::~GlRenderTarget()
void GlRenderTarget::init(GLint resolveId)
{
if (mFbo != 0 || mWidth == 0 || mHeight == 0) return;
if (mFbo != GL_INVALID_VALUE || mWidth == 0 || mHeight == 0) return;
//TODO: fbo is used. maybe we can consider the direct rendering with resolveId as well.
GL_CHECK(glGenFramebuffers(1, &mFbo));
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, mFbo));

View file

@ -44,12 +44,13 @@ public:
void setViewport(const RenderRegion& vp) { mViewport = vp; }
const RenderRegion& getViewport() const { return mViewport; }
bool invalid() const { return mFbo == GL_INVALID_VALUE; }
private:
uint32_t mWidth = 0;
uint32_t mHeight = 0;
RenderRegion mViewport{};
GLuint mFbo = 0;
GLuint mFbo = GL_INVALID_VALUE;
GLuint mColorBuffer = 0;
GLuint mDepthStencilBuffer = 0;
GLuint mResolveFbo = 0;

View file

@ -809,6 +809,8 @@ void GlRenderer::endRenderPass(RenderCompositor* cmp)
bool GlRenderer::clear()
{
if (mRootTarget.invalid()) return false;
mClearBuffer = true;
return true;
}
@ -896,6 +898,8 @@ RenderRegion GlRenderer::region(RenderData data)
bool GlRenderer::preRender()
{
if (mRootTarget.invalid()) return false;
currentContext();
if (mPrograms.empty()) initShaders();
mRenderPassStack.push(new GlRenderPass(&mRootTarget));
@ -1525,6 +1529,8 @@ bool GlRenderer::viewport(const RenderRegion& vp)
bool GlRenderer::preUpdate()
{
if (mRootTarget.invalid()) return false;
currentContext();
return true;
}

View file

@ -359,7 +359,7 @@ bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h,
bool SwRenderer::preUpdate()
{
return true;
return surface != nullptr;
}
@ -371,7 +371,7 @@ bool SwRenderer::postUpdate()
bool SwRenderer::preRender()
{
return true;
return surface != nullptr;
}

View file

@ -70,6 +70,11 @@ struct WgContext {
// release buffer objects
void releaseBuffer(WGPUBuffer& buffer);
bool invalid()
{
return !instance || !device;
}
};
#endif // _TVG_WG_COMMON_H_

View file

@ -195,6 +195,8 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
bool WgRenderer::preRender()
{
if (mContext.invalid()) return false;
// push rot render storage to the render tree stack
assert(mRenderStorageStack.count == 0);
mRenderStorageStack.push(&mRenderStorageRoot);
@ -301,6 +303,8 @@ const RenderSurface* WgRenderer::mainSurface()
bool WgRenderer::clear()
{
if (mContext.invalid()) return false;
//TODO: clear the current target buffer only if clear() is called
return true;
}
@ -632,6 +636,8 @@ void WgRenderer::dispose(RenderEffect* effect)
bool WgRenderer::preUpdate()
{
if (mContext.invalid()) return false;
return true;
}

View file

@ -121,6 +121,9 @@ TEST_CASE("Bounding Box", "[tvgPaint]")
Initializer::init(0);
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
uint32_t buffer[100*100];
canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888);
auto shape = Shape::gen();
canvas->push(shape);
canvas->sync();

View file

@ -80,7 +80,8 @@ TEST_CASE("Scene Clear And Reuse Shape", "[tvgScene]")
REQUIRE(Initializer::init(0) == Result::Success);
{
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
REQUIRE(canvas);
uint32_t buffer[100*100];
canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888);
auto scene = Scene::gen();
REQUIRE(scene);

View file

@ -120,6 +120,8 @@ TEST_CASE("Text Basic", "[tvgText]")
Initializer::init(0);
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
uint32_t buffer[100*100];
canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888);
auto text = Text::gen();
REQUIRE(text);
@ -144,6 +146,8 @@ TEST_CASE("Text with composite glyphs", "[tvgText]")
Initializer::init(0);
auto canvas = unique_ptr<SwCanvas>(SwCanvas::gen());
uint32_t buffer[100*100];
canvas->target(buffer, 100, 100, 100, ColorSpace::ABGR8888);
auto text = Text::gen();
REQUIRE(text);