mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-25 07:39:02 +00:00
sw_engine texmap: code refactoring.
Unrolled the blending stages by applying macro magics. I know this is a bit bad for code readibility but good for the performance and the optimal LOC.
This commit is contained in:
parent
aff755aeb5
commit
2ca6f76d91
1 changed files with 123 additions and 96 deletions
|
@ -43,46 +43,9 @@ static float dudx, dvdx;
|
||||||
static float dxdya, dxdyb, dudya, dvdya;
|
static float dxdya, dxdyb, dudya, dvdya;
|
||||||
static float xa, xb, ua, va;
|
static float xa, xb, ua, va;
|
||||||
|
|
||||||
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
|
|
||||||
{
|
|
||||||
#define RASTER_COMMON() \
|
|
||||||
uu = (int) u; \
|
|
||||||
vv = (int) v; \
|
|
||||||
/* FIXME: sometimes u and v are < 0 - don'tc crash */ \
|
|
||||||
if (uu < 0) uu = 0;\
|
|
||||||
if (vv < 0) vv = 0; \
|
|
||||||
\
|
|
||||||
/* Range exception handling */ \
|
|
||||||
/* OPTIMIZE ME, handle in advance? */ \
|
|
||||||
if (uu >= sw) uu = sw - 1; \
|
|
||||||
if (vv >= sh) vv = sh - 1; \
|
|
||||||
\
|
|
||||||
ar = (int)(255 * (1 - modff(u, &iptr))); \
|
|
||||||
ab = (int)(255 * (1 - modff(v, &iptr))); \
|
|
||||||
iru = uu + 1; \
|
|
||||||
irv = vv + 1; \
|
|
||||||
px = *(sbuf + (vv * sw) + uu); \
|
|
||||||
\
|
|
||||||
/* horizontal interpolate */ \
|
|
||||||
if (iru < sw) { \
|
|
||||||
/* right pixel */ \
|
|
||||||
int px2 = *(sbuf + (vv * sw) + iru); \
|
|
||||||
px = _interpolate(ar, px, px2); \
|
|
||||||
} \
|
|
||||||
/* vertical interpolate */ \
|
|
||||||
if (irv < sh) { \
|
|
||||||
/* bottom pixel */ \
|
|
||||||
int px2 = *(sbuf + (irv * sw) + uu); \
|
|
||||||
\
|
|
||||||
/* horizontal interpolate */ \
|
|
||||||
if (iru < sw) { \
|
|
||||||
/* bottom right pixel */ \
|
|
||||||
int px3 = *(sbuf + (irv * sw) + iru);\
|
|
||||||
px2 = _interpolate(ar, px2, px3); \
|
|
||||||
} \
|
|
||||||
px = _interpolate(ab, px, px2); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
static inline void _rasterRGBA(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, TVG_UNUSED uint32_t opacity, TVG_UNUSED uint32_t (*blendMethod)(uint32_t))
|
||||||
|
{
|
||||||
float _dudx = dudx, _dvdx = dvdx;
|
float _dudx = dudx, _dvdx = dvdx;
|
||||||
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya;
|
||||||
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
float _xa = xa, _xb = xb, _ua = ua, _va = va;
|
||||||
|
@ -125,57 +88,64 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
||||||
|
|
||||||
x = x1;
|
x = x1;
|
||||||
|
|
||||||
if (blendMethod) {
|
#ifdef TEXMAP_MAKSING
|
||||||
TVGLOG("SW_ENGINE", "Transformed Masked Image");
|
auto cmp = &surface->compositor->image.data[y * surface->compositor->image.stride + x1];
|
||||||
auto cmp = &surface->compositor->image.data[y * surface->compositor->image.stride + x1];
|
#endif
|
||||||
if (opacity == 255) {
|
//Draw horizontal line
|
||||||
//Draw horizontal line
|
while (x++ < x2) {
|
||||||
while (x++ < x2) {
|
uu = (int) u;
|
||||||
RASTER_COMMON();
|
vv = (int) v;
|
||||||
auto src = ALPHA_BLEND(px, blendMethod(*cmp));
|
/* FIXME: sometimes u and v are < 0 - don'tc crash */
|
||||||
*buf = src + ALPHA_BLEND(*buf, surface->blender.ialpha(src));
|
if (uu < 0) uu = 0;
|
||||||
++cmp;
|
if (vv < 0) vv = 0;
|
||||||
++buf;
|
|
||||||
//Step UV horizontally
|
/* Range exception handling */
|
||||||
u += _dudx;
|
/* OPTIMIZE ME, handle in advance? */
|
||||||
v += _dvdx;
|
if (uu >= sw) uu = sw - 1;
|
||||||
}
|
if (vv >= sh) vv = sh - 1;
|
||||||
} else {
|
|
||||||
//Draw horizontal line
|
ar = (int)(255 * (1 - modff(u, &iptr)));
|
||||||
while (x++ < x2) {
|
ab = (int)(255 * (1 - modff(v, &iptr)));
|
||||||
RASTER_COMMON();
|
iru = uu + 1;
|
||||||
auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blendMethod(*cmp)));
|
irv = vv + 1;
|
||||||
*buf = src + ALPHA_BLEND(*buf, surface->blender.ialpha(src));
|
px = *(sbuf + (vv * sw) + uu);
|
||||||
++buf;
|
|
||||||
++cmp;
|
/* horizontal interpolate */
|
||||||
//Step UV horizontally
|
if (iru < sw) {
|
||||||
u += _dudx;
|
/* right pixel */
|
||||||
v += _dvdx;
|
int px2 = *(sbuf + (vv * sw) + iru);
|
||||||
}
|
px = _interpolate(ar, px, px2);
|
||||||
}
|
}
|
||||||
} else {
|
/* vertical interpolate */
|
||||||
if (opacity == 255) {
|
if (irv < sh) {
|
||||||
//Draw horizontal line
|
/* bottom pixel */
|
||||||
while (x++ < x2) {
|
int px2 = *(sbuf + (irv * sw) + uu);
|
||||||
RASTER_COMMON();
|
|
||||||
*buf = px + ALPHA_BLEND(*buf, surface->blender.ialpha(px));
|
/* horizontal interpolate */
|
||||||
++buf;
|
if (iru < sw) {
|
||||||
//Step UV horizontally
|
/* bottom right pixel */
|
||||||
u += _dudx;
|
int px3 = *(sbuf + (irv * sw) + iru);
|
||||||
v += _dvdx;
|
px2 = _interpolate(ar, px2, px3);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Draw horizontal line
|
|
||||||
while (x++ < x2) {
|
|
||||||
RASTER_COMMON();
|
|
||||||
auto src = ALPHA_BLEND(px, opacity);
|
|
||||||
*buf = src + ALPHA_BLEND(*buf, surface->blender.ialpha(src));
|
|
||||||
++buf;
|
|
||||||
//Step UV horizontally
|
|
||||||
u += _dudx;
|
|
||||||
v += _dvdx;
|
|
||||||
}
|
}
|
||||||
|
px = _interpolate(ab, px, px2);
|
||||||
}
|
}
|
||||||
|
#if defined(TEXMAP_MAKSING) && defined(TEXTMAP_TRANSLUCENT)
|
||||||
|
auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blendMethod(*cmp)));
|
||||||
|
#elif defined(TEXMAP_MAKSING)
|
||||||
|
auto src = ALPHA_BLEND(px, blendMethod(*cmp));
|
||||||
|
#elif defined(TEXTMAP_TRANSLUCENT)
|
||||||
|
auto src = ALPHA_BLEND(px, opacity);
|
||||||
|
#else
|
||||||
|
auto src = px;
|
||||||
|
#endif
|
||||||
|
*buf = src + ALPHA_BLEND(*buf, surface->blender.ialpha(src));
|
||||||
|
++buf;
|
||||||
|
#ifdef TEXMAP_MAKSING
|
||||||
|
++cmp;
|
||||||
|
#endif
|
||||||
|
//Step UV horizontally
|
||||||
|
u += _dudx;
|
||||||
|
v += _dvdx;
|
||||||
}
|
}
|
||||||
next:
|
next:
|
||||||
//Step along both edges
|
//Step along both edges
|
||||||
|
@ -185,11 +155,42 @@ next:
|
||||||
_va += _dvdya;
|
_va += _dvdya;
|
||||||
|
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
xa = _xa;
|
xa = _xa;
|
||||||
xb = _xb;
|
xb = _xb;
|
||||||
ua = _ua;
|
ua = _ua;
|
||||||
va = _va;
|
va = _va;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
|
||||||
|
{
|
||||||
|
#define TEXTMAP_TRANSLUCENT
|
||||||
|
#define TEXMAP_MAKSING
|
||||||
|
_rasterRGBA(surface, image, region, ystart, yend, opacity, blendMethod);
|
||||||
|
#undef TEXMAP_MASKING
|
||||||
|
#undef TEXTMAP_TRANSLUCENT
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t (*blendMethod)(uint32_t))
|
||||||
|
{
|
||||||
|
#define TEXMAP_MAKSING
|
||||||
|
_rasterRGBA(surface, image, region, ystart, yend, 255, nullptr);
|
||||||
|
#undef TEXMAP_MASKING
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t opacity)
|
||||||
|
{
|
||||||
|
#define TEXTMAP_TRANSLUCENT
|
||||||
|
_rasterRGBA(surface, image, region, ystart, yend, opacity, nullptr);
|
||||||
|
#undef TEXTMAP_TRANSLUCENT
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend)
|
||||||
|
{
|
||||||
|
_rasterRGBA(surface, image, region, ystart, yend, 255, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -279,7 +280,15 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
// Set right edge X-slope and perform subpixel pre-stepping
|
// Set right edge X-slope and perform subpixel pre-stepping
|
||||||
dxdyb = dxdy[0];
|
dxdyb = dxdy[0];
|
||||||
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
|
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
|
||||||
_rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod);
|
|
||||||
|
if (blendMethod) {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod);
|
||||||
|
} else {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1]);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity);
|
||||||
|
}
|
||||||
|
|
||||||
upper = true;
|
upper = true;
|
||||||
}
|
}
|
||||||
//Draw lower segment if possibly visible
|
//Draw lower segment if possibly visible
|
||||||
|
@ -293,7 +302,13 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
// Set right edge X-slope and perform subpixel pre-stepping
|
// Set right edge X-slope and perform subpixel pre-stepping
|
||||||
dxdyb = dxdy[2];
|
dxdyb = dxdy[2];
|
||||||
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
|
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
|
||||||
_rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod);
|
if (blendMethod) {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod);
|
||||||
|
} else {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2]);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//Longer edge is on the right side
|
//Longer edge is on the right side
|
||||||
} else {
|
} else {
|
||||||
|
@ -316,7 +331,13 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
ua = u[0] + dy * dudya + (off_y * dudya);
|
ua = u[0] + dy * dudya + (off_y * dudya);
|
||||||
va = v[0] + dy * dvdya + (off_y * dvdya);
|
va = v[0] + dy * dvdya + (off_y * dvdya);
|
||||||
|
|
||||||
_rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod);
|
if (blendMethod) {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], blendMethod);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, blendMethod);
|
||||||
|
} else {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1]);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity);
|
||||||
|
}
|
||||||
|
|
||||||
upper = true;
|
upper = true;
|
||||||
}
|
}
|
||||||
|
@ -334,7 +355,13 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
||||||
ua = u[1] + dy * dudya + (off_y * dudya);
|
ua = u[1] + dy * dudya + (off_y * dudya);
|
||||||
va = v[1] + dy * dvdya + (off_y * dvdya);
|
va = v[1] + dy * dvdya + (off_y * dvdya);
|
||||||
|
|
||||||
_rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod);
|
if (blendMethod) {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], blendMethod);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, blendMethod);
|
||||||
|
} else {
|
||||||
|
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2]);
|
||||||
|
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue