common sw_engine: code refactoring

Renamed internal interfaces.

We need both blender & compositor interfaces.

Renamed SwCompositor -> SwBlender which is for pixel joining methods.

Added (SwCompositor, Compositor) which is designed for compositing images.
This commit is contained in:
Hermet Park 2020-12-25 20:44:07 +09:00
parent c1e36bcb01
commit 7d9023ac5c
10 changed files with 137 additions and 131 deletions

View file

@ -102,27 +102,27 @@ bool GlRenderer::postRender()
} }
void* GlRenderer::addCompositor(TVG_UNUSED CompositeMethod method, TVG_UNUSED uint32_t x, TVG_UNUSED uint32_t y, TVG_UNUSED uint32_t w, TVG_UNUSED uint32_t h, TVG_UNUSED uint32_t opacity) Compositor* GlRenderer::addCompositor(TVG_UNUSED uint32_t x, TVG_UNUSED uint32_t y, TVG_UNUSED uint32_t w, TVG_UNUSED uint32_t h)
{ {
//TODO: Prepare frameBuffer & Setup render target for composition //TODO: Prepare frameBuffer & Setup render target for composition
return nullptr; return nullptr;
} }
bool GlRenderer::delCompositor(TVG_UNUSED void* cmp) bool GlRenderer::delCompositor(TVG_UNUSED Compositor* cmp)
{ {
//TODO: delete the given compositor and restore the context //TODO: delete the given compositor and restore the context
return false; return false;
} }
bool GlRenderer::renderImage(TVG_UNUSED void* data, TVG_UNUSED void* cmp) bool GlRenderer::renderImage(TVG_UNUSED void* data, TVG_UNUSED Compositor* cmp)
{ {
return false; return false;
} }
bool GlRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp) bool GlRenderer::renderShape(RenderData data, TVG_UNUSED Compositor* cmp)
{ {
auto sdata = static_cast<GlShape*>(data); auto sdata = static_cast<GlShape*>(data);
if (!sdata) return false; if (!sdata) return false;

View file

@ -33,11 +33,11 @@ public:
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
bool dispose(RenderData data) override; bool dispose(RenderData data) override;
void* addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) override; Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
bool delCompositor(void* cmp) override; bool delCompositor(Compositor* cmp) override;
bool preRender() override; bool preRender() override;
bool renderShape(RenderData data, void* cmp) override; bool renderShape(RenderData data, Compositor* cmp) override;
bool renderImage(RenderData data, void* cmp) override; bool renderImage(RenderData data, Compositor* cmp) override;
bool postRender() override; bool postRender() override;
bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override; bool renderRegion(RenderData 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 target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);

View file

@ -220,7 +220,7 @@ struct SwImage
uint32_t w, h; uint32_t w, h;
}; };
struct SwCompositor struct SwBlender
{ {
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
uint32_t (*alpha)(uint32_t rgba); uint32_t (*alpha)(uint32_t rgba);
@ -228,7 +228,7 @@ struct SwCompositor
struct SwSurface : Surface struct SwSurface : Surface
{ {
SwCompositor comp; SwBlender blender;
}; };
static inline SwCoord TO_SWCOORD(float val) static inline SwCoord TO_SWCOORD(float val)

View file

@ -52,7 +52,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac
auto g = ALPHA_MULTIPLY(pColors->g, pColors->a); auto g = ALPHA_MULTIPLY(pColors->g, pColors->a);
auto b = ALPHA_MULTIPLY(pColors->b, pColors->a); auto b = ALPHA_MULTIPLY(pColors->b, pColors->a);
auto rgba = surface->comp.join(r, g, b, pColors->a); auto rgba = surface->blender.join(r, g, b, pColors->a);
auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE); auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE);
auto pos = 1.5f * inc; auto pos = 1.5f * inc;
uint32_t i = 0; uint32_t i = 0;
@ -75,7 +75,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac
auto g = ALPHA_MULTIPLY(next->g, next->a); auto g = ALPHA_MULTIPLY(next->g, next->a);
auto b = ALPHA_MULTIPLY(next->b, next->a); auto b = ALPHA_MULTIPLY(next->b, next->a);
auto rgba2 = surface->comp.join(r, g, b, next->a); auto rgba2 = surface->blender.join(r, g, b, next->a);
while (pos < next->offset && i < GRADIENT_STOP_SIZE) { while (pos < next->offset && i < GRADIENT_STOP_SIZE) {
auto t = (pos - curr->offset) * delta; auto t = (pos - curr->offset) * delta;

View file

@ -97,7 +97,7 @@ static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uin
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x; auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto ialpha = 255 - surface->comp.alpha(color); auto ialpha = 255 - surface->blender.alpha(color);
for (uint32_t y = 0; y < h; ++y) { for (uint32_t y = 0; y < h; ++y) {
auto dst = &buffer[y * surface->stride]; auto dst = &buffer[y * surface->stride];
@ -133,7 +133,7 @@ static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t c
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
else src = color; else src = color;
auto ialpha = 255 - surface->comp.alpha(src); auto ialpha = 255 - surface->blender.alpha(src);
for (uint32_t i = 0; i < span->len; ++i) { for (uint32_t i = 0; i < span->len; ++i) {
dst[i] = src + ALPHA_BLEND(dst[i], ialpha); dst[i] = src + ALPHA_BLEND(dst[i], ialpha);
} }
@ -157,7 +157,7 @@ static bool _rasterTranslucentImageRle(SwSurface* surface, SwRleData* rle, uint3
if (rX >= w || rY >= h) continue; if (rX >= w || rY >= h) continue;
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity); auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
auto src = ALPHA_BLEND(img[rY * w + rX], alpha); //TODO: need to use image's stride auto src = ALPHA_BLEND(img[rY * w + rX], alpha); //TODO: need to use image's stride
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); *dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
} }
++span; ++span;
} }
@ -178,7 +178,7 @@ static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, u
auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + ey2)); auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + ey2));
if (rX >= w || rY >= h) continue; if (rX >= w || rY >= h) continue;
auto src = ALPHA_BLEND(img[rY * w + rX], span->coverage); //TODO: need to use image's stride auto src = ALPHA_BLEND(img[rY * w + rX], span->coverage); //TODO: need to use image's stride
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); *dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
} }
++span; ++span;
} }
@ -197,7 +197,7 @@ static bool _rasterTranslucentImage(SwSurface* surface, uint32_t *img, uint32_t
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2)); auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2));
if (rX >= w || rY >= h) continue; if (rX >= w || rY >= h) continue;
auto src = ALPHA_BLEND(img[rX + (rY * w)], opacity); //TODO: need to use image's stride auto src = ALPHA_BLEND(img[rX + (rY * w)], opacity); //TODO: need to use image's stride
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); *dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
} }
} }
return true; return true;
@ -210,7 +210,7 @@ static bool _rasterImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t
auto dst = &surface->buffer[y * surface->stride + region.min.x]; auto dst = &surface->buffer[y * surface->stride + region.min.x];
auto src = img + region.min.x + (y * w); //TODO: need to use image's stride auto src = img + region.min.x + (y * w); //TODO: need to use image's stride
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(*src)); *dst = *src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(*src));
} }
} }
return true; return true;
@ -228,7 +228,7 @@ static bool _rasterImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t
auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2)); auto rY = static_cast<uint32_t>(roundf(x * invTransform->e21 + ey2));
if (rX >= w || rY >= h) continue; if (rX >= w || rY >= h) continue;
auto src = img[rX + (rY * w)]; //TODO: need to use image's stride auto src = img[rX + (rY * w)]; //TODO: need to use image's stride
*dst = src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(src)); *dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
} }
} }
return true; return true;
@ -276,7 +276,7 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
auto dst = &buffer[y * surface->stride]; auto dst = &buffer[y * surface->stride];
fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w); fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w);
for (uint32_t x = 0; x < w; ++x) { for (uint32_t x = 0; x < w; ++x) {
dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->blender.alpha(tmpBuf[x]));
} }
} }
//Opaque Gradient //Opaque Gradient
@ -307,7 +307,7 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
auto dst = &buffer[y * surface->stride]; auto dst = &buffer[y * surface->stride];
fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w); fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w);
for (uint32_t x = 0; x < w; ++x) { for (uint32_t x = 0; x < w; ++x) {
dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x])); dst[x] = tmpBuf[x] + ALPHA_BLEND(dst[x], 255 - surface->blender.alpha(tmpBuf[x]));
} }
} }
//Opaque Gradient //Opaque Gradient
@ -337,12 +337,12 @@ static bool _rasterLinearGradientRle(SwSurface* surface, SwRleData* rle, const S
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len); fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
if (span->coverage == 255) { if (span->coverage == 255) {
for (uint32_t i = 0; i < span->len; ++i) { for (uint32_t i = 0; i < span->len; ++i) {
dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(buf[i]));
} }
} else { } else {
for (uint32_t i = 0; i < span->len; ++i) { for (uint32_t i = 0; i < span->len; ++i) {
auto tmp = ALPHA_BLEND(buf[i], span->coverage); auto tmp = ALPHA_BLEND(buf[i], span->coverage);
dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(tmp));
} }
} }
++span; ++span;
@ -383,12 +383,12 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S
fillFetchRadial(fill, buf, span->y, span->x, span->len); fillFetchRadial(fill, buf, span->y, span->x, span->len);
if (span->coverage == 255) { if (span->coverage == 255) {
for (uint32_t i = 0; i < span->len; ++i) { for (uint32_t i = 0; i < span->len; ++i) {
dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i])); dst[i] = buf[i] + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(buf[i]));
} }
} else { } else {
for (uint32_t i = 0; i < span->len; ++i) { for (uint32_t i = 0; i < span->len; ++i) {
auto tmp = ALPHA_BLEND(buf[i], span->coverage); auto tmp = ALPHA_BLEND(buf[i], span->coverage);
dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp)); dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(tmp));
} }
} }
++span; ++span;
@ -420,11 +420,11 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S
bool rasterCompositor(SwSurface* surface) bool rasterCompositor(SwSurface* surface)
{ {
if (surface->cs == SwCanvas::ABGR8888) { if (surface->cs == SwCanvas::ABGR8888) {
surface->comp.alpha = _colorAlpha; surface->blender.alpha = _colorAlpha;
surface->comp.join = _abgrJoin; surface->blender.join = _abgrJoin;
} else if (surface->cs == SwCanvas::ARGB8888) { } else if (surface->cs == SwCanvas::ARGB8888) {
surface->comp.alpha = _colorAlpha; surface->blender.alpha = _colorAlpha;
surface->comp.join = _argbJoin; surface->blender.join = _argbJoin;
} else { } else {
//What Color Space ??? //What Color Space ???
return false; return false;
@ -455,7 +455,7 @@ bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g,
g = ALPHA_MULTIPLY(g, a); g = ALPHA_MULTIPLY(g, a);
b = ALPHA_MULTIPLY(b, a); b = ALPHA_MULTIPLY(b, a);
auto color = surface->comp.join(r, g, b, a); auto color = surface->blender.join(r, g, b, a);
//Fast Track //Fast Track
if (shape->rect) { if (shape->rect) {
@ -476,7 +476,7 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint
g = ALPHA_MULTIPLY(g, a); g = ALPHA_MULTIPLY(g, a);
b = ALPHA_MULTIPLY(b, a); b = ALPHA_MULTIPLY(b, a);
auto color = surface->comp.join(r, g, b, a); auto color = surface->blender.join(r, g, b, a);
if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color); if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color);
return _rasterTranslucentRle(surface, shape->strokeRle, color); return _rasterTranslucentRle(surface, shape->strokeRle, color);

View file

@ -30,14 +30,12 @@
static bool initEngine = false; static bool initEngine = false;
static uint32_t rendererCnt = 0; static uint32_t rendererCnt = 0;
struct SwComposite struct SwCompositor : Compositor
{ {
SwSurface surface; SwSurface surface;
SwComposite* recover; SwCompositor* recover;
SwImage image; SwImage image;
SwBBox bbox; SwBBox bbox;
CompositeMethod method;
uint32_t opacity;
bool valid; bool valid;
}; };
@ -67,7 +65,7 @@ struct SwShapeTask : SwTask
{ {
SwShape shape; SwShape shape;
const Shape* sdata = nullptr; const Shape* sdata = nullptr;
bool compStroking; bool cmpStroking;
void run(unsigned tid) override void run(unsigned tid) override
{ {
@ -134,23 +132,23 @@ struct SwShapeTask : SwTask
} }
//Clip Path //Clip Path
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape; auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
//Clip shape rle //Clip shape rle
if (shape.rle) { if (shape.rle) {
if (compShape->rect) rleClipRect(shape.rle, &compShape->bbox); if (clipper->rect) rleClipRect(shape.rle, &clipper->bbox);
else if (compShape->rle) rleClipPath(shape.rle, compShape->rle); else if (clipper->rle) rleClipPath(shape.rle, clipper->rle);
} }
//Clip stroke rle //Clip stroke rle
if (shape.strokeRle) { if (shape.strokeRle) {
if (compShape->rect) rleClipRect(shape.strokeRle, &compShape->bbox); if (clipper->rect) rleClipRect(shape.strokeRle, &clipper->bbox);
else if (compShape->rle) rleClipPath(shape.strokeRle, compShape->rle); else if (clipper->rle) rleClipPath(shape.strokeRle, clipper->rle);
} }
} }
end: end:
shapeDelOutline(&shape, tid); shapeDelOutline(&shape, tid);
if (addStroking == 2 && opacity < 255) compStroking = true; if (addStroking == 2 && opacity < 255) cmpStroking = true;
else compStroking = false; else cmpStroking = false;
} }
bool dispose() override bool dispose() override
@ -182,10 +180,10 @@ struct SwImageTask : SwTask
if (clips.count > 0) { if (clips.count > 0) {
if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end; if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
if (image.rle) { if (image.rle) {
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape; auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
if (compShape->rect) rleClipRect(image.rle, &compShape->bbox); if (clipper->rect) rleClipRect(image.rle, &clipper->bbox);
else if (compShape->rle) rleClipPath(image.rle, compShape->rle); else if (clipper->rle) rleClipPath(image.rle, clipper->rle);
} }
} }
} }
@ -282,7 +280,7 @@ bool SwRenderer::postRender()
} }
bool SwRenderer::renderImage(RenderData data, TVG_UNUSED void* cmp) bool SwRenderer::renderImage(RenderData data, TVG_UNUSED Compositor* cmp)
{ {
auto task = static_cast<SwImageTask*>(data); auto task = static_cast<SwImageTask*>(data);
task->done(); task->done();
@ -293,7 +291,7 @@ bool SwRenderer::renderImage(RenderData data, TVG_UNUSED void* cmp)
} }
bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp) bool SwRenderer::renderShape(RenderData data, TVG_UNUSED Compositor* cmp)
{ {
auto task = static_cast<SwShapeTask*>(data); auto task = static_cast<SwShapeTask*>(data);
task->done(); task->done();
@ -301,15 +299,17 @@ bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
if (task->opacity == 0) return true; if (task->opacity == 0) return true;
uint32_t opacity; uint32_t opacity;
void *cmp2 = nullptr; Compositor* cmp2 = nullptr;
//Do Composition //Do Composition
if (task->compStroking) { if (task->cmpStroking) {
uint32_t x, y, w, h; uint32_t x, y, w, h;
task->bounds(&x, &y, &w, &h); task->bounds(&x, &y, &w, &h);
opacity = 255; opacity = 255;
//CompositeMethod::None is used for a default alpha blending //CompositeMethod::None is used for a default alpha blending
cmp2 = addCompositor(CompositeMethod::None, x, y, w, h, opacity); cmp2 = addCompositor(x, y, w, h);
cmp2->method = CompositeMethod::None;
cmp2->opacity = opacity;
//No Composition //No Composition
} else { } else {
opacity = task->opacity; opacity = task->opacity;
@ -332,7 +332,7 @@ bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
if (a > 0) rasterStroke(surface, &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) delCompositor(cmp2); if (task->cmpStroking) delCompositor(cmp2);
return true; return true;
} }
@ -345,92 +345,90 @@ bool SwRenderer::renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_
} }
void* SwRenderer::addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) Compositor* SwRenderer::addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{ {
SwComposite* comp = nullptr; SwCompositor* cmp = nullptr;
//Use cached data //Use cached data
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) { for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
if ((*p)->valid) { if ((*p)->valid) {
comp = *p; cmp = *p;
break; break;
} }
} }
//New Composition //New Composition
if (!comp) { if (!cmp) {
comp = new SwComposite; cmp = new SwCompositor;
if (!comp) return nullptr; if (!cmp) 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
comp->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->w * surface->h); cmp->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->w * surface->h);
if (!comp->image.data) { if (!cmp->image.data) {
delete(comp); delete(cmp);
return nullptr; return nullptr;
} }
compositors.push(comp); compositors.push(cmp);
} }
comp->valid = false; cmp->valid = false;
comp->method = method;
comp->opacity = opacity;
//Boundary Check //Boundary Check
if (x + w > surface->w) w = (surface->w - x); if (x + w > surface->w) w = (surface->w - x);
if (y + h > surface->h) h = (surface->h - y); if (y + h > surface->h) h = (surface->h - y);
#ifdef THORVG_LOG_ENABLED #ifdef THORVG_LOG_ENABLED
printf("SW_ENGINE: Using intermediate composition [Method: %d][Region: %d %d %d %d]\n", (int)method, x, y, w, h); printf("SW_ENGINE: Using intermediate composition [Region: %d %d %d %d]\n", x, y, w, h);
#endif #endif
comp->bbox.min.x = x; cmp->bbox.min.x = x;
comp->bbox.min.y = y; cmp->bbox.min.y = y;
comp->bbox.max.x = x + w; cmp->bbox.max.x = x + w;
comp->bbox.max.y = y + h; cmp->bbox.max.y = y + h;
comp->image.w = surface->w; cmp->image.w = surface->w;
comp->image.h = surface->h; cmp->image.h = surface->h;
//Inherits attributes from main surface //Inherits attributes from main surface
comp->surface.comp = surface->comp; cmp->surface.blender = surface->blender;
comp->surface.stride = surface->w; cmp->surface.stride = surface->w;
comp->surface.cs = surface->cs; cmp->surface.cs = surface->cs;
//We know partial clear region //We know partial clear region
comp->surface.buffer = comp->image.data + (comp->surface.stride * y + x); cmp->surface.buffer = cmp->image.data + (cmp->surface.stride * y + x);
comp->surface.w = w; cmp->surface.w = w;
comp->surface.h = h; cmp->surface.h = h;
rasterClear(&comp->surface); rasterClear(&cmp->surface);
//Recover context //Recover context
comp->surface.buffer = comp->image.data; cmp->surface.buffer = cmp->image.data;
comp->surface.w = comp->image.w; cmp->surface.w = cmp->image.w;
comp->surface.h = comp->image.h; cmp->surface.h = cmp->image.h;
//Switch active compositor //Switch active compositor
comp->recover = compositor; //Backup current compositor cmp->recover = compositor; //Backup current compositor
compositor = comp; compositor = cmp;
//Switch render target //Switch render target
surface = &comp->surface; surface = &cmp->surface;
return comp; return cmp;
} }
bool SwRenderer::delCompositor(void* ctx) bool SwRenderer::delCompositor(Compositor* cmp)
{ {
if (!ctx) return false; if (!cmp) return false;
auto comp = static_cast<SwComposite*>(ctx); auto p = static_cast<SwCompositor*>(cmp);
comp->valid = true; p->valid = true;
//Recover Context //Recover Context
compositor = comp->recover; compositor = p->recover;
surface = compositor ? &compositor->surface : mainSurface; surface = compositor ? &compositor->surface : mainSurface;
//Default is alpha blending //Default is alpha blending
if (comp->method == CompositeMethod::None) { if (p->method == CompositeMethod::None) {
return rasterImage(surface, &comp->image, nullptr, comp->bbox, comp->opacity); return rasterImage(surface, &p->image, nullptr, p->bbox, p->opacity);
} }
return true; return true;
@ -460,8 +458,8 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
if (clips.count > 0) { if (clips.count > 0) {
//Guarantee composition targets get ready. //Guarantee composition targets get ready.
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
static_cast<SwShapeTask*>(*comp)->done(); static_cast<SwShapeTask*>(*clip)->done();
} }
task->clips = clips; task->clips = clips;
} }

