mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 20:14:37 +00:00
sw_engine: hotfix avx/neon 8 bit rasterizer.
recte/rle 8 bit rasterizer has been broken, make it work safely with c raster version. issue: https://github.com/thorvg/thorvg/issues/2146
This commit is contained in:
parent
25370f438e
commit
a9592ec3ef
2 changed files with 179 additions and 135 deletions
|
@ -101,16 +101,14 @@ static void avxRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32
|
||||||
|
|
||||||
static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
if (surface->channelSize != sizeof(uint32_t)) {
|
|
||||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto color = surface->join(r, g, b, a);
|
|
||||||
auto buffer = surface->buf32 + (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);
|
||||||
|
|
||||||
|
//32bits channels
|
||||||
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
|
auto color = surface->join(r, g, b, a);
|
||||||
|
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||||
|
|
||||||
uint32_t ialpha = 255 - a;
|
uint32_t ialpha = 255 - a;
|
||||||
|
|
||||||
auto avxColor = _mm_set1_epi32(color);
|
auto avxColor = _mm_set1_epi32(color);
|
||||||
|
@ -144,19 +142,29 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u
|
||||||
dst++;
|
dst++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//8bit grayscale
|
||||||
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
|
TVGLOG("SW_ENGINE", "Require AVX Optimization, Channel Size = %d", surface->channelSize);
|
||||||
|
auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
|
||||||
|
auto ialpha = ~a;
|
||||||
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
|
auto dst = &buffer[y * surface->stride];
|
||||||
|
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||||
|
*dst = a + MULTIPLY(*dst, ialpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
if (surface->channelSize != sizeof(uint32_t)) {
|
|
||||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto color = surface->join(r, g, b, a);
|
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
|
|
||||||
|
//32bit channels
|
||||||
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
|
auto color = surface->join(r, g, b, a);
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
|
@ -201,6 +209,20 @@ static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, ui
|
||||||
|
|
||||||
++span;
|
++span;
|
||||||
}
|
}
|
||||||
|
//8bit grayscale
|
||||||
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
|
TVGLOG("SW_ENGINE", "Require AVX Optimization, Channel Size = %d", surface->channelSize);
|
||||||
|
uint8_t src;
|
||||||
|
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||||
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
|
if (span->coverage < 255) src = MULTIPLY(span->coverage, a);
|
||||||
|
else src = a;
|
||||||
|
auto ialpha = ~a;
|
||||||
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
|
*dst = src + MULTIPLY(*dst, ialpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,13 +91,11 @@ static void neonRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int3
|
||||||
|
|
||||||
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
if (surface->channelSize != sizeof(uint32_t)) {
|
|
||||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto color = surface->join(r, g, b, a);
|
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
|
|
||||||
|
//32bit channels
|
||||||
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
|
auto color = surface->join(r, g, b, a);
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
uint8x8_t *vDst = nullptr;
|
uint8x8_t *vDst = nullptr;
|
||||||
uint16_t align;
|
uint16_t align;
|
||||||
|
@ -130,21 +128,33 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u
|
||||||
|
|
||||||
++span;
|
++span;
|
||||||
}
|
}
|
||||||
|
//8bit grayscale
|
||||||
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
|
TVGLOG("SW_ENGINE", "Require Neon Optimization, Channel Size = %d", surface->channelSize);
|
||||||
|
uint8_t src;
|
||||||
|
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||||
|
auto dst = &surface->buf8[span->y * surface->stride + span->x];
|
||||||
|
if (span->coverage < 255) src = MULTIPLY(span->coverage, a);
|
||||||
|
else src = a;
|
||||||
|
auto ialpha = ~a;
|
||||||
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
|
*dst = src + MULTIPLY(*dst, ialpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
if (surface->channelSize != sizeof(uint32_t)) {
|
|
||||||
TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto color = surface->join(r, g, b, a);
|
|
||||||
auto buffer = surface->buf32 + (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);
|
||||||
|
|
||||||
|
//32bits channels
|
||||||
|
if (surface->channelSize == sizeof(uint32_t)) {
|
||||||
|
auto color = surface->join(r, g, b, a);
|
||||||
|
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto ialpha = 255 - a;
|
auto ialpha = 255 - a;
|
||||||
|
|
||||||
auto vColor = vdup_n_u32(color);
|
auto vColor = vdup_n_u32(color);
|
||||||
|
@ -172,6 +182,18 @@ static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region,
|
||||||
auto leftovers = (w - align) % 2;
|
auto leftovers = (w - align) % 2;
|
||||||
if (leftovers > 0) dst[w - 1] = color + ALPHA_BLEND(dst[w - 1], ialpha);
|
if (leftovers > 0) dst[w - 1] = color + ALPHA_BLEND(dst[w - 1], ialpha);
|
||||||
}
|
}
|
||||||
|
//8bit grayscale
|
||||||
|
} else if (surface->channelSize == sizeof(uint8_t)) {
|
||||||
|
TVGLOG("SW_ENGINE", "Require Neon Optimization, Channel Size = %d", surface->channelSize);
|
||||||
|
auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
|
||||||
|
auto ialpha = ~a;
|
||||||
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
|
auto dst = &buffer[y * surface->stride];
|
||||||
|
for (uint32_t x = 0; x < w; ++x, ++dst) {
|
||||||
|
*dst = a + MULTIPLY(*dst, ialpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue