mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
sw_engine: optimize alpha blending operation.
Compact blending instructions by distinquish the shape & images. since we gurantee the shape color is premultiplied alpha. As a result, this enhanced performance by 0.002s in examples/Performance on my local machine. This also contains code cleanup chores.
This commit is contained in:
parent
36919dc70f
commit
ee9b947c0c
5 changed files with 129 additions and 136 deletions
|
@ -287,9 +287,14 @@ static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a)
|
|||
((((c & 0x00ff00ff) * a + 0x00ff00ff) >> 8) & 0x00ff00ff));
|
||||
}
|
||||
|
||||
static inline uint32_t INTERPOLATE(uint32_t a, uint32_t c0, uint32_t c1)
|
||||
static inline uint32_t INTERPOLATE(uint32_t s, uint32_t d, uint8_t a)
|
||||
{
|
||||
return (((((((c0 >> 8) & 0xff00ff) - ((c1 >> 8) & 0xff00ff)) * a) + (c1 & 0xff00ff00)) & 0xff00ff00) + ((((((c0 & 0xff00ff) - (c1 & 0xff00ff)) * a) >> 8) + (c1 & 0xff00ff)) & 0xff00ff));
|
||||
return (((((((s >> 8) & 0xff00ff) - ((d >> 8) & 0xff00ff)) * a) + (d & 0xff00ff00)) & 0xff00ff00) + ((((((s & 0xff00ff) - (d & 0xff00ff)) * a) >> 8) + (d & 0xff00ff)) & 0xff00ff));
|
||||
}
|
||||
|
||||
static inline uint8_t INTERPOLATE8(uint8_t s, uint8_t d, uint8_t a)
|
||||
{
|
||||
return ((s * a + 0xff) >> 8) + ((d * ~a + 0xff) >> 8);
|
||||
}
|
||||
|
||||
static inline SwCoord HALF_STROKE(float width)
|
||||
|
|
|
@ -80,7 +80,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, const SwSurface*
|
|||
auto dist = static_cast<int32_t>(255 * t);
|
||||
auto dist2 = 255 - dist;
|
||||
|
||||
auto color = INTERPOLATE(dist2, rgba, rgba2);
|
||||
auto color = INTERPOLATE(rgba, rgba2, dist2);
|
||||
fill->ctable[i] = ALPHA_BLEND((color | 0xff000000), (color >> 24));
|
||||
|
||||
++i;
|
||||
|
|
|
@ -100,12 +100,6 @@ static inline uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
|||
}
|
||||
|
||||
|
||||
#include "tvgSwRasterTexmap.h"
|
||||
#include "tvgSwRasterC.h"
|
||||
#include "tvgSwRasterAvx.h"
|
||||
#include "tvgSwRasterNeon.h"
|
||||
|
||||
|
||||
static inline bool _compositing(const SwSurface* surface)
|
||||
{
|
||||
if (!surface->compositor || (int)surface->compositor->method <= (int)CompositeMethod::ClipPath) return false;
|
||||
|
@ -113,6 +107,12 @@ static inline bool _compositing(const SwSurface* surface)
|
|||
}
|
||||
|
||||
|
||||
#include "tvgSwRasterTexmap.h"
|
||||
#include "tvgSwRasterC.h"
|
||||
#include "tvgSwRasterAvx.h"
|
||||
#include "tvgSwRasterNeon.h"
|
||||
|
||||
|
||||
static inline uint32_t _halfScale(float scale)
|
||||
{
|
||||
auto halfScale = static_cast<uint32_t>(0.5f / scale);
|
||||
|
@ -138,7 +138,7 @@ static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, flo
|
|||
auto c3 = img[rx2 + ry2 * w];
|
||||
auto c4 = img[rx + ry2 * w];
|
||||
|
||||
return INTERPOLATE(dy, INTERPOLATE(dx, c3, c4), INTERPOLATE(dx, c2, c1));
|
||||
return INTERPOLATE(INTERPOLATE(c3, c4, dx), INTERPOLATE(c2, c1, dx), dy);
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,12 +177,13 @@ void _rasterGrayscale8(uint8_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
|||
/* Rect */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a, SwAlpha alpha)
|
||||
static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8 + ((region.min.y * surface->compositor->image.stride + region.min.x) * csize); //compositor buffer
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
TVGLOG("SW_ENGINE", "Masked Rect [Region: %lu %lu %u %u]", region.min.x, region.min.y, w, h);
|
||||
|
||||
|
@ -194,8 +195,7 @@ static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t
|
|||
auto dst = &buffer[y * surface->stride];
|
||||
auto cmp = &cbuffer[y * surface->stride * csize];
|
||||
for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) {
|
||||
auto tmp = ALPHA_BLEND(color, alpha(cmp));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
*dst = INTERPOLATE(color, *dst, alpha(cmp));
|
||||
}
|
||||
}
|
||||
//8bits grayscale
|
||||
|
@ -205,8 +205,7 @@ static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t
|
|||
auto dst = &buffer[y * surface->stride];
|
||||
auto cmp = &cbuffer[y * surface->stride * csize];
|
||||
for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) {
|
||||
auto tmp = _multiply<uint8_t>(a, alpha(cmp));
|
||||
*dst = tmp + _multiply<uint8_t>(*dst, _ialpha(tmp));
|
||||
*dst = INTERPOLATE8(a, *dst, alpha(cmp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -240,8 +239,7 @@ static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint8_t r
|
|||
static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterMaskedRect(surface, region, r, g, b, a, alpha);
|
||||
return _rasterMaskedRect(surface, region, r, g, b, a);
|
||||
} else {
|
||||
if (a == 255) {
|
||||
return _rasterSolidRect(surface, region, r, g, b);
|
||||
|
@ -263,17 +261,18 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uin
|
|||
/* Rle */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a, SwAlpha alpha)
|
||||
static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Masked Rle");
|
||||
|
||||
auto span = rle->spans;
|
||||
uint32_t src;
|
||||
auto cbuffer = surface->compositor->image.buf8;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
//32bit channels
|
||||
if (surface->channelSize == sizeof(uint32_t)) {
|
||||
uint32_t src;
|
||||
auto color = surface->blender.join(r, g, b, a);
|
||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||
|
@ -281,20 +280,19 @@ static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint
|
|||
if (span->coverage == 255) src = color;
|
||||
else src = ALPHA_BLEND(color, span->coverage);
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) {
|
||||
auto tmp = ALPHA_BLEND(src, alpha(cmp));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
*dst = INTERPOLATE(src, *dst, alpha(cmp));
|
||||
}
|
||||
}
|
||||
//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];
|
||||
auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize];
|
||||
if (span->coverage == 255) src = a;
|
||||
else src = _multiply<uint8_t>(a, span->coverage);
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) {
|
||||
auto tmp = _multiply<uint8_t>(src, alpha(cmp));
|
||||
*dst = tmp + _multiply<uint8_t>(*dst, _ialpha(tmp));
|
||||
*dst = INTERPOLATE8(src, *dst, alpha(cmp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -343,8 +341,7 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g,
|
|||
if (!rle) return false;
|
||||
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterMaskedRle(surface, rle, r, g, b, a, alpha);
|
||||
return _rasterMaskedRle(surface, rle, r, g, b, a);
|
||||
} else {
|
||||
if (a == 255) {
|
||||
return _rasterSolidRle(surface, rle, r, g, b);
|
||||
|
@ -368,25 +365,21 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g,
|
|||
|
||||
static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, uint32_t opacity)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, alpha);
|
||||
} else {
|
||||
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr);
|
||||
}
|
||||
return false;
|
||||
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* RLE Scaled RGBA Image */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, SwAlpha alpha)
|
||||
static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Scaled Masked Translucent Rle Image");
|
||||
|
||||
auto span = image->rle->spans;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
//Center (Down-Scaled)
|
||||
if (image->scale < DOWN_SCALE_TOLERANCE) {
|
||||
|
@ -399,8 +392,8 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const
|
|||
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
|
||||
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
|
||||
if (sx >= image->w) continue;
|
||||
auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), a);
|
||||
auto tmp = ALPHA_BLEND(src, alpha(cmp));
|
||||
auto src = _interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale);
|
||||
auto tmp = ALPHA_BLEND(src, _multiply<uint8_t>(alpha(cmp), a));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
}
|
||||
|
@ -415,8 +408,8 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const
|
|||
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
|
||||
auto sx = x * itransform->e11 + itransform->e13;
|
||||
if ((uint32_t)sx >= image->w) continue;
|
||||
auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), a);
|
||||
auto tmp = ALPHA_BLEND(src, alpha(cmp));
|
||||
auto src = _interpUpScaler(image->buf32, image->w, image->h, sx, sy);
|
||||
auto tmp = ALPHA_BLEND(src, _multiply<uint8_t>(alpha(cmp), a));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
}
|
||||
|
@ -425,12 +418,13 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const
|
|||
}
|
||||
|
||||
|
||||
static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, SwAlpha alpha)
|
||||
static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Scaled Masked Rle Image");
|
||||
|
||||
auto span = image->rle->spans;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
//Center (Down-Scaled)
|
||||
if (image->scale < DOWN_SCALE_TOLERANCE) {
|
||||
|
@ -450,8 +444,8 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i
|
|||
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
|
||||
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
|
||||
if (sx >= image->w) continue;
|
||||
auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage);
|
||||
auto tmp = ALPHA_BLEND(src, alpha(cmp));
|
||||
auto src = _interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale);
|
||||
auto tmp = ALPHA_BLEND(src, _multiply<uint8_t>(span->coverage, alpha(cmp)));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
}
|
||||
|
@ -474,8 +468,8 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i
|
|||
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
|
||||
auto sx = x * itransform->e11 + itransform->e13;
|
||||
if ((uint32_t)sx >= image->w) continue;
|
||||
auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), span->coverage);
|
||||
auto tmp = ALPHA_BLEND(src, alpha(cmp));
|
||||
auto src = _interpUpScaler(image->buf32, image->w, image->h, sx, sy);
|
||||
auto tmp = ALPHA_BLEND(src, _multiply<uint8_t>(span->coverage, alpha(cmp)));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
}
|
||||
|
@ -586,9 +580,8 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
|
|||
auto halfScale = _halfScale(image->scale);
|
||||
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
if (opacity == 255) return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, alpha);
|
||||
else return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, alpha);
|
||||
if (opacity == 255) return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale);
|
||||
else return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale);
|
||||
} else {
|
||||
if (opacity == 255) return _rasterScaledRleRGBAImage(surface, image, &itransform, region, opacity, halfScale);
|
||||
else return _rasterScaledTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale);
|
||||
|
@ -601,13 +594,14 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
|
|||
/* RLE Direct RGBA Image */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, SwAlpha alpha)
|
||||
static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Direct Masked Rle Image");
|
||||
|
||||
auto span = image->rle->spans;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||
|
@ -630,13 +624,14 @@ static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const
|
|||
}
|
||||
|
||||
|
||||
static bool _rasterDirectMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, SwAlpha alpha)
|
||||
static bool _rasterDirectMaskedRleRGBAImage(SwSurface* surface, const SwImage* image)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Direct Masked Rle Image");
|
||||
|
||||
auto span = image->rle->spans;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
|
||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||
|
@ -700,9 +695,8 @@ static bool _rasterDirectRleRGBAImage(SwSurface* surface, const SwImage* image)
|
|||
static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
if (opacity == 255) return _rasterDirectMaskedRleRGBAImage(surface, image, alpha);
|
||||
else return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, alpha);
|
||||
if (opacity == 255) return _rasterDirectMaskedRleRGBAImage(surface, image);
|
||||
else return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity);
|
||||
} else {
|
||||
if (opacity == 255) return _rasterDirectRleRGBAImage(surface, image);
|
||||
else return _rasterDirectTranslucentRleRGBAImage(surface, image, opacity);
|
||||
|
@ -717,24 +711,12 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32
|
|||
|
||||
static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, alpha);
|
||||
} else {
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, nullptr);
|
||||
}
|
||||
return false;
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity);
|
||||
}
|
||||
|
||||
static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, alpha);
|
||||
} else {
|
||||
return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, nullptr);
|
||||
}
|
||||
return false;
|
||||
return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity);
|
||||
}
|
||||
|
||||
|
||||
|
@ -742,13 +724,14 @@ static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image,
|
|||
/*Scaled RGBA Image */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, SwAlpha alpha)
|
||||
static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Scaled Masked Image");
|
||||
|
||||
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
// Down-Scaled
|
||||
if (image->scale < DOWN_SCALE_TOLERANCE) {
|
||||
|
@ -760,9 +743,9 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
|
|||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
|
||||
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
|
||||
if (sx >= image->w) continue;
|
||||
auto a = _multiply<uint32_t>(opacity, alpha(cmp));
|
||||
auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), a);
|
||||
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
||||
auto src = _interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale);
|
||||
auto temp = ALPHA_BLEND(src, _multiply<uint32_t>(opacity, alpha(cmp)));
|
||||
*dst = temp + ALPHA_BLEND(*dst, _ialpha(temp));
|
||||
}
|
||||
dbuffer += surface->stride;
|
||||
cbuffer += surface->compositor->image.stride * csize;
|
||||
|
@ -777,9 +760,9 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
|
|||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
|
||||
auto sx = x * itransform->e11 + itransform->e13;
|
||||
if ((uint32_t)sx >= image->w) continue;
|
||||
auto a = _multiply<uint32_t>(opacity, alpha(cmp));
|
||||
auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), a);
|
||||
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
||||
auto src = _interpUpScaler(image->buf32, image->w, image->h, sx, sy);
|
||||
auto temp = ALPHA_BLEND(src, _multiply<uint32_t>(opacity, alpha(cmp)));
|
||||
*dst = temp + ALPHA_BLEND(*dst, _ialpha(temp));
|
||||
}
|
||||
dbuffer += surface->stride;
|
||||
cbuffer += surface->compositor->image.stride * csize;
|
||||
|
@ -789,13 +772,14 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
|
|||
}
|
||||
|
||||
|
||||
static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, SwAlpha alpha)
|
||||
static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Scaled Masked Image");
|
||||
|
||||
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
// Down-Scaled
|
||||
if (image->scale < DOWN_SCALE_TOLERANCE) {
|
||||
|
@ -807,8 +791,9 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
|
|||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
|
||||
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
|
||||
if (sx >= image->w) continue;
|
||||
auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha(cmp));
|
||||
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
||||
auto src = _interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale);
|
||||
auto temp = ALPHA_BLEND(src, alpha(cmp));
|
||||
*dst = temp + ALPHA_BLEND(*dst, _ialpha(temp));
|
||||
}
|
||||
dbuffer += surface->stride;
|
||||
cbuffer += surface->compositor->image.stride * csize;
|
||||
|
@ -823,8 +808,9 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
|
|||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
|
||||
auto sx = x * itransform->e11 + itransform->e13;
|
||||
if ((uint32_t)sx >= image->w) continue;
|
||||
auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), alpha(cmp));
|
||||
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
|
||||
auto src = _interpUpScaler(image->buf32, image->w, image->h, sx, sy);
|
||||
auto temp = ALPHA_BLEND(src, alpha(cmp));
|
||||
*dst = temp + ALPHA_BLEND(*dst, _ialpha(temp));
|
||||
}
|
||||
dbuffer += surface->stride;
|
||||
cbuffer += surface->compositor->image.stride * csize;
|
||||
|
@ -915,9 +901,8 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
|
|||
auto halfScale = _halfScale(image->scale);
|
||||
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
if (opacity == 255) return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, alpha);
|
||||
else return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, alpha);
|
||||
if (opacity == 255) return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale);
|
||||
else return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale);
|
||||
} else {
|
||||
if (opacity == 255) return _rasterScaledRGBAImage(surface, image, &itransform, region, halfScale);
|
||||
else return _rasterScaledTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale);
|
||||
|
@ -930,7 +915,7 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
|
|||
/* Direct RGBA Image */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwAlpha alpha)
|
||||
static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Direct Masked Image");
|
||||
|
||||
|
@ -938,6 +923,7 @@ static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* imag
|
|||
auto h2 = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer
|
||||
|
@ -958,7 +944,7 @@ static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* imag
|
|||
}
|
||||
|
||||
|
||||
static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, SwAlpha alpha)
|
||||
static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity)
|
||||
{
|
||||
TVGLOG("SW_ENGINE", "Direct Masked Translucent Image");
|
||||
|
||||
|
@ -966,6 +952,7 @@ static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
|
|||
auto h2 = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer
|
||||
|
@ -975,7 +962,7 @@ static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
|
|||
auto cmp = cbuffer;
|
||||
auto src = sbuffer;
|
||||
for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, cmp += csize) {
|
||||
auto tmp = ALPHA_BLEND(*src, _multiply<uint32_t>(opacity, alpha(cmp)));
|
||||
auto tmp = ALPHA_BLEND(*src, _multiply<uint8_t>(opacity, alpha(cmp)));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
buffer += surface->stride;
|
||||
|
@ -1027,9 +1014,8 @@ static bool _rasterDirectRGBAImage(SwSurface* surface, const SwImage* image, con
|
|||
static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
if (opacity == 255) return _rasterDirectMaskedRGBAImage(surface, image, region, alpha);
|
||||
else return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, alpha);
|
||||
if (opacity == 255) return _rasterDirectMaskedRGBAImage(surface, image, region);
|
||||
else return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity);
|
||||
} else {
|
||||
if (opacity == 255) return _rasterDirectRGBAImage(surface, image, region);
|
||||
else return _rasterDirectTranslucentRGBAImage(surface, image, region, opacity);
|
||||
|
@ -1059,7 +1045,7 @@ static bool _rasterRGBAImage(SwSurface* surface, SwImage* image, const Matrix* t
|
|||
/* Rect Linear Gradient */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwAlpha alpha)
|
||||
static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
|
||||
{
|
||||
if (fill->linear.len < FLT_EPSILON) return false;
|
||||
|
||||
|
@ -1068,6 +1054,7 @@ static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& re
|
|||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
|
||||
if (!sbuffer) return false;
|
||||
|
@ -1129,8 +1116,7 @@ static bool _rasterSolidLinearGradientRect(SwSurface* surface, const SwBBox& reg
|
|||
static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterLinearGradientMaskedRect(surface, region, fill, alpha);
|
||||
return _rasterLinearGradientMaskedRect(surface, region, fill);
|
||||
} else {
|
||||
if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill);
|
||||
else _rasterSolidLinearGradientRect(surface, region, fill);
|
||||
|
@ -1143,15 +1129,17 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
|
|||
/* Rle Linear Gradient */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwAlpha alpha)
|
||||
static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
|
||||
{
|
||||
if (fill->linear.len < FLT_EPSILON) return false;
|
||||
|
||||
auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||
if (!buffer) return false;
|
||||
|
||||
auto span = rle->spans;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8;
|
||||
auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||
if (!buffer) return false;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||
fillFetchLinear(fill, buffer, span->y, span->x, span->len);
|
||||
|
@ -1164,10 +1152,8 @@ static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData*
|
|||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
} else {
|
||||
auto ialpha = 255 - span->coverage;
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) {
|
||||
auto tmp = ALPHA_BLEND(*src, alpha(cmp));
|
||||
tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha);
|
||||
auto tmp = ALPHA_BLEND(*src, _multiply<uint8_t>(span->coverage, alpha(cmp)));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
}
|
||||
|
@ -1218,7 +1204,7 @@ static bool _rasterSolidLinearGradientRle(SwSurface* surface, const SwRleData* r
|
|||
fillFetchLinear(fill, buf, span->y, span->x, span->len);
|
||||
auto dst = &surface->buf32[span->y * surface->stride + span->x];
|
||||
for (uint32_t x = 0; x < span->len; ++x) {
|
||||
dst[x] = INTERPOLATE(span->coverage, buf[x], dst[x]);
|
||||
dst[x] = INTERPOLATE(buf[x], dst[x], span->coverage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1231,8 +1217,7 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c
|
|||
if (!rle) return false;
|
||||
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterLinearGradientMaskedRle(surface, rle, fill, alpha);
|
||||
return _rasterLinearGradientMaskedRle(surface, rle, fill);
|
||||
} else {
|
||||
if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill);
|
||||
else return _rasterSolidLinearGradientRle(surface, rle, fill);
|
||||
|
@ -1245,7 +1230,7 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c
|
|||
/* Rect Radial Gradient */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwAlpha alpha)
|
||||
static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
|
||||
{
|
||||
if (fill->radial.a < FLT_EPSILON) return false;
|
||||
|
||||
|
@ -1254,6 +1239,7 @@ static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& re
|
|||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
auto sbuffer = static_cast<uint32_t*>(alloca(w * sizeof(uint32_t)));
|
||||
if (!sbuffer) return false;
|
||||
|
@ -1316,8 +1302,7 @@ static bool _rasterSolidRadialGradientRect(SwSurface* surface, const SwBBox& reg
|
|||
static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
|
||||
{
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterRadialGradientMaskedRect(surface, region, fill, alpha);
|
||||
return _rasterRadialGradientMaskedRect(surface, region, fill);
|
||||
} else {
|
||||
if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill);
|
||||
else return _rasterSolidRadialGradientRect(surface, region, fill);
|
||||
|
@ -1330,15 +1315,17 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
|
|||
/* RLE Radial Gradient */
|
||||
/************************************************************************/
|
||||
|
||||
static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwAlpha alpha)
|
||||
static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
|
||||
{
|
||||
if (fill->radial.a < FLT_EPSILON) return false;
|
||||
|
||||
auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||
if (!buffer) return false;
|
||||
|
||||
auto span = rle->spans;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto cbuffer = surface->compositor->image.buf8;
|
||||
auto buffer = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||
if (!buffer) return false;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
|
||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||
fillFetchRadial(fill, buffer, span->y, span->x, span->len);
|
||||
|
@ -1352,7 +1339,7 @@ static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData*
|
|||
}
|
||||
} else {
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) {
|
||||
auto tmp = INTERPOLATE(span->coverage, ALPHA_BLEND(*src, alpha(cmp)), *dst);
|
||||
auto tmp = ALPHA_BLEND(*src, _multiply<uint8_t>(span->coverage, alpha(cmp)));
|
||||
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
|
||||
}
|
||||
}
|
||||
|
@ -1402,9 +1389,8 @@ static bool _rasterSolidRadialGradientRle(SwSurface* surface, const SwRleData* r
|
|||
fillFetchRadial(fill, dst, span->y, span->x, span->len);
|
||||
} else {
|
||||
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
||||
auto ialpha = 255 - span->coverage;
|
||||
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||
*dst = ALPHA_BLEND(buf[x], span->coverage) + ALPHA_BLEND(*dst, ialpha);
|
||||
*dst = INTERPOLATE(buf[x], *dst, span->coverage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1417,8 +1403,7 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c
|
|||
if (!rle) return false;
|
||||
|
||||
if (_compositing(surface)) {
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
return _rasterRadialGradientMaskedRle(surface, rle, fill, alpha);
|
||||
return _rasterRadialGradientMaskedRle(surface, rle, fill);
|
||||
} else {
|
||||
if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill);
|
||||
else return _rasterSolidRadialGradientRle(surface, rle, fill);
|
||||
|
|
|
@ -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, SwAlpha alpha, AASpans* aaSpans)
|
||||
static void _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, AASpans* aaSpans)
|
||||
{
|
||||
#define TEXMAP_TRANSLUCENT
|
||||
#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, SwAlpha alpha, AASpans* aaSpans)
|
||||
static void _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans)
|
||||
{
|
||||
#define TEXMAP_MASKING
|
||||
#include "tvgSwRasterTexmapInternal.h"
|
||||
|
@ -102,7 +102,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
|
|||
|
||||
|
||||
/* 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, SwAlpha alpha, AASpans* aaSpans)
|
||||
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, AASpans* aaSpans)
|
||||
{
|
||||
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};
|
||||
|
@ -165,6 +165,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
|||
if (mathEqual(y[1], y[2])) side = x[2] > x[1];
|
||||
|
||||
auto regionTop = region ? region->min.y : image->rle->spans->y; //Normal Image or Rle Image?
|
||||
auto masking = _compositing(surface); //Masking required
|
||||
|
||||
//Longer edge is on the left side
|
||||
if (!side) {
|
||||
|
@ -190,9 +191,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
|||
dxdyb = dxdy[0];
|
||||
xb = x[0] + dy * dxdyb + (off_y * dxdyb);
|
||||
|
||||
if (alpha) {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], alpha, aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, alpha, aaSpans);
|
||||
if (masking) {
|
||||
if (opacity == 255) _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
||||
} else {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
||||
|
@ -211,9 +212,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
|||
// Set right edge X-slope and perform subpixel pre-stepping
|
||||
dxdyb = dxdy[2];
|
||||
xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb);
|
||||
if (alpha) {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], alpha, aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, alpha, aaSpans);
|
||||
if (masking) {
|
||||
if (opacity == 255) _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
||||
} else {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
||||
|
@ -240,9 +241,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
|||
ua = u[0] + dy * dudya + (off_y * dudya);
|
||||
va = v[0] + dy * dvdya + (off_y * dvdya);
|
||||
|
||||
if (alpha) {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], alpha, aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, alpha, aaSpans);
|
||||
if (masking) {
|
||||
if (opacity == 255) _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
||||
} else {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], opacity, aaSpans);
|
||||
|
@ -264,9 +265,9 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
|
|||
ua = u[1] + dy * dudya + (off_y * dudya);
|
||||
va = v[1] + dy * dvdya + (off_y * dvdya);
|
||||
|
||||
if (alpha) {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], alpha, aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, alpha, aaSpans);
|
||||
if (masking) {
|
||||
if (opacity == 255) _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
||||
else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
||||
} else {
|
||||
if (opacity == 255) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans);
|
||||
else _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], opacity, aaSpans);
|
||||
|
@ -508,7 +509,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
|
|||
|
||||
pos = 1;
|
||||
while (pos <= line->length[0]) {
|
||||
*dst = INTERPOLATE((line->coverage[0] * pos), *dst, pixel);
|
||||
*dst = INTERPOLATE(*dst, pixel, line->coverage[0] * pos);
|
||||
++dst;
|
||||
++pos;
|
||||
}
|
||||
|
@ -520,7 +521,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
|
|||
|
||||
pos = width;
|
||||
while ((int32_t)(width - line->length[1]) < pos) {
|
||||
*dst = INTERPOLATE(255 - (line->coverage[1] * (line->length[1] - (width - pos))), *dst, pixel);
|
||||
*dst = INTERPOLATE(*dst, pixel, 255 - (line->coverage[1] * (line->length[1] - (width - pos))));
|
||||
--dst;
|
||||
--pos;
|
||||
}
|
||||
|
@ -545,7 +546,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans)
|
|||
| / |
|
||||
3 -- 2
|
||||
*/
|
||||
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, SwAlpha alpha)
|
||||
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity)
|
||||
{
|
||||
//Exceptions: No dedicated drawing area?
|
||||
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
|
||||
|
@ -576,14 +577,14 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
|||
polygon.vertex[1] = vertices[1];
|
||||
polygon.vertex[2] = vertices[3];
|
||||
|
||||
_rasterPolygonImage(surface, image, region, opacity, polygon, alpha, aaSpans);
|
||||
_rasterPolygonImage(surface, image, region, opacity, polygon, aaSpans);
|
||||
|
||||
//Draw the second polygon
|
||||
polygon.vertex[0] = vertices[1];
|
||||
polygon.vertex[1] = vertices[2];
|
||||
polygon.vertex[2] = vertices[3];
|
||||
|
||||
_rasterPolygonImage(surface, image, region, opacity, polygon, alpha, aaSpans);
|
||||
_rasterPolygonImage(surface, image, region, opacity, polygon, aaSpans);
|
||||
|
||||
return _apply(surface, aaSpans);
|
||||
}
|
||||
|
@ -602,7 +603,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
|
|||
Should provide two Polygons, one for each triangle.
|
||||
// TODO: region?
|
||||
*/
|
||||
static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, SwAlpha alpha)
|
||||
static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity)
|
||||
{
|
||||
//Exceptions: No dedicated drawing area?
|
||||
if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false;
|
||||
|
@ -636,7 +637,7 @@ static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, c
|
|||
auto aaSpans = _AASpans(ys, ye, image, region);
|
||||
if (aaSpans) {
|
||||
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||
_rasterPolygonImage(surface, image, region, opacity, transformedTris[i], alpha, aaSpans);
|
||||
_rasterPolygonImage(surface, image, region, opacity, transformedTris[i], aaSpans);
|
||||
}
|
||||
// Apply to surface (note: frees the AA spans)
|
||||
_apply(surface, aaSpans);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#ifdef TEXMAP_MASKING
|
||||
uint8_t* cmp;
|
||||
auto csize = surface->compositor->image.channelSize;
|
||||
auto alpha = surface->blender.alpha(surface->compositor->method);
|
||||
#endif
|
||||
|
||||
if (!_arrange(image, region, yStart, yEnd)) return;
|
||||
|
@ -115,7 +116,7 @@
|
|||
if (iru < sw) {
|
||||
/* right pixel */
|
||||
int px2 = *(sbuf + (vv * sw) + iru);
|
||||
px = INTERPOLATE(ar, px, px2);
|
||||
px = INTERPOLATE(px, px2, ar);
|
||||
}
|
||||
/* vertical interpolate */
|
||||
if (irv < sh) {
|
||||
|
@ -126,14 +127,17 @@
|
|||
if (iru < sw) {
|
||||
/* bottom right pixel */
|
||||
int px3 = *(sbuf + (irv * sw) + iru);
|
||||
px2 = INTERPOLATE(ar, px2, px3);
|
||||
px2 = INTERPOLATE(px2, px3, ar);
|
||||
}
|
||||
px = INTERPOLATE(ab, px, px2);
|
||||
px = INTERPOLATE(px, px2, ab);
|
||||
}
|
||||
|
||||
#if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT)
|
||||
auto src = ALPHA_BLEND(px, _multiply<uint32_t>(opacity, alpha(cmp)));
|
||||
cmp += csize;
|
||||
#elif defined(TEXMAP_MASKING)
|
||||
auto src = ALPHA_BLEND(px, alpha(cmp));
|
||||
cmp += csize;
|
||||
#elif defined(TEXMAP_TRANSLUCENT)
|
||||
auto src = ALPHA_BLEND(px, opacity);
|
||||
#else
|
||||
|
@ -141,9 +145,7 @@
|
|||
#endif
|
||||
*buf = src + ALPHA_BLEND(*buf, _ialpha(src));
|
||||
++buf;
|
||||
#ifdef TEXMAP_MASKING
|
||||
cmp += csize;
|
||||
#endif
|
||||
|
||||
//Step UV horizontally
|
||||
u += _dudx;
|
||||
v += _dvdx;
|
||||
|
|
Loading…
Add table
Reference in a new issue