sw_engine renderer: fix the invalid memory access in the corner case.

Tasks can be disposed while the renderer referencing it.
Now, we can delete the tasks with lazy approach by introducing some tags.

@Issue: https://github.com/Samsung/thorvg/issues/995
This commit is contained in:
Hermet Park 2021-11-09 16:50:20 +09:00 committed by Hermet Park
parent 14c1562b36
commit 097e10fea4

View file

@ -41,6 +41,8 @@ struct SwTask : Task
Array<RenderData> clips; Array<RenderData> clips;
uint32_t opacity; uint32_t opacity;
SwBBox bbox = {{0, 0}, {0, 0}}; //Whole Rendering Region SwBBox bbox = {{0, 0}, {0, 0}}; //Whole Rendering Region
bool pushed = false; //Pushed into task list?
bool disposed = false; //Disposed task?
RenderRegion bounds() const RenderRegion bounds() const
{ {
@ -249,7 +251,14 @@ SwRenderer::~SwRenderer()
bool SwRenderer::clear() bool SwRenderer::clear()
{ {
for (auto task = tasks.data; task < (tasks.data + tasks.count); ++task) (*task)->done(); for (auto task = tasks.data; task < (tasks.data + tasks.count); ++task) {
if ((*task)->disposed) {
delete(*task);
} else {
(*task)->done();
(*task)->pushed = false;
}
}
tasks.clear(); tasks.clear();
if (!sharedMpool) mpoolClear(mpool); if (!sharedMpool) mpoolClear(mpool);
@ -328,7 +337,11 @@ bool SwRenderer::postRender()
rasterUnpremultiply(surface); rasterUnpremultiply(surface);
} }
for (auto task = tasks.data; task < (tasks.data + tasks.count); ++task) {
(*task)->pushed = false;
}
tasks.clear(); tasks.clear();
clearCompositors(); clearCompositors();
return true; return true;
} }
@ -543,7 +556,9 @@ bool SwRenderer::dispose(RenderData data)
if (!task) return true; if (!task) return true;
task->done(); task->done();
task->dispose(); task->dispose();
delete(task);
if (task->pushed) task->disposed = true;
else delete(task);
return true; return true;
} }
@ -582,7 +597,11 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
task->bbox.max.x = min(static_cast<SwCoord>(surface->w), static_cast<SwCoord>(vport.x + vport.w)); task->bbox.max.x = min(static_cast<SwCoord>(surface->w), static_cast<SwCoord>(vport.x + vport.w));
task->bbox.max.y = min(static_cast<SwCoord>(surface->h), static_cast<SwCoord>(vport.y + vport.h)); task->bbox.max.y = min(static_cast<SwCoord>(surface->h), static_cast<SwCoord>(vport.y + vport.h));
tasks.push(task); if (!task->pushed) {
task->pushed = true;
tasks.push(task);
}
TaskScheduler::request(task); TaskScheduler::request(task);
return task; return task;