sw_engine: ++8bit grayscale rasterizer.

These rasterizers are added for 8bit maskings.
This commit is contained in:
Hermet Park 2023-05-05 23:57:47 +09:00 committed by Hermet Park
parent 737b89471a
commit 3376f44de5
8 changed files with 395 additions and 230 deletions

View file

@ -241,7 +241,7 @@ struct SwImage
struct SwBlender 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 (*lumaValue)(uint32_t c); uint8_t (*luma)(uint8_t* c);
}; };
struct SwCompositor; struct SwCompositor;

File diff suppressed because it is too large Load diff

View file

@ -82,8 +82,14 @@ static void avxRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_
} }
static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color) 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->blender.join(r, g, b, a);
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);
@ -125,8 +131,14 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u
} }
static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color) 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->blender.join(r, g, b, a);
auto span = rle->spans; auto span = rle->spans;
uint32_t src; uint32_t src;

View file

@ -20,45 +20,72 @@
* SOFTWARE. * SOFTWARE.
*/ */
static void inline cRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) template<typename PIXEL_T>
static void inline cRasterPixels(PIXEL_T* dst, uint32_t val, uint32_t offset, int32_t len)
{ {
dst += offset; dst += offset;
while (len--) *dst++ = val; while (len--) *dst++ = val;
} }
static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color) static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{ {
auto span = rle->spans; auto span = rle->spans;
uint32_t src;
//32bit channels
if (surface->channelSize == sizeof(uint32_t)) {
auto color = surface->blender.join(r, g, b, a);
uint32_t src;
for (uint32_t i = 0; i < rle->size; ++i, ++span) { for (uint32_t i = 0; i < rle->size; ++i, ++span) {
auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto dst = &surface->buf32[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;
for (uint32_t x = 0; x < span->len; ++x, ++dst) { for (uint32_t x = 0; x < span->len; ++x, ++dst) {
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
} }
//8bit grayscale
} else if (surface->channelSize == sizeof(uint8_t)) {
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<uint8_t>(span->coverage, a);
else src = a;
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
*dst = src + _multiply<uint8_t>(*dst, ~src);
}
}
}
return true; return true;
} }
static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color) static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t 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);
auto ialpha = _ialpha(color);
//32bits channels
if (surface->channelSize == sizeof(uint32_t)) {
auto color = surface->blender.join(r, g, b, a);
auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x;
auto ialpha = _ialpha(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];
for (uint32_t x = 0; x < w; ++x, ++dst) { for (uint32_t x = 0; x < w; ++x, ++dst) {
*dst = color + ALPHA_BLEND(*dst, ialpha); *dst = color + ALPHA_BLEND(*dst, ialpha);
} }
} }
//8bit grayscale
} else if (surface->channelSize == sizeof(uint8_t)) {
auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x;
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<uint8_t>(*dst, ~a);
}
}
}
return true; return true;
} }

View file

@ -49,8 +49,14 @@ static void neonRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32
} }
static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color) 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->blender.join(r, g, b, a);
auto span = rle->spans; auto span = rle->spans;
uint32_t src; uint32_t src;
uint8x8_t *vDst = nullptr; uint8x8_t *vDst = nullptr;
@ -88,8 +94,14 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u
} }
static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color) 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->blender.join(r, g, b, a);
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);

View file

@ -69,7 +69,7 @@ static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, in
} }
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint32_t (*blender)(uint32_t), AASpans* aaSpans) static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
{ {
#define TEXMAP_TRANSLUCENT #define TEXMAP_TRANSLUCENT
#define TEXMAP_MASKING #define TEXMAP_MASKING
@ -79,7 +79,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
} }
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t (*blender)(uint32_t), AASpans* aaSpans) static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
{ {
#define TEXMAP_MASKING #define TEXMAP_MASKING
#include "tvgSwRasterTexmapInternal.h" #include "tvgSwRasterTexmapInternal.h"
@ -102,7 +102,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
/* This mapping algorithm is based on Mikael Kalms's. */ /* This mapping algorithm is based on Mikael Kalms's. */
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint32_t (*blender)(uint32_t), AASpans* aaSpans) static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint8_t(*blender)(uint8_t*), AASpans* aaSpans)
{ {
float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x}; float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x};
float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y}; float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y};
@ -545,7 +545,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
| / | | / |
3 -- 2 3 -- 2
*/ */
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blender)(uint32_t)) static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
{ {
//Exceptions: No dedicated drawing area? //Exceptions: No dedicated drawing area?
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false; if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
@ -602,7 +602,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
Should provide two Polygons, one for each triangle. Should provide two Polygons, one for each triangle.
// TODO: region? // TODO: region?
*/ */
static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blender)(uint32_t)) static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*))
{ {
//Exceptions: No dedicated drawing area? //Exceptions: No dedicated drawing area?
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false; if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;

View file

@ -37,7 +37,8 @@
SwSpan* span = nullptr; //used only when rle based. SwSpan* span = nullptr; //used only when rle based.
#ifdef TEXMAP_MASKING #ifdef TEXMAP_MASKING
uint32_t* cmp; uint8_t* cmp;
auto csize = surface->compositor->image.channelSize;
#endif #endif
if (!_arrange(image, region, yStart, yEnd)) return; if (!_arrange(image, region, yStart, yEnd)) return;
@ -94,7 +95,7 @@
x = x1; x = x1;
#ifdef TEXMAP_MASKING #ifdef TEXMAP_MASKING
cmp = &surface->compositor->image.buf32[y * surface->compositor->image.stride + x1]; cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize];
#endif #endif
//Draw horizontal line //Draw horizontal line
while (x++ < x2) { while (x++ < x2) {
@ -130,9 +131,9 @@
px = INTERPOLATE(ab, px, px2); px = INTERPOLATE(ab, px, px2);
} }
#if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT) #if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT)
auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blender(*cmp))); auto src = ALPHA_BLEND(px, _multiply<uint32_t>(opacity, blender(cmp)));
#elif defined(TEXMAP_MASKING) #elif defined(TEXMAP_MASKING)
auto src = ALPHA_BLEND(px, blender(*cmp)); auto src = ALPHA_BLEND(px, blender(cmp));
#elif defined(TEXMAP_TRANSLUCENT) #elif defined(TEXMAP_TRANSLUCENT)
auto src = ALPHA_BLEND(px, opacity); auto src = ALPHA_BLEND(px, opacity);
#else #else
@ -141,7 +142,7 @@
*buf = src + ALPHA_BLEND(*buf, _ialpha(src)); *buf = src + ALPHA_BLEND(*buf, _ialpha(src));
++buf; ++buf;
#ifdef TEXMAP_MASKING #ifdef TEXMAP_MASKING
++cmp; cmp += csize;
#endif #endif
//Step UV horizontally //Step UV horizontally
u += _dudx; u += _dudx;

View file

@ -167,8 +167,7 @@ bool Paint::Impl::render(RenderMethod& renderer)
if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) {
auto region = smethod->bounds(renderer); auto region = smethod->bounds(renderer);
if (region.w == 0 || region.h == 0) return true; if (region.w == 0 || region.h == 0) return true;
//cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method));
cmp = renderer.target(region, renderer.colorSpace());
if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) { if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) {
compData->target->pImpl->render(renderer); compData->target->pImpl->render(renderer);
} }