Skip to content

Commit 6fa9b0f

Browse files
committed
Core: Wrap low-level alpha-blending routines in C++.
1 parent d490863 commit 6fa9b0f

File tree

5 files changed

+116
-48
lines changed

5 files changed

+116
-48
lines changed

libvisual/libvisual/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ SET(libvisual_SOURCES
6363
lv_cpu.c
6464
lv_error.c
6565
lv_gl.c
66-
lv_alpha_blend.c
6766
lv_util.c
6867

6968
lv_actor.cpp
69+
lv_alpha_blend.cpp
7070
lv_audio.cpp
7171
lv_bin.cpp
7272
lv_buffer.cpp

libvisual/libvisual/lv_alpha_blend.c

-46
This file was deleted.
+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include "config.h"
2+
#include "lv_alpha_blend.h"
3+
#include "lv_common.h"
4+
#include "lv_cpu.h"
5+
#include "lv_alpha_blend_orc.h"
6+
#include <cassert>
7+
8+
namespace {
9+
10+
#pragma pack(1)
11+
12+
struct rgb16_t {
13+
#if VISUAL_LITTLE_ENDIAN == 1
14+
std::uint16_t b:5, g:6, r:5;
15+
#else
16+
std::uint16_t r:5, g:6, b:5;
17+
#endif
18+
};
19+
20+
#pragma pack()
21+
22+
static_assert (sizeof (rgb16_t) == 2);
23+
24+
} // anonymous namespace
25+
26+
namespace LV {
27+
28+
void alpha_blend_8 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha)
29+
{
30+
assert (dst.data () != src1.data ());
31+
assert (dst.data () != src2.data ());
32+
assert (src1.size () == src2.size ());
33+
34+
auto size {static_cast<int> (std::min (dst.size (), src1.size ()))};
35+
::simd_interpolate_8 (dst.data (), src1.data (), src2.data (), alpha, size);
36+
}
37+
38+
void alpha_blend_16 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha)
39+
{
40+
assert (dst.data () != src1.data ());
41+
assert (dst.data () != src2.data ());
42+
assert (src1.size () == src2.size ());
43+
44+
auto dst_ptr = reinterpret_cast<rgb16_t*> (dst.data ());
45+
auto src1_ptr = reinterpret_cast<rgb16_t const*> (src1.data ());
46+
auto src2_ptr = reinterpret_cast<rgb16_t const*> (src2.data ());
47+
48+
auto size {static_cast<int> (std::min (dst.size (), src1.size ()))};
49+
50+
for (auto i = 0; i < size / sizeof (rgb16_t); i++) {
51+
dst_ptr[i].r = (alpha * (src2_ptr[i].r - src1_ptr[i].r)) / 255 + src1_ptr[i].r;
52+
dst_ptr[i].g = (alpha * (src2_ptr[i].g - src1_ptr[i].g)) / 255 + src1_ptr[i].g;
53+
dst_ptr[i].b = (alpha * (src2_ptr[i].b - src1_ptr[i].b)) / 255 + src1_ptr[i].b;
54+
}
55+
}
56+
57+
void alpha_blend_24 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha)
58+
{
59+
assert (dst.data () != src1.data ());
60+
assert (dst.data () != src2.data ());
61+
assert (src1.size () == src2.size ());
62+
63+
auto size {static_cast<int> (std::min (dst.size (), src1.size ()))};
64+
::simd_interpolate_8 (dst.data (), src1.data (), src2.data (), alpha, size * 3);
65+
}
66+
67+
void alpha_blend_32 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha)
68+
{
69+
assert (dst.data () != src1.data ());
70+
assert (dst.data () != src2.data ());
71+
assert (src1.size () == src2.size ());
72+
73+
auto size {static_cast<int> (std::min (dst.size (), src1.size ()))};
74+
::simd_interpolate_8 (dst.data (), src1.data (), src2.data (), alpha, size * 4);
75+
}
76+
77+
} // LV namespace
78+
79+
80+
void visual_alpha_blend_8 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha)
81+
{
82+
simd_interpolate_8 (dest, src1, src2, alpha, (int) size);
83+
}
84+
85+
void visual_alpha_blend_16 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha)
86+
{
87+
LV::alpha_blend_16 ({dest, size}, {src1, size}, {src2, size}, alpha);
88+
}
89+
90+
void visual_alpha_blend_24 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha)
91+
{
92+
simd_interpolate_8 (dest, src1, src2, alpha, (int) size * 3);
93+
}
94+
95+
void visual_alpha_blend_32 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha)
96+
{
97+
simd_interpolate_8 (dest, src1, src2, alpha, (int) size * 4);
98+
}

libvisual/libvisual/lv_alpha_blend.h

+16
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
#include <libvisual/lv_defines.h>
66
#include <libvisual/lv_types.h>
77

8+
#ifdef __cplusplus
9+
10+
#include <cstdint>
11+
#include <span>
12+
13+
namespace LV {
14+
15+
LV_API void alpha_blend_8 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha);
16+
LV_API void alpha_blend_16 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha);
17+
LV_API void alpha_blend_24 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha);
18+
LV_API void alpha_blend_32 (std::span<std::uint8_t> dst, std::span<std::uint8_t const> src1, std::span<std::uint8_t const> src2, std::uint8_t alpha);
19+
20+
} // LV namespace
21+
22+
#endif /* __cplusplus */
23+
824
LV_BEGIN_DECLS
925

1026
LV_API void visual_alpha_blend_8 (uint8_t *LV_RESTRICT dest, const uint8_t *LV_RESTRICT src1, const uint8_t *LV_RESTRICT src2, visual_size_t size, uint8_t alpha);

libvisual/po/POTFILES.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
libvisual/lv_libvisual.cpp
22
libvisual/lv_libvisual_c.cpp
33
libvisual/lv_actor.cpp
4-
libvisual/lv_alpha_blend.c
4+
libvisual/lv_alpha_blend.cpp
55
libvisual/lv_audio.cpp
66
libvisual/lv_audio_c.cpp
77
libvisual/lv_buffer.cpp

0 commit comments

Comments
 (0)