sw_engine renderer: refactoring code & optimize composition.

Move the prepare stage of shape & stroking composition stage to a separate function
this returns SwImage to use in composite stage.

Also clear partial region buffer since we know composition area.
This commit is contained in:
Hermet Park 2020-12-03 15:29:40 +09:00 committed by Hermet Park
parent 3881f20e9c
commit ceb14e73a8
3 changed files with 56 additions and 37 deletions

View file

@ -91,6 +91,7 @@ static SwBBox _clipRegion(Surface* surface, SwBBox& in)
return bbox;
}
static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
{
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
@ -502,7 +503,7 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, ui
Matrix invTransform;
if (transform) _inverse(transform, &invTransform);
else invTransform = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
else invTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
if (image->rle) {
if (opacity < 255) return _rasterTranslucentImageRle(surface, image->rle, image->data, image->w, image->h, opacity, &invTransform);

View file

@ -268,6 +268,54 @@ bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data)
}
bool SwRenderer::prepareComposite(const SwShapeTask* task, SwImage* image)
{
if (!compSurface) {
compSurface = new SwSurface;
if (!compSurface) return false;
*compSurface = *mainSurface;
compSurface->buffer = (uint32_t*) malloc(sizeof(uint32_t) * mainSurface->w * mainSurface->h);
if (!compSurface->buffer) {
delete(compSurface);
compSurface = nullptr;
return false;
}
}
//Setup SwImage to return
image->data = compSurface->buffer;
image->w = compSurface->w;
image->h = compSurface->h;
image->rle = nullptr;
//Add stroke size to bounding box.
auto strokeWidth = static_cast<SwCoord>(ceilf(task->sdata->strokeWidth() * 0.5f));
image->bbox.min.x = task->shape.bbox.min.x - strokeWidth;
image->bbox.min.y = task->shape.bbox.min.y - strokeWidth;
image->bbox.max.x = task->shape.bbox.max.x + strokeWidth;
image->bbox.max.y = task->shape.bbox.max.y + strokeWidth;
if (image->bbox.min.x < 0) image->bbox.min.x = 0;
if (image->bbox.min.y < 0) image->bbox.min.y = 0;
if (image->bbox.max.x > image->w) image->bbox.max.x = image->w;
if (image->bbox.max.y > image->h) image->bbox.max.y = image->h;
//We know partial clear region
compSurface->buffer = compSurface->buffer + (compSurface->stride * image->bbox.min.y) + image->bbox.min.x;
compSurface->w = image->bbox.max.x - image->bbox.min.x;
compSurface->h = image->bbox.max.y - image->bbox.min.y;
rasterClear(compSurface);
//Recover context
compSurface->buffer = image->data;
compSurface->w = image->w;
compSurface->h = image->h;
return true;
}
bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
{
auto task = static_cast<SwShapeTask*>(data);
@ -276,32 +324,18 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
if (task->opacity == 0) return true;
SwSurface* renderTarget;
SwImage image;
uint32_t opacity;
bool composite;
//Do Composition
if (task->compStroking) {
//Setup Composition Surface
if (!compSurface) {
compSurface = new SwSurface;
if (!compSurface) return false;
*compSurface = *mainSurface;
compSurface->buffer = (uint32_t*) malloc(sizeof(uint32_t) * mainSurface->stride * mainSurface->h);
if (!compSurface->buffer) {
delete(compSurface);
compSurface = nullptr;
return false;
}
}
rasterClear(compSurface);
if (!prepareComposite(task, &image)) return false;
renderTarget = compSurface;
opacity = 255;
composite = true;
//No Composition
} else {
renderTarget = mainSurface;
opacity = task->opacity;
composite = false;
}
//Main raster stage
@ -321,26 +355,7 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
if (a > 0) rasterStroke(renderTarget, &task->shape, r, g, b, a);
//Composition (Shape + Stroke) stage
if (composite) {
SwImage image;
image.data = compSurface->buffer;
image.w = compSurface->w;
image.h = compSurface->h;
image.rle = nullptr;
//Add stroke size to bounding box.
auto strokeWidth = static_cast<SwCoord>(ceilf(task->sdata->strokeWidth() * 0.5f));
image.bbox.min.x = task->shape.bbox.min.x - strokeWidth;
image.bbox.min.y = task->shape.bbox.min.y - strokeWidth;
image.bbox.max.x = task->shape.bbox.max.x + strokeWidth;
image.bbox.max.y = task->shape.bbox.max.y + strokeWidth;
if (image.bbox.min.x < 0) image.bbox.min.x = 0;
if (image.bbox.min.y < 0) image.bbox.min.y = 0;
if (image.bbox.max.x > compSurface->w) image.bbox.max.x = compSurface->w;
if (image.bbox.max.y > compSurface->h) image.bbox.max.y = compSurface->h;
rasterImage(mainSurface, &image, nullptr, task->opacity);
}
if (task->compStroking) rasterImage(mainSurface, &image, nullptr, task->opacity);
return true;
}

View file

@ -27,6 +27,8 @@
struct SwSurface;
struct SwTask;
struct SwShapeTask;
struct SwImage;
namespace tvg
{
@ -56,6 +58,7 @@ private:
SwRenderer(){};
~SwRenderer();
bool prepareComposite(const SwShapeTask* task, SwImage* image);
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags);
};