mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
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:
parent
c1e36bcb01
commit
7d9023ac5c
10 changed files with 137 additions and 131 deletions
|
@ -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
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
||||
bool GlRenderer::renderShape(RenderData data, TVG_UNUSED Compositor* cmp)
|
||||
{
|
||||
auto sdata = static_cast<GlShape*>(data);
|
||||
if (!sdata) return false;
|
||||
|
|
|
@ -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 Picture& picture, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) 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;
|
||||
bool delCompositor(void* cmp) override;
|
||||
Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
|
||||
bool delCompositor(Compositor* cmp) override;
|
||||
bool preRender() override;
|
||||
bool renderShape(RenderData data, void* cmp) override;
|
||||
bool renderImage(RenderData data, void* cmp) override;
|
||||
bool renderShape(RenderData data, Compositor* cmp) override;
|
||||
bool renderImage(RenderData data, Compositor* cmp) override;
|
||||
bool postRender() 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);
|
||||
|
|
|
@ -220,7 +220,7 @@ struct SwImage
|
|||
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 (*alpha)(uint32_t rgba);
|
||||
|
@ -228,7 +228,7 @@ struct SwCompositor
|
|||
|
||||
struct SwSurface : Surface
|
||||
{
|
||||
SwCompositor comp;
|
||||
SwBlender blender;
|
||||
};
|
||||
|
||||
static inline SwCoord TO_SWCOORD(float val)
|
||||
|
|
|
@ -52,7 +52,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surfac
|
|||
auto g = ALPHA_MULTIPLY(pColors->g, 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 pos = 1.5f * inc;
|
||||
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 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) {
|
||||
auto t = (pos - curr->offset) * delta;
|
||||
|
|
|
@ -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 h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
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) {
|
||||
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];
|
||||
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
|
||||
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) {
|
||||
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;
|
||||
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
|
||||
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;
|
||||
}
|
||||
|
@ -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));
|
||||
if (rX >= w || rY >= h) continue;
|
||||
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;
|
||||
}
|
||||
|
@ -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));
|
||||
if (rX >= w || rY >= h) continue;
|
||||
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;
|
||||
|
@ -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 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++) {
|
||||
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->comp.alpha(*src));
|
||||
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(*src));
|
||||
}
|
||||
}
|
||||
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));
|
||||
if (rX >= w || rY >= h) continue;
|
||||
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;
|
||||
|
@ -276,7 +276,7 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
|
|||
auto dst = &buffer[y * surface->stride];
|
||||
fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w);
|
||||
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
|
||||
|
@ -307,7 +307,7 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
|
|||
auto dst = &buffer[y * surface->stride];
|
||||
fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w);
|
||||
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
|
||||
|
@ -337,12 +337,12 @@ static bool _rasterLinearGradientRle(SwSurface* surface, SwRleData* rle, const S
|
|||
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
||||
if (span->coverage == 255) {
|
||||
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 {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
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;
|
||||
|
@ -383,12 +383,12 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S
|
|||
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
||||
if (span->coverage == 255) {
|
||||
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 {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
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;
|
||||
|
@ -420,11 +420,11 @@ static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const S
|
|||
bool rasterCompositor(SwSurface* surface)
|
||||
{
|
||||
if (surface->cs == SwCanvas::ABGR8888) {
|
||||
surface->comp.alpha = _colorAlpha;
|
||||
surface->comp.join = _abgrJoin;
|
||||
surface->blender.alpha = _colorAlpha;
|
||||
surface->blender.join = _abgrJoin;
|
||||
} else if (surface->cs == SwCanvas::ARGB8888) {
|
||||
surface->comp.alpha = _colorAlpha;
|
||||
surface->comp.join = _argbJoin;
|
||||
surface->blender.alpha = _colorAlpha;
|
||||
surface->blender.join = _argbJoin;
|
||||
} else {
|
||||
//What Color Space ???
|
||||
return false;
|
||||
|
@ -455,7 +455,7 @@ bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g,
|
|||
g = ALPHA_MULTIPLY(g, 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
|
||||
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);
|
||||
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);
|
||||
return _rasterTranslucentRle(surface, shape->strokeRle, color);
|
||||
|
|
|
@ -30,14 +30,12 @@
|
|||
static bool initEngine = false;
|
||||
static uint32_t rendererCnt = 0;
|
||||
|
||||
struct SwComposite
|
||||
struct SwCompositor : Compositor
|
||||
{
|
||||
SwSurface surface;
|
||||
SwComposite* recover;
|
||||
SwCompositor* recover;
|
||||
SwImage image;
|
||||
SwBBox bbox;
|
||||
CompositeMethod method;
|
||||
uint32_t opacity;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
|
@ -67,7 +65,7 @@ struct SwShapeTask : SwTask
|
|||
{
|
||||
SwShape shape;
|
||||
const Shape* sdata = nullptr;
|
||||
bool compStroking;
|
||||
bool cmpStroking;
|
||||
|
||||
void run(unsigned tid) override
|
||||
{
|
||||
|
@ -134,23 +132,23 @@ struct SwShapeTask : SwTask
|
|||
}
|
||||
|
||||
//Clip Path
|
||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
||||
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape;
|
||||
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
|
||||
//Clip shape rle
|
||||
if (shape.rle) {
|
||||
if (compShape->rect) rleClipRect(shape.rle, &compShape->bbox);
|
||||
else if (compShape->rle) rleClipPath(shape.rle, compShape->rle);
|
||||
if (clipper->rect) rleClipRect(shape.rle, &clipper->bbox);
|
||||
else if (clipper->rle) rleClipPath(shape.rle, clipper->rle);
|
||||
}
|
||||
//Clip stroke rle
|
||||
if (shape.strokeRle) {
|
||||
if (compShape->rect) rleClipRect(shape.strokeRle, &compShape->bbox);
|
||||
else if (compShape->rle) rleClipPath(shape.strokeRle, compShape->rle);
|
||||
if (clipper->rect) rleClipRect(shape.strokeRle, &clipper->bbox);
|
||||
else if (clipper->rle) rleClipPath(shape.strokeRle, clipper->rle);
|
||||
}
|
||||
}
|
||||
end:
|
||||
shapeDelOutline(&shape, tid);
|
||||
if (addStroking == 2 && opacity < 255) compStroking = true;
|
||||
else compStroking = false;
|
||||
if (addStroking == 2 && opacity < 255) cmpStroking = true;
|
||||
else cmpStroking = false;
|
||||
}
|
||||
|
||||
bool dispose() override
|
||||
|
@ -182,10 +180,10 @@ struct SwImageTask : SwTask
|
|||
if (clips.count > 0) {
|
||||
if (!imageGenRle(&image, pdata, clip, bbox, false, true)) goto end;
|
||||
if (image.rle) {
|
||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
||||
auto compShape = &static_cast<SwShapeTask*>(*comp)->shape;
|
||||
if (compShape->rect) rleClipRect(image.rle, &compShape->bbox);
|
||||
else if (compShape->rle) rleClipPath(image.rle, compShape->rle);
|
||||
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
|
||||
if (clipper->rect) rleClipRect(image.rle, &clipper->bbox);
|
||||
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);
|
||||
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);
|
||||
task->done();
|
||||
|
@ -301,15 +299,17 @@ bool SwRenderer::renderShape(RenderData data, TVG_UNUSED void* cmp)
|
|||
if (task->opacity == 0) return true;
|
||||
|
||||
uint32_t opacity;
|
||||
void *cmp2 = nullptr;
|
||||
Compositor* cmp2 = nullptr;
|
||||
|
||||
//Do Composition
|
||||
if (task->compStroking) {
|
||||
if (task->cmpStroking) {
|
||||
uint32_t x, y, w, h;
|
||||
task->bounds(&x, &y, &w, &h);
|
||||
opacity = 255;
|
||||
//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
|
||||
} else {
|
||||
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);
|
||||
|
||||
//Composition (Shape + Stroke) stage
|
||||
if (task->compStroking) delCompositor(cmp2);
|
||||
if (task->cmpStroking) delCompositor(cmp2);
|
||||
|
||||
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
|
||||
for (auto p = compositors.data; p < (compositors.data + compositors.count); ++p) {
|
||||
if ((*p)->valid) {
|
||||
comp = *p;
|
||||
cmp = *p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//New Composition
|
||||
if (!comp) {
|
||||
comp = new SwComposite;
|
||||
if (!comp) return nullptr;
|
||||
if (!cmp) {
|
||||
cmp = new SwCompositor;
|
||||
if (!cmp) return nullptr;
|
||||
//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);
|
||||
if (!comp->image.data) {
|
||||
delete(comp);
|
||||
cmp->image.data = (uint32_t*) malloc(sizeof(uint32_t) * surface->w * surface->h);
|
||||
if (!cmp->image.data) {
|
||||
delete(cmp);
|
||||
return nullptr;
|
||||
}
|
||||
compositors.push(comp);
|
||||
compositors.push(cmp);
|
||||
}
|
||||
|
||||
comp->valid = false;
|
||||
comp->method = method;
|
||||
comp->opacity = opacity;
|
||||
cmp->valid = false;
|
||||
|
||||
//Boundary Check
|
||||
if (x + w > surface->w) w = (surface->w - x);
|
||||
if (y + h > surface->h) h = (surface->h - y);
|
||||
|
||||
#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
|
||||
|
||||
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;
|
||||
cmp->bbox.min.x = x;
|
||||
cmp->bbox.min.y = y;
|
||||
cmp->bbox.max.x = x + w;
|
||||
cmp->bbox.max.y = y + h;
|
||||
cmp->image.w = surface->w;
|
||||
cmp->image.h = surface->h;
|
||||
|
||||
//Inherits attributes from main surface
|
||||
comp->surface.comp = surface->comp;
|
||||
comp->surface.stride = surface->w;
|
||||
comp->surface.cs = surface->cs;
|
||||
cmp->surface.blender = surface->blender;
|
||||
cmp->surface.stride = surface->w;
|
||||
cmp->surface.cs = surface->cs;
|
||||
|
||||
//We know partial clear region
|
||||
comp->surface.buffer = comp->image.data + (comp->surface.stride * y + x);
|
||||
comp->surface.w = w;
|
||||
comp->surface.h = h;
|
||||
cmp->surface.buffer = cmp->image.data + (cmp->surface.stride * y + x);
|
||||
cmp->surface.w = w;
|
||||
cmp->surface.h = h;
|
||||
|
||||
rasterClear(&comp->surface);
|
||||
rasterClear(&cmp->surface);
|
||||
|
||||
//Recover context
|
||||
comp->surface.buffer = comp->image.data;
|
||||
comp->surface.w = comp->image.w;
|
||||
comp->surface.h = comp->image.h;
|
||||
cmp->surface.buffer = cmp->image.data;
|
||||
cmp->surface.w = cmp->image.w;
|
||||
cmp->surface.h = cmp->image.h;
|
||||
|
||||
//Switch active compositor
|
||||
comp->recover = compositor; //Backup current compositor
|
||||
compositor = comp;
|
||||
cmp->recover = compositor; //Backup current compositor
|
||||
compositor = cmp;
|
||||
|
||||
//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);
|
||||
comp->valid = true;
|
||||
auto p = static_cast<SwCompositor*>(cmp);
|
||||
p->valid = true;
|
||||
|
||||
//Recover Context
|
||||
compositor = comp->recover;
|
||||
compositor = p->recover;
|
||||
surface = compositor ? &compositor->surface : mainSurface;
|
||||
|
||||
//Default is alpha blending
|
||||
if (comp->method == CompositeMethod::None) {
|
||||
return rasterImage(surface, &comp->image, nullptr, comp->bbox, comp->opacity);
|
||||
if (p->method == CompositeMethod::None) {
|
||||
return rasterImage(surface, &p->image, nullptr, p->bbox, p->opacity);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -460,8 +458,8 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
|
|||
|
||||
if (clips.count > 0) {
|
||||
//Guarantee composition targets get ready.
|
||||
for (auto comp = clips.data; comp < (clips.data + clips.count); ++comp) {
|
||||
static_cast<SwShapeTask*>(*comp)->done();
|
||||
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
|
||||
static_cast<SwShapeTask*>(*clip)->done();
|
||||
}
|
||||
task->clips = clips;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
struct SwSurface;
|
||||
struct SwTask;
|
||||
struct SwComposite;
|
||||
struct SwCompositor;
|
||||
|
||||
namespace tvg
|
||||
{
|
||||
|
@ -36,15 +36,15 @@ class SwRenderer : public RenderMethod
|
|||
public:
|
||||
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;
|
||||
void* addCompositor(CompositeMethod method, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t opacity) override;
|
||||
bool delCompositor(void* cmp) override;
|
||||
Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
|
||||
bool delCompositor(Compositor* cmp) override;
|
||||
bool dispose(RenderData data) override;
|
||||
bool preRender() override;
|
||||
bool postRender() override;
|
||||
bool renderRegion(RenderData data, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) override;
|
||||
bool clear() override;
|
||||
bool renderShape(RenderData data, void* cmp) override;
|
||||
bool renderImage(RenderData data, void* cmp) override;
|
||||
bool renderShape(RenderData data, Compositor* cmp) override;
|
||||
bool renderImage(RenderData data, Compositor* cmp) override;
|
||||
bool sync() override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||
|
||||
|
@ -54,10 +54,10 @@ public:
|
|||
|
||||
private:
|
||||
SwSurface* surface = nullptr; //active surface
|
||||
SwComposite* compositor = nullptr; //active compositor
|
||||
SwCompositor* compositor = nullptr; //active compositor
|
||||
SwSurface* mainSurface = nullptr; //main (default) surface
|
||||
Array<SwTask*> tasks; //async task list
|
||||
Array<SwComposite*> compositors; //compositor cache list
|
||||
Array<SwCompositor*> compositors; //compositor cache list
|
||||
|
||||
SwRenderer(){};
|
||||
~SwRenderer();
|
||||
|
|
|
@ -47,13 +47,13 @@ namespace tvg
|
|||
RenderTransform *rTransform = nullptr;
|
||||
uint32_t flag = RenderUpdateFlag::None;
|
||||
|
||||
Paint* compTarget = nullptr;
|
||||
CompositeMethod compMethod = CompositeMethod::None;
|
||||
Paint* cmpTarget = nullptr;
|
||||
CompositeMethod cmpMethod = CompositeMethod::None;
|
||||
|
||||
uint8_t opacity = 255;
|
||||
|
||||
~Impl() {
|
||||
if (compTarget) delete(compTarget);
|
||||
if (cmpTarget) delete(cmpTarget);
|
||||
if (smethod) delete(smethod);
|
||||
if (rTransform) delete(rTransform);
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ namespace tvg
|
|||
|
||||
bool dispose(RenderMethod& renderer)
|
||||
{
|
||||
if (compTarget) compTarget->pImpl->dispose(renderer);
|
||||
if (cmpTarget) cmpTarget->pImpl->dispose(renderer);
|
||||
return smethod->dispose(renderer);
|
||||
}
|
||||
|
||||
|
@ -147,11 +147,11 @@ namespace tvg
|
|||
}
|
||||
}
|
||||
|
||||
void *compdata = nullptr;
|
||||
void *cmpData = nullptr;
|
||||
|
||||
if (compTarget) {
|
||||
compdata = compTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag);
|
||||
if (compMethod == CompositeMethod::ClipPath) clips.push(compdata);
|
||||
if (cmpTarget) {
|
||||
cmpData = cmpTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag);
|
||||
if (cmpMethod == CompositeMethod::ClipPath) clips.push(cmpData);
|
||||
}
|
||||
|
||||
void *edata = nullptr;
|
||||
|
@ -167,21 +167,23 @@ namespace tvg
|
|||
edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
|
||||
}
|
||||
|
||||
if (compdata) clips.pop();
|
||||
if (cmpData) clips.pop();
|
||||
|
||||
return edata;
|
||||
}
|
||||
|
||||
bool render(RenderMethod& renderer)
|
||||
{
|
||||
void* cmp = nullptr;
|
||||
Compositor* cmp = nullptr;
|
||||
|
||||
/* Note: only ClipPath is processed in update() step */
|
||||
if (compTarget && compMethod != CompositeMethod::ClipPath) {
|
||||
if (cmpTarget && cmpMethod != CompositeMethod::ClipPath) {
|
||||
uint32_t x, y, w, h;
|
||||
if (!compTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false;
|
||||
cmp = renderer.addCompositor(compMethod, x, y, w, h, 255);
|
||||
compTarget->pImpl->render(renderer);
|
||||
if (!cmpTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false;
|
||||
cmp = renderer.addCompositor(x, y, w, h);
|
||||
cmp->method = CompositeMethod::None;
|
||||
cmp->opacity = 255;
|
||||
cmpTarget->pImpl->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;
|
||||
compTarget = target;
|
||||
compMethod = method;
|
||||
cmpTarget = target;
|
||||
cmpMethod = method;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -39,6 +39,11 @@ struct Surface
|
|||
|
||||
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};
|
||||
|
||||
struct RenderTransform
|
||||
|
@ -57,18 +62,17 @@ struct RenderTransform
|
|||
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
|
||||
};
|
||||
|
||||
class RenderMethod
|
||||
struct RenderMethod
|
||||
{
|
||||
public:
|
||||
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 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 bool delCompositor(void* cmp) = 0;
|
||||
virtual Compositor* addCompositor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) = 0;
|
||||
virtual bool delCompositor(Compositor* cmp) = 0;
|
||||
virtual bool dispose(RenderData data) = 0;
|
||||
virtual bool preRender() = 0;
|
||||
virtual bool renderShape(RenderData data, void* cmp) = 0;
|
||||
virtual bool renderImage(RenderData data, void* cmp) = 0;
|
||||
virtual bool renderShape(RenderData data, Compositor* cmp) = 0;
|
||||
virtual bool renderImage(RenderData data, Compositor* cmp) = 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 clear() = 0;
|
||||
|
|
|
@ -63,14 +63,16 @@ struct Scene::Impl
|
|||
|
||||
bool render(RenderMethod& renderer)
|
||||
{
|
||||
void* cmp = nullptr;
|
||||
Compositor* cmp = nullptr;
|
||||
|
||||
//Half translucent. This condition requires intermediate composition.
|
||||
if (opacity < 255 && opacity > 0 && (paints.count > 1)) {
|
||||
uint32_t x, y, w, h;
|
||||
if (!bounds(renderer, &x, &y, &w, &h)) return false;
|
||||
//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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue