sw_engine renderer: code refactoring.

Unify Shape+Stroke composition with CompositeCtx which is added for Scene Composition

This fixes clipping issue as well.

@Issues: 164
This commit is contained in:
Hermet Park 2020-12-08 20:26:06 +09:00 committed by Hermet Park
parent e794c678ec
commit 924490a7a5
3 changed files with 44 additions and 97 deletions

View file

@ -62,9 +62,9 @@ void tvgDrawCmds(tvg::Canvas* canvas)
//Circle //Circle
auto shape4 = tvg::Shape::gen(); auto shape4 = tvg::Shape::gen();
auto cx = 550.0f; auto cx = 150.0f;
auto cy = 550.0f; auto cy = 150.0f;
auto radius = 125.0f; auto radius = 50.0f;
auto halfRadius = radius * 0.552284f; auto halfRadius = radius * 0.552284f;
//Append Paths //Append Paths
@ -77,6 +77,7 @@ void tvgDrawCmds(tvg::Canvas* canvas)
shape4->stroke(10); shape4->stroke(10);
shape4->stroke(0, 0, 255, 255); shape4->stroke(0, 0, 255, 255);
shape4->opacity(200); shape4->opacity(200);
shape4->scale(3);
scene2->push(move(shape4)); scene2->push(move(shape4));
//Draw the Scene onto the Canvas //Draw the Scene onto the Canvas

View file

@ -211,7 +211,7 @@ SwRenderer::~SwRenderer()
{ {
clear(); clear();
if (mainSurface) delete(mainSurface); if (surface) delete(surface);
--rendererCnt; --rendererCnt;
if (!initEngine) _termEngine(); if (!initEngine) _termEngine();
@ -237,24 +237,24 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
{ {
if (!buffer || stride == 0 || w == 0 || h == 0) return false; if (!buffer || stride == 0 || w == 0 || h == 0) return false;
if (!mainSurface) { if (!surface) {
mainSurface = new SwSurface; surface = new SwSurface;
if (!mainSurface) return false; if (!surface) return false;
} }
mainSurface->buffer = buffer; surface->buffer = buffer;
mainSurface->stride = stride; surface->stride = stride;
mainSurface->w = w; surface->w = w;
mainSurface->h = h; surface->h = h;
mainSurface->cs = cs; surface->cs = cs;
return rasterCompositor(mainSurface); return rasterCompositor(surface);
} }
bool SwRenderer::preRender() bool SwRenderer::preRender()
{ {
return rasterClear(mainSurface); return rasterClear(surface);
} }
@ -262,13 +262,6 @@ bool SwRenderer::postRender()
{ {
tasks.clear(); tasks.clear();
//Clear Composite Surface
if (compSurface) {
if (compSurface->buffer) free(compSurface->buffer);
delete(compSurface);
}
compSurface = nullptr;
return true; return true;
} }
@ -278,7 +271,7 @@ bool SwRenderer::render(TVG_UNUSED const Picture& picture, void *data)
auto task = static_cast<SwImageTask*>(data); auto task = static_cast<SwImageTask*>(data);
task->done(); task->done();
return rasterImage(mainSurface, &task->image, task->transform, task->opacity); return rasterImage(surface, &task->image, task->transform, task->opacity);
} }
@ -288,7 +281,7 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
if (!ctx) return nullptr; if (!ctx) return nullptr;
//SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H //SwImage, Optimize Me: Surface size from MainSurface(WxH) to Parameter W x H
ctx->image.data = (uint32_t*) malloc(sizeof(uint32_t) * mainSurface->w * mainSurface->h); ctx->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->w * surface->h);
if (!ctx->image.data) { if (!ctx->image.data) {
delete(ctx); delete(ctx);
return nullptr; return nullptr;
@ -297,26 +290,26 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
//Boundary Check //Boundary Check
if (x < 0) x = 0; if (x < 0) x = 0;
if (y < 0) y = 0; if (y < 0) y = 0;
if (x + w > mainSurface->w) w = (mainSurface->w - x); if (x + w > surface->w) w = (surface->w - x);
if (y + h > mainSurface->h) h = (mainSurface->h - y); if (y + h > surface->h) h = (surface->h - y);
//FIXME: Should be removed if xywh is proper. //FIXME: Should be removed if xywh is proper.
x = 0; x = 0;
y = 0; y = 0;
w = mainSurface->w; w = surface->w;
h = mainSurface->h; h = surface->h;
ctx->image.bbox.min.x = x; ctx->image.bbox.min.x = x;
ctx->image.bbox.min.y = y; ctx->image.bbox.min.y = y;
ctx->image.bbox.max.x = x + w; ctx->image.bbox.max.x = x + w;
ctx->image.bbox.max.y = y + h; ctx->image.bbox.max.y = y + h;
ctx->image.w = mainSurface->w; ctx->image.w = surface->w;
ctx->image.h = mainSurface->h; ctx->image.h = surface->h;
//Inherits attributes from main surface //Inherits attributes from main surface
ctx->surface.comp = mainSurface->comp; ctx->surface.comp = surface->comp;
ctx->surface.stride = mainSurface->w; ctx->surface.stride = surface->w;
ctx->surface.cs = mainSurface->cs; ctx->surface.cs = surface->cs;
//We know partial clear region //We know partial clear region
ctx->surface.buffer = ctx->image.data + (ctx->surface.stride * y + x); ctx->surface.buffer = ctx->image.data + (ctx->surface.stride * y + x);
@ -331,8 +324,8 @@ void* SwRenderer::beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
ctx->surface.h = ctx->image.h; ctx->surface.h = ctx->image.h;
//Switch render target //Switch render target
ctx->recover = mainSurface; ctx->recover = surface;
mainSurface = &ctx->surface; surface = &ctx->surface;
return ctx; return ctx;
} }
@ -344,9 +337,9 @@ bool SwRenderer::endComposite(void* p, uint32_t opacity)
auto ctx = static_cast<CompositeCtx*>(p); auto ctx = static_cast<CompositeCtx*>(p);
//Recover render target //Recover render target
mainSurface = ctx->recover; surface = ctx->recover;
auto ret = rasterImage(mainSurface, &ctx->image, nullptr, opacity); auto ret = rasterImage(surface, &ctx->image, nullptr, opacity);
//Free resources //Free resources
free(ctx->image.data); free(ctx->image.data);
@ -356,54 +349,6 @@ bool SwRenderer::endComposite(void* p, uint32_t opacity)
} }
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) bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
{ {
auto task = static_cast<SwShapeTask*>(data); auto task = static_cast<SwShapeTask*>(data);
@ -411,18 +356,21 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
if (task->opacity == 0) return true; if (task->opacity == 0) return true;
SwSurface* renderTarget;
SwImage image;
uint32_t opacity; uint32_t opacity;
void *ctx = nullptr;
//Do Composition //Do Composition
if (task->compStroking) { if (task->compStroking) {
if (!prepareComposite(task, &image)) return false; //Add stroke size to bounding box.
renderTarget = compSurface; 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;
ctx = beginComposite(x, y, w, h);
opacity = 255; opacity = 255;
//No Composition //No Composition
} else { } else {
renderTarget = mainSurface;
opacity = task->opacity; opacity = task->opacity;
} }
@ -431,19 +379,19 @@ bool SwRenderer::render(TVG_UNUSED const Shape& shape, void *data)
if (auto fill = task->sdata->fill()) { if (auto fill = task->sdata->fill()) {
//FIXME: pass opacity to apply gradient fill? //FIXME: pass opacity to apply gradient fill?
rasterGradientShape(renderTarget, &task->shape, fill->id()); rasterGradientShape(surface, &task->shape, fill->id());
} else{ } else{
task->sdata->fillColor(&r, &g, &b, &a); task->sdata->fillColor(&r, &g, &b, &a);
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255); a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
if (a > 0) rasterSolidShape(renderTarget, &task->shape, r, g, b, a); if (a > 0) rasterSolidShape(surface, &task->shape, r, g, b, a);
} }
task->sdata->strokeColor(&r, &g, &b, &a); task->sdata->strokeColor(&r, &g, &b, &a);
a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255); a = static_cast<uint8_t>((opacity * (uint32_t) a) / 255);
if (a > 0) rasterStroke(renderTarget, &task->shape, r, g, b, a); if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a);
//Composition (Shape + Stroke) stage //Composition (Shape + Stroke) stage
if (task->compStroking) rasterImage(mainSurface, &image, nullptr, task->opacity); if (task->compStroking) endComposite(ctx, task->opacity);
return true; return true;
} }
@ -480,7 +428,7 @@ void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, u
} }
task->opacity = opacity; task->opacity = opacity;
task->surface = mainSurface; task->surface = surface;
task->flags = flags; task->flags = flags;
tasks.push_back(task); tasks.push_back(task);

View file

@ -54,14 +54,12 @@ public:
static bool term(); static bool term();
private: private:
SwSurface* mainSurface = nullptr; SwSurface* surface = nullptr;
SwSurface* compSurface = nullptr; //Composition Surface to use temporarily in the intermediate rendering
vector<SwTask*> tasks; vector<SwTask*> tasks;
SwRenderer(){}; SwRenderer(){};
~SwRenderer(); ~SwRenderer();
bool prepareComposite(const SwShapeTask* task, SwImage* image);
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags); void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags);
}; };