View file

@ -26,7 +26,7 @@
struct SwSurface; struct SwSurface;
struct SwTask; struct SwTask;
struct SwComposite; struct SwCompositor;
namespace tvg namespace tvg
{ {
@ -36,15 +36,15 @@ class SwRenderer : public RenderMethod
public: public:
RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override; RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
void* addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) override; Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
bool delCompositor(void* cmp) override; bool delCompositor(Compositor* cmp) override;
bool dispose(RenderData data) override; bool dispose(RenderData data) override;
bool preRender() override; bool preRender() override;
bool postRender() override; bool postRender() override;
bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override; bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
bool clear() override; bool clear() override;
bool renderShape(RenderData data, void* cmp) override; bool renderShape(RenderData data, Compositor* cmp) override;
bool renderImage(RenderData data, void* cmp) override; bool renderImage(RenderData data, Compositor* cmp) override;
bool sync() override; bool sync() override;
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs); bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
@ -53,11 +53,11 @@ public:
static bool term(); static bool term();
private: private:
SwSurface* surface = nullptr; //active surface SwSurface* surface = nullptr; //active surface
SwComposite* compositor = nullptr; //active compositor SwCompositor* compositor = nullptr; //active compositor
SwSurface* mainSurface = nullptr; //main (default) surface SwSurface* mainSurface = nullptr; //main (default) surface
Array<SwTask*> tasks; //async task list Array<SwTask*> tasks; //async task list
Array<SwComposite*> compositors; //compositor cache list Array<SwCompositor*> compositors; //compositor cache list
SwRenderer(){}; SwRenderer(){};
~SwRenderer(); ~SwRenderer();

View file

@ -47,13 +47,13 @@ namespace tvg
RenderTransform *rTransform = nullptr; RenderTransform *rTransform = nullptr;
uint32_t flag = RenderUpdateFlag::None; uint32_t flag = RenderUpdateFlag::None;
Paint* compTarget = nullptr; Paint* cmpTarget = nullptr;
CompositeMethod compMethod = CompositeMethod::None; CompositeMethod cmpMethod = CompositeMethod::None;
uint8_t opacity = 255; uint8_t opacity = 255;
~Impl() { ~Impl() {
if (compTarget) delete(compTarget); if (cmpTarget) delete(cmpTarget);
if (smethod) delete(smethod); if (smethod) delete(smethod);
if (rTransform) delete(rTransform); if (rTransform) delete(rTransform);
} }
@ -133,7 +133,7 @@ namespace tvg
bool dispose(RenderMethod& renderer) bool dispose(RenderMethod& renderer)
{ {
if (compTarget) compTarget->pImpl->dispose(renderer); if (cmpTarget) cmpTarget->pImpl->dispose(renderer);
return smethod->dispose(renderer); return smethod->dispose(renderer);
} }
@ -147,11 +147,11 @@ namespace tvg
} }
} }
void *compdata = nullptr; void *cmpData = nullptr;
if (compTarget) { if (cmpTarget) {
compdata = compTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag); cmpData = cmpTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag);
if (compMethod == CompositeMethod::ClipPath) clips.push(compdata); if (cmpMethod == CompositeMethod::ClipPath) clips.push(cmpData);
} }
void *edata = nullptr; void *edata = nullptr;
@ -167,21 +167,23 @@ namespace tvg
edata = smethod->update(renderer, outTransform, opacity, clips, newFlag); edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
} }
if (compdata) clips.pop(); if (cmpData) clips.pop();
return edata; return edata;
} }
bool render(RenderMethod& renderer) bool render(RenderMethod& renderer)
{ {
void* cmp = nullptr; Compositor* cmp = nullptr;
/* Note: only ClipPath is processed in update() step */ /* Note: only ClipPath is processed in update() step */
if (compTarget && compMethod != CompositeMethod::ClipPath) { if (cmpTarget && cmpMethod != CompositeMethod::ClipPath) {
uint32_t x, y, w, h; uint32_t x, y, w, h;
if (!compTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false; if (!cmpTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false;
cmp = renderer.addCompositor(compMethod, x, y, w, h, 255); cmp = renderer.addCompositor(x, y, w, h);
compTarget->pImpl->render(renderer); cmp->method = CompositeMethod::None;
cmp->opacity = 255;
cmpTarget->pImpl->render(renderer);
} }
auto ret = smethod->render(renderer); auto ret = smethod->render(renderer);
@ -213,8 +215,8 @@ namespace tvg
{ {
if (!target && method != CompositeMethod::None) return false; if (!target && method != CompositeMethod::None) return false;
if (target && method == CompositeMethod::None) return false; if (target && method == CompositeMethod::None) return false;
compTarget = target; cmpTarget = target;
compMethod = method; cmpMethod = method;
return true; return true;
} }
}; };

View file

@ -39,6 +39,11 @@ struct Surface
using RenderData = void*; using RenderData = void*;
struct Compositor {
CompositeMethod method;
uint32_t opacity;
};
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, All = 64}; enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, All = 64};
struct RenderTransform struct RenderTransform
@ -57,18 +62,17 @@ struct RenderTransform
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
}; };
class RenderMethod struct RenderMethod
{ {
public:
virtual ~RenderMethod() {} virtual ~RenderMethod() {}
virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0; virtual RenderData prepare(const Shape& shape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
virtual RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0; virtual RenderData prepare(const Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
virtual void* addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) = 0; virtual Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) = 0;
virtual bool delCompositor(void* cmp) = 0; virtual bool delCompositor(Compositor* cmp) = 0;
virtual bool dispose(RenderData data) = 0; virtual bool dispose(RenderData data) = 0;
virtual bool preRender() = 0; virtual bool preRender() = 0;
virtual bool renderShape(RenderData data, void* cmp) = 0; virtual bool renderShape(RenderData data, Compositor* cmp) = 0;
virtual bool renderImage(RenderData data, void* cmp) = 0; virtual bool renderImage(RenderData data, Compositor* cmp) = 0;
virtual bool postRender() = 0; virtual bool postRender() = 0;
virtual bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) = 0; virtual bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) = 0;
virtual bool clear() = 0; virtual bool clear() = 0;

View file

@ -63,14 +63,16 @@ struct Scene::Impl
bool render(RenderMethod& renderer) bool render(RenderMethod& renderer)
{ {
void* cmp = nullptr; Compositor* cmp = nullptr;
//Half translucent. This condition requires intermediate composition. //Half translucent. This condition requires intermediate composition.
if (opacity < 255 && opacity > 0 && (paints.count > 1)) { if (opacity < 255 && opacity > 0 && (paints.count > 1)) {
uint32_t x, y, w, h; uint32_t x, y, w, h;
if (!bounds(renderer, &x, &y, &w, &h)) return false; if (!bounds(renderer, &x, &y, &w, &h)) return false;
//CompositeMethod::None is used for a default alpha blending //CompositeMethod::None is used for a default alpha blending
cmp = renderer.addCompositor(CompositeMethod::None, x, y, w, h, opacity); cmp = renderer.addCompositor(x, y, w, h);
cmp->method = CompositeMethod::None;
cmp->opacity = opacity;
} }
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {