mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-10 22:51:58 +00:00
renderer: ++stabilization
This introduces a managed condition to precisely control the canvas updates. This prevents a crash when the target is changed and drawn without any update calls. issue: https://github.com/thorvg/thorvg/issues/2484
This commit is contained in:
parent
3019bb81e8
commit
38e2812004
4 changed files with 21 additions and 21 deletions
|
@ -26,7 +26,7 @@
|
|||
#include "tvgPaint.h"
|
||||
|
||||
|
||||
enum Status : uint8_t {Synced = 0, Updating, Drawing};
|
||||
enum Status : uint8_t {Synced = 0, Updating, Drawing, Damanged};
|
||||
|
||||
struct Canvas::Impl
|
||||
{
|
||||
|
@ -35,8 +35,6 @@ struct Canvas::Impl
|
|||
RenderRegion vport = {0, 0, INT32_MAX, INT32_MAX};
|
||||
Status status = Status::Synced;
|
||||
|
||||
bool refresh = false; //if all paints should be updated by force.
|
||||
|
||||
Impl(RenderMethod* pRenderer) : renderer(pRenderer)
|
||||
{
|
||||
renderer->ref();
|
||||
|
@ -87,18 +85,13 @@ struct Canvas::Impl
|
|||
return Result::Success;
|
||||
}
|
||||
|
||||
void needRefresh()
|
||||
{
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
Result update(Paint* paint, bool force)
|
||||
{
|
||||
if (paints.empty() || status == Status::Drawing) return Result::InsufficientCondition;
|
||||
|
||||
Array<RenderData> clips;
|
||||
auto flag = RenderUpdateFlag::None;
|
||||
if (refresh || force) flag = RenderUpdateFlag::All;
|
||||
if (status == Status::Damanged || force) flag = RenderUpdateFlag::All;
|
||||
|
||||
if (paint) {
|
||||
paint->pImpl->update(renderer, nullptr, clips, 255, flag);
|
||||
|
@ -106,7 +99,6 @@ struct Canvas::Impl
|
|||
for (auto paint : paints) {
|
||||
paint->pImpl->update(renderer, nullptr, clips, 255, flag);
|
||||
}
|
||||
refresh = false;
|
||||
}
|
||||
status = Status::Updating;
|
||||
return Result::Success;
|
||||
|
@ -114,6 +106,7 @@ struct Canvas::Impl
|
|||
|
||||
Result draw()
|
||||
{
|
||||
if (status == Status::Damanged) update(nullptr, false);
|
||||
if (status == Status::Drawing || paints.empty() || !renderer->preRender()) return Result::InsufficientCondition;
|
||||
|
||||
bool rendered = false;
|
||||
|
@ -129,7 +122,7 @@ struct Canvas::Impl
|
|||
|
||||
Result sync()
|
||||
{
|
||||
if (status == Status::Synced) return Result::InsufficientCondition;
|
||||
if (status == Status::Synced || status == Status::Damanged) return Result::InsufficientCondition;
|
||||
|
||||
if (renderer->sync()) {
|
||||
status = Status::Synced;
|
||||
|
@ -141,7 +134,8 @@ struct Canvas::Impl
|
|||
|
||||
Result viewport(int32_t x, int32_t y, int32_t w, int32_t h)
|
||||
{
|
||||
if (status != Status::Synced) return Result::InsufficientCondition;
|
||||
if (status != Status::Damanged && status != Status::Synced) return Result::InsufficientCondition;
|
||||
|
||||
RenderRegion val = {x, y, w, h};
|
||||
//intersect if the target buffer is already set.
|
||||
auto surface = renderer->mainSurface();
|
||||
|
@ -151,7 +145,7 @@ struct Canvas::Impl
|
|||
if (vport == val) return Result::Success;
|
||||
renderer->viewport(val);
|
||||
vport = val;
|
||||
needRefresh();
|
||||
status = Status::Damanged;
|
||||
return Result::Success;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -62,7 +62,9 @@ GlCanvas::~GlCanvas()
|
|||
Result GlCanvas::target(int32_t id, uint32_t w, uint32_t h) noexcept
|
||||
{
|
||||
#ifdef THORVG_GL_RASTER_SUPPORT
|
||||
if (Canvas::pImpl->status != Status::Synced) return Result::InsufficientCondition;
|
||||
if (Canvas::pImpl->status != Status::Damanged && Canvas::pImpl->status != Status::Synced) {
|
||||
return Result::InsufficientCondition;
|
||||
}
|
||||
|
||||
//We know renderer type, avoid dynamic_cast for performance.
|
||||
auto renderer = static_cast<GlRenderer*>(Canvas::pImpl->renderer);
|
||||
|
@ -73,7 +75,7 @@ Result GlCanvas::target(int32_t id, uint32_t w, uint32_t h) noexcept
|
|||
renderer->viewport(Canvas::pImpl->vport);
|
||||
|
||||
//Paints must be updated again with this new target.
|
||||
Canvas::pImpl->needRefresh();
|
||||
Canvas::pImpl->status = Status::Damanged;
|
||||
|
||||
return Result::Success;
|
||||
#endif
|
||||
|
|
|
@ -82,7 +82,9 @@ Result SwCanvas::mempool(MempoolPolicy policy) noexcept
|
|||
Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept
|
||||
{
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
if (Canvas::pImpl->status != Status::Synced) return Result::InsufficientCondition;
|
||||
if (Canvas::pImpl->status != Status::Damanged && Canvas::pImpl->status != Status::Synced) {
|
||||
return Result::InsufficientCondition;
|
||||
}
|
||||
|
||||
//We know renderer type, avoid dynamic_cast for performance.
|
||||
auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer);
|
||||
|
@ -92,12 +94,12 @@ Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
|||
Canvas::pImpl->vport = {0, 0, (int32_t)w, (int32_t)h};
|
||||
renderer->viewport(Canvas::pImpl->vport);
|
||||
|
||||
//Paints must be updated again with this new target.
|
||||
Canvas::pImpl->needRefresh();
|
||||
|
||||
//FIXME: The value must be associated with an individual canvas instance.
|
||||
ImageLoader::cs = static_cast<ColorSpace>(cs);
|
||||
|
||||
//Paints must be updated again with this new target.
|
||||
Canvas::pImpl->status = Status::Damanged;
|
||||
|
||||
return Result::Success;
|
||||
#endif
|
||||
return Result::NonSupport;
|
||||
|
|
|
@ -57,7 +57,9 @@ WgCanvas::~WgCanvas()
|
|||
Result WgCanvas::target(void* instance, void* surface, uint32_t w, uint32_t h) noexcept
|
||||
{
|
||||
#ifdef THORVG_WG_RASTER_SUPPORT
|
||||
if (Canvas::pImpl->status != Status::Synced) return Result::InsufficientCondition;
|
||||
if (Canvas::pImpl->status != Status::Damanged && Canvas::pImpl->status != Status::Synced) {
|
||||
return Result::InsufficientCondition;
|
||||
}
|
||||
|
||||
if (!instance || !surface || (w == 0) || (h == 0)) return Result::InvalidArguments;
|
||||
|
||||
|
@ -70,7 +72,7 @@ Result WgCanvas::target(void* instance, void* surface, uint32_t w, uint32_t h) n
|
|||
renderer->viewport(Canvas::pImpl->vport);
|
||||
|
||||
//Paints must be updated again with this new target.
|
||||
Canvas::pImpl->needRefresh();
|
||||
Canvas::pImpl->status = Status::Damanged;
|
||||
|
||||
return Result::Success;
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue