mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-22 07:51:28 +00:00
common sw_engine: apply partial composition.
Introduce RendererMethod::renderRegion() to return acutal drawing region info. That is used by scene composition to composite actual partial drawing region for better performance. @Issues: 173
This commit is contained in:
parent
e3eff97fac
commit
64d3897816
13 changed files with 118 additions and 48 deletions
|
@ -73,6 +73,12 @@ bool GlRenderer::sync()
|
|||
}
|
||||
|
||||
|
||||
bool GlRenderer::renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::preRender()
|
||||
{
|
||||
if (mRenderTasks.size() == 0)
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
bool render(const Shape& shape, void *data) override;
|
||||
bool render(const Picture& picture, void *data) override;
|
||||
bool postRender() override;
|
||||
bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||
bool sync() override;
|
||||
bool clear() override;
|
||||
|
|
|
@ -207,7 +207,7 @@ struct SwShape
|
|||
SwFill* fill = nullptr;
|
||||
SwRleData* rle = nullptr;
|
||||
SwRleData* strokeRle = nullptr;
|
||||
SwBBox bbox;
|
||||
SwBBox bbox; //keep it boundary without stroke region. Using for optimal filling.
|
||||
|
||||
bool rect; //Fast Track: Othogonal rectangle?
|
||||
};
|
||||
|
@ -217,7 +217,6 @@ struct SwImage
|
|||
SwOutline* outline = nullptr;
|
||||
SwRleData* rle = nullptr;
|
||||
uint32_t* data = nullptr;
|
||||
SwBBox bbox;
|
||||
uint32_t w, h;
|
||||
};
|
||||
|
||||
|
@ -277,12 +276,12 @@ SwPoint mathTransform(const Point* to, const Matrix* transform);
|
|||
|
||||
void shapeReset(SwShape* shape);
|
||||
bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform);
|
||||
bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform);
|
||||
bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
|
||||
bool shapePrepared(SwShape* shape);
|
||||
bool shapeGenRle(SwShape* shape, const Shape* sdata, const SwSize& clip, bool antiAlias, bool hasComposite);
|
||||
void shapeDelOutline(SwShape* shape, uint32_t tid);
|
||||
void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
|
||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip);
|
||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip, SwBBox& bbox);
|
||||
void shapeFree(SwShape* shape);
|
||||
void shapeDelStroke(SwShape* shape);
|
||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, bool ctable);
|
||||
|
@ -294,9 +293,9 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
|
|||
SwOutline* strokeExportOutline(SwStroke* stroke, unsigned tid);
|
||||
void strokeFree(SwStroke* stroke);
|
||||
|
||||
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform);
|
||||
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox);
|
||||
bool imagePrepared(SwImage* image);
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite);
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, SwBBox& bbox, bool antiAlias, bool hasComposite);
|
||||
void imageDelOutline(SwImage* image, uint32_t tid);
|
||||
void imageReset(SwImage* image);
|
||||
bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform);
|
||||
|
@ -325,7 +324,7 @@ void mpoolRetStrokeOutline(unsigned idx);
|
|||
bool rasterCompositor(SwSurface* surface);
|
||||
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
|
||||
bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, uint8_t opacity);
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, SwBBox& bbox, uint8_t opacity);
|
||||
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
bool rasterClear(SwSurface* surface);
|
||||
|
||||
|
|
|
@ -90,13 +90,13 @@ static bool _checkValid(const SwOutline* outline, const SwBBox& bbox, const SwSi
|
|||
/************************************************************************/
|
||||
|
||||
|
||||
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform)
|
||||
bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox)
|
||||
{
|
||||
if (!imageGenOutline(image, pdata, tid, transform)) return false;
|
||||
|
||||
if (!_updateBBox(image->outline, image->bbox, clip)) return false;
|
||||
if (!_updateBBox(image->outline, bbox, clip)) return false;
|
||||
|
||||
if (!_checkValid(image->outline, image->bbox, clip)) return false;
|
||||
if (!_checkValid(image->outline, bbox, clip)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -108,9 +108,9 @@ bool imagePrepared(SwImage* image)
|
|||
}
|
||||
|
||||
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, bool antiAlias, bool hasComposite)
|
||||
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwSize& clip, SwBBox& bbox, bool antiAlias, bool hasComposite)
|
||||
{
|
||||
if ((image->rle = rleRender(image->rle, image->outline, image->bbox, clip, antiAlias))) return true;
|
||||
if ((image->rle = rleRender(image->rle, image->outline, bbox, clip, antiAlias))) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -127,7 +127,6 @@ void imageReset(SwImage* image)
|
|||
{
|
||||
rleReset(image->rle);
|
||||
image->rle = nullptr;
|
||||
_initBBox(image->bbox);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -498,7 +498,7 @@ bool rasterClear(SwSurface* surface)
|
|||
}
|
||||
|
||||
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, uint8_t opacity)
|
||||
bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, SwBBox& bbox, uint8_t opacity)
|
||||
{
|
||||
Matrix invTransform;
|
||||
|
||||
|
@ -512,11 +512,11 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, ui
|
|||
else {
|
||||
// Fast track
|
||||
if (_identify(transform)) {
|
||||
return _rasterImage(surface, image->data, image->w, image->h, image->bbox);
|
||||
return _rasterImage(surface, image->data, image->w, image->h, bbox);
|
||||
}
|
||||
else {
|
||||
if (opacity < 255) return _rasterTranslucentImage(surface, image->data, image->w, image->h, opacity, image->bbox, &invTransform);
|
||||
return _rasterImage(surface, image->data, image->w, image->h, image->bbox, &invTransform);
|
||||
if (opacity < 255) return _rasterTranslucentImage(surface, image->data, image->w, image->h, opacity, bbox, &invTransform);
|
||||
return _rasterImage(surface, image->data, image->w, image->h, bbox, &invTransform);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ struct SwComposite
|
|||
SwSurface surface;
|
||||
SwSurface* recover;
|
||||
SwImage image;
|
||||
SwBBox bbox;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
|
@ -46,6 +47,15 @@ struct SwTask : Task
|
|||
RenderUpdateFlag flags = RenderUpdateFlag::None;
|
||||
Array<Composite> compList;
|
||||
uint32_t opacity;
|
||||
SwBBox bbox = {{0, 0}, {0, 0}}; //Whole Rendering Region
|
||||
|
||||
void bounds(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
if (x) *x = bbox.min.x;
|
||||
if (y) *y = bbox.min.y;
|
||||
if (w) *w = bbox.max.x - bbox.min.x;
|
||||
if (h) *h = bbox.max.y - bbox.min.y;
|
||||
}
|
||||
|
||||
virtual bool dispose() = 0;
|
||||
};
|
||||
|
@ -86,7 +96,7 @@ struct SwShapeTask : SwTask
|
|||
bool renderShape = (alpha > 0 || sdata->fill());
|
||||
if (renderShape || strokeAlpha) {
|
||||
shapeReset(&shape);
|
||||
if (!shapePrepare(&shape, sdata, tid, clip, transform)) goto end;
|
||||
if (!shapePrepare(&shape, sdata, tid, clip, transform, bbox)) goto end;
|
||||
if (renderShape) {
|
||||
/* We assume that if stroke width is bigger than 2,
|
||||
shape outline below stroke could be full covered by stroke drawing.
|
||||
|
@ -114,7 +124,7 @@ struct SwShapeTask : SwTask
|
|||
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
|
||||
if (strokeAlpha > 0) {
|
||||
shapeResetStroke(&shape, sdata, transform);
|
||||
if (!shapeGenStrokeRle(&shape, sdata, tid, transform, clip)) goto end;
|
||||
if (!shapeGenStrokeRle(&shape, sdata, tid, transform, clip, bbox)) goto end;
|
||||
++addStroking;
|
||||
} else {
|
||||
shapeDelStroke(&shape);
|
||||
|
@ -167,11 +177,11 @@ struct SwImageTask : SwTask
|
|||
|
||||
if (prepareImage) {
|
||||
imageReset(&image);
|
||||
if (!imagePrepare(&image, pdata, tid, clip, transform)) goto end;
|
||||
if (!imagePrepare(&image, pdata, tid, clip, transform, bbox)) goto end;
|
||||
|
||||
//Composition?
|
||||
if (compList.count > 0) {
|
||||
if (!imageGenRle(&image, pdata, clip, false, true)) goto end;
|
||||
if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
|
||||
if (image.rle) {
|
||||
for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
|
||||
if ((*comp).method == CompositeMethod::ClipPath) {
|
||||
|
@ -274,12 +284,21 @@ bool SwRenderer::postRender()
|
|||
}
|
||||
|
||||
|
||||
bool SwRenderer::renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
static_cast<SwTask*>(data)->bounds(x, y, w, h);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data)
|
||||
{
|
||||
auto task = static_cast<SwImageTask*>(data);
|
||||
task->done();
|
||||
|
||||
return rasterImage(surface, &task->image, task->transform, task->opacity);
|
||||
return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity);
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,16 +335,10 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
|
|||
if (x + w > surface->w) w = (surface->w - x);
|
||||
if (y + h > surface->h) h = (surface->h - y);
|
||||
|
||||
//FIXME: Should be removed if xywh is proper.
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = surface->w;
|
||||
h = surface->h;
|
||||
|
||||
comp->image.bbox.min.x = x;
|
||||
comp->image.bbox.min.y = y;
|
||||
comp->image.bbox.max.x = x + w;
|
||||
comp->image.bbox.max.y = y + h;
|
||||
comp->bbox.min.x = x;
|
||||
comp->bbox.min.y = y;
|
||||
comp->bbox.max.x = x + w;
|
||||
comp->bbox.max.y = y + h;
|
||||
comp->image.w = surface->w;
|
||||
comp->image.h = surface->h;
|
||||
|
||||
|
@ -362,7 +375,7 @@ bool SwRenderer::endComposite(void* p, uint32_t opacity)
|
|||
//Recover render target
|
||||
surface = comp->recover;
|
||||
|
||||
auto ret = rasterImage(surface, &comp->image, nullptr, opacity);
|
||||
auto ret = rasterImage(surface, &comp->image, nullptr, comp->bbox, opacity);
|
||||
|
||||
comp->valid = true;
|
||||
|
||||
|
@ -382,12 +395,8 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
|
|||
|
||||
//Do Composition
|
||||
if (task->compStroking) {
|
||||
//Add stroke size to bounding box.
|
||||
auto strokeWidth = static_cast<SwCoord>(ceilf(task->sdata->strokeWidth() * 0.5f));
|
||||
auto x = task->shape.bbox.min.x - strokeWidth;
|
||||
auto y = task->shape.bbox.min.y - strokeWidth;
|
||||
auto w = task->shape.bbox.max.x + strokeWidth - x;
|
||||
auto h = task->shape.bbox.max.y + strokeWidth - y;
|
||||
uint32_t x, y, w, h;
|
||||
task->bounds(&x, &y, &w, &h);
|
||||
ctx = beginComposite(x, y, w, h);
|
||||
opacity = 255;
|
||||
//No Composition
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
bool dispose(void *data) override;
|
||||
bool preRender() override;
|
||||
bool postRender() override;
|
||||
bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
|
||||
bool clear() override;
|
||||
bool render(const Shape& shape, void *data) override;
|
||||
bool render(const Picture& picture, void *data) override;
|
||||
|
|
|
@ -420,7 +420,7 @@ bool _fastTrack(const SwOutline* outline)
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform)
|
||||
bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform, SwBBox& bbox)
|
||||
{
|
||||
if (!shapeGenOutline(shape, sdata, tid, transform)) return false;
|
||||
|
||||
|
@ -428,6 +428,8 @@ bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize
|
|||
|
||||
if (!_checkValid(shape->outline, shape->bbox, clip)) return false;
|
||||
|
||||
bbox = shape->bbox;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -588,7 +590,7 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor
|
|||
}
|
||||
|
||||
|
||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip)
|
||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip, SwBBox& bbox)
|
||||
{
|
||||
SwOutline* shapeOutline = nullptr;
|
||||
SwOutline* strokeOutline = nullptr;
|
||||
|
@ -619,7 +621,6 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const M
|
|||
goto fail;
|
||||
}
|
||||
|
||||
SwBBox bbox;
|
||||
_updateBBox(strokeOutline, bbox);
|
||||
|
||||
if (!_checkValid(strokeOutline, bbox, clip)) {
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace tvg
|
|||
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag) = 0; //Return engine data if it has.
|
||||
virtual bool render(RenderMethod& renderer) = 0;
|
||||
virtual bool bounds(float* x, float* y, float* w, float* h) const = 0;
|
||||
virtual bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const = 0;
|
||||
virtual Paint* duplicate() = 0;
|
||||
};
|
||||
|
||||
|
@ -125,6 +126,11 @@ namespace tvg
|
|||
return smethod->bounds(x, y, w, h);
|
||||
}
|
||||
|
||||
bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const
|
||||
{
|
||||
return smethod->bounds(renderer, x, y, w, h);
|
||||
}
|
||||
|
||||
bool dispose(RenderMethod& renderer)
|
||||
{
|
||||
if (compTarget) compTarget->pImpl->dispose(renderer);
|
||||
|
@ -212,6 +218,11 @@ namespace tvg
|
|||
return inst->bounds(x, y, w, h);
|
||||
}
|
||||
|
||||
bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const override
|
||||
{
|
||||
return inst->bounds(renderer, x, y, w, h);
|
||||
}
|
||||
|
||||
bool dispose(RenderMethod& renderer) override
|
||||
{
|
||||
return inst->dispose(renderer);
|
||||
|
|
|
@ -153,6 +153,13 @@ struct Picture::Impl
|
|||
return paint->pImpl->bounds(x, y, w, h);
|
||||
}
|
||||
|
||||
bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
if (edata) return renderer.renderRegion(edata, x, y, w, h);
|
||||
if (paint) paint->pImpl->bounds(renderer, x, y, w, h);
|
||||
return false;
|
||||
}
|
||||
|
||||
Result load(const string& path)
|
||||
{
|
||||
if (loader) loader->close();
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
virtual bool render(const Shape& shape, void *data) = 0;
|
||||
virtual bool render(const Picture& picture, void *data) = 0;
|
||||
virtual bool postRender() = 0;
|
||||
virtual bool renderRegion(void* data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) = 0;
|
||||
virtual bool clear() = 0;
|
||||
virtual bool sync() = 0;
|
||||
};
|
||||
|
|
|
@ -63,17 +63,15 @@ struct Scene::Impl
|
|||
return edata;
|
||||
}
|
||||
|
||||
bool render(RenderMethod &renderer)
|
||||
bool render(RenderMethod& renderer)
|
||||
{
|
||||
void* ctx = nullptr;
|
||||
|
||||
//Half translucent. This requires intermediate composition.
|
||||
if (opacity < 255 && opacity > 0) {
|
||||
//FIXME: Get Render Boundary of Shapes.
|
||||
//float x, y, w, h;
|
||||
//if (!bounds(&x, &y, &w, &h)) return false;
|
||||
//ctx = renderer.beginComposite(roundf(x), roundf(y), roundf(w), roundf(h));
|
||||
ctx = renderer.beginComposite(0, 0, 0, 0);
|
||||
uint32_t x, y, w, h;
|
||||
if (!bounds(renderer, &x, &y, &w, &h)) return false;
|
||||
ctx = renderer.beginComposite(x, y, w, h);
|
||||
}
|
||||
|
||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||
|
@ -85,6 +83,38 @@ struct Scene::Impl
|
|||
return true;
|
||||
}
|
||||
|
||||
bool bounds(RenderMethod& renderer, uint32_t* px, uint32_t* py, uint32_t* pw, uint32_t* ph)
|
||||
{
|
||||
if (paints.count == 0) return false;
|
||||
|
||||
uint32_t x1 = UINT32_MAX;
|
||||
uint32_t y1 = UINT32_MAX;
|
||||
uint32_t x2 = 0;
|
||||
uint32_t y2 = 0;
|
||||
|
||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||
uint32_t x = UINT32_MAX;
|
||||
uint32_t y = UINT32_MAX;
|
||||
uint32_t w = 0;
|
||||
uint32_t h = 0;
|
||||
|
||||
if (!(*paint)->pImpl->bounds(renderer, &x, &y, &w, &h)) continue;
|
||||
|
||||
//Merge regions
|
||||
if (x < x1) x1 = x;
|
||||
if (x2 < x + w) x2 = (x + w);
|
||||
if (y < y1) y1 = y;
|
||||
if (y2 < y + h) y2 = (y + h);
|
||||
}
|
||||
|
||||
if (px) *px = x1;
|
||||
if (py) *py = y1;
|
||||
if (pw) *pw = (x2 - x1);
|
||||
if (ph) *ph = (y2 - y1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bounds(float* px, float* py, float* pw, float* ph)
|
||||
{
|
||||
if (paints.count == 0) return false;
|
||||
|
|
|
@ -230,6 +230,11 @@ struct Shape::Impl
|
|||
return this->edata;
|
||||
}
|
||||
|
||||
bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
|
||||
{
|
||||
return renderer.renderRegion(edata, x, y, w, h);
|
||||
}
|
||||
|
||||
bool bounds(float* x, float* y, float* w, float* h)
|
||||
{
|
||||
auto ret = path.bounds(x, y, w, h);
|
||||
|
|
Loading…
Add table
Reference in a new issue