Skip to content

Commit 40bf88a

Browse files
committed
Performance: Limit blitting work to overlapping area
1 parent ffec698 commit 40bf88a

File tree

1 file changed

+16
-65
lines changed

1 file changed

+16
-65
lines changed

src/client/tile.cpp

+16-65
Original file line numberDiff line numberDiff line change
@@ -539,14 +539,11 @@ u32 TextureSource::getTextureId(const std::string &name)
539539

540540
// Draw an image on top of another one, using the alpha channel of the
541541
// source image
542+
// overlay: only modify destination pixels that are fully opaque.
543+
template<bool overlay = false>
542544
static void blit_with_alpha(video::IImage *src, video::IImage *dst,
543545
v2s32 src_pos, v2s32 dst_pos, v2u32 size);
544546

545-
// Like blit_with_alpha, but only modifies destination pixels that
546-
// are fully opaque
547-
static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
548-
v2s32 src_pos, v2s32 dst_pos, v2u32 size);
549-
550547
// Apply a color to an image. Uses an int (0-255) to calculate the ratio.
551548
// If the ratio is 255 or -1 and keep_alpha is true, then it multiples the
552549
// color alpha with the destination alpha.
@@ -2042,81 +2039,35 @@ static inline video::SColor blitPixel(const video::SColor src_c, const video::SC
20422039
This exists because IImage::copyToWithAlpha() doesn't seem to always
20432040
work.
20442041
*/
2042+
template<bool overlay>
20452043
static void blit_with_alpha(video::IImage *src, video::IImage *dst,
20462044
v2s32 src_pos, v2s32 dst_pos, v2u32 size)
20472045
{
2048-
// FIXME: loop should be restricted to actual overlap
2049-
// (if dst smaller than size or dst_pos negative)
2050-
for (u32 y0=0; y0<size.Y; y0++)
2051-
for (u32 x0=0; x0<size.X; x0++)
2052-
{
2053-
s32 src_x = src_pos.X + x0;
2054-
s32 src_y = src_pos.Y + y0;
2055-
s32 dst_x = dst_pos.X + x0;
2056-
s32 dst_y = dst_pos.Y + y0;
2057-
video::SColor src_c = src->getPixel(src_x, src_y);
2058-
video::SColor dst_c = dst->getPixel(dst_x, dst_y);
2059-
dst_c = blitPixel(src_c, dst_c, src_c.getAlpha());
2060-
dst->setPixel(dst_x, dst_y, dst_c);
2061-
}
2062-
}
2063-
2064-
/*
2065-
Draw an image on top of another one, using the alpha channel of the
2066-
source image; only modify fully opaque pixels in destinaion
2067-
*/
2068-
static void blit_with_alpha_overlay(video::IImage *src, video::IImage *dst,
2069-
v2s32 src_pos, v2s32 dst_pos, v2u32 size)
2070-
{
2071-
// FIXME: same as above here
2072-
for (u32 y0=0; y0<size.Y; y0++)
2073-
for (u32 x0=0; x0<size.X; x0++)
2046+
auto src_dim = src->getDimension();
2047+
auto dst_dim = dst->getDimension();
2048+
2049+
// Limit y and x to the overlapping ranges
2050+
// s.t. the positions are all in bounds after offsetting.
2051+
for (u32 y0 = std::max(0, -dst_pos.Y);
2052+
y0 < std::min<s64>({size.Y, src_dim.Height, dst_dim.Height - (s64) dst_pos.Y});
2053+
++y0)
2054+
for (u32 x0 = std::max(0, -dst_pos.X);
2055+
x0 < std::min<s64>({size.X, src_dim.Width, dst_dim.Width - (s64) dst_pos.X});
2056+
++x0)
20742057
{
20752058
s32 src_x = src_pos.X + x0;
20762059
s32 src_y = src_pos.Y + y0;
20772060
s32 dst_x = dst_pos.X + x0;
20782061
s32 dst_y = dst_pos.Y + y0;
20792062
video::SColor src_c = src->getPixel(src_x, src_y);
20802063
video::SColor dst_c = dst->getPixel(dst_x, dst_y);
2081-
if (dst_c.getAlpha() == 255 && src_c.getAlpha() != 0)
2082-
{
2064+
if (!overlay || (dst_c.getAlpha() == 255 && src_c.getAlpha() != 0)) {
20832065
dst_c = blitPixel(src_c, dst_c, src_c.getAlpha());
20842066
dst->setPixel(dst_x, dst_y, dst_c);
20852067
}
20862068
}
20872069
}
20882070

2089-
// This function has been disabled because it is currently unused.
2090-
// Feel free to re-enable if you find it handy.
2091-
#if 0
2092-
/*
2093-
Draw an image on top of another one, using the specified ratio
2094-
modify all partially-opaque pixels in the destination.
2095-
*/
2096-
static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst,
2097-
v2s32 src_pos, v2s32 dst_pos, v2u32 size, int ratio)
2098-
{
2099-
for (u32 y0 = 0; y0 < size.Y; y0++)
2100-
for (u32 x0 = 0; x0 < size.X; x0++)
2101-
{
2102-
s32 src_x = src_pos.X + x0;
2103-
s32 src_y = src_pos.Y + y0;
2104-
s32 dst_x = dst_pos.X + x0;
2105-
s32 dst_y = dst_pos.Y + y0;
2106-
video::SColor src_c = src->getPixel(src_x, src_y);
2107-
video::SColor dst_c = dst->getPixel(dst_x, dst_y);
2108-
if (dst_c.getAlpha() > 0 && src_c.getAlpha() != 0)
2109-
{
2110-
if (ratio == -1)
2111-
dst_c = src_c.getInterpolated(dst_c, (float)src_c.getAlpha()/255.0f);
2112-
else
2113-
dst_c = src_c.getInterpolated(dst_c, (float)ratio/255.0f);
2114-
dst->setPixel(dst_x, dst_y, dst_c);
2115-
}
2116-
}
2117-
}
2118-
#endif
2119-
21202071
/*
21212072
Apply color to destination, using a weighted interpolation blend
21222073
*/
@@ -2455,7 +2406,7 @@ static void draw_crack(video::IImage *crack, video::IImage *dst,
24552406
if (!crack_scaled)
24562407
return;
24572408

2458-
auto blit = use_overlay ? blit_with_alpha_overlay : blit_with_alpha;
2409+
auto blit = use_overlay ? blit_with_alpha<true> : blit_with_alpha<false>;
24592410
for (s32 i = 0; i < frame_count; ++i) {
24602411
v2s32 dst_pos(0, frame_size.Height * i);
24612412
blit(crack_scaled, dst, v2s32(0,0), dst_pos, frame_size);

0 commit comments

Comments
 (0)